Search code examples
javaseleniumwebdriverwebdriverwaitimplicitwait

Does Selenium findElements() have to implicitly wait to return 0 elements?


I come here with a question about Selenium. In my test, I need to delete some item in web app and then I want to verify if items list is empty. I know that it looks trivial but I have some small problem. This is how I want to check if my items list is empty:

Assert.assertEquals(page.getSearchResultList().size(), 0);

Simply and works but... slow because of implicitlyWait.

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Due to fact when I delete item, then getSearchResultList().size() is 0 and Selenium always waits 10 seconds before findElements() returns 0 size.

To avoid this 10 seconds waiting I have a workaround to modify implicitlyWait just before my Assertion but I think it's not a good idea.

page.getDriver().manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
Assert.assertEquals(page.getSearchResultList().size(), 0);

Is there any another, better solution?

Update for request @KunduK

Assert without WebDriverWait:

    Instant start = Instant.now();
    List<WebElement> resultSearchList = page.getDriver().findElements(By.cssSelector("[ng-repeat='searchResult in $ctrl.searchResults']"));
    Assert.assertEquals(resultSearchList.size(), 0);
    Instant stop = Instant.now();
    log.debug("Assert Took: " + Duration.between(start, stop).getSeconds() + " sec");

Output:

10:49:59.081 [main] DEBUG impl.AssertNewEntityPage - Assert Took: 10 sec

Assert with WebDriverWait

    Instant start = Instant.now();
    new WebDriverWait(page.getDriver(), 10).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("[ng-repeat='searchResult in $ctrl.searchResults']")));
    List<WebElement> resultSearchList = page.getDriver().findElements(By.cssSelector("[ng-repeat='searchResult in $ctrl.searchResults']"));
    Assert.assertEquals(resultSearchList.size(), 0);
    Instant stop = Instant.now();
    log.debug("Assert Took: " + Duration.between(start, stop).getSeconds() + " sec");

Output:

10:57:08.215 [main] DEBUG impl.AssertNewEntityPage - Assert Took: 20 sec

Solution

  • stalenessOf()

    stalenessOf() is the expectation to wait until an element is no longer attached to the DOM.


    This usecase

    This usecase of ...deleting an item in web app... maps to the ExpectedConditions of stalenessOf(WebElement element). So effectively your code block will be:

    new WebDriverWait(driver, 10).until(ExpectedConditions.stalenessOf(By.cssSelector("cssSelector_of_element_to_be_stale")));
    Assert.assertEquals(page.getSearchResultList().size(), 0);
    

    Note: As your usecase already involves implicitlyWait and this answer suggests to induce WebDriverWait i.e. ExplicitWait, as per the documentation, ...Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds...

    You can find a relevant discussion in How to combine implicit and explicit timeouts in Selenium?