Skip to content
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

The chained commands in new element api continue executing even when previous command has failed. #3991

Open
garg3133 opened this issue Jan 12, 2024 · 8 comments

Comments

@garg3133
Copy link
Member

garg3133 commented Jan 12, 2024

Description of the bug/issue

Nightwatch continues to execute further commands even when the previous .find() command fails and returns an error response.

image

Steps to reproduce

Just run browser.element.find('.invalid_selector').getProperty('innerHTML');.

Even after getting no elements from the .find() command, it will still try to run the .getProperty() command.

Sample test

No response

Command to run

No response

Verbose Output

No response

Nightwatch Configuration

No response

Nightwatch.js Version

3.3.7

Node Version

No response

Browser

No response

Operating System

No response

Additional Information

No response

@reallymello
Copy link
Contributor

I think I am encountering something similar, but not necessarily with find, at least not directly. In my case I believe the tests seem to continue when it can't locate an element on the page, but I'm using browser.expect.element('something it cannot find').is.present as an example

@dikwickley
Copy link
Contributor

dikwickley commented Feb 26, 2024

After hours of debugging, I did manage to find a solution.
So this is where the exception of not finding an element by selector is caught.

if (suppressNotFoundErrors) {
return null;
}
const narrowedError = createNarrowedError({error, condition, timeout});
Logger.error(narrowedError);
if (abortOnFailure) {
this.reporter.registerTestError(narrowedError);
// TODO: find a way to reject here without unhandled promise rejection
// reject(narrowedError);
}
return null;

If we just add this.queue.empty() at Line 178.
This will essentially empty the queue when such an exception is encountered, in turn stopping execution of further chained methods.

What do you think @garg3133 will this work?

here it is action:

test:

describe('Demo', function () {
  before((browser) => {
    browser.navigateTo('https://github.com/login');
  });

  it('Demo github login', function (browser) {
    const result = browser
      .waitForElementVisible('body')
      .element.find('.auth-form-header2') //wrong selector name
      .getProperty('innerHTML');
  });

  after((browser) => browser.end());
});

without this.queue.empty() (there is getElementProperty error as well)

aniket@air nightwatch % node ./bin/nightwatch ./examples/aniket/test.js


[Demo] Test Suite
──────────────────────────────────
ℹ Connected to GeckoDriver on port 4444 (1410ms).
  Using: firefox (119.0.1) on MAC.


  Running Demo github login:
───────────────────────────────────────────────────────────────────────────────────────────────────
  ✔ Element <body> was visible after 14 milliseconds.
  Error
   Timed out while waiting for element "By(css selector, .auth-form-header2)" to be present for 5000 milliseconds.

    Error location:
    /Users/aniket/Projects/gsoc/nightwatch/lib/api/web-element/scoped-element.js:328
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
     326 | function createNarrowedError({error, condition, timeout}) {
     327 |   return error.name === 'TimeoutError'
     328 |     ? new Error(`Timed out while waiting for element "${condition}" to be present for ${timeout} milliseconds.`) 
     329 |     : error;
     330 | }
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

    Error   Error while running .getElementProperty() protocol action: The element with the reference null is not known in the current browsing context


  FAILED: 1 errors and  1 passed (5.113s)

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  ️TEST FAILURE (8.87s): 
   - 1 error during execution; 
   - 0 assertions failed; 1 passed

   ✖ 1) test

   – Demo github login (5.113s)


  - OTHER ERRORS:
  Error
    Error
   Timed out while waiting for element "By(css selector, .auth-form-header2)" to be present for 5000 milliseconds.

    Error location:
    /Users/aniket/Projects/gsoc/nightwatch/lib/api/web-element/scoped-element.js:328
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
     326 | function createNarrowedError({error, condition, timeout}) {
     327 |   return error.name === 'TimeoutError'
     328 |     ? new Error(`Timed out while waiting for element "${condition}" to be present for ${timeout} milliseconds.`) 
     329 |     : error;
     330 | }
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––


 Wrote HTML report file to: /Users/aniket/Projects/gsoc/nightwatch/tests_output/nightwatch-html-report/index.html

after adding this.queue.empty()

aniket@air nightwatch % node ./bin/nightwatch ./examples/aniket/test.js


