Skip to content

Commit fd36c53

Browse files
authored
[dotnet] Allow setting a different pointer, keyboard, or wheel on input device (#11513)
* [dotnet] Allow setting a different pointer, keyboard, or pointer on input device Related to #10724
1 parent 067f10a commit fd36c53

8 files changed

Lines changed: 262 additions & 34 deletions

File tree

common/src/web/login.html

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<html>
2+
3+
<head>
4+
<title>Login</title>
5+
</head>
6+
7+
<body>
8+
<main id="main-holder">
9+
<h1 id="login-header">Login</h1>
10+
<form id="login-form">
11+
<input type="text" name="username" id="username-field" class="login-form-field" placeholder="Username">
12+
<input type="password" name="password" id="password-field" class="login-form-field" placeholder="Password">
13+
<input type="submit" value="Login" id="login-form-submit">
14+
</form>
15+
16+
</main>
17+
</body>
18+
19+
<script type="text/javascript">
20+
const loginForm = document.getElementById("login-form");
21+
const loginButton = document.getElementById("login-form-submit");
22+
23+
loginButton.addEventListener("click", (e) => {
24+
e.preventDefault();
25+
26+
const username = loginForm.username.value;
27+
const password = loginForm.password.value;
28+
29+
if (username === "username" && password === "password") {
30+
alert("You have successfully logged in.");
31+
} else {
32+
alert("Please enter valid credentials");
33+
location.reload();
34+
}
35+
})
36+
37+
</script>
38+
39+
</html>

dotnet/src/webdriver/Interactions/ActionSequence.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ public int Count
6969
get { return this.interactions.Count; }
7070
}
7171

72+
public InputDevice inputDevice
73+
{
74+
get { return this.inputDevice; }
75+
}
76+
7277
/// <summary>
7378
/// Adds an action to the sequence.
7479
/// </summary>

dotnet/src/webdriver/Interactions/Actions.cs

Lines changed: 157 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ public class Actions : IAction
3030
private readonly TimeSpan DefaultScrollDuration = TimeSpan.FromMilliseconds(250);
3131
private readonly TimeSpan DefaultMouseMoveDuration = TimeSpan.FromMilliseconds(250);
3232
private ActionBuilder actionBuilder = new ActionBuilder();
33-
private PointerInputDevice defaultMouse = new PointerInputDevice(PointerKind.Mouse, "default mouse");
34-
private KeyInputDevice defaultKeyboard = new KeyInputDevice("default keyboard");
35-
private WheelInputDevice defaultWheel = new WheelInputDevice("default wheel");
33+
private PointerInputDevice activePointer;
34+
private KeyInputDevice activeKeyboard;
35+
private WheelInputDevice activeWheel;
3636
private IActionExecutor actionExecutor;
3737

3838
/// <summary>
@@ -58,6 +58,129 @@ protected IActionExecutor ActionExecutor
5858
get { return this.actionExecutor; }
5959
}
6060

61+
public Actions setActivePointer(PointerKind kind, String name)
62+
{
63+
IList<ActionSequence> sequences = this.actionBuilder.ToActionSequenceList();
64+
65+
InputDevice device = null;
66+
67+
foreach (var sequence in sequences)
68+
{
69+
Dictionary<String, Object> actions = sequence.ToDictionary();
70+
71+
String id = (string)actions["id"];
72+
73+
if (id.Equals(name))
74+
{
75+
device = sequence.inputDevice;
76+
break;
77+
}
78+
}
79+
80+
if (device == null)
81+
{
82+
this.activePointer = new PointerInputDevice(kind, name);
83+
}
84+
else
85+
{
86+
this.activePointer = (PointerInputDevice)device;
87+
}
88+
89+
return this;
90+
}
91+
92+
public Actions setActiveKeyboard(String name)
93+
{
94+
IList<ActionSequence> sequences = this.actionBuilder.ToActionSequenceList();
95+
96+
InputDevice device = null;
97+
98+
foreach (var sequence in sequences)
99+
{
100+
Dictionary<String, Object> actions = sequence.ToDictionary();
101+
102+
String id = (string)actions["id"];
103+
104+
if (id.Equals(name))
105+
{
106+
device = sequence.inputDevice;
107+
break;
108+
}
109+
}
110+
111+
if (device == null)
112+
{
113+
this.activeKeyboard = new KeyInputDevice(name);
114+
}
115+
else
116+
{
117+
this.activeKeyboard = (KeyInputDevice)device;
118+
}
119+
120+
return this;
121+
}
122+
123+
public Actions setActiveWheel(String name)
124+
{
125+
IList<ActionSequence> sequences = this.actionBuilder.ToActionSequenceList();
126+
127+
InputDevice device = null;
128+
129+
foreach (var sequence in sequences)
130+
{
131+
Dictionary<String, Object> actions = sequence.ToDictionary();
132+
133+
String id = (string)actions["id"];
134+
135+
if (id.Equals(name))
136+
{
137+
device = sequence.inputDevice;
138+
break;
139+
}
140+
}
141+
142+
if (device == null)
143+
{
144+
this.activeWheel = new WheelInputDevice(name);
145+
}
146+
else
147+
{
148+
this.activeWheel = (WheelInputDevice)device;
149+
}
150+
151+
return this;
152+
}
153+
154+
155+
public PointerInputDevice getActivePointer()
156+
{
157+
if (this.activePointer == null)
158+
{
159+
setActivePointer(PointerKind.Mouse, "default mouse");
160+
}
161+
return this.activePointer;
162+
}
163+
164+
public KeyInputDevice getActiveKeyboard()
165+
{
166+
if (this.activeKeyboard == null)
167+
{
168+
setActiveKeyboard("default keyboard");
169+
}
170+
return this.activeKeyboard;
171+
}
172+
173+
public WheelInputDevice getActiveWheel()
174+
{
175+
if (this.activeWheel == null)
176+
{
177+
setActiveWheel("default wheel");
178+
}
179+
return this.activeWheel;
180+
}
181+
182+
183+
61184
/// <summary>
62185
/// Sends a modifier key down message to the browser.
63186
/// </summary>
@@ -92,13 +215,13 @@ public Actions KeyDown(IWebElement element, string theKey)
92215
ILocatable target = GetLocatableFromElement(element);
93216
if (element != null)
94217
{
95-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
96-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
97-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
218+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
219+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
220+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
98221
}
99222

