google / pageloader

A framework for creating page objects for in-browser or WebDriver tests.
https://pub.dartlang.org/packages/pageloader
Apache License 2.0
40 stars 46 forks source link

PageLoaderElement.exists throws on removed element when using with WebDriver #208

Closed szepeshazi closed 3 years ago

szepeshazi commented 4 years ago

Using PageLoader with WebDriver on Windows x64, dart 2.7.2, pageloader 3.3.0, chromedriver 80.0.3987.106

Having the following PO snippet:

@ByCss("button.i-am-here-when-the-page-loads")
PageLoaderElement get initiallyPresentButton;

Future<void> trigger() async {
  if (initiallyPresentButton.exists) {
    await initiallyPresentButton.click();
  }
}

and

  1. calling trigger() in the above block,
  2. removing the button from DOM
  3. and calling trigger() again will throw
Unhandled exception:
StaleElementReferenceException (404): stale element reference: element is not attached to the page document
  (Session info: chrome=80.0.3987.149)
#0      parseW3cResponse (package:webdriver/src/handler/w3c/utils.dart:82:9)
#1      W3cElementFinder.parseFindElementsResponse (package:webdriver/src/handler/w3c/element_finder.dart:45:13) #2      SyncRequestClient.send (package:webdriver/src/common/request_client.dart:46:25)
#3      WebElement.findElements (package:webdriver/src/sync/web_element.dart:135:25)
#4      WebDriverPageLoaderElement.elements (package:pageloader/src/webdriver/webdriver_page_loader_element.dart:179:12)
#5      WebDriverPageLoaderElement.exists (package:pageloader/src/webdriver/webdriver_page_loader_element.dart:270:19)

Seems like the exists getter is not wrapped in retryWhenStale(), causing exception on removed elements.

mk13 commented 3 years ago

Calling exists will implicitly try to grab the most recent "version" of that element, as a result retryWhenStale is not necessary since it actively refreshes it.

If exists is failing, consider two things:

  1. Add some delay before calling trigger() or implicitly add a delay before the if-conditional check. If some action occurred and your page hasn't fully loaded, the exists check may return false since it hasn't been fully rendered yet.

  2. Your element isn't loaded for some reason OR you're looking it from the wrong parent element.