nightwatchjs / nightwatch

Integrated end-to-end testing framework written in Node.js and using W3C Webdriver API. Developed at @browserstack
https://nightwatchjs.org
MIT License
11.85k stars 1.35k forks source link

Nightwatch commands in `waitUntil` callback return `NightwatchAPI` instead of a `Promise`. #4158

Open garg3133 opened 8 months ago

garg3133 commented 8 months ago

Another issue I've found with waitUntil is that if we pass an async callback to waitUntil command, Nightwatch commands inside the callback still just return NightwatchAPI and no promise which can be awaited to get the result. While in perform command, it works fine and Nightwatch commands return a promise inside async callback passed to perfom command.

All this is when we do not use async in the test case function.

Edit: This problem goes away if we set always_async_commands top-level setting to true in the Nightwatch config file.

To reproduce:

This issue can be reproduced by running the following example test:

describe('ecosia demo', function() {
  before(() => {
    browser
      .navigateTo('https://ecosia.org/');
  });

  it('waitUntil callback demo', function() {
    browser
      .waitUntil(async function() {
        const title = await browser.getTitle();
        console.log(title); // <-- returns NightwatchAPI

        return true;
      })
      .perform(async function() {
        const title = await browser.getTitle();
        console.log(title); // <-- returns correct result (title)
      });
  });
});

Previous conversation regarding this:

Priyansh: I am not able to await Nightwatch commands and get the result inside waitUntil command if the test case is not an async function. If I make the test case async, I get the result value on awaiting the Nightwatch commands inside waitUntil, while on removing async from the test case, I only get the NightwatchAPI instance. This is not the case with perform command, there I always get the result value no matter the test case is an async function of not.

image

Andrei: maybe this will help https://github.com/nightwatchjs/vite-plugin-nightwatch/blob/main/nightwatch/commands/mountReactComponent.js

Priyansh: But here the command function is async, so maybe that's why it works. Can we not make Nightwatch commands inside waitUntil return Promise if an async callback is passed to waitUntil no matter the main test case is async or not? Just like we do with perform command?

Priyansh: Even putting waitUntil inside perform isn't working, idk why (considering Nightwatch commands inside perform returns promises when async callback is passed to perform, the callback passed to waitUntil should also work the same since it's running in same async environment?)

image


Issue created from https://github.com/nightwatchjs/nightwatch/issues/3511#issuecomment-1365243803

Temidayo32 commented 8 months ago

I am looking into this issue

Temidayo32 commented 8 months ago

@garg3133 Can I get the full script so I can test it locally?

garg3133 commented 8 months ago

You can use this example test to reproduce this:

describe('ecosia demo', function() {
  before(() => {
    browser
      .navigateTo('https://ecosia.org/');
  });

  it('waitUntil callback demo', function() {
    browser
      .waitUntil(async function() {
        const title = await browser.getTitle();
        console.log(title); // <-- returns NightwatchAPI

        return true;
      })
      .perform(async function() {
        const title = await browser.getTitle();
        console.log(title); // <-- returns correct result (title)
      });
  });
});
Temidayo32 commented 8 months ago

@garg3133 I was able to reproduce the problem. Thanks.

Temidayo32 commented 8 months ago

Here is an update: I have regressed to previous versions of Nightwatchjs, all the way back to 3.1.0, and I get the same error. It appears waitUntil never really worked as expected 🤔

garg3133 commented 8 months ago

Yeah, it didn't for this particular case. But if you change the line it('waitUntil callback demo', function() { to it('waitUntil callback demo', async function() { in the example test (notice the added async before function definition), it will work correctly.

Temidayo32 commented 8 months ago

Yeah, it didn't for this particular case. But if you change the line it('waitUntil callback demo', function() { to it('waitUntil callback demo', async function() { in the example test (notice the added async before function definition), it will work correctly.

Exactly, I just observed that.

Temidayo32 commented 8 months ago

As a contrast, in the perform function, I removed async/await and made it non-async and I get the same error. That is, the Nightwatch API.

Ayush-Vish commented 8 months ago

I am woking on this issue and was able to reproduce it. Looking forward to solve it .