diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/ApplicationActions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/ApplicationActions.cs
new file mode 100644
index 0000000..feca2e5
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/ApplicationActions.cs
@@ -0,0 +1,47 @@
+using Aquality.Selenium.Core.Localization;
+using OpenQA.Selenium.Appium.Windows;
+using System;
+using SeleniumActions = OpenQA.Selenium.Interactions.Actions;
+
+namespace Aquality.WinAppDriver.Actions
+{
+ ///
+ /// Abstract class for any actions against the whole application.
+ ///
+ public abstract class ApplicationActions
+ {
+ private readonly LocalizationLogger localizationLogger;
+ private readonly Func> windowsDriverSupplier;
+
+
+ ///
+ /// Instantiates Aplication actions.
+ ///
+ /// Logger for localized values.
+ /// Method to get current application session.
+ protected ApplicationActions(LocalizationLogger localizationLogger, Func> windowsDriverSupplier)
+ {
+ this.localizationLogger = localizationLogger;
+ this.windowsDriverSupplier = windowsDriverSupplier;
+ }
+
+ ///
+ /// Performs submitted action against new object.
+ ///
+ /// Action to be performed.
+ protected virtual void PerformAction(Func action)
+ {
+ action(new SeleniumActions(windowsDriverSupplier())).Build().Perform();
+ }
+
+ ///
+ /// Logs keyboard action in specific format.
+ ///
+ /// Key of the localized message.
+ /// Arguments for the localized message.
+ protected virtual void LogAction(string messageKey, params object[] args)
+ {
+ localizationLogger.Info(messageKey, args);
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/IKeyboardActions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/IKeyboardActions.cs
new file mode 100644
index 0000000..83c8b40
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/IKeyboardActions.cs
@@ -0,0 +1,34 @@
+namespace Aquality.WinAppDriver.Actions
+{
+ ///
+ /// Provides methods representing basic keyboard actions.
+ ///
+ public interface IKeyboardActions
+ {
+ ///
+ /// Presses a key.
+ ///
+ /// The value representing the key to press.
+ void PressKey(ModifierKey keyToPress);
+
+ ///
+ /// Releases a key.
+ ///
+ /// The value representing the key to release.
+ void ReleaseKey(ModifierKey keyToRelease);
+
+ ///
+ /// Sends a sequence of keystrokes to the target.
+ ///
+ /// A string representing the keystrokes to send.
+ void SendKeys(string keySequence);
+
+ ///
+ /// Sends a sequence of keystrokes to the application, holding a specified key.
+ /// After the action, holded key is released.
+ ///
+ /// A string representing the keystrokes to send.
+ /// The value representing the key to hold.
+ void SendKeysWithKeyHold(string keySequence, ModifierKey keyToHold);
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/IMouseActions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/IMouseActions.cs
new file mode 100644
index 0000000..b222bbd
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/IMouseActions.cs
@@ -0,0 +1,47 @@
+namespace Aquality.WinAppDriver.Actions
+{
+ ///
+ /// Provides methods representing basic mouse actions.
+ ///
+ public interface IMouseActions
+ {
+ ///
+ /// Clicks the mouse at the last known mouse coordinates.
+ ///
+ void Click();
+
+ ///
+ /// Clicks and holds the mouse button at the last known mouse coordinates.
+ ///
+ void ClickAndHold();
+
+ ///
+ /// Releases the mouse button at the last known mouse coordinates.
+ ///
+ void Release();
+
+ ///
+ /// Right-clicks the mouse at the last known mouse coordinates.
+ ///
+ void ContextClick();
+
+ ///
+ /// Double-clicks the mouse at the last known mouse coordinates.
+ ///
+ void DoubleClick();
+
+ ///
+ /// Moves the mouse to the specified offset of the last known mouse coordinates.
+ ///
+ /// The horizontal offset to which to move the mouse.
+ /// The vertical offset to which to move the mouse.
+ void MoveByOffset(int offsetX, int offsetY);
+
+ ///
+ /// Scrolls the current screen by specified offset.
+ ///
+ /// The horizontal offset relative to the view port.
+ /// The vertical offset relative to the view port.
+ void Scroll(int offsetX, int offsetY);
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/KeyboardActions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/KeyboardActions.cs
new file mode 100644
index 0000000..c2ba474
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/KeyboardActions.cs
@@ -0,0 +1,42 @@
+using Aquality.Selenium.Core.Localization;
+using OpenQA.Selenium.Appium.Windows;
+using System;
+
+namespace Aquality.WinAppDriver.Actions
+{
+ ///
+ /// Implements Keyboard actions for the whole application.
+ ///
+ public class KeyboardActions : ApplicationActions, IKeyboardActions
+ {
+ public KeyboardActions(LocalizationLogger localizationLogger, Func> windowsDriverSupplier)
+ : base(localizationLogger, windowsDriverSupplier)
+ {
+ }
+
+ public void PressKey(ModifierKey keyToPress)
+ {
+ LogAction("loc.keyboard.presskey", keyToPress);
+ PerformAction(actions => actions.KeyDown(keyToPress.GetKeysString()));
+ }
+
+ public void ReleaseKey(ModifierKey keyToRelease)
+ {
+ LogAction("loc.keyboard.releasekey", keyToRelease);
+ PerformAction(actions => actions.KeyUp(keyToRelease.GetKeysString()));
+ }
+
+ public void SendKeys(string keySequence)
+ {
+ LogAction("loc.keyboard.sendkeys", keySequence);
+ PerformAction(actions => actions.SendKeys(keySequence));
+ }
+
+ public void SendKeysWithKeyHold(string keySequence, ModifierKey keyToHold)
+ {
+ var keyToHoldString = keyToHold.GetKeysString();
+ LogAction("loc.keyboard.sendkeys.withkeyhold", keySequence, keyToHold);
+ PerformAction(actions => actions.KeyDown(keyToHoldString).SendKeys(keySequence).KeyUp(keyToHoldString));
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/ModifierKey.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/ModifierKey.cs
new file mode 100644
index 0000000..e613f51
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/ModifierKey.cs
@@ -0,0 +1,56 @@
+using OpenQA.Selenium;
+using System.Linq;
+using System.Reflection;
+
+namespace Aquality.WinAppDriver.Actions
+{
+ ///
+ /// Represents modifier keys which could be used in .
+ /// Directly related to
+ ///
+ public enum ModifierKey
+ {
+ ///
+ /// Represents the Alt key.
+ ///
+ Alt,
+ ///
+ /// Represents the function key COMMAND.
+ ///
+ Command,
+ ///
+ /// Represents the Control key.
+ ///
+ Control,
+ ///
+ /// Represents the Left Alt key.
+ ///
+ LeftAlt,
+ ///
+ /// Represents the Left Control key.
+ ///
+ LeftControl,
+ ///
+ /// Represents the Left Shift key.
+ ///
+ LeftShift,
+ ///
+ /// Represents the function key META.
+ ///
+ Meta,
+ ///
+ /// Represents the Shift key.
+ ///
+ Shift
+ }
+
+ internal static class ModifierKeyExtensions
+ {
+ public static string GetKeysString(this ModifierKey modifierKey)
+ {
+ return typeof(Keys)
+ .GetFields(BindingFlags.Public | BindingFlags.Static)
+ .FirstOrDefault(field => field.Name == modifierKey.ToString())?.GetValue(null).ToString();
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/MouseActions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/MouseActions.cs
new file mode 100644
index 0000000..9aaef02
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Actions/MouseActions.cs
@@ -0,0 +1,63 @@
+using Aquality.Selenium.Core.Localization;
+using OpenQA.Selenium.Appium.Windows;
+using OpenQA.Selenium.Remote;
+using System;
+
+namespace Aquality.WinAppDriver.Actions
+{
+ ///
+ /// Implements Mouse actions for the whole application.
+ ///
+ public class MouseActions : ApplicationActions, IMouseActions
+ {
+ private readonly Func remoteTouchScreenSupplier;
+
+ public MouseActions(LocalizationLogger localizationLogger, Func> windowsDriverSupplier)
+ : base(localizationLogger, windowsDriverSupplier)
+ {
+ remoteTouchScreenSupplier = () => new RemoteTouchScreen(windowsDriverSupplier());
+ }
+
+ public void Click()
+ {
+ LogAction("loc.mouse.click");
+ PerformAction(actions => actions.Click());
+ }
+
+ public void ClickAndHold()
+ {
+ LogAction("loc.mouse.clickandhold");
+ PerformAction(actions => actions.ClickAndHold());
+ }
+
+ public void Release()
+ {
+ LogAction("loc.mouse.release");
+ PerformAction(actions => actions.Release());
+ }
+
+ public void ContextClick()
+ {
+ LogAction("loc.mouse.contextclick");
+ PerformAction(actions => actions.ContextClick());
+ }
+
+ public void DoubleClick()
+ {
+ LogAction("loc.mouse.doubleclick");
+ PerformAction(actions => actions.DoubleClick());
+ }
+
+ public void MoveByOffset(int offsetX, int offsetY)
+ {
+ LogAction("loc.mouse.movebyoffset", offsetX, offsetY);
+ PerformAction(actions => actions.MoveByOffset(offsetX, offsetY));
+ }
+
+ public void Scroll(int offsetX, int offsetY)
+ {
+ LogAction("loc.mouse.scrollbyoffset", offsetX, offsetY);
+ remoteTouchScreenSupplier().Scroll(offsetX, offsetY);
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/Application.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/Application.cs
index 89d8adb..4102c0c 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/Application.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/Application.cs
@@ -2,6 +2,8 @@
using Aquality.Selenium.Core.Applications;
using Aquality.Selenium.Core.Configurations;
using Aquality.Selenium.Core.Localization;
+using Aquality.WinAppDriver.Actions;
+using Microsoft.Extensions.DependencyInjection;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Remote;
@@ -13,19 +15,21 @@ namespace Aquality.WinAppDriver.Applications
public class Application : IApplication
{
private TimeSpan implicitWait;
-
+
///
/// Instantiate application.
///
/// Instance of WinAppDriver
- /// Instance of
- /// Instance of
- public Application(WindowsDriver windowsDriver, ITimeoutConfiguration timeoutConfiguration, LocalizationLogger logger)
+ /// Service provider to resolve all dependencies from DI container
+ public Application(WindowsDriver windowsDriver, IServiceProvider serviceProvider)
{
- Logger = logger;
WindowsDriver = windowsDriver;
+ Logger = serviceProvider.GetRequiredService();
+ KeyboardActions = serviceProvider.GetRequiredService();
+ MouseActions = serviceProvider.GetRequiredService();
+ var timeoutConfiguration = serviceProvider.GetRequiredService();
WindowsDriver.Manage().Timeouts().ImplicitWait = timeoutConfiguration.Implicit;
- logger.Info("loc.application.ready");
+ Logger.Info("loc.application.ready");
}
private LocalizationLogger Logger { get; }
@@ -37,6 +41,10 @@ public Application(WindowsDriver windowsDriver, ITimeoutConfigur
///
public WindowsDriver WindowsDriver { get; }
+ public IKeyboardActions KeyboardActions { get; }
+
+ public IMouseActions MouseActions { get; }
+
///
/// Sets WinAppDriver ImplicitWait timeout.
/// Default value: .
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/ApplicationFactory.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/ApplicationFactory.cs
index b0e634a..7a647be 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/ApplicationFactory.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/ApplicationFactory.cs
@@ -1,5 +1,7 @@
-using Aquality.Selenium.Core.Localization;
-using OpenQA.Selenium.Appium;
+using Aquality.Selenium.Core.Configurations;
+using Aquality.Selenium.Core.Localization;
+using Aquality.WinAppDriver.Configurations;
+using Microsoft.Extensions.DependencyInjection;
using OpenQA.Selenium.Appium.Windows;
using System;
@@ -7,20 +9,28 @@ namespace Aquality.WinAppDriver.Applications
{
public abstract class ApplicationFactory : IApplicationFactory
{
- private readonly LocalizationLogger localizationLogger;
+ private readonly IDriverSettings driverSettings;
+ private readonly ITimeoutConfiguration timeoutConfiguration;
- protected ApplicationFactory(LocalizationLogger localizationLogger)
+ protected LocalizationLogger LocalizationLogger { get; }
+ protected IServiceProvider ServiceProvider { get; }
+
+ protected ApplicationFactory(IServiceProvider serviceProvider)
{
- this.localizationLogger = localizationLogger;
+ LocalizationLogger = serviceProvider.GetRequiredService();
+ driverSettings = serviceProvider.GetRequiredService();
+ timeoutConfiguration = serviceProvider.GetRequiredService();
+ ServiceProvider = serviceProvider;
}
public abstract Application Application { get; }
- protected WindowsDriver GetDriver(Uri driverServerUri, AppiumOptions options, TimeSpan commandTimeout)
+ protected WindowsDriver GetDriver(Uri driverServerUri)
{
+ var options = driverSettings.AppiumOptions;
options.ToDictionary().TryGetValue("app", out var appPath);
- localizationLogger.Info("loc.application.start", appPath);
- return new WindowsDriver(driverServerUri, options, commandTimeout);
+ LocalizationLogger.Info("loc.application.start", appPath);
+ return new WindowsDriver(driverServerUri, options, timeoutConfiguration.Command);
}
}
}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/ApplicationManager.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/ApplicationManager.cs
index 7d8846d..3e818a6 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/ApplicationManager.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/ApplicationManager.cs
@@ -11,6 +11,7 @@
using OpenQA.Selenium.Appium.Service;
using Aquality.Selenium.Core.Logging;
using System.Reflection;
+using Aquality.WinAppDriver.Actions;
namespace Aquality.WinAppDriver.Applications
{
@@ -41,18 +42,57 @@ public static bool TryToStopAppiumLocalService()
///
/// Provides current instance of application
///
- public static Application Application => GetApplication(StartApplicationFunction, () => RegisterServices(services => Application));
+ public static Application Application
+ {
+ get
+ {
+ return GetApplication(StartApplicationFunction, () => RegisterServices(services => Application));
+ }
+ set
+ {
+ SetApplication(value);
+ }
+ }
///
/// Provides access to Aquality services, registered in DI container.
///
- public static IServiceProvider ServiceProvider => GetServiceProvider(services => Application, () => RegisterServices(services => Application));
+ public static IServiceProvider ServiceProvider
+ {
+ get
+ {
+ return GetServiceProvider(services => Application, () => RegisterServices(services => Application));
+ }
+ set
+ {
+ SetServiceProvider(value);
+ }
+ }
+
+ ///
+ /// Factory for application creation.
+ ///
+ public static IApplicationFactory ApplicationFactory
+ {
+ get
+ {
+ if (!ApplicationFactoryContainer.IsValueCreated)
+ {
+ SetDefaultFactory();
+ }
+ return ApplicationFactoryContainer.Value;
+ }
+ set
+ {
+ ApplicationFactoryContainer.Value = value;
+ }
+ }
///
/// Resolves required service from
///
/// type of required service
- /// .
+ /// Thrown if there is no service of the required type.
///
public static T GetRequiredService()
{
@@ -66,30 +106,17 @@ public static T GetRequiredService()
public static void SetDefaultFactory()
{
var appProfile = GetRequiredService();
- var driverSettings = GetRequiredService();
- var localizationLogger = GetRequiredService();
- var timeoutConfiguration = GetRequiredService();
-
IApplicationFactory applicationFactory;
if (appProfile.IsRemote)
{
- applicationFactory = new RemoteApplicationFactory(appProfile.RemoteConnectionUrl, driverSettings, timeoutConfiguration, localizationLogger);
+ applicationFactory = new RemoteApplicationFactory(appProfile.RemoteConnectionUrl, ServiceProvider);
}
else
{
- applicationFactory = new LocalApplicationFactory(AppiumLocalServiceContainer.Value, driverSettings, timeoutConfiguration, localizationLogger);
+ applicationFactory = new LocalApplicationFactory(AppiumLocalServiceContainer.Value, ServiceProvider);
}
- SetFactory(applicationFactory);
- }
-
- ///
- /// Sets custom application factory.
- ///
- /// Custom implementation of
- public static void SetFactory(IApplicationFactory applicationFactory)
- {
- ApplicationFactoryContainer.Value = applicationFactory;
+ ApplicationFactory = applicationFactory;
}
private static IServiceCollection RegisterServices(Func applicationSupplier)
@@ -100,10 +127,12 @@ private static IServiceCollection RegisterServices(Func();
services.AddTransient();
- var driverSettings = new DriverSettings(settingsFile);
- services.AddSingleton(driverSettings);
- services.AddSingleton(new ApplicationProfile(settingsFile, driverSettings));
- services.AddSingleton(new LocalizationManager(new LoggerConfiguration(settingsFile), Logger.Instance, Assembly.GetExecutingAssembly()));
+ services.AddSingleton(serviceProvider => new DriverSettings(settingsFile));
+ services.AddSingleton(serviceProvider => new ApplicationProfile(settingsFile, serviceProvider.GetRequiredService()));
+ services.AddSingleton(serviceProvider => new LocalizationManager(serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService(), Assembly.GetExecutingAssembly()));
+ services.AddSingleton(serviceProvider => new KeyboardActions(serviceProvider.GetRequiredService(), () => Application.WindowsDriver));
+ services.AddSingleton(serviceProvider => new MouseActions(serviceProvider.GetRequiredService(), () => Application.WindowsDriver));
+ services.AddSingleton(serviceProvider => ApplicationFactory);
return services;
}
@@ -111,11 +140,7 @@ private static Func StartApplicationFunction
{
get
{
- if (!ApplicationFactoryContainer.IsValueCreated)
- {
- SetDefaultFactory();
- }
- return (services) => ApplicationFactoryContainer.Value.Application;
+ return (services) => ApplicationFactory.Application;
}
}
}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/LocalApplicationFactory.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/LocalApplicationFactory.cs
index cc4cff7..0f528f7 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/LocalApplicationFactory.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/LocalApplicationFactory.cs
@@ -1,23 +1,17 @@
-using Aquality.Selenium.Core.Configurations;
-using Aquality.Selenium.Core.Localization;
-using Aquality.WinAppDriver.Configurations;
+using Aquality.Selenium.Core.Localization;
using OpenQA.Selenium.Appium.Service;
+using System;
namespace Aquality.WinAppDriver.Applications
{
public class LocalApplicationFactory : ApplicationFactory
{
private readonly AppiumLocalService driverService;
- private readonly IDriverSettings driverSettings;
- private readonly ITimeoutConfiguration timeoutConfiguration;
- private readonly LocalizationLogger localizationLogger;
- public LocalApplicationFactory(AppiumLocalService driverService, IDriverSettings driverSettings, ITimeoutConfiguration timeoutConfiguration, LocalizationLogger localizationLogger) : base(localizationLogger)
+ public LocalApplicationFactory(AppiumLocalService driverService, IServiceProvider serviceProvider)
+ : base(serviceProvider)
{
this.driverService = driverService;
- this.driverSettings = driverSettings;
- this.timeoutConfiguration = timeoutConfiguration;
- this.localizationLogger = localizationLogger;
}
public override Application Application
@@ -26,9 +20,9 @@ public override Application Application
{
driverService.Start();
var serviceUrl = driverService.ServiceUrl;
- localizationLogger.Info("loc.application.driver.service.local.start", serviceUrl);
- var driver = GetDriver(serviceUrl, driverSettings.AppiumOptions, timeoutConfiguration.Command);
- return new Application(driver, timeoutConfiguration, localizationLogger);
+ LocalizationLogger.Info("loc.application.driver.service.local.start", serviceUrl);
+ var driver = GetDriver(serviceUrl);
+ return new Application(driver, ServiceProvider);
}
}
}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/RemoteApplicationFactory.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/RemoteApplicationFactory.cs
index 6bed05e..2622205 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/RemoteApplicationFactory.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Applications/RemoteApplicationFactory.cs
@@ -1,6 +1,4 @@
-using Aquality.Selenium.Core.Configurations;
-using Aquality.Selenium.Core.Localization;
-using Aquality.WinAppDriver.Configurations;
+using Aquality.Selenium.Core.Localization;
using OpenQA.Selenium.Remote;
using System;
@@ -9,26 +7,21 @@ namespace Aquality.WinAppDriver.Applications
public class RemoteApplicationFactory : ApplicationFactory
{
private readonly Uri driverServerUri;
- private readonly IDriverSettings driverSettings;
- private readonly ITimeoutConfiguration timeoutConfiguration;
- private readonly LocalizationLogger localizationLogger;
- public RemoteApplicationFactory(Uri driverServerUri, IDriverSettings driverSettings, ITimeoutConfiguration timeoutConfiguration, LocalizationLogger localizationLogger) : base(localizationLogger)
+ public RemoteApplicationFactory(Uri driverServerUri, IServiceProvider serviceProvider)
+ : base(serviceProvider)
{
this.driverServerUri = driverServerUri;
- this.driverSettings = driverSettings;
- this.timeoutConfiguration = timeoutConfiguration;
- this.localizationLogger = localizationLogger;
}
public override Application Application
{
get
{
- localizationLogger.Info("loc.application.driver.service.remote", driverServerUri);
- var driver = GetDriver(driverServerUri, driverSettings.AppiumOptions, timeoutConfiguration.Command);
+ LocalizationLogger.Info("loc.application.driver.service.remote", driverServerUri);
+ var driver = GetDriver(driverServerUri);
driver.FileDetector = new LocalFileDetector();
- return new Application(driver, timeoutConfiguration, localizationLogger);
+ return new Application(driver, ServiceProvider);
}
}
}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Aquality.WinAppDriver.csproj b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Aquality.WinAppDriver.csproj
index 0c59001..4508ec3 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Aquality.WinAppDriver.csproj
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Aquality.WinAppDriver.csproj
@@ -18,6 +18,11 @@
true
+
+ Aquality.WinAppDriver.xml
+ 1701;1702;1591
+
+
@@ -41,7 +46,7 @@
-
+
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Aquality.WinAppDriver.xml b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Aquality.WinAppDriver.xml
new file mode 100644
index 0000000..b09b64a
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Aquality.WinAppDriver.xml
@@ -0,0 +1,571 @@
+
+
+
+ Aquality.WinAppDriver
+
+
+
+
+ Abstract class for any actions against the whole application.
+
+
+
+
+ Instantiates Aplication actions.
+
+ Logger for localized values.
+ Method to get current application session.
+
+
+
+ Performs submitted action against new object.
+
+ Action to be performed.
+
+
+
+ Logs keyboard action in specific format.
+
+ Key of the localized message.
+ Arguments for the localized message.
+
+
+
+ Provides methods representing basic keyboard actions.
+
+
+
+
+ Presses a key.
+
+ The value representing the key to press.
+
+
+
+ Releases a key.
+
+ The value representing the key to release.
+
+
+
+ Sends a sequence of keystrokes to the target.
+
+ A string representing the keystrokes to send.
+
+
+
+ Sends a sequence of keystrokes to the application, holding a specified key.
+ After the action, holded key is released.
+
+ A string representing the keystrokes to send.
+ The value representing the key to hold.
+
+
+
+ Provides methods representing basic mouse actions.
+
+
+
+
+ Clicks the mouse at the last known mouse coordinates.
+
+
+
+
+ Clicks and holds the mouse button at the last known mouse coordinates.
+
+
+
+
+ Releases the mouse button at the last known mouse coordinates.
+
+
+
+
+ Right-clicks the mouse at the last known mouse coordinates.
+
+
+
+
+ Double-clicks the mouse at the last known mouse coordinates.
+
+
+
+
+ Moves the mouse to the specified offset of the last known mouse coordinates.
+
+ The horizontal offset to which to move the mouse.
+ The vertical offset to which to move the mouse.
+
+
+
+ Scrolls the current screen by specified offset.
+
+ The horizontal offset relative to the view port.
+ The vertical offset relative to the view port.
+
+
+
+ Implements Keyboard actions for the whole application.
+
+
+
+
+ Represents modifier keys which could be used in .
+ Directly related to
+
+
+
+
+ Represents the Alt key.
+
+
+
+
+ Represents the function key COMMAND.
+
+
+
+
+ Represents the Control key.
+
+
+
+
+ Represents the Left Alt key.
+
+
+
+
+ Represents the Left Control key.
+
+
+
+
+ Represents the Left Shift key.
+
+
+
+
+ Represents the function key META.
+
+
+
+
+ Represents the Shift key.
+
+
+
+
+ Implements Mouse actions for the whole application.
+
+
+
+
+ Provides functionality to work with Windows application via WinAppDriver.
+
+
+
+
+ Instantiate application.
+
+ Instance of WinAppDriver
+ Service provider to resolve all dependencies from DI container
+
+
+
+ Provides instance of Windows Driver
+
+
+
+
+ Sets WinAppDriver ImplicitWait timeout.
+ Default value: .
+
+ Desired Implicit wait timeout.
+
+
+
+ Quit application.
+
+
+
+
+ Controls application and Aquality services
+
+
+
+
+ Stops appium local service.
+
+ True if service was running, false otherwise
+
+
+
+ Provides current instance of application
+
+
+
+
+ Provides access to Aquality services, registered in DI container.
+
+
+
+
+ Factory for application creation.
+
+
+
+
+ Resolves required service from
+
+ type of required service
+ Thrown if there is no service of the required type.
+
+
+
+
+ Sets default factory responsible for application creation.
+ RemoteApplicationFactory if value set in configuration and LocalApplicationFactory otherwise.
+
+
+
+
+ Provides application profile.
+
+
+
+
+ Instantiates class using JSON file with general settings.
+
+ JSON settings file.
+ Instance of
+
+
+
+ Provides target application profile.
+
+
+
+
+ Instantiates class using JSON file with general settings.
+
+ JSON settings file.
+
+
+
+ Defines does the current settings have the application path defined
+
+
+
+
+ Describes application settings.
+
+
+
+
+ Is remote WinAppDriver service or not: true to use and false to create default .
+
+
+
+
+ Gets remote connection URI is case of remote browser.
+
+
+
+
+ Gets WinAppDriver settings for application.
+
+
+
+
+ Describes WinAppDriver settings.
+
+
+
+
+ Gets desired WinAppDriver options
+
+
+
+
+ Provides a path to the application
+
+
+
+
+ Abstract class for any actions agains element.
+
+
+
+
+ Instantiates Element actions for a specific element.
+
+ Target element.
+ Target element's type.
+ Method to get current application session.
+ Logger for localized values.
+ Retrier for element actions.
+
+
+
+ Performs submitted action against new object.
+
+ Action to be performed.
+
+
+
+ Logs element action in specific format.
+
+ Key of the localized message.
+ Arguments for the localized message.
+
+
+
+ Provides methods representing basic mouse actions against the current element.
+ Current element's coordinates are user as last known mouse coordinates.
+
+
+
+
+ Performs a drag-and-drop operation on the current element; drops it on target element.
+
+ The element on which the drop is performed.
+
+
+
+ Performs a drag-and-drop operation on the current element to a specified offset.
+
+ The horizontal offset to which to move the mouse.
+ The vertical offset to which to move the mouse.
+
+
+
+ Moves the current element to a specified offset. Works the same as to
+
+ The horizontal offset to which to move the mouse.
+ The vertical offset to which to move the mouse.
+
+
+
+ Moves the mouse from the current element.
+
+
+
+
+ Moves the mouse to the current element.
+
+
+
+
+ Moves the mouse to the specified offset of the top-left corner of the current element.
+
+ The horizontal offset to which to move the mouse.
+ The vertical offset to which to move the mouse.
+
+
+
+ Moves the mouse to the specified offset of specified offset origin of the current element.
+
+ The horizontal offset to which to move the mouse.
+ The vertical offset to which to move the mouse.
+ The value from which to calculate the offset.
+
+
+
+ Scrolls the current screen by specified offset, starting from the current element.
+
+
+
+
+
+
+ Implements Keyboard actions for a specific element.
+
+
+
+
+ Instantiates Keyboard actions for a specific element.
+
+ Target element.
+ Target element's type.
+ Method to get current application session.
+ Logger for localized values.
+ Retrier for element actions.
+
+
+
+ Implements Mouse actions for a specific element.
+
+
+
+
+ Instantiates Mouse actions for a specific element.
+
+ Target element.
+ Target element's type.
+ Method to get current application session.
+ Logger for localized values.
+ Retrier for element actions.
+
+
+
+ Defines Button UI element.
+
+
+
+
+ Factory that creates elements.
+
+
+
+
+ Describes behavior of Button UI element.
+
+
+
+
+ Descibes behavior of any application element.
+
+
+
+
+ Provides access to against the current element.
+
+
+
+
+ Provides access to against the current element.
+
+
+
+
+ Defines the interface used to create the windows application's elements.
+
+
+
+
+ Creates element that implements IButton interface.
+
+ Element locator
+ Element name
+ Instance of element that implements IButton interface
+
+
+
+ Creates element that implements ILabel interface.
+
+ Element locator
+ Element name
+ Instance of element that implements ILabel interface
+
+
+
+ Creates element that implements ITextBox interface.
+
+ Element locator
+ Element name
+ Instance of element that implements ITextBox interface
+
+
+
+ Describes behavior of Label UI element.
+
+
+
+
+ Describes behavior of TextBox UI element.
+
+
+
+
+ Gets text value of an element.
+
+ String representation of element's value
+
+
+
+ Type text in an element.
+
+ Text to type.
+ Should the typing text be hidden in logs or not. False by default.
+
+
+
+ Clear element text and type value.
+
+ Text to type.
+ Should the typing text be hidden in logs or not. False by default.
+
+
+
+ Defines Label UI element.
+
+
+
+
+ Defines TextBox UI element.
+
+
+
+
+ Provides extension methods for classes.
+
+
+
+
+ element.GetType().Name provides a non-localized name;
+ ElementType property is localized, but has the protected access and is not defined in the IElement interface.
+ So current method allows to get ElementType if the current element is assignable from
+
+
+
+
+
+
+ Defines base class for any application's window.
+
+
+
+
+ Constructor with parameters.
+
+ Unique locator of the window.
+ Name of the window.
+
+
+
+ Locator of specified window.
+
+
+
+
+ Name of specified window.
+
+
+
+
+ Instance of logger
+
+ Logger instance.
+
+
+
+ Element factory
+
+ Element factory.
+
+
+
+ Return window state for window locator
+
+ True - window is opened,
+ False - window is not opened.
+
+
+
+ Gets size of window element defined by its locator.
+
+
+
+
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Configurations/ApplicationProfile.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Configurations/ApplicationProfile.cs
index 19098ca..9bd75cc 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Configurations/ApplicationProfile.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Configurations/ApplicationProfile.cs
@@ -12,6 +12,7 @@ public class ApplicationProfile : IApplicationProfile
/// Instantiates class using JSON file with general settings.
///
/// JSON settings file.
+ /// Instance of
public ApplicationProfile(JsonFile settingsFile, IDriverSettings driverSettings)
{
SettingsFile = settingsFile;
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/ElementActions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/ElementActions.cs
new file mode 100644
index 0000000..d72d988
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/ElementActions.cs
@@ -0,0 +1,61 @@
+using Aquality.Selenium.Core.Applications;
+using Aquality.Selenium.Core.Localization;
+using Aquality.Selenium.Core.Utilities;
+using Aquality.WinAppDriver.Elements.Interfaces;
+using OpenQA.Selenium;
+using System;
+using SeleniumActions = OpenQA.Selenium.Interactions.Actions;
+
+namespace Aquality.WinAppDriver.Elements.Actions
+{
+ ///
+ /// Abstract class for any actions agains element.
+ ///
+ public abstract class ElementActions
+ {
+ private readonly IElement element;
+ private readonly string elementType;
+ private readonly Func applicationSupplier;
+ private readonly LocalizationLogger localizationLogger;
+ private readonly ElementActionRetrier elementActionsRetrier;
+
+ ///
+ /// Instantiates Element actions for a specific element.
+ ///
+ /// Target element.
+ /// Target element's type.
+ /// Method to get current application session.
+ /// Logger for localized values.
+ /// Retrier for element actions.
+ protected ElementActions(IElement element, string elementType, Func applicationSupplier, LocalizationLogger localizationLogger, ElementActionRetrier elementActionsRetrier)
+ {
+ this.element = element;
+ this.elementType = elementType;
+ this.applicationSupplier = applicationSupplier;
+ this.localizationLogger = localizationLogger;
+ this.elementActionsRetrier = elementActionsRetrier;
+ }
+
+ ///
+ /// Performs submitted action against new object.
+ ///
+ /// Action to be performed.
+ protected virtual void PerformAction(Func action)
+ {
+ elementActionsRetrier.DoWithRetry(() =>
+ {
+ action(new SeleniumActions(applicationSupplier().Driver), element.GetElement()).Build().Perform();
+ });
+ }
+
+ ///
+ /// Logs element action in specific format.
+ ///
+ /// Key of the localized message.
+ /// Arguments for the localized message.
+ protected virtual void LogAction(string messageKey, params object[] args)
+ {
+ localizationLogger.InfoElementAction(elementType, element.Name, messageKey, args);
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/IMouseActions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/IMouseActions.cs
new file mode 100644
index 0000000..5f9db93
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/IMouseActions.cs
@@ -0,0 +1,64 @@
+using Aquality.WinAppDriver.Elements.Interfaces;
+using OpenQA.Selenium.Interactions;
+
+namespace Aquality.WinAppDriver.Elements.Actions
+{
+ ///
+ /// Provides methods representing basic mouse actions against the current element.
+ /// Current element's coordinates are user as last known mouse coordinates.
+ ///
+ public interface IMouseActions : WinAppDriver.Actions.IMouseActions
+ {
+ ///
+ /// Performs a drag-and-drop operation on the current element; drops it on target element.
+ ///
+ /// The element on which the drop is performed.
+ void DragAndDrop(IElement target);
+
+ ///
+ /// Performs a drag-and-drop operation on the current element to a specified offset.
+ ///
+ /// The horizontal offset to which to move the mouse.
+ /// The vertical offset to which to move the mouse.
+ void DragAndDropToOffset(int offsetX, int offsetY);
+
+ ///
+ /// Moves the current element to a specified offset. Works the same as to
+ ///
+ /// The horizontal offset to which to move the mouse.
+ /// The vertical offset to which to move the mouse.
+ new void MoveByOffset(int offsetX, int offsetY);
+
+ ///
+ /// Moves the mouse from the current element.
+ ///
+ void MoveFromElement();
+
+ ///
+ /// Moves the mouse to the current element.
+ ///
+ void MoveToElement();
+
+ ///
+ /// Moves the mouse to the specified offset of the top-left corner of the current element.
+ ///
+ /// The horizontal offset to which to move the mouse.
+ /// The vertical offset to which to move the mouse.
+ void MoveToElement(int offsetX, int offsetY);
+
+ ///
+ /// Moves the mouse to the specified offset of specified offset origin of the current element.
+ ///
+ /// The horizontal offset to which to move the mouse.
+ /// The vertical offset to which to move the mouse.
+ /// The value from which to calculate the offset.
+ void MoveToElement(int offsetX, int offsetY, MoveToElementOffsetOrigin offsetOrigin);
+
+ ///
+ /// Scrolls the current screen by specified offset, starting from the current element.
+ ///
+ ///
+ ///
+ new void Scroll(int offsetX, int offsetY);
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/KeyboardActions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/KeyboardActions.cs
new file mode 100644
index 0000000..922bd0f
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/KeyboardActions.cs
@@ -0,0 +1,53 @@
+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 System;
+
+namespace Aquality.WinAppDriver.Elements.Actions
+{
+ ///
+ /// Implements Keyboard actions for a specific element.
+ ///
+ public class KeyboardActions : ElementActions, IKeyboardActions
+ {
+ ///
+ /// Instantiates Keyboard actions for a specific element.
+ ///
+ /// Target element.
+ /// Target element's type.
+ /// Method to get current application session.
+ /// Logger for localized values.
+ /// Retrier for element actions.
+ public KeyboardActions(IElement element, string elementType, Func applicationSupplier, LocalizationLogger localizationLogger, ElementActionRetrier elementActionsRetrier)
+ : base(element, elementType, applicationSupplier, localizationLogger, elementActionsRetrier)
+ {
+ }
+
+ public void PressKey(ModifierKey keyToPress)
+ {
+ LogAction("loc.keyboard.presskey", keyToPress);
+ PerformAction((actions, element) => actions.KeyDown(element, keyToPress.GetKeysString()));
+ }
+
+ public void ReleaseKey(ModifierKey keyToRelease)
+ {
+ LogAction("loc.keyboard.releasekey", keyToRelease);
+ PerformAction((actions, element) => actions.KeyUp(element, keyToRelease.GetKeysString()));
+ }
+
+ public void SendKeys(string keySequence)
+ {
+ LogAction("loc.keyboard.sendkeys", keySequence);
+ PerformAction((actions, element) => actions.SendKeys(element, keySequence));
+ }
+
+ public void SendKeysWithKeyHold(string keySequence, ModifierKey keyToHold)
+ {
+ var keyToHoldString = keyToHold.GetKeysString();
+ LogAction("loc.keyboard.sendkeys.withkeyhold", keySequence, keyToHold);
+ PerformAction((actions, element) => actions.KeyDown(element, keyToHoldString).SendKeys(element, keySequence).KeyUp(element, keyToHoldString));
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/MouseActions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/MouseActions.cs
new file mode 100644
index 0000000..5c4cf57
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Actions/MouseActions.cs
@@ -0,0 +1,114 @@
+using Aquality.Selenium.Core.Applications;
+using Aquality.Selenium.Core.Localization;
+using Aquality.Selenium.Core.Utilities;
+using Aquality.WinAppDriver.Elements.Interfaces;
+using Aquality.WinAppDriver.Extensions;
+using OpenQA.Selenium.Interactions;
+using OpenQA.Selenium.Remote;
+using System;
+
+namespace Aquality.WinAppDriver.Elements.Actions
+{
+ ///
+ /// Implements Mouse actions for a specific element.
+ ///
+ public class MouseActions : ElementActions, IMouseActions
+ {
+ private readonly IElement element;
+ private readonly Func remoteTouchScreenSupplier;
+
+ ///
+ /// Instantiates Mouse actions for a specific element.
+ ///
+ /// Target element.
+ /// Target element's type.
+ /// Method to get current application session.
+ /// Logger for localized values.
+ /// Retrier for element actions.
+ public MouseActions(IElement element, string elementType, Func applicationSupplier, LocalizationLogger localizationLogger, ElementActionRetrier elementActionsRetrier)
+ : base(element, elementType, applicationSupplier, localizationLogger, elementActionsRetrier)
+ {
+ this.element = element;
+ remoteTouchScreenSupplier = () => new RemoteTouchScreen(applicationSupplier().Driver);
+ }
+
+ public void Click()
+ {
+ LogAction("loc.mouse.click");
+ PerformAction((actions, element) => actions.Click(element));
+ }
+
+ public void ClickAndHold()
+ {
+ LogAction("loc.mouse.clickandhold");
+ PerformAction((actions, element) => actions.ClickAndHold(element));
+ }
+
+ public void Release()
+ {
+ LogAction("loc.mouse.release");
+ PerformAction((actions, element) => actions.Release(element));
+ }
+
+ public void ContextClick()
+ {
+ LogAction("loc.mouse.contextclick");
+ PerformAction((actions, element) => actions.ContextClick(element));
+ }
+
+ public void DoubleClick()
+ {
+ LogAction("loc.mouse.doubleclick");
+ PerformAction((actions, element) => actions.DoubleClick(element));
+ }
+
+ public void MoveByOffset(int offsetX, int offsetY)
+ {
+ DragAndDropToOffset(offsetX, offsetY);
+ }
+
+ public void DragAndDrop(IElement target)
+ {
+ LogAction("loc.mouse.draganddrop", target.GetElementType(), target.Name);
+ PerformAction((actions, element) => actions.DragAndDrop(element, target.GetElement()));
+ }
+
+ public void DragAndDropToOffset(int offsetX, int offsetY)
+ {
+ LogAction("loc.mouse.draganddrop.tooffset", offsetX, offsetY);
+ PerformAction((actions, element) => actions.DragAndDropToOffset(element, offsetX, offsetY));
+ }
+
+ public void MoveFromElement()
+ {
+ var offsetX = - element.GetElement().Size.Width / 2;
+ var offsetY = - element.GetElement().Size.Height / 2;
+ LogAction("loc.mouse.movefromelement", offsetX, offsetY);
+ PerformAction((actions, element) => actions.MoveToElement(element, offsetX, offsetY));
+ }
+
+ public void MoveToElement()
+ {
+ LogAction("loc.mouse.movetoelement");
+ PerformAction((actions, element) => actions.MoveToElement(element));
+ }
+
+ public void MoveToElement(int offsetX, int offsetY)
+ {
+ LogAction("loc.mouse.movetoelement.byoffset", offsetX, offsetY);
+ PerformAction((actions, element) => actions.MoveToElement(element, offsetX, offsetY));
+ }
+
+ public void MoveToElement(int offsetX, int offsetY, MoveToElementOffsetOrigin offsetOrigin)
+ {
+ LogAction("loc.mouse.movetoelement.byoffset.withorigin", offsetX, offsetY, offsetOrigin);
+ PerformAction((actions, element) => actions.MoveToElement(element, offsetX, offsetY, offsetOrigin));
+ }
+
+ public void Scroll(int offsetX, int offsetY)
+ {
+ LogAction("loc.mouse.scrollbyoffset", offsetX, offsetY);
+ remoteTouchScreenSupplier().Scroll(element.GetElement().Coordinates, offsetX, offsetY);
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Element.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Element.cs
index 801ce0f..dcb7241 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Element.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Element.cs
@@ -4,15 +4,17 @@
using Aquality.Selenium.Core.Utilities;
using Aquality.Selenium.Core.Waitings;
using Aquality.WinAppDriver.Applications;
+using Aquality.WinAppDriver.Elements.Actions;
using Aquality.WinAppDriver.Elements.Interfaces;
using OpenQA.Selenium;
+using IKeyboardActions = Aquality.WinAppDriver.Actions.IKeyboardActions;
using CoreElement = Aquality.Selenium.Core.Elements.Element;
using CoreElementFactory = Aquality.Selenium.Core.Elements.Interfaces.IElementFactory;
using CoreElementFinder = Aquality.Selenium.Core.Elements.Interfaces.IElementFinder;
namespace Aquality.WinAppDriver.Elements
{
- public abstract class Element : CoreElement
+ public abstract class Element : CoreElement, IElement
{
protected Element(By locator, string name) : base(locator, name, ElementState.Displayed)
{
@@ -26,7 +28,11 @@ protected Element(By locator, string name) : base(locator, name, ElementState.Di
protected override CoreElementFactory Factory => CustomFactory;
- protected IElementFactory CustomFactory => ApplicationManager.GetRequiredService();
+ protected virtual IElementFactory CustomFactory => ApplicationManager.GetRequiredService();
+
+ public virtual IKeyboardActions KeyboardActions => new KeyboardActions(this, ElementType, () => Application, LocalizationLogger, ActionRetrier);
+
+ public virtual IMouseActions MouseActions => new MouseActions(this, ElementType, () => Application, LocalizationLogger, ActionRetrier);
public T FindChildElement(By childLocator, ElementSupplier supplier = null) where T : IElement
{
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Interfaces/IElement.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Interfaces/IElement.cs
index f059d7b..9416781 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Interfaces/IElement.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Interfaces/IElement.cs
@@ -1,8 +1,22 @@
-using CoreElement = Aquality.Selenium.Core.Elements.Interfaces.IElement;
+using Aquality.WinAppDriver.Elements.Actions;
+using CoreElement = Aquality.Selenium.Core.Elements.Interfaces.IElement;
+using IKeyboardActions = Aquality.WinAppDriver.Actions.IKeyboardActions;
namespace Aquality.WinAppDriver.Elements.Interfaces
{
+ ///
+ /// Descibes behavior of any application element.
+ ///
public interface IElement : CoreElement
{
+ ///
+ /// Provides access to against the current element.
+ ///
+ IKeyboardActions KeyboardActions { get; }
+
+ ///
+ /// Provides access to against the current element.
+ ///
+ IMouseActions MouseActions { get; }
}
}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Interfaces/IElementFactory.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Interfaces/IElementFactory.cs
index dc651fd..57407dd 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Interfaces/IElementFactory.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Elements/Interfaces/IElementFactory.cs
@@ -21,7 +21,6 @@ public interface IElementFactory : CoreElementFactory
///
/// Element locator
/// Element name
- /// Element state
/// Instance of element that implements ILabel interface
ILabel GetLabel(By locator, string name);
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Extensions/ElementExtensions.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Extensions/ElementExtensions.cs
new file mode 100644
index 0000000..abe7a89
--- /dev/null
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Extensions/ElementExtensions.cs
@@ -0,0 +1,30 @@
+using Aquality.Selenium.Core.Elements;
+using Aquality.WinAppDriver.Elements.Interfaces;
+using System.Reflection;
+
+namespace Aquality.WinAppDriver.Extensions
+{
+ ///
+ /// Provides extension methods for classes.
+ ///
+ internal static class ElementExtensions
+ {
+ ///
+ /// element.GetType().Name provides a non-localized name;
+ /// ElementType property is localized, but has the protected access and is not defined in the IElement interface.
+ /// So current method allows to get ElementType if the current element is assignable from
+ ///
+ ///
+ ///
+ internal static string GetElementType(this IElement element)
+ {
+ string elementType = null;
+ if (typeof(Element).IsAssignableFrom(element.GetType()))
+ {
+ elementType = element.GetType().GetProperty("ElementType", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(element).ToString();
+ }
+
+ return elementType ?? element.GetType().Name;
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/be.json b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/be.json
index 1cfb140..a7b06d4 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/be.json
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/be.json
@@ -17,5 +17,22 @@
"loc.label": "Надпіс",
"loc.text.field": "Тэкставае поле",
"loc.text.clearing": "Aчышчаем",
- "loc.text.typing": "Уводзім значэнне '{0}'"
+ "loc.text.typing": "Уводзім значэнне '{0}'",
+ "loc.keyboard.presskey": "Заціскаем клавішу '{0}'",
+ "loc.keyboard.releasekey": "Адпускаем клавішу '{0}'",
+ "loc.keyboard.sendkeys": "Націскаем клавішы '{0}'",
+ "loc.keyboard.sendkeys.withkeyhold": "Націскаем клавішы '{0}' з заціснутай клавішай '{1}'",
+ "loc.mouse.click": "Націскаем кнопку мышы",
+ "loc.mouse.clickandhold": "Заціскаем кнопку мышы",
+ "loc.mouse.release": "Адпускаем кнопку мышы",
+ "loc.mouse.contextclick": "Націскаем правую кнопку мышы",
+ "loc.mouse.doubleclick": "Падвойна націскаем кнопку мышы",
+ "loc.mouse.movebyoffset": "Перамяшчаем курсор мышы на '{0}' пунктаў па вертыкалі і '{1}' пунктаў па гарызанталі",
+ "loc.mouse.draganddrop": "Перамяшчаем курсор мышы да элемента '{0} '{1}''",
+ "loc.mouse.draganddrop.tooffset": "Перамяшчаем курсор мышы на '{0}' пунктаў па вертыкалі і '{1}' пунктаў па гарызанталі",
+ "loc.mouse.movefromelement": "Адводзім курсор мышы ад элемента",
+ "loc.mouse.movetoelement": "Наводзім курсор мышы на элемент",
+ "loc.mouse.movetoelement.byoffset": "Наводзім курсор мышы на элемент са змяшчэннем на '{0}' пунктаў па вертыкалі і '{1}' пунктаў па гарызанталі",
+ "loc.mouse.movetoelement.byoffset.withorigin": "Наводзім курсор мышы на элемент са змяшчэннем на '{0}' пунктаў па вертыкалі і '{1}' пунктаў па гарызанталі, пачынаючы ад '{2}'",
+ "loc.mouse.scrollbyoffset": "Пракручваем кольца мышы на '{0}' пунктаў па вертыкалі і '{1}' пунктаў па гарызанталі"
}
\ No newline at end of file
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/en.json b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/en.json
index 67e7054..84bac09 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/en.json
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/en.json
@@ -17,5 +17,22 @@
"loc.label": "Label",
"loc.text.field": "Text Field",
"loc.text.clearing": "Clearing",
- "loc.text.typing": "Typing '{0}'"
+ "loc.text.typing": "Typing '{0}'",
+ "loc.keyboard.presskey": "Pressing key '{0}'",
+ "loc.keyboard.releasekey": "Releasing key '{0}'",
+ "loc.keyboard.sendkeys": "Sending keys '{0}'",
+ "loc.keyboard.sendkeys.withkeyhold": "Sending keys '{0}' with holded key '{1}'",
+ "loc.mouse.click": "Clicking mouse button",
+ "loc.mouse.clickandhold": "Holding mouse button",
+ "loc.mouse.release": "Releasing mouse button",
+ "loc.mouse.contextclick": "Clicking right mouse button",
+ "loc.mouse.doubleclick": "Double-clicking mouse button",
+ "loc.mouse.movebyoffset": "Moving mouse by '{0}' vertical and '{1}' horizontal offset",
+ "loc.mouse.draganddrop": "Drag-and-drop to element '{0} '{1}''",
+ "loc.mouse.draganddrop.tooffset": "Drag-and-drop to '{0}' vertical and '{1}' horizontal offset",
+ "loc.mouse.movefromelement": "Moving mouse from element",
+ "loc.mouse.movetoelement": "Moving mouse to element",
+ "loc.mouse.movetoelement.byoffset": "Moving mouse to element by '{0}' vertical and '{1}' horizontal offset",
+ "loc.mouse.movetoelement.byoffset.withorigin": "Moving mouse to element by '{0}' vertical and '{1}' horizontal offset with origin at '{2}'",
+ "loc.mouse.scrollbyoffset": "Scroll mouse wheel by '{0}' vertical and '{1}' horizontal offset"
}
\ No newline at end of file
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/ru.json b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/ru.json
index 835bca8..ec379db 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/ru.json
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Resources/Localization/ru.json
@@ -17,5 +17,22 @@
"loc.label": "Надпись",
"loc.text.field": "Текстовое поле",
"loc.text.clearing": "Очищаем",
- "loc.text.typing": "Вводим значение '{0}'"
+ "loc.text.typing": "Вводим значение '{0}'",
+ "loc.keyboard.presskey": "Зажимаем клавишу '{0}'",
+ "loc.keyboard.releasekey": "Отпускаем клавишу '{0}'",
+ "loc.keyboard.sendkeys": "Нажимаем клавиши '{0}'",
+ "loc.keyboard.sendkeys.withkeyhold": "Нажимаем клавиши '{0}' с зажатой клавишей '{1}'",
+ "loc.mouse.click": "Щёлкаем кнопку мыши",
+ "loc.mouse.clickandhold": "Зажимаем кнопку мыши",
+ "loc.mouse.release": "Отпускаем кнопку мыши",
+ "loc.mouse.contextclick": "Щёлкаем правую кнопку мыши",
+ "loc.mouse.doubleclick": "Дважды щёлкаем кнопку мыши",
+ "loc.mouse.movebyoffset": "Перемещаем курсор мыши на '{0}' пунктов по вертикали и '{1}' пунктов по горизонтали",
+ "loc.mouse.draganddrop": "Перемещаем к элементу '{0} '{1}''",
+ "loc.mouse.draganddrop.tooffset": "Перемещаем на '{0}' пунктов по вертикали и '{1}' пунктов по горизонтали",
+ "loc.mouse.movefromelement": "Отводим курсор мыши от элемента",
+ "loc.mouse.movetoelement": "Наводим курсор мыши на элемент",
+ "loc.mouse.movetoelement.byoffset": "Наводим курсор мыши на элемент со смещением на '{0}' пунктов по вертикали и '{1}' пунктов по горизонтали",
+ "loc.mouse.movetoelement.byoffset.withorigin": "Наводим курсор мыши на элемент со смещением на '{0}' пунктов по вертикали и '{1}' пунктов по горизонтали, отсчитывая от '{2}'",
+ "loc.mouse.scrollbyoffset": "Прокручиваем колёсико мыши на '{0}' пунктов по вертикали и '{1}' пунктов по горизонтали"
}
\ No newline at end of file
diff --git a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Windows/Window.cs b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Windows/Window.cs
index d72703e..4dc3748 100644
--- a/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Windows/Window.cs
+++ b/Aquality.WinAppDriver/src/Aquality.WinAppDriver/Windows/Window.cs
@@ -34,13 +34,13 @@ protected Window(By locator, string name)
public string Name { get; }
///
- /// Instance of logger
+ /// Instance of logger
///
/// Logger instance.
protected Logger Logger => ApplicationManager.GetRequiredService();
///
- /// Element factory
+ /// Element factory
///
/// Element factory.
protected IElementFactory ElementFactory => ApplicationManager.GetRequiredService();
diff --git a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Actions/KeyboardActionsTests.cs b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Actions/KeyboardActionsTests.cs
new file mode 100644
index 0000000..e9184ad
--- /dev/null
+++ b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Actions/KeyboardActionsTests.cs
@@ -0,0 +1,64 @@
+using Aquality.WinAppDriver.Actions;
+using Aquality.WinAppDriver.Applications;
+using Aquality.WinAppDriver.Elements.Interfaces;
+using Aquality.WinAppDriver.Tests.Applications.Locators;
+using NUnit.Framework;
+using System;
+
+namespace Aquality.WinAppDriver.Tests.Actions
+{
+ public class KeyboardActionsTests : TestWithApplication
+ {
+ private const string ValueToSend = "abc";
+
+ protected virtual IKeyboardActions KeyboardActions => ApplicationManager.GetRequiredService();
+
+ protected ITextBox RightArgumentTextBox => new CalculatorWindow().RightArgumentTextBox;
+
+ protected static readonly ModifierKey[] modifierKeys = Enum.GetValues(typeof(ModifierKey)) as ModifierKey[];
+
+ [Test]
+ public void Should_SendKeys_ViaKeyboardActions()
+ {
+ RightArgumentTextBox.Click();
+ KeyboardActions.SendKeys(ValueToSend);
+ Assert.AreEqual(ValueToSend, RightArgumentTextBox.Value);
+ }
+
+ [Test]
+ public void Should_PressKey_ViaKeyboardActions()
+ {
+ RightArgumentTextBox.Click();
+ KeyboardActions.PressKey(ModifierKey.Shift);
+ KeyboardActions.SendKeys(ValueToSend);
+ KeyboardActions.ReleaseKey(ModifierKey.Shift);
+ Assert.AreEqual(ValueToSend.ToUpper(), RightArgumentTextBox.Value);
+ }
+
+ [Test]
+ public void Should_SendKeysWithKeyHold_ViaKeyboardActions()
+ {
+ RightArgumentTextBox.Click();
+ KeyboardActions.SendKeysWithKeyHold(ValueToSend, ModifierKey.Shift);
+ Assert.AreEqual(ValueToSend.ToUpper(), RightArgumentTextBox.Value);
+ }
+
+ [Test]
+ public void Should_ReleaseKey_ViaKeyboardActions()
+ {
+ RightArgumentTextBox.Click();
+ KeyboardActions.PressKey(ModifierKey.Shift);
+ KeyboardActions.SendKeys(ValueToSend);
+ KeyboardActions.ReleaseKey(ModifierKey.Shift);
+ KeyboardActions.SendKeys(ValueToSend);
+ Assert.AreEqual($"{ValueToSend.ToUpper()}{ValueToSend}", RightArgumentTextBox.Value);
+ }
+
+ [Test]
+ public void Should_NotThrow_WhenHoldModifierKeys_ViaKeyboardActions([ValueSource(nameof(modifierKeys))] ModifierKey modifierKey)
+ {
+ RightArgumentTextBox.Click();
+ Assert.DoesNotThrow(() => KeyboardActions.SendKeysWithKeyHold(ValueToSend, modifierKey));
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Actions/MouseActionsTests.cs b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Actions/MouseActionsTests.cs
new file mode 100644
index 0000000..a948783
--- /dev/null
+++ b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Actions/MouseActionsTests.cs
@@ -0,0 +1,31 @@
+using Aquality.WinAppDriver.Actions;
+using Aquality.WinAppDriver.Applications;
+using Aquality.WinAppDriver.Elements.Interfaces;
+using Aquality.WinAppDriver.Tests.Applications.Locators;
+using NUnit.Framework;
+
+namespace Aquality.WinAppDriver.Tests.Actions
+{
+ public class MouseActionsTests : TestWithApplication
+ {
+ protected virtual IMouseActions MouseActions => ApplicationManager.GetRequiredService();
+
+ protected ITextBox RightArgumentTextBox => new CalculatorWindow().RightArgumentTextBox;
+
+ [Test]
+ public void Should_PerformMouseActions()
+ {
+ RightArgumentTextBox.Click();
+ Assert.DoesNotThrow(() =>
+ {
+ MouseActions.Click();
+ MouseActions.ClickAndHold();
+ MouseActions.Release();
+ MouseActions.ContextClick();
+ MouseActions.DoubleClick();
+ MouseActions.MoveByOffset(10, 10);
+ MouseActions.Scroll(10, 10);
+ });
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/KeyboardActionsTests.cs b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/KeyboardActionsTests.cs
new file mode 100644
index 0000000..faaa143
--- /dev/null
+++ b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/KeyboardActionsTests.cs
@@ -0,0 +1,10 @@
+using Aquality.WinAppDriver.Actions;
+using Aquality.WinAppDriver.Applications;
+
+namespace Aquality.WinAppDriver.Tests.Applications
+{
+ public class KeyboardActionsTests : Actions.KeyboardActionsTests
+ {
+ protected override IKeyboardActions KeyboardActions => ApplicationManager.Application.KeyboardActions;
+ }
+}
diff --git a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/Locators/CalculatorWindow.cs b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/Locators/CalculatorWindow.cs
index 4d5bbbc..dbefe7e 100644
--- a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/Locators/CalculatorWindow.cs
+++ b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/Locators/CalculatorWindow.cs
@@ -9,6 +9,8 @@ public class CalculatorWindow : Window
{
private static By WindowLocator => By.TagName("Window");
+ public ITextBox LeftArgumentTextBox => ElementFactory.GetTextBox(MobileBy.AccessibilityId("50"), "Left Argument");
+
public ITextBox RightArgumentTextBox => ElementFactory.GetTextBox(By.XPath("//*[@AutomationId='49']"), "Right Argument");
public IButton OneButton => ElementFactory.GetButton(By.Name("1"), "1");
diff --git a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/MouseActionsTests.cs b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/MouseActionsTests.cs
new file mode 100644
index 0000000..f92483a
--- /dev/null
+++ b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Applications/MouseActionsTests.cs
@@ -0,0 +1,10 @@
+using Aquality.WinAppDriver.Actions;
+using Aquality.WinAppDriver.Applications;
+
+namespace Aquality.WinAppDriver.Tests.Applications
+{
+ public class MouseActionsTests : Actions.MouseActionsTests
+ {
+ protected override IMouseActions MouseActions => ApplicationManager.Application.MouseActions;
+ }
+}
diff --git a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Elements/Actions/KeyboardActionsTests.cs b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Elements/Actions/KeyboardActionsTests.cs
new file mode 100644
index 0000000..8f0e79e
--- /dev/null
+++ b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Elements/Actions/KeyboardActionsTests.cs
@@ -0,0 +1,9 @@
+using Aquality.WinAppDriver.Actions;
+
+namespace Aquality.WinAppDriver.Tests.Elements.Actions
+{
+ public class KeyboardActionsTests : Tests.Actions.KeyboardActionsTests
+ {
+ protected override IKeyboardActions KeyboardActions => RightArgumentTextBox.KeyboardActions;
+ }
+}
diff --git a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Elements/Actions/MouseActionsTests.cs b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Elements/Actions/MouseActionsTests.cs
new file mode 100644
index 0000000..701d241
--- /dev/null
+++ b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Elements/Actions/MouseActionsTests.cs
@@ -0,0 +1,32 @@
+using Aquality.WinAppDriver.Actions;
+using Aquality.WinAppDriver.Elements.Interfaces;
+using Aquality.WinAppDriver.Tests.Applications.Locators;
+using NUnit.Framework;
+using OpenQA.Selenium.Interactions;
+
+namespace Aquality.WinAppDriver.Tests.Elements.Actions
+{
+ public class MouseActionsTests : Tests.Actions.MouseActionsTests
+ {
+ protected override IMouseActions MouseActions => RightArgumentTextBox.MouseActions;
+ private ITextBox LeftArgumentTextBox => new CalculatorWindow().LeftArgumentTextBox;
+
+ [Test]
+ public void Should_PerformElementSpecificMouseActions()
+ {
+ RightArgumentTextBox.Click();
+ Assert.DoesNotThrow(() =>
+ {
+ RightArgumentTextBox.MouseActions.DragAndDrop(LeftArgumentTextBox);
+ RightArgumentTextBox.MouseActions.DragAndDropToOffset(10, 10);
+ RightArgumentTextBox.MouseActions.MoveByOffset(10, 10);
+ RightArgumentTextBox.MouseActions.MoveFromElement();
+ RightArgumentTextBox.MouseActions.MoveToElement();
+ RightArgumentTextBox.MouseActions.MoveToElement(10, 10);
+ RightArgumentTextBox.MouseActions.MoveToElement(10, 10, MoveToElementOffsetOrigin.Center);
+ RightArgumentTextBox.MouseActions.MoveToElement(10, 10, MoveToElementOffsetOrigin.TopLeft);
+ RightArgumentTextBox.MouseActions.Scroll(10, 10);
+ });
+ }
+ }
+}
diff --git a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Localization/LocalizationFilesTest.cs b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Localization/LocalizationFilesTest.cs
index c057c34..2b9f40a 100644
--- a/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Localization/LocalizationFilesTest.cs
+++ b/Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Localization/LocalizationFilesTest.cs
@@ -13,14 +13,14 @@ namespace Aquality.WinAppDriver.Tests.Localization
{
public class LocalizationFilesTest
{
- private static readonly string[] SupportedLanguages = { "be", "en", "ru" };
+ private const string EnglishLanguageCode = "en";
+ private static readonly string[] SupportedLanguages = { "be", EnglishLanguageCode, "ru" };
private static readonly Assembly LibraryAssembly = Assembly.GetAssembly(typeof(ApplicationManager));
- private static readonly IList> LocalizationFileDictionary
- = new JsonFile("Resources.Localization.en.json", LibraryAssembly).GetValue>("$").ToList();
- private static readonly IEnumerable KeysWithoutParams = LocalizationFileDictionary.Where(pair => !pair.Value.Contains("{0}")).Select(pair => pair.Key);
- private static readonly IEnumerable KeysWithOneParameter = LocalizationFileDictionary.Where(pair => pair.Value.Contains("{0}") && !pair.Value.Contains("{1}")).Select(pair => pair.Key);
- private static readonly IEnumerable KeysWithTwoAndMoreParameters = LocalizationFileDictionary.Where(pair => pair.Value.Contains("{1}")).Select(pair => pair.Key);
- private static readonly IEnumerable KeysWithParameters = LocalizationFileDictionary.Where(pair => pair.Value.Contains("{0}")).Select(pair => pair.Key);
+ private static readonly IList> LocalizationFileEnglishDictionary = GetLocalizationDictionaryAsList(EnglishLanguageCode);
+ private static readonly IEnumerable KeysWithoutParams = LocalizationFileEnglishDictionary.Where(pair => !pair.Value.Contains("{0}")).Select(pair => pair.Key);
+ private static readonly IEnumerable KeysWithOneParameter = LocalizationFileEnglishDictionary.Where(pair => pair.Value.Contains("{0}") && !pair.Value.Contains("{1}")).Select(pair => pair.Key);
+ private static readonly IEnumerable KeysWithTwoAndMoreParameters = LocalizationFileEnglishDictionary.Where(pair => pair.Value.Contains("{1}")).Select(pair => pair.Key);
+ private static readonly IEnumerable KeysWithParameters = LocalizationFileEnglishDictionary.Where(pair => pair.Value.Contains("{0}")).Select(pair => pair.Key);
private LocalizationManager LocalizationManager => ApplicationManager.GetRequiredService();
@@ -58,7 +58,7 @@ public void Should_ReturnNonKeyValues_AndNotEmptyValues_ForKeysWithOneParameter(
[Test]
public void Should_ReturnNonKeyValues_AndNotEmptyValues_ForKeysWithTwoAndMoreParameters([ValueSource(nameof(SupportedLanguages))] string language, [ValueSource(nameof(KeysWithTwoAndMoreParameters))] string key)
{
- var paramsArray = new[] { "a", "b" };
+ var paramsArray = new[] { "a", "b" , "c", "d" };
var localizedValue = GetLocalizationManager(language).GetLocalizedMessage(key, paramsArray);
Assert.AreNotEqual(key, localizedValue, "Value should be defined in resource files");
Assert.IsNotEmpty(localizedValue, "Value should not be empty");
@@ -72,6 +72,28 @@ public void Should_ThrowsFormatException_WhenKeysRequireParams([ValueSource(name
Assert.Throws(() => GetLocalizationManager(language).GetLocalizedMessage(key));
}
+ [Test]
+ public void Should_HaveSameAmountOfValues([ValueSource(nameof(SupportedLanguages))] string language)
+ {
+ Assert.AreEqual(LocalizationFileEnglishDictionary.Count, GetLocalizationDictionaryAsList(language).Count);
+ }
+
+ [Test]
+ public void Should_HaveNotAllValuesTheSame_InDifferentLanguages([ValueSource(nameof(SupportedLanguages))] string language)
+ {
+ var currentLanguageDictionary = GetLocalizationDictionaryAsList(language);
+
+ foreach (var dictionary in SupportedLanguages.Except(new[] { language }).Select(lang => GetLocalizationDictionaryAsList(lang)))
+ {
+ CollectionAssert.AreNotEquivalent(currentLanguageDictionary, dictionary);
+ }
+ }
+
+ private static IList> GetLocalizationDictionaryAsList(string language)
+ {
+ return new JsonFile($"Resources.Localization.{language}.json", LibraryAssembly).GetValue>("$").ToList();
+ }
+
private LocalizationManager GetLocalizationManager(string customLanguage)
{
var configuration = new DynamicConfiguration