[Demo] Test Suite
──────────────────────────────────
ℹ Connected to GeckoDriver on port 4444 (1374ms).
  Using: firefox (119.0.1) on MAC.


  Running Demo github login:
───────────────────────────────────────────────────────────────────────────────────────────────────
  ✔ Element <body> was visible after 22 milliseconds.
  Error
   Timed out while waiting for element "By(css selector, .auth-form-header2)" to be present for 5000 milliseconds.

    Error location:
    /Users/aniket/Projects/gsoc/nightwatch/lib/api/web-element/scoped-element.js:328
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
     326 | function createNarrowedError({error, condition, timeout}) {
     327 |   return error.name === 'TimeoutError'
     328 |     ? new Error(`Timed out while waiting for element "${condition}" to be present for ${timeout} milliseconds.`) 
     329 |     : error;
     330 | }
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––


  FAILED: 1 errors and  1 passed (5.117s)

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  ️TEST FAILURE (8.024s): 
   - 1 error during execution; 
   - 0 assertions failed; 1 passed

   ✖ 1) test

   – Demo github login (5.117s)


  - OTHER ERRORS:
  Error
    Error
   Timed out while waiting for element "By(css selector, .auth-form-header2)" to be present for 5000 milliseconds.

    Error location:
    /Users/aniket/Projects/gsoc/nightwatch/lib/api/web-element/scoped-element.js:328
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
     326 | function createNarrowedError({error, condition, timeout}) {
     327 |   return error.name === 'TimeoutError'
     328 |     ? new Error(`Timed out while waiting for element "${condition}" to be present for ${timeout} milliseconds.`) 
     329 |     : error;
     330 | }
    ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––


 Wrote HTML report file to: /Users/aniket/Projects/gsoc/nightwatch/tests_output/nightwatch-html-report/index.html

@garg3133
Copy link
Member Author

garg3133 commented Feb 28, 2024

Listing the current issues I can see here if the element is not found:

  • Further commands send HTTP request with element id as null. (relatively easy fix)
  • Throws TimeoutError instead of NotSuchElementError. (should be easy)
  • Further chained .find() commands should not throw the Timeout or any other error again. Ex. in browser.element('.invalid-selector').find('selector').getText();, there should only be one error due to browser.element() and .find() should not throw an error again (suppress the error for it).
  • Test continues with execution even when abortOnFailure is set to true. (not a priority for now)
  • Test continues while using this command: browser.expect.element('something it cannot find').is.present

The above issues can be taken up separately.

@garg3133
Copy link
Member Author

@dikwickley Doing this.queue.empty() is not an ideal solution for this. This is because, at any given point, it is not necessary that the queue only contains the commands related to the current browser.element(), it might contain other subsequent commands as well if browser.element() is not used with await, which we might not wish to remove.

Also, if we want to abort the test case completely, then also doing this.queue.empty() wouldn't help because it is not necessary at all the commands in a test case will be present in the queue at any given time and while it will remove some commands, the further encountered commands will keep on adding to the queue and run from there.

For now, let's forget about the abortOnFailure and you can take up the 3rd task from the list above.

@Honey2339
Copy link

@garg3133 Cant we just get error.name and then suppress them accordingly?

Something like :

const isTimeoutError = error.name === 'TimeoutError';
const isElementNotFoundError = error.name === 'ElementNotFoundError';

and then later down the line suppress it using

if (!isTimeoutError) {
        return null;
}
// If it's a TimeoutError, rethrow it to propagate it further
throw error;

@garg3133
Copy link
Member Author

garg3133 commented Mar 1, 2024

@Honey2339 We don't want to always suppress the TimeoutError but only in case of chained find() commands if the previous command has already thrown that error. We just don't wish to keep repeating the same error for all the chained commands.

@Honey2339
Copy link

From what i understood, As soon as we encounter an error the code has to throw that error and not the chained commands. Please have a look on the attached video

issuehelperer.mp4

@garg3133
Copy link
Member Author

garg3133 commented Mar 1, 2024

@Honey2339 In your case the code is throwing an unhandledRejection (which is probably due to the change you've made in local) due to which the entire Nightwatch process is exiting, which is not ideal. But if you run the command in a fresh project, you'll see multiple errors in the first situation you showed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants