Hi, I am using java-client 7.6 and JDK 11 with Page Object Model (POM).
The android app that I test refreshes during the test and it causes me some problems.
when I implemented the page object/appium widget classes I used selenium’s FluentWait inside the PO/widget methods to wait for elements to become visible/clickable before performing any action on them (getText/click).
- The problem: if the screen is refreshing while waiting for element to become visible/clickable appium will throw a NoSuchElementException wrapping a StaleElementReferenceException. I expect the FluentWait instance to throw the exception (because it is not ignored) and to catch the exception in the @Test method inside the test class.
but for some reason, the FluentWait instance does not throw the exception so it is never getting to the @Test method and the element’s proxy keeps using stale element for lookup.
added a sample code, let me know if you have any suggestions or ideas for different implementations. or what might cause the Fluent Wait instance to not throwing the unignored exception?
//widget class
public class WidgetExample extends Widget {
protected WidgetExample(WebElement element) {
super(element);
}
@AndroidFindBy(id = "text box locator")
private WebElement textBoxElement;
public WebElement getTextBoxElement() {
return textBoxElement;
}
public String getTextBoxText() {
String result = "";
//option 1
result = textBoxElement.getText();
//option 2
result = getText(textBoxElement);
return result;
}
private String getText(WebElement element) {
return new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(30))
.until(visibilityOf(element))
.getText();
}
//page object class
public class PageObjectExample {
@AndroidFindBy(id = "widget locator")
private WidgetExample widgetExample;
public WidgetExample getWidgetExample() {
return widgetExample;
}
}
//test class
public class TestClassExample {
//wait instance
WebDriverWait webDriverWait = new WebDriverWait(driver, 30);
//page object
PageObjectExample pageObjectExample;
//-------- init page object instance with PageFactory and AppiumFieldDecorator --------
@Test
public void textBoxTest() {
//the screen might get refreshed during the lookup!
//desired behaviour - invoke the condition *again* from the beginning if it (returns false/null) or (throws one of the exceptions: NoSuchElementException/StaleElementReferenceException)
waitFor(refreshed(webDriver -> pageObjectExample.getWidgetExample().getTextBoxText().equals("expected text")));
//keep testing
//.....
}
private <T> T waitFor(ExpectedCondition<T> expectedCondition) {
return webDriverWait.until(expectedCondition);
}
}
- I am currently implementing the getTextBoxText with option 2
maybe it does not have such a difference but if I want to click an element I must wait for it to become clickable first.