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.79k stars 1.31k forks source link

How to suppress stale element reference error? #2584

Closed kretschmannj closed 3 years ago

kretschmannj commented 3 years ago

Under the covers, many Nightwatch commands first run an 'elements' command to get the element ID and then they run the actual command (click, visible, etc). If the DOM is refreshed between the time that the 'elements' command is run and the time the actual command is run then a stale element error is thrown. I see this all the time, especially when dealing with dynamic elements like page spinners. Is there a way to suppress this error?

Nightwatch v 1.5.0

kretschmannj commented 3 years ago

Unfortunately, I never found a way to "suppress" these errors in Nightwatch. However, I did find a way to execute Javascript directly which allows you to use try/catch to suppress the errors. Here's an example ...

// Executing javascript directly allows us to use try/catch to suppress 'stale element reference' errors
browser.execute(function (className) { // capture the class attribute
    try {
        var x = document.getElementsByClassName(className)[0].getAttribute('class')
    }
    catch { }
    return x
}, [spinner], result => {
 console.log(result)
})
Dharin-shah commented 3 years ago

https://github.com/nightwatchjs/nightwatch/pull/2632 This should help, suppressNotFoundErrors option eg usage - https://nightwatchjs.org/api/clearValue.html#apimethod-page

It will be fixed in the next patch version

Dharin-shah commented 3 years ago

Duplicate https://github.com/nightwatchjs/nightwatch/issues/2527

Closing this one

Dharin-shah commented 3 years ago

Reopening, waiting on @kretschmannj to confirm. Please add your specific test case as well according to this format, i can try and run on my local to verify.

kretschmannj commented 3 years ago

I opened this ticket 2 months ago and now, I'm not so sure that suppressing the error is the right thing to do. The 'elements' command, which is run as a precursor to commands like 'click', retrieves an element ID that is then used in the subsequent command. If the DOM is refreshed between the time that the element ID is retrieved and the time that the 'click' command (for example) is executed then I would expect the 'click' command to fail. I have since realized that the correct way to handle this situation is to identify what is causing the DOM to refresh (in my case a background process that is causing a page spinner to display) and then wait for that situation to pass (i.e. wait for the spinner to go away). Therefore, I think this issue could be closed unless someone feels otherwise.

MicahLC commented 2 years ago

I've encountered this same issue and had to work around it multiple times now. In single page applications (like React), it's not unreasonable for an element to be unloaded from the page and then re-enter with a new value, and it would be great if Nightwatch could recognize that the element ID it's holding on to is stale and to fetch a new one.

beatfactor commented 2 years ago

@MicahLC have you tried this in v2-beta? we have improved the behaviour.

MicahLC commented 2 years ago

@beatfactor I have not yet, I'm trying to update to v2 but running into various issues.

beatfactor commented 2 years ago

@MicahLC Ok, let us know in the Discussions if there's something we can do to help.

deepikaG5 commented 2 years ago

This is an issue with V2. Can we reopen this issue

RezhaBlue commented 2 years ago

Come here to echo deepikaG5 We use angular and vuejs front end code. Components are constantly loading elements in and out of the page. But this is also a problem anytime say a button click causes the entire page to refresh. Trying to make sure the page finished loading by waiting or asserting on it is impossible to do in a non-flaky way because if it takes a while to load it will verify before the reload happens, or it will verify after the reload and get a stale element reference.

We are still in need of a way to capture an element after the whole or part of the DOM is reloaded.

RezhaBlue commented 2 years ago

For the record, kretschmannj's suggestion to "identify what is causing the DOM to refresh... and then wait for that situation to pass" is not sufficient, it still poses another race condition. If the spinner comes and goes too fast, this cant be relied on to know when a state change has taken place.

We run into this very example with our app frequently where we wait for the spinner to no longer be visible to know when the state has changed but sometimes it comes and goes so fast Nightwatch/the test thinks there was no state change.

RezhaBlue commented 2 years ago

Please consider looking at the following for inspiration to at least help developers by exposing some tooling to observe DOM mutations, if not providing more readily packaged implementation behind nightwatch API commands. https://stackoverflow.com/questions/3219758/detect-changes-in-the-dom https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver