-
Notifications
You must be signed in to change notification settings - Fork 2
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
Feature/keyboard and mouse actions #12
Changes from 4 commits
be4339b
1748e8d
be6ab9a
5023348
cc70fc9
b713e48
5134446
968b9ff
dcac790
c94773c
79625bf
2403470
7cd3231
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
namespace Aquality.WinAppDriver.Actions | ||
{ | ||
/// <summary> | ||
/// Provides methods representing basic keyboard actions. | ||
/// </summary> | ||
public interface IKeyboardActions | ||
{ | ||
/// <summary> | ||
/// Presses a key. | ||
/// </summary> | ||
/// <param name="keyToPress">The key value representing the key to press.</param> | ||
/// <remarks>The key value must be one of the values from the <see cref="OpenQA.Selenium.Keys"/> class.</remarks> | ||
/// <exception cref="System.ArgumentException">If the key sent is not is not one of: | ||
/// <see cref="OpenQA.Selenium.Keys.Shift"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Control"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Alt"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Meta"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Command"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.LeftAlt"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.LeftShift"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Shift"/> | ||
/// </exception> | ||
void PressKey(string keyToPress); | ||
|
||
/// <summary> | ||
/// Releases a key. | ||
/// </summary> | ||
/// <param name="keyToRelease">The key value representing the key to release.</param> | ||
/// <remarks>The key value must be one of the values from the <see cref="OpenQA.Selenium.Keys"/> class.</remarks> | ||
/// <exception cref="System.ArgumentException">If the key sent is not is not one of: | ||
/// <see cref="OpenQA.Selenium.Keys.Shift"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Control"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Alt"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Meta"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Command"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.LeftAlt"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.LeftShift"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Shift"/> | ||
/// </exception> | ||
void ReleaseKey(string keyToRelease); | ||
|
||
/// <summary> | ||
/// Sends a sequence of keystrokes to the target. | ||
/// </summary> | ||
/// <param name="keySequence">A string representing the keystrokes to send.</param> | ||
void SendKeys(string keySequence); | ||
|
||
/// <summary> | ||
/// Sends a sequence of keystrokes to the target, holding a specified key. | ||
/// After the action, holded key is released. | ||
/// </summary> | ||
/// <param name="keySequence">A string representing the keystrokes to send.</param> | ||
/// <param name="keyToHold">The key value representing the key to hold. | ||
/// <remarks>The key value must be one of the values from the <see cref="OpenQA.Selenium.Keys"/> class.</remarks></param> | ||
/// <exception cref="System.ArgumentException">If the key sent is not is not one of: | ||
/// <see cref="OpenQA.Selenium.Keys.Shift"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Control"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Alt"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Meta"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Command"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.LeftAlt"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.LeftShift"/>, | ||
/// <see cref="OpenQA.Selenium.Keys.Shift"/> | ||
/// </exception> | ||
void SendKeysWithKeyHold(string keySequence, string keyToHold); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
using Aquality.Selenium.Core.Localization; | ||
using Aquality.WinAppDriver.Extensions; | ||
using OpenQA.Selenium.Appium.Windows; | ||
using System; | ||
using SeleniumActions = OpenQA.Selenium.Interactions.Actions; | ||
|
||
namespace Aquality.WinAppDriver.Actions | ||
{ | ||
public class KeyboardActions : IKeyboardActions | ||
{ | ||
private readonly LocalizationLogger localizationLogger; | ||
private readonly WindowsDriver<WindowsElement> windowsDriver; | ||
|
||
public KeyboardActions(LocalizationLogger localizationLogger, WindowsDriver<WindowsElement> windowsDriver) | ||
{ | ||
this.localizationLogger = localizationLogger; | ||
this.windowsDriver = windowsDriver; | ||
} | ||
|
||
public void PressKey(string keyToPress) | ||
{ | ||
LogAction("loc.keyboard.presskey", keyToPress.GetLoggableValueForKeyboardKey()); | ||
PerformAction(actions => actions.KeyDown(keyToPress)); | ||
} | ||
|
||
public void ReleaseKey(string keyToRelease) | ||
{ | ||
LogAction("loc.keyboard.releasekey", keyToRelease.GetLoggableValueForKeyboardKey()); | ||
PerformAction(actions => actions.KeyUp(keyToRelease)); | ||
} | ||
|
||
public void SendKeys(string keySequence) | ||
{ | ||
LogAction("loc.keyboard.sendkeys", keySequence); | ||
PerformAction(actions => actions.SendKeys(keySequence)); | ||
} | ||
|
||
public void SendKeysWithKeyHold(string keySequence, string keyToHold) | ||
{ | ||
LogAction("loc.keyboard.sendkeys.withkeyhold", keySequence, keyToHold.GetLoggableValueForKeyboardKey()); | ||
PerformAction(actions => actions.KeyDown(keyToHold).SendKeys(keySequence).KeyUp(keyToHold)); | ||
} | ||
|
||
/// <summary> | ||
/// Performs submited action against new <see cref="SeleniumActions"/> object. | ||
mialeska marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// </summary> | ||
/// <param name="action">Action to be performed.</param> | ||
protected virtual void PerformAction(Func<SeleniumActions, SeleniumActions> action) | ||
{ | ||
action(new SeleniumActions(windowsDriver)).Build().Perform(); | ||
} | ||
|
||
/// <summary> | ||
/// Logs keyboard action in specific format. | ||
/// </summary> | ||
/// <param name="messageKey">Key of the localized message.</param> | ||
/// <param name="args">arguments for the localized message</param> | ||
mialeska marked this conversation as resolved.
Show resolved
Hide resolved
|
||
protected virtual void LogAction(string messageKey, params object[] args) | ||
{ | ||
localizationLogger.Info(messageKey, args); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
using Aquality.Selenium.Core.Applications; | ||
using Aquality.Selenium.Core.Localization; | ||
using Aquality.Selenium.Core.Utilities; | ||
using Aquality.WinAppDriver.Actions; | ||
using Aquality.WinAppDriver.Elements.Interfaces; | ||
using Aquality.WinAppDriver.Extensions; | ||
using OpenQA.Selenium; | ||
using System; | ||
using SeleniumActions = OpenQA.Selenium.Interactions.Actions; | ||
|
||
namespace Aquality.WinAppDriver.Elements.Actions | ||
{ | ||
/// <summary> | ||
/// Implements Keyboard actions for a specific element. | ||
mialeska marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// </summary> | ||
public class KeyboardActions : IKeyboardActions | ||
{ | ||
private readonly IElement element; | ||
private readonly string elementType; | ||
private readonly IApplication application; | ||
private readonly LocalizationLogger localizationLogger; | ||
private readonly ElementActionRetrier elementActionsRetrier; | ||
|
||
/// <summary> | ||
/// Instantiates Keyboard actions for a specific element. | ||
/// </summary> | ||
/// <param name="element">Target element.</param> | ||
/// <param name="elementType">Target element's type.</param> | ||
/// <param name="application">Current application session.</param> | ||
/// <param name="localizationLogger">Logger for localized values.</param> | ||
/// <param name="elementActionsRetrier">Retrier for element actions.</param> | ||
public KeyboardActions(IElement element, string elementType, IApplication application, LocalizationLogger localizationLogger, ElementActionRetrier elementActionsRetrier) | ||
{ | ||
this.element = element; | ||
this.elementType = elementType; | ||
this.application = application; | ||
this.localizationLogger = localizationLogger; | ||
this.elementActionsRetrier = elementActionsRetrier; | ||
} | ||
|
||
public void PressKey(string keyToPress) | ||
{ | ||
LogElementAction("loc.keyboard.presskey", keyToPress.GetLoggableValueForKeyboardKey()); | ||
PerformAction((actions, element) => actions.KeyDown(element, keyToPress)); | ||
} | ||
|
||
public void ReleaseKey(string keyToRelease) | ||
{ | ||
LogElementAction("loc.keyboard.releasekey", keyToRelease.GetLoggableValueForKeyboardKey()); | ||
PerformAction((actions, element) => actions.KeyUp(element, keyToRelease)); | ||
} | ||
|
||
public void SendKeys(string keySequence) | ||
{ | ||
LogElementAction("loc.keyboard.sendkeys", keySequence); | ||
PerformAction((actions, element) => actions.SendKeys(element, keySequence)); | ||
} | ||
|
||
public void SendKeysWithKeyHold(string keySequence, string keyToHold) | ||
{ | ||
LogElementAction("loc.keyboard.sendkeys.withkeyhold", keySequence, keyToHold.GetLoggableValueForKeyboardKey()); | ||
PerformAction((actions, element) => actions.KeyDown(element, keyToHold).SendKeys(element, keySequence).KeyUp(element, keyToHold)); | ||
} | ||
|
||
/// <summary> | ||
/// Performs submited action against new <see cref="SeleniumActions"/> object. | ||
/// </summary> | ||
/// <param name="action">Action to be performed.</param> | ||
protected virtual void PerformAction(Func<SeleniumActions, IWebElement, SeleniumActions> action) | ||
{ | ||
elementActionsRetrier.DoWithRetry(() => | ||
{ | ||
action(new SeleniumActions(application.Driver), element.GetElement()).Build().Perform(); | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Logs element action in specific format. | ||
/// </summary> | ||
/// <param name="messageKey">Key of the localized message.</param> | ||
/// <param name="args">arguments for the localized message</param> | ||
protected virtual void LogElementAction(string messageKey, params object[] args) | ||
{ | ||
localizationLogger.InfoElementAction(elementType, element.Name, messageKey, args); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
using CoreElement = Aquality.Selenium.Core.Elements.Interfaces.IElement; | ||
using Aquality.WinAppDriver.Actions; | ||
using CoreElement = Aquality.Selenium.Core.Elements.Interfaces.IElement; | ||
|
||
namespace Aquality.WinAppDriver.Elements.Interfaces | ||
{ | ||
public interface IElement : CoreElement | ||
{ | ||
IKeyboardActions KeyboardActions { get; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using OpenQA.Selenium; | ||
using System.Linq; | ||
using System.Reflection; | ||
|
||
namespace Aquality.WinAppDriver.Extensions | ||
{ | ||
public static class StringExtensions | ||
{ | ||
/// <summary> | ||
/// Returns name of the value from <see cref="Keys"/>, readable in the log. | ||
/// </summary> | ||
/// <param name="key">Keyboard key to define.</param> | ||
/// <returns>Readable value.</returns> | ||
public static string GetLoggableValueForKeyboardKey(this string key) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why it is public? It looks like helper for some library actions, but not as public method that should be available in client code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't see any reason why should we hide the functionality that could be used by the customer. |
||
{ | ||
return typeof(Keys) | ||
.GetFields(BindingFlags.Public | BindingFlags.Static) | ||
.FirstOrDefault(field => key.Equals(field.GetValue(null)))?.Name ?? key; | ||
} | ||
} | ||
} |
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.
Do you really need this list of Keys in summary?
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.
yes I do. Selenium has it. We either need to follow it's notation, or define a custom Enum with mapping to this values, and accept only them in our methods. I like the first variant more, but we can discuss it