- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 8.6k
 
[dotnet] Unwrap element wrapper recursively #15362
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
base: trunk
Are you sure you want to change the base?
Conversation
          PR Reviewer Guide 🔍Here are some key observations to aid the review process: 
  | 
    
          PR Code Suggestions ✨Explore these optional code suggestions: 
  | 
    ||||||||||||||
| elementReference = elementWrapper.WrappedElement as IWebDriverObjectReference; | ||
| if (ReferenceEquals(elementWrapper, elementWrapper.WrappedElement)) | ||
| { | ||
| throw new InvalidOperationException("Cannot determine root element: element wrapper wraps itself"); | 
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.
This protects against a user that has something like
public class MyElementWrapper : IWebElement, IWrapsElement
{
    public IWebElement WrappedElement => this;
}An infinite loop is probably the last thing we want here.
Should we have stronger protections? Maybe a maximum unwrap count, or cycle detection?
| if (elementReference == null) | ||
| { | ||
| throw new ArgumentException("Target element cannot be converted to IWebElementReference"); | ||
| throw new ArgumentException($"Target element cannot be converted to {nameof(IWebDriverObjectReference)}"); | 
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.
According to the history, IWebElementReference was renamed to IWebDriverObjectReference in the past. Fixing that in the string as well.
Should the message be improved? IWebDriverObjectReference is an internal type, an implementation detail. The real error here is:
"target element does not ultimately wrap `WebElement`; cannot use fully custom `IWebElement` here"
I'm not sure if that's what we want to tell users though.
User description
Description
In many places, we only unwrap
IWrapsElementonce. This, however, has led to user issues.This PR fixes that in a pain point from a user report. However, we should audit our usage of
IWrapsElementand make sure this problem does not exist elsewhere.There's also a lot of code duplication (or code that should be duplicated, but is implemented differently). We should centralize the element unwrapping logic.
Motivation and Context
Fixes #14513
Types of changes
Checklist
PR Type
Bug fix, Tests
Description
Fixed recursive unwrapping of
IWrapsElementto handle nested wrappers.Added error handling for self-referencing element wrappers.
Introduced new tests to validate double-wrapped element handling.
Added
WebElementWrapperclass for testing wrapped elements.Changes walkthrough 📝
PointerInputDevice.cs
Enhance `ConvertElement` to handle nested wrappersdotnet/src/webdriver/Interactions/PointerInputDevice.cs
ConvertElementto recursively unwrapIWrapsElement.WheelInputDevice.cs
Enhance `ConvertElement` to handle nested wrappersdotnet/src/webdriver/Interactions/WheelInputDevice.cs
ConvertElementto recursively unwrapIWrapsElement.BasicMouseInterfaceTest.cs
Add test for double-wrapped elements in mouse actionsdotnet/test/common/Interactions/BasicMouseInterfaceTest.cs
MoveToElementandClickfunctionality with wrapped elements.BasicWheelInterfaceTest.cs
Add test for double-wrapped elements in wheel actionsdotnet/test/common/Interactions/BasicWheelInterfaceTest.cs
ScrollToElementfunctionality with wrapped elements.WebElementWrapper.cs
Introduce `WebElementWrapper` for testingdotnet/test/common/WebElementWrapper.cs
WebElementWrapperclass implementingIWebElementandIWrapsElement.