Skip to content

fix: support Selenium WebDriverDecorator across AppiumFieldDecorator elements and widgets - #2498

Open
hoanle0126 wants to merge 3 commits into
appium:masterfrom
hoanle0126:fix/pagefactory-decorator-interoperability
Open

hoanle0126 wants to merge 3 commits into
appium:masterfrom
hoanle0126:fix/pagefactory-decorator-interoperability

Conversation

@hoanle0126

@hoanle0126 hoanle0126 commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Proposed Changes

Fixes #2368
Fixes #2051

This PR completes interoperability between AppiumFieldDecorator and Selenium's WebDriverDecorator (such as EventFiringDecorator) as well as nested driver and element wrappers:

  • Adds ElementHelpers for cached Decorated and WrapsElement unwrapping with cycle protection, and updates WebDriverUnpackUtility to unwrap nested driver and decorator wrappers without package cycles.
  • Updates capability lookup in AppiumFieldDecorator with single-pass wrapper stepping so an outer wrapper with empty or partial capabilities does not shadow platform and automation capabilities on the inner driver when building mobile locators.
  • Updates ElementInterceptor and ElementListInterceptor to resolve methods across public interfaces implemented by decorated elements, unwrap for AppiumWebElement methods, and adapt decorated items in place only for AppiumWebElement lists.
  • Centralizes element equality and hash code handling across AppiumWebElement and page factory interceptors/locators so unwrapped element IDs stay consistent in hash collections.

Testing

  • Added unit tests in SeleniumDecoratorCompatibilityTest covering mobile locator translation through decorated and wrapped drivers, non-WebElement interface calls, AppiumWebElement methods, symmetric equality and hash codes, element lists, widgets and widget lists, and dual-wrapper / cycle unpacking.

@mykola-mokhnach mykola-mokhnach left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • src/main/java/io/appium/java_client/remote/AppiumWebElement.java:266: equals now treats a Selenium-decorated element as equal to an AppiumWebElement. It unwraps via Decorated.getOriginal and compares getId(), but hashCode still uses the id field. The decorated proxy keeps its own identity hash. So appiumElement.equals(decoratedFound) is true (the new test asserts it), yet the two have different hash codes. Putting both in a HashSet or HashMap gives duplicates or failed lookups. SearchingWidgetRootHandler.hashCode returns resolved.hashCode() while its equals unwraps decorators, so it has the same contract violation. Should hashCode hash the unwrapped element's id?

@hoanle0126

Copy link
Copy Markdown
Contributor Author

Addressed in 8df1f09. InterceptorOfASingleElement and SearchingWidgetRootHandler now hash the unwrapped element via Objects.hashCode(unwrapElement(...)) so page factory proxies, SearchingWidgetRoot, Decorated proxies, and AppiumWebElement produce matching hash codes in HashSet and HashMap.

@mykola-mokhnach mykola-mokhnach left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Earlier threads are addressed; remaining notes are inline.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants