Repository navigation
feat: allow @OverrideWidget fields declared as interfaces - #2486
Conversation
|
@Ganesh2325 please resolve conflicts in the PR |
An @OverrideWidget field may be an interface implemented by the platform widget classes. Calls are proxied to the concrete widget for the current content type.
30688b0 to
336d165
Compare
|
@mykola-mokhnach Thanks, conflicts are resolved. I rebased onto the latest master. The conflicts were with #2480 (default LocatorGroupStrategy), and both changes are kept: interface-typed @OverrideWidget fields and list items now also receive the decorator's defaultLocatorGroupStrategy. |
mykola-mokhnach
left a comment
There was a problem hiding this comment.
- Test coverage:
OverriddenWidgetInterfaceTestdoesn't exercise the paths where interface proxies differ from class proxies. These are list items after the element reference is cleared (see the inline comment onWidgetListInterceptor),toString/equals/hashCodeon an interface proxy, a widget with nested@FindByfields, a non-public interface, and an interface with default methods. Please add tests for the ones you intend to support.
Hold a list item's element until its widget exists, generate interface proxies in Helpers, and reject non-public interfaces or disconnected class loaders with IllegalArgumentException.
Document that a public interface is accepted when either class loader can see the other side, and that other cases throw IllegalArgumentException.
|
Thanks! Added tests for cleared weak references, |
|
@Ganesh2325 could you please resolve the conflicts? |
|
Thanks! I merged the latest master and resolved the conflicts in 8a414c5. All tests pass locally. |
Change list
Fixes #1926. An @OverrideWidget field, or a List of that field, may be declared as an interface implemented by the platform widget classes. Calls are proxied to the concrete Widget for the current content type. Fields declared as Widget classes, including abstract classes, behave as they do today.
The override class must implement the interface and extend Widget.
A content type with no override stays unresolved until that content is used, then throws InstantiationException.
Locators are still taken from the selected widget class, including class-level @AndroidFindBy and @iOSXCUITFindBy.
An interface that extends WebElement is left to the normal element decorator.
Types of changes
New feature (non-breaking change which adds functionality)
Details
public interface UsersWidget {
void doWork();
}
public class IosUsersWidget extends Widget implements UsersWidget {
protected IosUsersWidget(WebElement element) {
super(element);
}
@OverRide
public void doWork() {
// iOS behavior
}
}
@findby(id = "users")
@OverrideWidget(iOSXCUITAutomation = IosUsersWidget.class,
androidUIAutomator = AndroidUsersWidget.class,
html = HtmlUsersWidget.class)
UsersWidget widget;
Name a concrete class for every content type the field is used with. A partial override, such as only iOSXCUITAutomation, works on that content and throws InstantiationException on another.
./gradlew test checkstyleMain checkstyleTest javadoc
Local validation on
a732abba:./gradlew test checkstyleMain checkstyleTest javadocpassed. All 240 java-client tests and 12 selenium-bridge tests passed with no failures. Checkstyle and Javadoc also passed. These are local results, not upstream CI results.The interface must be public. The library’s class loader must be able to load the interface, or the interface’s loader must be able to load the library. Unsupported loader setups and non-public interfaces throw
IllegalArgumentException.Rebased on #2480; widget interceptors created for interface fields use the configured default LocatorGroupStrategy.