Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Stale element reference" error behavior undestanding

Code 1:

element(by.id('myButtonId')).click();
return element(by.id('myValidationSummaryId')).getText().then(function (val) {
    return val;
});

Above code worked fine many times and then it started giving below error

"Failed: stale element reference: element is not attached to the page document"

this id 'myValidationSummaryId' is no where used before, clicking button posts form and success/failure message available from service side in 'myValidationSummaryId'.

Code 2:

return element(by.id('myButtonId')).click().then(function () {
    return element(by.id('myValidationSummaryId')).getText().then(function (val) {
      return val;
    });
});

Fixing code as above fixed original issue and it worked consistently fine many times but later it started failing randomly with original stale element reference error.

Code 3:

return element(by.id('myButtonId')).click().then(function () {
    return element(by.id('myValidationSummaryId')).waitReady().then(function (isReady) {
        if (isReady) {
            return element(by.id('myValidationSummaryId')).getText().then(function (val) {
                return val;
            });
        } else {
            return 'Failed to check success/failure message';
        }
    });
});

Then I fixed code as above and now it works fine consistently, waitReady function actively wait for an element present and displayed up to specified time.

Shouldn't protractor/WebdriverJS supposed to handle this issues fine natively.

1> could you please explain why Code 1 and Code 2 sometime worked and sometime failed?

2> do you think Code 3 is now fine and expected to work every time?

Element 'myValidationSummaryId' used only once and after click so if pages is not loaded fully and if element is yet not available it should say No Element Found but why stale element reference? I have used pageLoadTimeout as 5 minutes and page is loaded in few second. This is non AngularJS application and browser.ignoreSynchronization = true.

everywhere it talked about what code can fix it but not found much on why this behavior and why WebdriverJS itself not able to handle it.

like image 684
Morbia Avatar asked Aug 03 '15 16:08

Morbia


1 Answers

I don't think we can be certainly sure why that happens, but you're definitely not alone (1) (2). This may be due to the way your page is rendered specifically (e.g. how your app/framework is handling rendering DOM elements), or just a Selenium/driver thing. If you're interested into an exact explanation, you might have better luck if using Protractor bug report system.

A good guess, however, may be that it is related to the way Selenium defines stale element:

A less common, but still common cause is where a JS library has deleted an element and replaced it with one with the same ID or attributes

Some libraries can fool Selenium into believing an element is gone from the DOM, but it has been really just replaced in an instant. Adding there a tight, frail timing between clicking and element being placed in the DOM (race condition basically) - that might be the cause. You might be interested in reading a little more about it here.

Anyway, if you're having such issues, I'd recommend you using browser.wait and Expected Conditions.

Expected conditions are basically functions that return true or false, and you can specify a timeout that will cause test to fail if true is not returned in that time - you can see how it's used in a similar question.

Basically, you might want to do it like this:

var EC = protractor.ExpectedConditions;
var summaryId = element(by.id('myValidationSummaryId'));

browser.wait(EC.presenceOf(summaryId), 5000);
//rest of your code
like image 110
wap300 Avatar answered Sep 23 '22 08:09

wap300