100-
this.actionBuilder.AddAction(this.defaultKeyboard.CreateKeyDown(theKey[0]));
101-
this.actionBuilder.AddAction(new PauseInteraction(this.defaultKeyboard, TimeSpan.FromMilliseconds(100)));
223+
this.actionBuilder.AddAction(this.getActiveKeyboard().CreateKeyDown(theKey[0]));
224+
this.actionBuilder.AddAction(new PauseInteraction(this.getActiveKeyboard(), TimeSpan.FromMilliseconds(100)));
102225
return this;
103226
}
104227

@@ -136,12 +259,12 @@ public Actions KeyUp(IWebElement element, string theKey)
136259
ILocatable target = GetLocatableFromElement(element);
137260
if (element != null)
138261
{
139-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
140-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
141-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
262+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
263+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
264+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
142265
}
143266

144-
this.actionBuilder.AddAction(this.defaultKeyboard.CreateKeyUp(theKey[0]));
267+
this.actionBuilder.AddAction(this.getActiveKeyboard().CreateKeyUp(theKey[0]));
145268
return this;
146269
}
147270

@@ -171,15 +294,15 @@ public Actions SendKeys(IWebElement element, string keysToSend)
171294
ILocatable target = GetLocatableFromElement(element);
172295
if (element != null)
173296
{
174-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
175-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
176-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
297+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
298+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
299+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
177300
}
178301

179302
foreach (char key in keysToSend)
180303
{
181-
this.actionBuilder.AddAction(this.defaultKeyboard.CreateKeyDown(key));
182-
this.actionBuilder.AddAction(this.defaultKeyboard.CreateKeyUp(key));
304+
this.actionBuilder.AddAction(this.getActiveKeyboard().CreateKeyDown(key));
305+
this.actionBuilder.AddAction(this.getActiveKeyboard().CreateKeyUp(key));
183306
}
184307

185308
return this;
@@ -202,7 +325,7 @@ public Actions ClickAndHold(IWebElement onElement)
202325
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
203326
public Actions ClickAndHold()
204327
{
205-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
328+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
206329
return this;
207330
}
208331

@@ -223,7 +346,7 @@ public Actions Release(IWebElement onElement)
223346
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
224347
public Actions Release()
225348
{
226-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
349+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
227350
return this;
228351
}
229352

@@ -244,8 +367,8 @@ public Actions Click(IWebElement onElement)
244367
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
245368
public Actions Click()
246369
{
247-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
248-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
370+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
371+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
249372
return this;
250373
}
251374

@@ -266,10 +389,10 @@ public Actions DoubleClick(IWebElement onElement)
266389
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
267390
public Actions DoubleClick()
268391
{
269-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
270-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
271-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
272-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
392+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
393+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
394+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
395+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
273396
return this;
274397
}
275398

@@ -298,7 +421,7 @@ public Actions MoveToElement(IWebElement toElement)
298421
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
299422
public Actions MoveToElement(IWebElement toElement, int offsetX, int offsetY)
300423
{
301-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerMove(toElement, offsetX, offsetY, DefaultMouseMoveDuration));
424+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerMove(toElement, offsetX, offsetY, DefaultMouseMoveDuration));
302425
return this;
303426
}
304427

