Repository navigation
feat: allow @WithTimeout annotation on page object and widget classes #2481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,8 +17,10 @@ | |
| package io.appium.java_client.pagefactory_tests; | ||
|
|
||
| import io.appium.java_client.pagefactory.AppiumFieldDecorator; | ||
| import io.appium.java_client.pagefactory.Widget; | ||
| import io.appium.java_client.pagefactory.WithTimeout; | ||
| import io.appium.java_client.pagefactory_tests.widget.tests.AbstractStubWebDriver; | ||
| import io.appium.java_client.pagefactory_tests.widget.tests.StubWebElement; | ||
| import io.appium.java_client.support.FindAll; | ||
| import io.appium.java_client.support.FindBy; | ||
| import org.junit.jupiter.api.BeforeEach; | ||
|
|
@@ -41,7 +43,7 @@ public class TimeoutTest { | |
|
|
||
| private static final Duration DEFAULT_TIMEOUT = ofMillis(300); | ||
| private static final long CLOCK_SLACK_MS = 50; | ||
| private static final long ACCEPTABLE_OVERRUN_MS = 1500; | ||
| private static final long ACCEPTABLE_OVERRUN_MS = 3000; | ||
|
|
||
| @FindAll({ | ||
| @FindBy(className = "ClassWhichDoesNotExist"), | ||
|
|
@@ -63,12 +65,24 @@ private static void assertWaitsFor(Duration expected, Runnable runnable) { | |
| lessThanOrEqualTo(expected.toMillis() + ACCEPTABLE_OVERRUN_MS)); | ||
| } | ||
|
|
||
| private WebDriver driver; | ||
|
|
||
| @BeforeEach public void setUp() { | ||
| WebDriver driver = new AbstractStubWebDriver() { | ||
| driver = new AbstractStubWebDriver() { | ||
| @Override | ||
| public List<WebElement> findElements(By by) { | ||
| return List.of(); | ||
| } | ||
|
|
||
| @Override | ||
| public StubWebElement findElement(By by) { | ||
| return new StubWebElement(this, by) { | ||
| @Override | ||
| public List<WebElement> findElements(By childBy) { | ||
| return List.of(); | ||
| } | ||
| }; | ||
| } | ||
| }; | ||
| initElements(new AppiumFieldDecorator(driver, DEFAULT_TIMEOUT), this); | ||
| } | ||
|
|
@@ -77,4 +91,89 @@ public List<WebElement> findElements(By by) { | |
| assertWaitsFor(DEFAULT_TIMEOUT, () -> stubElements.size()); | ||
| assertWaitsFor(ofMillis(800), () -> stubElements2.size()); | ||
| } | ||
|
|
||
| @Test public void withClassLevelTimeOutTest() { | ||
| ClassWithTimeoutPage page = new ClassWithTimeoutPage(); | ||
| initElements(new AppiumFieldDecorator(driver, DEFAULT_TIMEOUT), page); | ||
|
|
||
| assertWaitsFor(ofMillis(600), () -> page.classTimeoutElements.size()); | ||
| assertWaitsFor(ofMillis(1100), () -> page.fieldOverrideElements.size()); | ||
| } | ||
|
|
||
| @Test public void withInheritedClassLevelTimeOutTest() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These tests assert on wall-clock time with a tight overrun bound ( |
||
| InheritedClassTimeoutPage page = new InheritedClassTimeoutPage(); | ||
| initElements(new AppiumFieldDecorator(driver, DEFAULT_TIMEOUT), page); | ||
|
|
||
| assertWaitsFor(ofMillis(600), () -> page.subclassElements.size()); | ||
| } | ||
|
|
||
| @Test public void withAnnotatedSubclassSuperclassFieldTimeOutTest() { | ||
| AnnotatedSubclassPage page = new AnnotatedSubclassPage(); | ||
| initElements(new AppiumFieldDecorator(driver, DEFAULT_TIMEOUT), page); | ||
|
|
||
| assertWaitsFor(ofMillis(600), () -> page.baseElements.size()); | ||
| } | ||
|
|
||
| @Test public void withWidgetClassLevelTimeOutTest() { | ||
| PageWithTimeoutWidget page = new PageWithTimeoutWidget(); | ||
| initElements(new AppiumFieldDecorator(driver, DEFAULT_TIMEOUT), page); | ||
|
|
||
| assertWaitsFor(ofMillis(600), () -> page.widgetList.size()); | ||
| assertWaitsFor(ofMillis(600), () -> page.widget.innerElementsCount()); | ||
| assertWaitsFor(ofMillis(1100), () -> page.widget.fieldOverrideInnerElementsCount()); | ||
| } | ||
|
|
||
| @WithTimeout(time = 600, chronoUnit = MILLIS) | ||
| private static class ClassWithTimeoutPage { | ||
| @FindBy(className = "ClassWhichDoesNotExist") | ||
| private List<WebElement> classTimeoutElements; | ||
|
|
||
| @WithTimeout(time = 1100, chronoUnit = MILLIS) | ||
| @FindBy(className = "ClassWhichDoesNotExist") | ||
| private List<WebElement> fieldOverrideElements; | ||
| } | ||
|
|
||
| private static class InheritedClassTimeoutPage extends ClassWithTimeoutPage { | ||
| @FindBy(className = "ClassWhichDoesNotExist") | ||
| private List<WebElement> subclassElements; | ||
| } | ||
|
|
||
| private static class UnannotatedBasePage { | ||
| @FindBy(className = "ClassWhichDoesNotExist") | ||
| protected List<WebElement> baseElements; | ||
| } | ||
|
|
||
| @WithTimeout(time = 600, chronoUnit = MILLIS) | ||
| private static class AnnotatedSubclassPage extends UnannotatedBasePage { | ||
| } | ||
|
|
||
| @WithTimeout(time = 600, chronoUnit = MILLIS) | ||
| public static class CustomTimeoutWidget extends Widget { | ||
| @FindBy(className = "ClassWhichDoesNotExist") | ||
| private List<WebElement> innerElements; | ||
|
|
||
| @WithTimeout(time = 1100, chronoUnit = MILLIS) | ||
| @FindBy(className = "ClassWhichDoesNotExist") | ||
| private List<WebElement> fieldOverrideInnerElements; | ||
|
|
||
| protected CustomTimeoutWidget(WebElement element) { | ||
| super(element); | ||
| } | ||
|
|
||
| public int innerElementsCount() { | ||
| return innerElements.size(); | ||
| } | ||
|
|
||
| public int fieldOverrideInnerElementsCount() { | ||
| return fieldOverrideInnerElements.size(); | ||
| } | ||
| } | ||
|
|
||
| private static class PageWithTimeoutWidget { | ||
| @FindBy(className = "WidgetRoot") | ||
| private CustomTimeoutWidget widget; | ||
|
|
||
| @FindBy(className = "MissingWidgetList") | ||
| private List<CustomTimeoutWidget> widgetList; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new Javadoc says the annotation applies to a "page object/widget class", but a
@WithTimeouton aWidgetsubclass has no effect on locating the widget field itself:createLocator(field)resolves against the page class. Only the widget's own inner fields honor it. Worth either handling the field type here or narrowing the Javadoc.