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.84k stars 1.33k forks source link

While executing custom command program exits after first assert in Promise. #3286

Open efosoner opened 2 years ago

efosoner commented 2 years ago

Describe the bug

While executing custom command (listed below) program exits after first assert in Promise. When assert.elementPresent() changed to waitForElementPresent() and assert.visible() changed to waitForElementVisible() it executes as expected.

Sample test

customClickTest.ts

```js // Sample test import {NightwatchBrowser} from 'nightwatch'; module.exports = { "Browser Context": async function (browser: NightwatchBrowser) { const selectorObject = { selector: '//*[@data-test-id="search-form-submit"]', locateStrategy: 'xpath' }; const selector = '[data-test-id="search-form-submit"]'; const nonExistingSelector = '.NoneExisting'; const pageObject = browser.page.ecosiaPage(); await browser.url('https://www.ecosia.org/') await browser.waitForElementVisible('body') await browser.verify.titleContains('Ecosia') await browser.assert.elementPresent(selectorObject); await browser.assert.visible(selectorObject); await browser.click(selectorObject); await browser.customClick(selectorObject); await browser.customClick(selector); await browser.customClick(nonExistingSelector); } }; ```

Sample command

customClick.js

```js // Sample test module.exports = class customClick { async command(elementSelector) { return new Promise(async (resolve) => { await this.api.assert.elementPresent(elementSelector); await this.api.assert.visible(elementSelector); await this.api.click(elementSelector); resolve(this.api); }); } }; ```

Run with command

node ./runner.js ./tests/customClickTest.ts

Verbose output

debug.log

```txt [Custom Click Test] Test Suite ──────────────────────────────────────────────────────────── ⠧ Starting ChromeDriver on port 9515... ℹ Connected to ChromeDriver on port 9515 (1586ms). Using: chrome (103.0.5060.114) on WINDOWS. Running Browser Context: ─────────────────────────────────────────────────────────────────────────────────────────────────── ℹ Loaded url https://www.ecosia.org/ in 1429ms √ Element was visible after 60 milliseconds. √ Testing if the page title contains 'Ecosia' (32ms) √ Testing if element is present (36ms) √ Testing if element is visible (65ms) ...[DEBUG]: [2022-07-11T12:30:16.350Z] Classic click √ Testing if element is present (31ms) Waiting for the debugger to disconnect... ```

Configuration

nightwatch.json

```js { Default config with specified custom_commands_path } ```

Your Environment

Executable Version
nightwatch --version 2.2.2
npm --version 6.14.17
node --version 14.19.3
Browser driver Version
NAME VERSION
chromedriver 103
OS Version
NAME VERSION
Windows 10 19044
garg3133 commented 2 years ago

I am able to reproduce this issue. The cause of this issue seems to be something happening in the Nightwatch queue due to the mixing of command and assertions (putting assertions inside a command).

garg3133 commented 2 years ago

@efosoner Can you please confirm that the following is working for you?

module.exports = class customClick {
  async command(elementSelector) {
    return new Promise(async (resolve) => {
      await this.api.waitForElementPresent(elementSelector);
      await this.api.assert.visible(elementSelector);
      await this.api.click(elementSelector);
      resolve(this.api);
    });
  }
};

The above is not working for me but said in the issue description that it is working for you.

When assert.elementPresent() changed to waitForElementPresent() it executes as expected

efosoner commented 2 years ago

I checked it and I’ve made a mistake. assert.visible should also be changed to waitForElementVisible and only then command starts working as expected. Sorry for misleading description

gravityvi commented 2 years ago

Hey @efosoner 👋🏻 , Thanks for raising this issue. We can simplify (omit use of async/await) the test a bit like this:

//test.js

  it('sample custom click',  function(browser) {
    const selectorObject = {
      selector: '//*[@data-test-id="search-form-submit"]',
      locateStrategy: 'xpath'
    };
    const selector = '[data-test-id="search-form-submit"]';
    const nonExistingSelector = '.NoneExisting';

    browser.url('https://www.ecosia.org/');
    browser.waitForElementVisible('body');
    browser.verify.titleContains('Ecosia');
    browser.assert.elementPresent(selectorObject);
    browser.waitForElementVisible(selectorObject);
    browser.click(selectorObject);
    browser.customClick(selectorObject);
    browser.customClick(selector);
    browser.customClick(nonExistingSelector);  
  });
//customClick.js
module.exports = class customClick {
  command(elementSelector) {
    this.api.assert.elementPresent(elementSelector);
    this.api.assert.visible(elementSelector);

    return this.api.click(elementSelector);
  }
};

We use async/await in nightwatch when we want to retrieve values from Nightwatch command for example:

const result = await brower.getCookies()

I've tried this code and it works for me. Hopefully it would work for you as well 🙂

AutomatedTester commented 2 years ago

Possibly fixed by #3266 ? @swrdfish can you check if your PR fixes this?