Home > database >  The wait.until returns stale element, how to wait until DOM is stable
The wait.until returns stale element, how to wait until DOM is stable

Time:09-22

I have a blazor application running fine and want to have some behavior test with selenium. The test does now currently the following:

  • goes to a page (directly using an URL, no page loaded before)
  • tries to click on a button

The first point does work, but the second has an issue. If I use the wait.until the button is available, then I receive back an early version of the button, which then redrawn and updated in the DOM later. This will give me the "stale element reference: element is not attached to the page document" error.

Here is the code:

            var xPath = By.XPath($".//tr//td[normalize-space()=\"{name}\"]/ancestor-or-self::tr//button");
            var button = _wait.Until(ExpectedConditions.ElementToBeClickable(xPath));
            Thread.Sleep(1000);
            button = _chromeDriver.FindElement(xPath);
            button.Click();

the _wait.until will return an item that will be stale, while the next FindElement will return a valid, but only after ~1 sec sleep. If I don't have sleep there, it will return the same as the other line.

The final question: How can I ensure in the _wait.until line, that my returned element is the final one to avoid using Thread.Sleep?

CodePudding user response:

There is no gentle solution for such issues.
The only solution I know for this is to make a loop:
Wait for element clickability and click it.
In case exception is thrown wait for the clickability again.
If click succed - break the loop and continue to outer code / return True.
Something like this:

for(i=0; i<6; i  ){
    try: {
        wait.Until(ExpectedConditions.ElementToBeClickable(xPath)).Click(); 
        break;
    }
    catch(Exception e){
        Thread.Sleep(100);
    }
}

CodePudding user response:

Selenium Wait.Until conditions are not 100% reliable. I was in shocked when I figure this myself, but yes, after the condition has finished you sometimes have to wait or try clicking or hovering in a loop.

I wish to suggest 2 options here:

  1. Wait for the element to be both Clickable and Enabled:

    getWait().until((ExpectedCondition) driver -> element.isEnabled());

  2. Use a much better UI tool for testing like Playwright. It has a much sophisticated waiting system conditions and also faster and very reliable.

CodePudding user response:

@golddragon007, you can wait for the element to become stale.

_wait.Until(ExpectedConditions.StalenessOf(_chromeDriver.FindElement(xPath)))

you can check the following link for more details:

https://www.selenium.dev/selenium/docs/api/dotnet/html/M_OpenQA_Selenium_Support_UI_ExpectedConditions_StalenessOf.htm

  • Related