@@ -310,7 +433,7 @@ public Actions MoveToElement(IWebElement toElement, int offsetX, int offsetY)
310433
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
311434
public Actions MoveByOffset(int offsetX, int offsetY)
312435
{
313-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerMove(CoordinateOrigin.Pointer, offsetX, offsetY, DefaultMouseMoveDuration));
436+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerMove(CoordinateOrigin.Pointer, offsetX, offsetY, DefaultMouseMoveDuration));
314437
return this;
315438
}
316439

@@ -331,8 +454,8 @@ public Actions ContextClick(IWebElement onElement)
331454
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
332455
public Actions ContextClick()
333456
{
334-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Right));
335-
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Right));
457+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Right));
458+
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Right));
336459
return this;
337460
}
338461

@@ -368,7 +491,7 @@ public Actions DragAndDropToOffset(IWebElement source, int offsetX, int offsetY)
368491
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
369492
public Actions ScrollToElement(IWebElement element)
370493
{
371-
this.actionBuilder.AddAction(this.defaultWheel.CreateWheelScroll(element, 0, 0, 0, 0, DefaultScrollDuration));
494+
this.actionBuilder.AddAction(this.getActiveWheel().CreateWheelScroll(element, 0, 0, 0, 0, DefaultScrollDuration));
372495

373496
return this;
374497
}
@@ -381,7 +504,7 @@ public Actions ScrollToElement(IWebElement element)
381504
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
382505
public Actions ScrollByAmount(int deltaX, int deltaY)
383506
{
384-
this.actionBuilder.AddAction(this.defaultWheel.CreateWheelScroll(deltaX, deltaY, DefaultScrollDuration));
507+
this.actionBuilder.AddAction(this.getActiveWheel().CreateWheelScroll(deltaX, deltaY, DefaultScrollDuration));
385508

386509
return this;
387510
}
@@ -408,12 +531,12 @@ public Actions ScrollFromOrigin(WheelInputDevice.ScrollOrigin scrollOrigin, int
408531

409532
if (scrollOrigin.Viewport)
410533
{
411-
this.actionBuilder.AddAction(this.defaultWheel.CreateWheelScroll(CoordinateOrigin.Viewport,
534+
this.actionBuilder.AddAction(this.getActiveWheel().CreateWheelScroll(CoordinateOrigin.Viewport,
412535
scrollOrigin.XOffset, scrollOrigin.YOffset, deltaX, deltaY, DefaultScrollDuration));
413536
}
414537
else
415538
{
416-
this.actionBuilder.AddAction(this.defaultWheel.CreateWheelScroll(scrollOrigin.Element,
539+
this.actionBuilder.AddAction(this.getActiveWheel().CreateWheelScroll(scrollOrigin.Element,
417540
scrollOrigin.XOffset, scrollOrigin.YOffset, deltaX, deltaY, DefaultScrollDuration));
418541
}
419542

@@ -427,7 +550,7 @@ public Actions ScrollFromOrigin(WheelInputDevice.ScrollOrigin scrollOrigin, int
427550
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
428551
public Actions Pause(TimeSpan duration)
429552
{
430-
this.actionBuilder.AddAction(new PauseInteraction(this.defaultMouse, duration));
553+
this.actionBuilder.AddAction(new PauseInteraction(this.getActivePointer(), duration));
431554
return this;
432555
}
433556

dotnet/test/common/DriverTestFixture.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public abstract class DriverTestFixture
2626

2727
public string javascriptPage = EnvironmentManager.Instance.UrlBuilder.WhereIs("javascriptPage.html");
2828

29+
public string loginPage = EnvironmentManager.Instance.UrlBuilder.WhereIs("login.html");
30+
2931
public string clickEventPage = EnvironmentManager.Instance.UrlBuilder.WhereIs("clickEventPage.html");
3032

3133
public string resultPage = EnvironmentManager.Instance.UrlBuilder.WhereIs("resultPage.html");

dotnet/test/common/Interactions/BasicKeyboardInterfaceTest.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ public void ReleaseModifierKeys()
3131
}
3232
}
3333

34+
[Test]
35+
public void ShouldSetActiveKeyboard()
36+
{
37+
Actions actionProvider = new Actions(driver);
38+
actionProvider.setActiveKeyboard("test keyboard");
39+
40+
KeyInputDevice device = actionProvider.getActiveKeyboard();
41+
42+
Assert.AreEqual("test keyboard", device.DeviceName);
43+
}
44+
3445
[Test]
3546
[IgnoreBrowser(Browser.Remote, "API not implemented in driver")]
3647
public void ShouldAllowBasicKeyboardInput()

0 commit comments

Comments
 (0)