GRme
GRme

Reputation: 2757

Using REST client in Nightwatch command queue

I'm using Nightwatch-Cucumber based on Nightwatch.js for our tests. Ans also I use the PageObject Pattern. These tests are not only end2end tests based on Selenium but also REST API tests. For the REST tests I'm using an Atlassian JIRA REST client for Node. Now I want to combine the power of Nightwatch, including Selenium, with the power of REST. So, I want to use both technologies together and I want to integrate the REST API calls within the Nightwatch framework.

I've tried to integrate the REST API calls within the perform() function of Nightwatch to add the REST calls to the Nightwatch command queue, but without a complete success. I have to ensure that the REST calls are completely done before executing the next Nightwatch commands. Currently the following steps after the REST calls will be execute before the REST call is completely done. But how can I solve that problem?

This is my Cucumber Feature file:

Feature: JIRA projects tests

  Scenario: my first test
    When the user logs out
    When the user deletes a still existing project with key "ABC-123" via REST API
    When the user logs out

These are my Step Definitions:

const { client } = require("nightwatch-cucumber");
const { defineSupportCode } = require("cucumber");

const myPage = client.page.myPageView();

defineSupportCode(({ Given, When, Then }) => {
  When(/^the user logs out$/, () => {
    return myPage.logoutUser(client);
  });

  When(
    /^the user deletes a still existing project with key "([^"]*)" via REST API$/,
    projectKey => {
      return myPage.deleteProjectViaRestApi(client, projectKey);
    }
  );
});

And these are my Page Object functions:

const restClientConnector = require("../../rest/restClientConnector");
const environmentVariables = require("../../helpers/getEnvironmentVariables");

module.exports = {
  elements: {},
  commands: [
    {
      logoutUser(client) {
        console.log("1");
        return client
          .deleteCookies()
          .url(
            environmentVariables.launchUrl(client) +
              "/crowd/console/logoff.action"
          );
      },

      deleteProjectViaRestApi(client, projectKey) {
        return client
          .perform(function() {
            //delete the given project
            restClientConnector
              .jiraConnector(
                environmentVariables.jiraHostUrl,
                environmentVariables.jiraAdminUsername,
                environmentVariables.jiraAdminPassword
              )
              .project.deleteProject(
                {
                  projectIdOrKey: projectKey
                },
                function(error, result) {
                  console.log("2");
                }
              );
          })
          .perform(function() {
            restClientConnector
              .jiraConnector(
                environmentVariables.jiraHostUrl,
                environmentVariables.jiraAdminUsername,
                environmentVariables.jiraAdminPassword
              )
              .project.getProject(
                {
                  projectIdOrKey: projectKey
                },
                function(error, result) {
                  console.log("3");
                }
              );
          });
        //.waitForTime(4000);
      }
    }
  ]
};

So, I want that the 3 Cucumber steps are running synchronously, one after the next. I've added some console.log() outputs to check this. While my test run I expect the sequence of console output:

1
2
3
1

Instead I get the following output:

Starting selenium server... started - PID:  10436
.1
..1
..

1 scenario (1 passed)
3 steps (3 passed)
0m03.782s
3
2

So, the second call of Cucumber step When the user logs out started to execute before the Cucumber step When the user deletes a still existing project with key "ABC-123" via REST API has completely finished.

If I uncomment the line .waitForTime(4000) (it is a custom command) in my Page Object then I get the correct output, but I don't want to wait in such a static way. It's very dirty:

Starting selenium server... started - PID:  10554
.1
.2
3
.1
..

1 scenario (1 passed)
3 steps (3 passed)
0m07.783s

How can I solve my problem to execute exactly one step after the next or how can I integrate the REST calls within the Nightwatch command queue. I've also tried to make my funtions async and to execute all commands with await, but also without success.

Upvotes: 2

Views: 1109

Answers (1)

tehbeardedone
tehbeardedone

Reputation: 2858

If you have an async task that you need to run synchronously you have to use the done callback in your perform function.

browser.perform(function(done) {
  //do some async stuff...

  done();
});

You want to call done once your async task is completed. In your case it should be something similar to this:

deleteProjectViaRestApi(client, projectKey) {
    return client
      .perform(function(done) {
        //delete the given project
        restClientConnector
          .jiraConnector(
            environmentVariables.jiraHostUrl,
            environmentVariables.jiraAdminUsername,
            environmentVariables.jiraAdminPassword
          )
          .project.deleteProject(
            {
              projectIdOrKey: projectKey                  
            },
            function(error, result) {
              console.log("2");
              done();
            }
          );
      })
      .perform(function(done) {
        restClientConnector
          .jiraConnector(
            environmentVariables.jiraHostUrl,
            environmentVariables.jiraAdminUsername,
            environmentVariables.jiraAdminPassword
          )
          .project.getProject(
            {
              projectIdOrKey: projectKey
            },
            function(error, result) {
              console.log("3");
              done();
            }
          );
      });
  }

If you run into issues with the done callback timing out you should increase the duration of asyncHookTimeout in your external globals file to something appropriate.

Upvotes: 3

Related Questions