Reputation: 2757
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
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