Skip to content

Commit 001a885

Browse files
[dotnet] Unwrap element wrapper recursively (#15362)
* [dotnet] Unwrap element wrapper more than once * fix whitespace
1 parent a2b4269 commit 001a885

File tree

5 files changed

+156
-4
lines changed

5 files changed

+156
-4
lines changed

dotnet/src/webdriver/Interactions/PointerInputDevice.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,15 +595,21 @@ private Dictionary<string, object> ConvertElement()
595595
if (elementReference == null)
596596
{
597597
IWrapsElement? elementWrapper = this.target as IWrapsElement;
598-
if (elementWrapper != null)
598+
while (elementWrapper != null)
599599
{
600600
elementReference = elementWrapper.WrappedElement as IWebDriverObjectReference;
601+
if (ReferenceEquals(elementWrapper, elementWrapper.WrappedElement))
602+
{
603+
throw new InvalidOperationException("Cannot determine root element: element wrapper wraps itself");
604+
}
605+
606+
elementWrapper = elementWrapper.WrappedElement as IWrapsElement;
601607
}
602608
}
603609

604610
if (elementReference == null)
605611
{
606-
throw new ArgumentException("Target element cannot be converted to IWebElementReference");
612+
throw new ArgumentException($"Target element cannot be converted to {nameof(IWebDriverObjectReference)}");
607613
}
608614

609615
Dictionary<string, object> elementDictionary = elementReference.ToDictionary();

dotnet/src/webdriver/Interactions/WheelInputDevice.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,21 @@ private Dictionary<string, object> ConvertElement()
211211
if (elementReference == null)
212212
{
213213
IWrapsElement? elementWrapper = this.target as IWrapsElement;
214-
if (elementWrapper != null)
214+
while (elementWrapper != null)
215215
{
216216
elementReference = elementWrapper.WrappedElement as IWebDriverObjectReference;
217+
if (ReferenceEquals(elementWrapper, elementWrapper.WrappedElement))
218+
{
219+
throw new InvalidOperationException("Cannot determine root element: element wrapper wraps itself");
220+
}
221+
222+
elementWrapper = elementWrapper.WrappedElement as IWrapsElement;
217223
}
218224
}
219225

220226
if (elementReference == null)
221227
{
222-
throw new ArgumentException("Target element cannot be converted to IWebElementReference");
228+
throw new ArgumentException($"Target element cannot be converted to {nameof(IWebDriverObjectReference)}");
223229
}
224230

225231
Dictionary<string, object> elementDictionary = elementReference.ToDictionary();

dotnet/test/common/Interactions/BasicMouseInterfaceTest.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,24 @@ public void ShouldAllowMoveAndClick()
162162
Assert.That(toClick.GetAttribute("value"), Is.EqualTo("Clicked"), "Value should change to Clicked.");
163163
}
164164

165+
[Test]
166+
[IgnoreBrowser(Browser.Remote, "API not implemented in driver")]
167+
public void ShouldAllowMoveAndClickDoubleWrappedElement()
168+
{
169+
driver.Url = javascriptPage;
170+
171+
IWebElement toClick = driver.FindElement(By.Id("clickField"));
172+
173+
toClick = new WebElementWrapper(toClick);
174+
toClick = new WebElementWrapper(toClick);
175+
176+
Actions actionProvider = new Actions(driver);
177+
IAction contextClick = actionProvider.MoveToElement(toClick).Click().Build();
178+
179+
contextClick.Perform();
180+
Assert.That(toClick.GetAttribute("value"), Is.EqualTo("Clicked"), "Value should change to Clicked.");
181+
}
182+
165183
[Test]
166184
[IgnoreBrowser(Browser.Chrome, "Not working properly in RBE, works locally with pinned browsers")]
167185
[IgnoreBrowser(Browser.Edge, "Not working properly in RBE, works locally with pinned browsers")]

dotnet/test/common/Interactions/BasicWheelInterfaceTest.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,23 @@ public void ShouldNotAllowScrollingWhenOriginOffsetIsOutOfViewport()
165165
Throws.InstanceOf<MoveTargetOutOfBoundsException>());
166166
}
167167

168+
[Test]
169+
[IgnoreBrowser(Browser.Firefox, "Incorrectly throws out of bounds exception")]
170+
public void ShouldAllowScrollingToADoubleWrappedElement()
171+
{
172+
driver.Url = scrollFrameOutOfViewport;
173+
IWebElement iframe = driver.FindElement(By.TagName("iframe"));
174+
175+
Assert.That(IsInViewport(iframe), Is.False);
176+
177+
var wrappedFrame = new WebElementWrapper(iframe);
178+
wrappedFrame = new WebElementWrapper(wrappedFrame);
179+
180+
new Actions(driver).ScrollToElement(wrappedFrame).Build().Perform();
181+
182+
Assert.That(IsInViewport(iframe), Is.True);
183+
}
184+
168185
private bool IsInViewport(IWebElement element)
169186
{
170187
String script =
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// <copyright file="WebElementWrapper.cs" company="Selenium Committers">
2+
// Licensed to the Software Freedom Conservancy (SFC) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The SFC licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
// </copyright>
19+
20+
using System.Collections.ObjectModel;
21+
using System.Drawing;
22+
23+
namespace OpenQA.Selenium
24+
{
25+
public class WebElementWrapper : IWebElement, IWrapsElement
26+
{
27+
private readonly IWebElement _webElement;
28+
29+
public WebElementWrapper(IWebElement element)
30+
{
31+
_webElement = element;
32+
}
33+
34+
public IWebElement WrappedElement => _webElement;
35+
36+
public string TagName => _webElement.TagName;
37+
38+
public string Text => _webElement.Text;
39+
40+
public bool Enabled => _webElement.Enabled;
41+
42+
public bool Selected => _webElement.Selected;
43+
44+
public Point Location => _webElement.Location;
45+
46+
public Size Size => _webElement.Size;
47+
48+
public bool Displayed => _webElement.Displayed;
49+
50+
public void Clear()
51+
{
52+
_webElement.Clear();
53+
}
54+
55+
public void Click()
56+
{
57+
_webElement.Click();
58+
}
59+
60+
public IWebElement FindElement(By by)
61+
{
62+
return _webElement.FindElement(by);
63+
}
64+
65+
public ReadOnlyCollection<IWebElement> FindElements(By by)
66+
{
67+
return _webElement.FindElements(by);
68+
}
69+
70+
public string GetAttribute(string attributeName)
71+
{
72+
return _webElement.GetAttribute(attributeName);
73+
}
74+
75+
public string GetCssValue(string propertyName)
76+
{
77+
return _webElement.GetCssValue(propertyName);
78+
}
79+
80+
public string GetDomAttribute(string attributeName)
81+
{
82+
return _webElement.GetDomAttribute(attributeName);
83+
}
84+
85+
public string GetDomProperty(string propertyName)
86+
{
87+
return _webElement.GetDomProperty(propertyName);
88+
}
89+
90+
public ISearchContext GetShadowRoot()
91+
{
92+
return _webElement.GetShadowRoot();
93+
}
94+
95+
public void SendKeys(string text)
96+
{
97+
_webElement.SendKeys(text);
98+
}
99+
100+
public void Submit()
101+
{
102+
_webElement.Submit();
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)