-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
[java] Extendable and Containerized Element Support #15600
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
Conversation
…e, backwards compatible
This change adds an abstract extensible element which provide an 'out-of-the-box' way for users to define custom containerized element groupings, or singular elements with specific behaviors. The design uses only classes instead of interfaces with implementing classes to keep usage simplistic and allows for future annotations to enable context specific overriding. The change should be backwards compatible. Potentially addresses comment in SeleniumHQ#3680 SeleniumHQ#3680 (comment)
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
|
Thank you, @iFatRain for this code suggestion. The support packages contain example code that many users find helpful, but they do not necessarily represent We actively encourage people to add the wrapper and helper code that makes sense for them to their own frameworks. |
PR Code Suggestions ✨Explore these optional code suggestions:
|
|||||||||||||||||
User description
🔗 Related Issues
Potentially addresses comment in #3680 -> #3680 (comment)
💥 What does this PR do?
This PR adds functionality and mechanisms to support out-of-the-box element extensibility and containerization of groupings for easy reuse. The intent is to provide a simple and backwards compatible way for a user to define their own types of elements and groupings, leveraging the default PageFactory annotations and its mechanisms, with the newly added AbstractExtendedElement. Previously if a user wanted this type of functionality, you typically had to create your own solution using custom page factories, decorators, handlers ect. This is still possible of course, but this PR provides a simpler out of the box solution. This implementation uses just simple classes that would extend the AbstractExtendedElement, as opposed to a solution involving Interfaces and Implementing classes. This keeps the usage simple and new classes smaller.
🔧 Implementation Notes
The base philosophy has been around for many years. Developers create reusable pieces that get populated with differing sets of data from API calls; Why don't we enable a framework design pattern which mimics that behavior? This PR aims to do just that. It seeks to maintain a PageObject as a high level abstraction, and EVERYTHING contained within to be elements (As opposed to Pages of Pages) and can be seen somewhat analogous to "Page Fragments" mentioned in some early literature, but maintains the WebElement as the main point of reference (anything with a tag can be an element after all 👍). Because we treat even the container as an element itself, we can also pass the container element into relevant functions ( like waits/checks for presence and interactibility ect.) which can be very useful.
💡 Additional Considerations
The changes are meant to be backwards compatible, as well as provide a potentially desired new way of doing Selects out of the box. Of course because of this implementation, the old way of doing things is still valid; ElementType element = new ElementType(baseElement); There is also the idea in the future to extend on top of the .findElement and .findElements to return beyond just a WebElement with something such as a .findElementAs(By by, Class typeToResolveAs) and .findElementsAs(By by, Class typeForListToContain) to allow for similar non-page factory usages and directly resolve to the custom elements a user can define.
By implementing as a class instead of interfaces and implementing classes it also opens the door to a future change I have been experimenting with; Annotations which function similar to some seen in Appium for context specific overrides over the class to resolve to. The base theory I have been testing for this annotation would allow a user to define under what conditions should the override take place, and when those conditions evaluate to true, what alternative element class should be created over the default. In Appium this is often seen between different OS platforms, but I wanted it to be more generic and user-defined allows potential for browser specific, environment specific, url specific ect; a example use case would be if a user had different urls or environments in which you need to test across where the locators or implementation may be different (A project overhaul or something).
🔄 Types of changes
PR Type
Enhancement, Documentation
Description
Introduced
AbstractExtendedElementfor custom reusable elements.Enhanced
DefaultFieldDecoratorto support extended elements.Updated
LocatingElementListHandlerfor extended element lists.Extended
Selectclass to inherit fromAbstractExtendedElement.Added tests for extended elements and
Selectintegration.Updated Bazel build files for new dependencies.
Changes walkthrough 📝
4 files
Enhanced DefaultFieldDecorator to support extended elementsUpdated LocatingElementListHandler for extended element listsIntroduced AbstractExtendedElement for reusable elementsExtended Select class to support AbstractExtendedElement2 files
Added tests for extended elements in PageFactoryAdded tests for Select integration with extended elements2 files
Updated Bazel build file for new dependenciesUpdated Bazel build file for AbstractExtendedElement