Skip to content

Commit

Permalink
[dotnet] Allow setting a different pointer, keyboard, or wheel on inp…
Browse files Browse the repository at this point in the history
…ut device (#11513)

* [dotnet] Allow setting a different pointer, keyboard, or pointer on input device

Related to #10724
  • Loading branch information
pujagani committed Jul 12, 2023
1 parent 067f10a commit fd36c53
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 34 deletions.
39 changes: 39 additions & 0 deletions common/src/web/login.html
@@ -0,0 +1,39 @@
<html>

<head>
<title>Login</title>
</head>

<body>
<main id="main-holder">
<h1 id="login-header">Login</h1>
<form id="login-form">
<input type="text" name="username" id="username-field" class="login-form-field" placeholder="Username">
<input type="password" name="password" id="password-field" class="login-form-field" placeholder="Password">
<input type="submit" value="Login" id="login-form-submit">
</form>

</main>
</body>

<script type="text/javascript">
const loginForm = document.getElementById("login-form");
const loginButton = document.getElementById("login-form-submit");

loginButton.addEventListener("click", (e) => {
e.preventDefault();

const username = loginForm.username.value;
const password = loginForm.password.value;

if (username === "username" && password === "password") {
alert("You have successfully logged in.");
} else {
alert("Please enter valid credentials");
location.reload();
}
})

</script>

</html>
5 changes: 5 additions & 0 deletions dotnet/src/webdriver/Interactions/ActionSequence.cs
Expand Up @@ -69,6 +69,11 @@ public int Count
get { return this.interactions.Count; }
}

public InputDevice inputDevice
{
get { return this.inputDevice; }
}

/// <summary>
/// Adds an action to the sequence.
/// </summary>
Expand Down
191 changes: 157 additions & 34 deletions dotnet/src/webdriver/Interactions/Actions.cs
Expand Up @@ -30,9 +30,9 @@ public class Actions : IAction
private readonly TimeSpan DefaultScrollDuration = TimeSpan.FromMilliseconds(250);
private readonly TimeSpan DefaultMouseMoveDuration = TimeSpan.FromMilliseconds(250);
private ActionBuilder actionBuilder = new ActionBuilder();
private PointerInputDevice defaultMouse = new PointerInputDevice(PointerKind.Mouse, "default mouse");
private KeyInputDevice defaultKeyboard = new KeyInputDevice("default keyboard");
private WheelInputDevice defaultWheel = new WheelInputDevice("default wheel");
private PointerInputDevice activePointer;
private KeyInputDevice activeKeyboard;
private WheelInputDevice activeWheel;
private IActionExecutor actionExecutor;

/// <summary>
Expand All @@ -58,6 +58,129 @@ protected IActionExecutor ActionExecutor
get { return this.actionExecutor; }
}

public Actions setActivePointer(PointerKind kind, String name)
{
IList<ActionSequence> sequences = this.actionBuilder.ToActionSequenceList();

InputDevice device = null;

foreach (var sequence in sequences)
{
Dictionary<String, Object> actions = sequence.ToDictionary();

String id = (string)actions["id"];

if (id.Equals(name))
{
device = sequence.inputDevice;
break;
}
}

if (device == null)
{
this.activePointer = new PointerInputDevice(kind, name);
}
else
{
this.activePointer = (PointerInputDevice)device;
}

return this;
}

public Actions setActiveKeyboard(String name)
{
IList<ActionSequence> sequences = this.actionBuilder.ToActionSequenceList();

InputDevice device = null;

foreach (var sequence in sequences)
{
Dictionary<String, Object> actions = sequence.ToDictionary();

String id = (string)actions["id"];

if (id.Equals(name))
{
device = sequence.inputDevice;
break;
}
}

if (device == null)
{
this.activeKeyboard = new KeyInputDevice(name);
}
else
{
this.activeKeyboard = (KeyInputDevice)device;
}

return this;
}

public Actions setActiveWheel(String name)
{
IList<ActionSequence> sequences = this.actionBuilder.ToActionSequenceList();

InputDevice device = null;

foreach (var sequence in sequences)
{
Dictionary<String, Object> actions = sequence.ToDictionary();

String id = (string)actions["id"];

if (id.Equals(name))
{
device = sequence.inputDevice;
break;
}
}

if (device == null)
{
this.activeWheel = new WheelInputDevice(name);
}
else
{
this.activeWheel = (WheelInputDevice)device;
}

return this;
}


public PointerInputDevice getActivePointer()
{
if (this.activePointer == null)
{
setActivePointer(PointerKind.Mouse, "default mouse");
}
return this.activePointer;
}

public KeyInputDevice getActiveKeyboard()
{
if (this.activeKeyboard == null)
{
setActiveKeyboard("default keyboard");
}
return this.activeKeyboard;
}

public WheelInputDevice getActiveWheel()
{
if (this.activeWheel == null)
{
setActiveWheel("default wheel");
}
return this.activeWheel;
}



/// <summary>
/// Sends a modifier key down message to the browser.
/// </summary>
Expand Down Expand Up @@ -92,13 +215,13 @@ public Actions KeyDown(IWebElement element, string theKey)
ILocatable target = GetLocatableFromElement(element);
if (element != null)
{
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
}

this.actionBuilder.AddAction(this.defaultKeyboard.CreateKeyDown(theKey[0]));
this.actionBuilder.AddAction(new PauseInteraction(this.defaultKeyboard, TimeSpan.FromMilliseconds(100)));
this.actionBuilder.AddAction(this.getActiveKeyboard().CreateKeyDown(theKey[0]));
this.actionBuilder.AddAction(new PauseInteraction(this.getActiveKeyboard(), TimeSpan.FromMilliseconds(100)));
return this;
}

Expand Down Expand Up @@ -136,12 +259,12 @@ public Actions KeyUp(IWebElement element, string theKey)
ILocatable target = GetLocatableFromElement(element);
if (element != null)
{
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
}

this.actionBuilder.AddAction(this.defaultKeyboard.CreateKeyUp(theKey[0]));
this.actionBuilder.AddAction(this.getActiveKeyboard().CreateKeyUp(theKey[0]));
return this;
}

Expand Down Expand Up @@ -171,15 +294,15 @@ public Actions SendKeys(IWebElement element, string keysToSend)
ILocatable target = GetLocatableFromElement(element);
if (element != null)
{
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerMove(element, 0, 0, DefaultMouseMoveDuration));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
}

foreach (char key in keysToSend)
{
this.actionBuilder.AddAction(this.defaultKeyboard.CreateKeyDown(key));
this.actionBuilder.AddAction(this.defaultKeyboard.CreateKeyUp(key));
this.actionBuilder.AddAction(this.getActiveKeyboard().CreateKeyDown(key));
this.actionBuilder.AddAction(this.getActiveKeyboard().CreateKeyUp(key));
}

return this;
Expand All @@ -202,7 +325,7 @@ public Actions ClickAndHold(IWebElement onElement)
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
public Actions ClickAndHold()
{
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
return this;
}

Expand All @@ -223,7 +346,7 @@ public Actions Release(IWebElement onElement)
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
public Actions Release()
{
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
return this;
}

Expand All @@ -244,8 +367,8 @@ public Actions Click(IWebElement onElement)
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
public Actions Click()
{
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
return this;
}

Expand All @@ -266,10 +389,10 @@ public Actions DoubleClick(IWebElement onElement)
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
public Actions DoubleClick()
{
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Left));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Left));
return this;
}

Expand Down Expand Up @@ -298,7 +421,7 @@ public Actions MoveToElement(IWebElement toElement)
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
public Actions MoveToElement(IWebElement toElement, int offsetX, int offsetY)
{
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerMove(toElement, offsetX, offsetY, DefaultMouseMoveDuration));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerMove(toElement, offsetX, offsetY, DefaultMouseMoveDuration));
return this;
}

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

Expand All @@ -331,8 +454,8 @@ public Actions ContextClick(IWebElement onElement)
/// <returns>A self-reference to this <see cref="Actions"/>.</returns>
public Actions ContextClick()
{
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerDown(MouseButton.Right));
this.actionBuilder.AddAction(this.defaultMouse.CreatePointerUp(MouseButton.Right));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerDown(MouseButton.Right));
this.actionBuilder.AddAction(this.getActivePointer().CreatePointerUp(MouseButton.Right));
return this;
}

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

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

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

if (scrollOrigin.Viewport)
{
this.actionBuilder.AddAction(this.defaultWheel.CreateWheelScroll(CoordinateOrigin.Viewport,
this.actionBuilder.AddAction(this.getActiveWheel().CreateWheelScroll(CoordinateOrigin.Viewport,
scrollOrigin.XOffset, scrollOrigin.YOffset, deltaX, deltaY, DefaultScrollDuration));
}
else
{
this.actionBuilder.AddAction(this.defaultWheel.CreateWheelScroll(scrollOrigin.Element,
this.actionBuilder.AddAction(this.getActiveWheel().CreateWheelScroll(scrollOrigin.Element,
scrollOrigin.XOffset, scrollOrigin.YOffset, deltaX, deltaY, DefaultScrollDuration));
}

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

Expand Down
2 changes: 2 additions & 0 deletions dotnet/test/common/DriverTestFixture.cs
Expand Up @@ -26,6 +26,8 @@ public abstract class DriverTestFixture

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

public string loginPage = EnvironmentManager.Instance.UrlBuilder.WhereIs("login.html");

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

public string resultPage = EnvironmentManager.Instance.UrlBuilder.WhereIs("resultPage.html");
Expand Down
11 changes: 11 additions & 0 deletions dotnet/test/common/Interactions/BasicKeyboardInterfaceTest.cs
Expand Up @@ -31,6 +31,17 @@ public void ReleaseModifierKeys()
}
}

[Test]
public void ShouldSetActiveKeyboard()
{
Actions actionProvider = new Actions(driver);
actionProvider.setActiveKeyboard("test keyboard");

KeyInputDevice device = actionProvider.getActiveKeyboard();

Assert.AreEqual("test keyboard", device.DeviceName);
}

[Test]
[IgnoreBrowser(Browser.Remote, "API not implemented in driver")]
public void ShouldAllowBasicKeyboardInput()
Expand Down

0 comments on commit fd36c53

Please sign in to comment.