-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
waitUntil
not working with async/await
#3511
Comments
Another issue I've found with All this is when we do not use Edit: This problem goes away if we set Previous conversation regarding this:
|
I also was running into the same issue as mentioned above. I was seeing another side effect, that I don't know if it is directly related to this issue or not. But when commenting out the waitUntil check the issue resolves itself: waitForServicesToLoad: async function () {
const page = this;
await this.waitForElementVisible(
'xpath',
'@servicesContainer'
);
await this.api.waitUntil(async function () {
const val = await page.getText('xpath', '@servicesContainer');
console.log('Test 1 ' + val);
return val !== 'Loading...';
});
console.log('Test 2 ' + await this.getText('xpath', '@servicesContainer'));
}, getServiceTypePhase: async function (serviceTypeId) {
await this.toggleServiceTypeRow(serviceTypeId, false);
await this.api.waitForElementVisible(
'xpath',
this._getServiceTypePhase(serviceTypeId)
);
let phase = await this.api.getText('xpath', this._getServiceTypePhase(serviceTypeId));
phase = await this.api.getText('xpath', this._getServiceTypePhase(serviceTypeId));
return phase;
}, toggleServiceTypeRow: async function (serviceTypeId, toggleOpen = true) {
await this.waitForServicesToLoad();
await this.api.waitForElementPresent('xpath', this._getServiceTypeRowCollapsed(serviceTypeId));
const collapsed = await this.api.isVisible('xpath', this._getServiceTypeRowCollapsed(serviceTypeId));
if (toggleOpen && collapsed) {
await this.api.click('xpath', this._getServiceTypeRowCollapsed(serviceTypeId));
await this.api.waitForElementVisible(
'xpath',
this._getServiceTypeRowExpandedBanner(serviceTypeId)
);
} else if (!toggleOpen && !collapsed) {
await this.api.waitForElementVisible(
'xpath',
this._getServiceTypeRowExpandedBanner(serviceTypeId)
);
await this.api.click('xpath', this._getServiceTypeRowExpandedBanner(serviceTypeId));
await this.api.waitForElementVisible(
'xpath',
this._getServiceTypeRowCollapsed(serviceTypeId)
);
}
}, In the first function we wait for the container to finish loading the ajax request for services. The second function first has to ensure that the service in question is in a collapsed state before retrieving the status. The third function toggles the service in question to be in an expanded or collapsed state. |
I was able to reproduce this with a simpler example without requiring mobile config.
|
@pujagani has done a quick test and it looks like the issue is with how we wrap the The test that works at the moment is it('doubleClick(element)', async function () {
await driver.get(fileServer.whereIs('/data/actions/click.html'))
let box = await driver.findElement(By.id('box'))
assert.strictEqual(await box.getAttribute('class'), '')
await driver.actions().doubleClick(box).perform()
await driver.wait(async function() {
return await box.getAttribute('class') === 'blue'
}, 10000)
assert.strictEqual(await box.getAttribute('class'), 'blue')
}) |
We need to compare other commands with where |
As far as I remember, the issue here is with how Nightwatch creates and handles the queue. When Nightwatch sees Now the problem here is that, if the But if The issue with the |
Here is something i noticed, this bug happens only when any command inside the So this test waits all the way till the
and this test has the above mentioned behaviour of not waiting for the callback and continue execution of test
|
@dikwickley It's not about having a failing command inside |
As far as my understanding goes with this, @garg3133 is right. The way queuing works in nightwatch is that if all the child nodes of a parent node are resolved, it calls the method to resolve the parent node too. In this case also, whenever child nodes (the commands inside conditional function) of waitUntil command node are resolved the method is called for resolution of waitUntil command thus prematurely resolving even though the condition might not have been true as of now. For reference see : |
On further inspection about why when waitUntil throws an error, the execution stops in case we are chaining commands but it move forwards in case of individual commands, we can refer to runChildNode snippet where errors are handled : nightwatch/lib/core/asynctree.js Lines 137 to 163 in b4e273a
Error is thrown in case of both chained and non-chained test cases and thus waitUntil is resolved and queue clears in both cases. The difference lies henceforth, i.e. in case of chained commands, the other commands beside waitUntil wait to get resolved but since the queue is empty now, they don't get resolved and execution waits there and eventually throws error. On the other hand in case of individual commands, waitUntil when resolved it simply moves to next command, add them in queue and continue execution. One possible fix for this can be to reject waitUntil's promise in case it throws an error, that can be done by altering the condition inside shouldNodeRejectPromise : nightwatch/lib/core/asynctree.js Line 95 in b4e273a
|
@stimothy Just to make sure that your issue is also solved with this issue, does your test work fine if you chain the waitForServicesToLoad: async function () {
const page = this;
await this.waitForElementVisible(
'xpath',
'@servicesContainer'
);
await this.api.waitUntil(async function () {
const val = await page.getText('xpath', '@servicesContainer');
console.log('Test 1 ' + val);
return val !== 'Loading...';
}).getTitle(); // <-- change here (chained a getTitle() command which shouldn't have any effect on the test)
console.log('Test 2 ' + await this.getText('xpath', '@servicesContainer'));
}, If not, would you mind sharing the verbose logs for the test run (after chaining the |
Description of the bug/issue
When using
waitUntil
command with async/await, Nightwatch does not wait for the callback passed towaitUntil
to returntrue
. The callback is executed only once (no matter what is the return value of callback) and then the commands following thewaitUntil
command start to execute, while the callback towaitUntil
keeps on running in the background untiltrue
is returned.The command works fine when used without async/await.
Additional discussion: https://browserstack.slack.com/archives/C027A82KQC9/p1669788479985619
Steps to reproduce
Write any test using
waitUntil
command with async/await (the callback passed towaitUntil
should returnfalse
) and add a few other commands afterwaitUntil
and then run it. The callback will run over the other commands.Sample test:
Sample test
The following code fails:
But the following code works:
Command to run
No response
Verbose Output
No response
Nightwatch Configuration
Nightwatch.js Version
2.4.1
Node Version
No response
Browser
No response
Operating System
No response
Additional Information
No response
The text was updated successfully, but these errors were encountered: