From 9a83999557e06cd4e3a8ca4e8a2ddd7d64fe7209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alaksiej=20Miale=C5=A1ka?= Date: Thu, 2 Jul 2020 17:07:13 +0200 Subject: [PATCH] Support logging of Element property getters +semver: feature (#192) * Support logging of Element property getters. * Update localized values and enhance/add missing methods to use them. * Fixed localization resourse files * Add logging of "loc.browser.ready" to resolve #164 and close #165 * Enhanced logging for CheckBox, RadioButton, ComboBox and TextBox methods and JS actions * Add logging of Browser's handle alert and wait for loading methods * Reworked BrowserFactory classes: make Browser {get;} a template method --- .../Aquality.Selenium.csproj | 5 +- .../Aquality.Selenium/Aquality.Selenium.xml | 355 +++++++++++++++++- .../Browsers/AqualityServices.cs | 5 +- .../src/Aquality.Selenium/Browsers/Browser.cs | 9 +- .../Browsers/BrowserFactory.cs | 31 +- .../Browsers/IBrowserFactory.cs | 2 +- .../Browsers/LocalBrowserFactory.cs | 90 ++--- .../Browsers/RemoteBrowserFactory.cs | 24 +- .../WebDriverSettings/DriverSettings.cs | 57 ++- .../WebDriverSettings/EdgeChromiumSettings.cs | 3 +- .../Elements/Actions/CheckBoxJsActions.cs | 15 +- .../Elements/Actions/ComboBoxJsActions.cs | 8 +- .../Elements/Actions/JsActions.cs | 14 +- .../Elements/Actions/MouseActions.cs | 12 + .../Aquality.Selenium/Elements/CheckBox.cs | 15 +- .../Elements/CheckableElement.cs | 28 ++ .../Aquality.Selenium/Elements/ComboBox.cs | 40 +- .../src/Aquality.Selenium/Elements/Element.cs | 27 +- .../Elements/ElementStateProvider.cs | 7 +- .../Elements/Interfaces/IElement.cs | 6 + .../src/Aquality.Selenium/Elements/Key.cs | 263 +++++++++++++ .../Aquality.Selenium/Elements/RadioButton.cs | 4 +- .../src/Aquality.Selenium/Elements/TextBox.cs | 2 + .../Resources/Localization/be.json | 76 ++++ .../Resources/Localization/en.json | 43 ++- .../Resources/Localization/ru.json | 144 +++---- .../Aquality.Selenium/Resources/settings.json | 3 +- .../Integration/Elements/ComboBoxTests.cs | 2 +- .../Integration/Elements/TextBoxTests.cs | 13 +- .../Integration/UITest.cs | 5 +- .../Usecases/CustomBrowserFactoryTests.cs | 23 +- .../Resources/settings.azure.json | 3 +- .../Resources/settings.json | 3 +- .../Resources/settings.local.json | 3 +- .../Configuration/CustomConfigurationTests.cs | 2 + 35 files changed, 1122 insertions(+), 220 deletions(-) create mode 100644 Aquality.Selenium/src/Aquality.Selenium/Elements/CheckableElement.cs create mode 100644 Aquality.Selenium/src/Aquality.Selenium/Elements/Key.cs create mode 100644 Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json diff --git a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj index 4bf7e505..de963765 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj +++ b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj @@ -20,9 +20,11 @@ Aquality.Selenium.xml + 1591 + @@ -59,6 +61,7 @@ + @@ -66,7 +69,7 @@ - + diff --git a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml index 381618a9..f11c8b41 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml +++ b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml @@ -87,7 +87,7 @@ Sets Selenium WebDriver ImplicitWait timeout. - Default value: . + Default value: . Desired Implicit wait timeout. @@ -330,7 +330,7 @@ - Factory that creates instance of desired Browser based on . + Factory that creates instance of desired Browser based on . @@ -510,6 +510,17 @@ JSON settings file. + + + Settings specific for Edge(chromium) web driver. + + + + + Instantiates class using JSON file with general settings + + JSON settings file. + Settings specific for Edge web driver. @@ -654,7 +665,12 @@ Performs click on element. - + + + Highlights the element. + Default value is from configuration: + + Scrolling page to the element. @@ -739,6 +755,333 @@ Moves mouse to the element. + + + Moves mouse from this element. + + + + + Represents action keys which could be used to . + Used to enhance logging of SendKeys actions + Directly related to + + + + + Represents the NUL keystroke. + + + + + Represents the number pad 0 key. + + + + + Represents the number pad 1 key. + + + + + Represents the number pad 2 key. + + + + + Represents the number pad 3 key. + + + + + Represents the number pad 4 key. + + + + + Represents the number pad 5 key. + + + + + Represents the number pad 6 key. + + + + + Represents the number pad 7 key. + + + + + Represents the number pad 8 key. + + + + + Represents the number pad 9 key. + + + + + Represents the number pad multiplication key. + + + + + Represents the number pad addition key. + + + + + Represents the number pad thousands separator key. + + + + + Represents the equal sign key. + + + + + Represents the number pad subtraction key. + + + + + Represents the number pad division key. + + + + + Represents the function key F1. + + + + + Represents the function key F2. + + + + + Represents the function key F3. + + + + + Represents the function key F4. + + + + + Represents the function key F5. + + + + + Represents the function key F6. + + + + + Represents the function key F7. + + + + + Represents the function key F8. + + + + + Represents the function key F9. + + + + + Represents the function key F10. + + + + + Represents the function key F11. + + + + + Represents the function key F12. + + + + + Represents the number pad decimal separator key. + + + + + Represents the function key META. + + + + + Represents the semi-colon key. + + + + + Represents the Insert key. + + + + + Represents the Cancel keystroke. + + + + + Represents the Help keystroke. + + + + + Represents the Backspace key. + + + + + Represents the Tab key. + + + + + Represents the Clear keystroke. + + + + + Represents the Return key. + + + + + Represents the Enter key. + + + + + Represents the Shift key. + + + + + Represents the Shift key. + + + + + Represents the Control key. + + + + + Represents the Control key. + + + + + Represents the Alt key. + + + + + Represents the Alt key. + + + + + Represents the Delete key. + + + + + Represents the Pause key. + + + + + Represents the Spacebar key. + + + + + Represents the Page Up key. + + + + + Represents the Page Down key. + + + + + Represents the End key. + + + + + Represents the Home key. + + + + + Represents the left arrow key. + + + + + Represents the left arrow key. + + + + + Represents the up arrow key. + + + + + Represents the up arrow key. + + + + + Represents the right arrow key. + + + + + Represents the right arrow key. + + + + + Represents the Left arrow key. + + + + + Represents the Left arrow key. + + + + + Represents the Escape key. + + + + + Represents the function key COMMAND. + + Defines Button UI element. @@ -968,6 +1311,12 @@ Value to set. + + + Send key. + + Key for sending. + Defines the interface used to create the elements. diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/AqualityServices.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/AqualityServices.cs index f2c18582..90ba4916 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/AqualityServices.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/AqualityServices.cs @@ -6,6 +6,7 @@ using Aquality.Selenium.Core.Localization; using Aquality.Selenium.Core.Logging; using Aquality.Selenium.Core.Waitings; +using Aquality.Selenium.Core.Utilities; namespace Aquality.Selenium.Browsers { @@ -90,11 +91,11 @@ public static void SetDefaultFactory() IBrowserFactory applicationFactory; if (appProfile.IsRemote) { - applicationFactory = new RemoteBrowserFactory(); + applicationFactory = new RemoteBrowserFactory(Get(), Get(), Get(), LocalizedLogger); } else { - applicationFactory = new LocalBrowserFactory(); + applicationFactory = new LocalBrowserFactory(Get(), Get(), Get(), LocalizedLogger); } BrowserFactory = applicationFactory; diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs index 208694e5..6dc438c1 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs @@ -58,7 +58,7 @@ public Browser(RemoteWebDriver webDriver) /// /// Sets Selenium WebDriver ImplicitWait timeout. - /// Default value: . + /// Default value: . /// /// Desired Implicit wait timeout. public void SetImplicitWaitTimeout(TimeSpan timeout) @@ -109,7 +109,9 @@ public string CurrentUrl get { Logger.Info("loc.browser.getUrl"); - return Driver.Url; + var url = Driver.Url; + Logger.Info("loc.browser.url.value", url); + return url; } } @@ -192,11 +194,13 @@ public IBrowserTabNavigation Tabs() /// Thrown when no alert found. public void HandleAlert(AlertAction alertAction, string text = null) { + Logger.Info($"loc.browser.alert.{alertAction.ToString().ToLower()}"); try { var alert = Driver.SwitchTo().Alert(); if (!string.IsNullOrEmpty(text)) { + Logger.Info("loc.send.text", text); alert.SendKeys(text); } if (alertAction.Equals(AlertAction.Accept)) @@ -230,6 +234,7 @@ public void Maximize() /// Throws when timeout exceeded and page is not loaded. public void WaitForPageToLoad() { + Logger.Info("loc.browser.page.wait"); var errorMessage = LocalizationManager.GetLocalizedMessage("loc.browser.page.timeout"); conditionalWait.WaitForTrue(() => ExecuteScript(JavaScript.IsPageLoaded), pageLoadTimeout, message: errorMessage); } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserFactory.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserFactory.cs index c1432ad4..eaa644cb 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserFactory.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserFactory.cs @@ -1,14 +1,39 @@ -namespace Aquality.Selenium.Browsers +using Aquality.Selenium.Configurations; +using Aquality.Selenium.Core.Localization; +using Aquality.Selenium.Core.Utilities; +using OpenQA.Selenium; +using OpenQA.Selenium.Remote; + +namespace Aquality.Selenium.Browsers { /// /// Abstract representation of . /// public abstract class BrowserFactory : IBrowserFactory { - protected BrowserFactory() + protected BrowserFactory(IActionRetrier actionRetrier, IBrowserProfile browserProfile, ITimeoutConfiguration timeoutConfiguration, ILocalizedLogger localizedLogger) { + ActionRetrier = actionRetrier; + BrowserProfile = browserProfile; + TimeoutConfiguration = timeoutConfiguration; + LocalizedLogger = localizedLogger; } - public abstract Browser Browser { get; } + protected IActionRetrier ActionRetrier { get; } + protected IBrowserProfile BrowserProfile { get; } + protected ITimeoutConfiguration TimeoutConfiguration { get; } + protected ILocalizedLogger LocalizedLogger { get; } + + protected abstract RemoteWebDriver Driver { get; } + + public virtual Browser Browser + { + get + { + var browser = new Browser(ActionRetrier.DoWithRetry(() => Driver, new[] { typeof(WebDriverException) })); + LocalizedLogger.Info("loc.browser.ready", BrowserProfile.BrowserName); + return browser; + } + } } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/IBrowserFactory.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/IBrowserFactory.cs index 3ecfd09a..9a838706 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/IBrowserFactory.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/IBrowserFactory.cs @@ -1,7 +1,7 @@ namespace Aquality.Selenium.Browsers { /// - /// Factory that creates instance of desired Browser based on . + /// Factory that creates instance of desired Browser based on . /// public interface IBrowserFactory { diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/LocalBrowserFactory.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/LocalBrowserFactory.cs index e7f7a5ca..5863f461 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/LocalBrowserFactory.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/LocalBrowserFactory.cs @@ -17,6 +17,7 @@ using EdgeChromiumOptions = Microsoft.Edge.SeleniumTools.EdgeOptions; using EdgeChromiumService = Microsoft.Edge.SeleniumTools.EdgeDriverService; using EdgeChromiumDriver = Microsoft.Edge.SeleniumTools.EdgeDriver; +using Aquality.Selenium.Core.Localization; namespace Aquality.Selenium.Browsers { @@ -27,61 +28,60 @@ public class LocalBrowserFactory : BrowserFactory { private static readonly object WebDriverDownloadingLock = new object(); - public LocalBrowserFactory() : base() + public LocalBrowserFactory(IActionRetrier actionRetrier, IBrowserProfile browserProfile, ITimeoutConfiguration timeoutConfiguration, ILocalizedLogger localizedLogger) + : base(actionRetrier, browserProfile, timeoutConfiguration, localizedLogger) { } - public override Browser Browser => CreateBrowser(); - - private Browser CreateBrowser() + protected override RemoteWebDriver Driver { - var browserProfile = AqualityServices.Get(); - var commandTimeout = AqualityServices.Get().Command; - var browserName = browserProfile.BrowserName; - var driverSettings = browserProfile.DriverSettings; - RemoteWebDriver driver; - switch (browserName) + get { - case BrowserName.Chrome: - SetUpDriver(new ChromeConfig(), driverSettings); - driver = GetDriver(ChromeDriverService.CreateDefaultService(), - (ChromeOptions)driverSettings.DriverOptions, commandTimeout); - break; - case BrowserName.Firefox: - SetUpDriver(new FirefoxConfig(), driverSettings); - var geckoService = FirefoxDriverService.CreateDefaultService(); - geckoService.Host = "::1"; - driver = GetDriver(geckoService, (FirefoxOptions)driverSettings.DriverOptions, commandTimeout); - break; - case BrowserName.IExplorer: - SetUpDriver(new InternetExplorerConfig(), driverSettings); - driver = GetDriver(InternetExplorerDriverService.CreateDefaultService(), - (InternetExplorerOptions)driverSettings.DriverOptions, commandTimeout); - break; - case BrowserName.Edge: - driver = GetDriver(EdgeDriverService.CreateDefaultService(), - (EdgeOptions)driverSettings.DriverOptions, commandTimeout); - break; - case BrowserName.EdgeChromium: - SetUpDriver(new EdgeConfig(), driverSettings); - driver = GetDriver(EdgeChromiumService.CreateChromiumService(), - (EdgeChromiumOptions)driverSettings.DriverOptions, commandTimeout); - break; - case BrowserName.Safari: - driver = GetDriver(SafariDriverService.CreateDefaultService(), - (SafariOptions)driverSettings.DriverOptions, commandTimeout); - break; - default: - throw new ArgumentOutOfRangeException($"Browser {browserName} is not supported."); + var commandTimeout = TimeoutConfiguration.Command; + var browserName = BrowserProfile.BrowserName; + var driverSettings = BrowserProfile.DriverSettings; + RemoteWebDriver driver; + switch (browserName) + { + case BrowserName.Chrome: + SetUpDriver(new ChromeConfig(), driverSettings); + driver = GetDriver(ChromeDriverService.CreateDefaultService(), + (ChromeOptions)driverSettings.DriverOptions, commandTimeout); + break; + case BrowserName.Firefox: + SetUpDriver(new FirefoxConfig(), driverSettings); + var geckoService = FirefoxDriverService.CreateDefaultService(); + geckoService.Host = "::1"; + driver = GetDriver(geckoService, (FirefoxOptions)driverSettings.DriverOptions, commandTimeout); + break; + case BrowserName.IExplorer: + SetUpDriver(new InternetExplorerConfig(), driverSettings); + driver = GetDriver(InternetExplorerDriverService.CreateDefaultService(), + (InternetExplorerOptions)driverSettings.DriverOptions, commandTimeout); + break; + case BrowserName.Edge: + driver = GetDriver(EdgeDriverService.CreateDefaultService(), + (EdgeOptions)driverSettings.DriverOptions, commandTimeout); + break; + case BrowserName.EdgeChromium: + SetUpDriver(new EdgeConfig(), driverSettings); + driver = GetDriver(EdgeChromiumService.CreateChromiumService(), + (EdgeChromiumOptions)driverSettings.DriverOptions, commandTimeout); + break; + case BrowserName.Safari: + driver = GetDriver(SafariDriverService.CreateDefaultService(), + (SafariOptions)driverSettings.DriverOptions, commandTimeout); + break; + default: + throw new NotSupportedException($"Browser [{browserName}] is not supported."); + } + return driver; } - - return new Browser(driver); } private RemoteWebDriver GetDriver(DriverService driverService, DriverOptions driverOptions, TimeSpan commandTimeout) where T : RemoteWebDriver { - return AqualityServices.Get().DoWithRetry(() => - (T)Activator.CreateInstance(typeof(T), driverService, driverOptions, commandTimeout)); + return (T) Activator.CreateInstance(typeof(T), driverService, driverOptions, commandTimeout); } private static void SetUpDriver(IDriverConfig driverConfig, IDriverSettings driverSettings) diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/RemoteBrowserFactory.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/RemoteBrowserFactory.cs index 4b4025de..4eda7a4b 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/RemoteBrowserFactory.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/RemoteBrowserFactory.cs @@ -1,4 +1,5 @@ using Aquality.Selenium.Configurations; +using Aquality.Selenium.Core.Localization; using Aquality.Selenium.Core.Utilities; using OpenQA.Selenium.Remote; using System; @@ -10,21 +11,26 @@ namespace Aquality.Selenium.Browsers /// public class RemoteBrowserFactory : BrowserFactory { - public RemoteBrowserFactory() : base() + public RemoteBrowserFactory(IActionRetrier actionRetrier, IBrowserProfile browserProfile, ITimeoutConfiguration timeoutConfiguration, ILocalizedLogger localizedLogger) + : base(actionRetrier, browserProfile, timeoutConfiguration, localizedLogger) { } - public override Browser Browser + protected override RemoteWebDriver Driver { get { - var browserProfile = AqualityServices.Get(); - var capabilities = browserProfile.DriverSettings.DriverOptions.ToCapabilities(); - var timeoutConfiguration = AqualityServices.Get(); - var driver = AqualityServices.Get().DoWithRetry(() => - (RemoteWebDriver)Activator.CreateInstance(typeof(RemoteWebDriver), - browserProfile.RemoteConnectionUrl, capabilities, timeoutConfiguration.Command)); - return new Browser(driver); + LocalizedLogger.Info("loc.browser.grid"); + var capabilities = BrowserProfile.DriverSettings.DriverOptions.ToCapabilities(); + try + { + return new RemoteWebDriver(BrowserProfile.RemoteConnectionUrl, capabilities, TimeoutConfiguration.Command); + } + catch (Exception e) + { + LocalizedLogger.Fatal("loc.browser.grid.fail", e); + throw; + } } } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Configurations/WebDriverSettings/DriverSettings.cs b/Aquality.Selenium/src/Aquality.Selenium/Configurations/WebDriverSettings/DriverSettings.cs index 67c34f7d..fd5c8c73 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Configurations/WebDriverSettings/DriverSettings.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Configurations/WebDriverSettings/DriverSettings.cs @@ -15,6 +15,10 @@ namespace Aquality.Selenium.Configurations.WebDriverSettings /// public abstract class DriverSettings : IDriverSettings { + private IReadOnlyDictionary options; + private IReadOnlyDictionary capabilities; + private IReadOnlyList startArguments; + /// /// Instantiates class using JSON file with general settings. /// @@ -50,11 +54,58 @@ public virtual string DownloadDir public abstract string DownloadDirCapabilityKey { get; } - protected IReadOnlyDictionary BrowserCapabilities => SettingsFile.GetValueDictionaryOrEmpty($"{DriverSettingsPath}.capabilities"); + protected IReadOnlyDictionary BrowserCapabilities + { + get + { + if (capabilities == null) + { + capabilities = SettingsFile.GetValueDictionaryOrEmpty($"{DriverSettingsPath}.{nameof(capabilities)}"); + if (capabilities.Any()) + { + AqualityServices.LocalizedLogger.Debug("loc.browser.capabilities", + args: string.Join(",", capabilities.Select(cap => $"{Environment.NewLine}{cap.Key}: {cap.Value}"))); + } + } + + return capabilities; + } + } + + protected IReadOnlyDictionary BrowserOptions + { + get + { + if (options == null) + { + options = SettingsFile.GetValueDictionaryOrEmpty($"{DriverSettingsPath}.{nameof(options)}"); + if (options.Any()) + { + AqualityServices.LocalizedLogger.Debug("loc.browser.options", + args: string.Join(",", options.Select(opt => $"{Environment.NewLine}{opt.Key}: {opt.Value}"))); + } + } + + return options; + } + } - protected IReadOnlyDictionary BrowserOptions => SettingsFile.GetValueDictionaryOrEmpty($"{DriverSettingsPath}.options"); + protected IReadOnlyList BrowserStartArguments + { + get + { + if (startArguments == null) + { + startArguments = SettingsFile.GetValueListOrEmpty($"{DriverSettingsPath}.{nameof(startArguments)}"); - protected IReadOnlyList BrowserStartArguments => SettingsFile.GetValueListOrEmpty($"{DriverSettingsPath}.startArguments"); + if (startArguments.Any()) + { + AqualityServices.LocalizedLogger.Debug("loc.browser.arguments", args: string.Join(" ", startArguments)); + } + } + return startArguments; + } + } private string DriverSettingsPath => $".driverSettings.{BrowserName.ToString().ToLowerInvariant()}"; diff --git a/Aquality.Selenium/src/Aquality.Selenium/Configurations/WebDriverSettings/EdgeChromiumSettings.cs b/Aquality.Selenium/src/Aquality.Selenium/Configurations/WebDriverSettings/EdgeChromiumSettings.cs index 45be1072..8a1f8764 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Configurations/WebDriverSettings/EdgeChromiumSettings.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Configurations/WebDriverSettings/EdgeChromiumSettings.cs @@ -1,5 +1,4 @@ -using System; -using Aquality.Selenium.Browsers; +using Aquality.Selenium.Browsers; using Aquality.Selenium.Core.Configurations; using Microsoft.Edge.SeleniumTools; using OpenQA.Selenium; diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/CheckBoxJsActions.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/CheckBoxJsActions.cs index 6106a8cc..07abf648 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/CheckBoxJsActions.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/CheckBoxJsActions.cs @@ -21,8 +21,10 @@ public CheckBoxJsActions(IElement element, string elementType, ILocalizedLogger /// True if checked and false otherwise public bool IsChecked() { - LogElementAction("loc.checkbox.get.state"); - return ExecuteScript(JavaScript.GetCheckBoxState); + LogElementAction("loc.checkable.get.state"); + var state = GetState(); + LogElementAction("loc.checkable.state", state); + return state; } /// @@ -46,16 +48,21 @@ public void Uncheck() /// public void Toggle() { - SetState(!IsChecked()); + SetState(!GetState()); } private void SetState(bool state) { LogElementAction("loc.setting.value", state); - if (state != IsChecked()) + if (state != GetState()) { Click(); } } + + private bool GetState() + { + return ExecuteScript(JavaScript.GetCheckBoxState); + } } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/ComboBoxJsActions.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/ComboBoxJsActions.cs index c3538b3f..c568ef1e 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/ComboBoxJsActions.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/ComboBoxJsActions.cs @@ -24,7 +24,9 @@ public ComboBoxJsActions(IElement element, string elementType, ILocalizedLogger public IList GetTexts() { LogElementAction("loc.combobox.get.texts.js"); - return ExecuteScript>(JavaScript.GetComboBoxTexts).Select(item => item.ToString()).ToList(); + var values = ExecuteScript>(JavaScript.GetComboBoxTexts).Select(item => item.ToString()).ToList(); + LogElementAction("loc.combobox.texts", string.Join(", ", values.Select(value => $"'{value}'"))); + return values; } /// @@ -34,7 +36,9 @@ public IList GetTexts() public string GetSelectedText() { LogElementAction("loc.combobox.get.text.js"); - return ExecuteScript(JavaScript.GetComboBoxSelectedText); + var text = ExecuteScript(JavaScript.GetComboBoxSelectedText); + LogElementAction("loc.combobox.selected.text", text); + return text; } /// diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/JsActions.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/JsActions.cs index 1542ab16..e85d5155 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/JsActions.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/JsActions.cs @@ -55,7 +55,7 @@ public void Click() /// /// Highlights the element. - /// Default value is from configuration: + /// Default value is from configuration: /// public void HighlightElement(HighlightState highlightState = HighlightState.Default) { @@ -122,7 +122,9 @@ public void SetFocus() public bool IsElementOnScreen() { LogElementAction("loc.is.present.js"); - return ExecuteScript(JavaScript.ElementIsOnScreen); + var value = ExecuteScript(JavaScript.ElementIsOnScreen); + LogElementAction("loc.is.present.value", value); + return value; } /// @@ -132,7 +134,9 @@ public bool IsElementOnScreen() public string GetElementText() { LogElementAction("loc.get.text.js"); - return ExecuteScript(JavaScript.GetElementText); + var value = ExecuteScript(JavaScript.GetElementText); + LogElementAction("loc.text.value", value); + return value; } /// @@ -151,7 +155,9 @@ public void HoverMouse() public string GetXPath() { LogElementAction("loc.get.xpath.js"); - return ExecuteScript(JavaScript.GetElementXPath); + var value = ExecuteScript(JavaScript.GetElementXPath); + LogElementAction("loc.xpath.value", value); + return value; } /// diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/MouseActions.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/MouseActions.cs index c5b3137a..bc115bd3 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/MouseActions.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/Actions/MouseActions.cs @@ -68,6 +68,18 @@ public void MoveToElement() elementActionsRetrier.DoWithRetry(() => PerformAction(MoveToElement)); } + /// + /// Moves mouse from this element. + /// + public void MoveMouseFromElement() + { + LogElementAction("loc.movingFrom"); + elementActionsRetrier.DoWithRetry( + () => PerformAction( + element => new SeleniumActions(AqualityServices.Browser.Driver) + .MoveToElement(element, -element.Size.Width / 2, -element.Size.Height / 2))); + } + private SeleniumActions MoveToElement(IWebElement element) { return new SeleniumActions(AqualityServices.Browser.Driver).MoveToElement(element); diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/CheckBox.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/CheckBox.cs index fdd48fdd..6c9a699d 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/CheckBox.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/CheckBox.cs @@ -8,7 +8,7 @@ namespace Aquality.Selenium.Elements /// /// Defines CheckBox UI element. /// - public class CheckBox : Element, ICheckBox + public class CheckBox : CheckableElement, ICheckBox { protected internal CheckBox(By locator, string name, ElementState state) : base(locator, name, state) { @@ -16,15 +16,6 @@ protected internal CheckBox(By locator, string name, ElementState state) : base( protected override string ElementType => LocalizationManager.GetLocalizedMessage("loc.checkbox"); - public bool IsChecked - { - get - { - LogElementAction("loc.checkbox.get.state"); - return GetElement().Selected; - } - } - public new CheckBoxJsActions JsActions => new CheckBoxJsActions(this, ElementType, LocalizedLogger, BrowserProfile); public void Check() @@ -39,13 +30,13 @@ public void Uncheck() public void Toggle() { - SetState(!IsChecked); + SetState(!GetState()); } private void SetState(bool state) { LogElementAction("loc.setting.value", state); - if (state != IsChecked) + if (state != GetState()) { Click(); } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/CheckableElement.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/CheckableElement.cs new file mode 100644 index 00000000..c7057fd0 --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/CheckableElement.cs @@ -0,0 +1,28 @@ +using Aquality.Selenium.Core.Elements; +using OpenQA.Selenium; + +namespace Aquality.Selenium.Elements +{ + public abstract class CheckableElement : Element + { + protected CheckableElement(By locator, string name, ElementState state) : base(locator, name, state) + { + } + + public bool IsChecked + { + get + { + LogElementAction("loc.checkable.get.state"); + var state = GetState(); + LogElementAction("loc.checkable.state", state); + return state; + } + } + + protected virtual bool GetState() + { + return DoWithRetry(() => GetElement().Selected); + } + } +} diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/ComboBox.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/ComboBox.cs index 4bbdda30..b193d80c 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/ComboBox.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/ComboBox.cs @@ -19,16 +19,36 @@ protected internal ComboBox(By locator, string name, ElementState state) : base( protected override string ElementType => LocalizationManager.GetLocalizedMessage("loc.combobox"); - public string SelectedText => DoWithRetry(() => new SelectElement(GetElement()).SelectedOption.Text); + public string SelectedText + { + get + { + LogElementAction("loc.combobox.getting.selected.text"); + var text = DoWithRetry(() => new SelectElement(GetElement()).SelectedOption.Text); + LogElementAction("loc.combobox.selected.text", text); + return text; + } + } - public string SelectedValue => DoWithRetry(() => new SelectElement(GetElement()).SelectedOption.GetAttribute(Attributes.Value)); + public string SelectedValue + { + get + { + LogElementAction("loc.combobox.getting.selected.value"); + var value = DoWithRetry(() => new SelectElement(GetElement()).SelectedOption.GetAttribute(Attributes.Value)); + LogElementAction("loc.combobox.selected.value", value); + return value; + } + } public IList Texts { get { LogElementAction("loc.combobox.get.texts"); - return DoWithRetry(() => new SelectElement(GetElement()).Options.Select(option => option.Text).ToList()); + var values = DoWithRetry(() => new SelectElement(GetElement()).Options.Select(option => option.Text).ToList()); + LogElementAction("loc.combobox.texts", string.Join(", ", values.Select(value => $"'{value}'"))); + return values; } } @@ -37,7 +57,9 @@ public IList Values get { LogElementAction("loc.combobox.get.values"); - return DoWithRetry(() => new SelectElement(GetElement()).Options.Select(option => option.GetAttribute(Attributes.Value)).ToList()); + var values = DoWithRetry(() => new SelectElement(GetElement()).Options.Select(option => option.GetAttribute(Attributes.Value)).ToList()); + LogElementAction("loc.combobox.values", string.Join(", ", values.Select(value => $"'{value}'"))); + return values; } } @@ -45,7 +67,7 @@ public IList Values public void SelectByContainingText(string text) { - LogElementAction("loc.selecting.value"); + LogElementAction("loc.combobox.select.by.text", text); DoWithRetry(() => { var select = new SelectElement(GetElement()); @@ -64,7 +86,7 @@ public void SelectByContainingText(string text) public void SelectByContainingValue(string value) { - LogElementAction("loc.selecting.value"); + LogElementAction("loc.selecting.value", value); DoWithRetry(() => { var select = new SelectElement(GetElement()); @@ -83,19 +105,19 @@ public void SelectByContainingValue(string value) public void SelectByIndex(int index) { - LogElementAction("loc.selecting.value"); + LogElementAction("loc.selecting.value", $"#{index}"); DoWithRetry(() => new SelectElement(GetElement()).SelectByIndex(index)); } public void SelectByText(string text) { - LogElementAction("loc.selecting.value"); + LogElementAction("loc.combobox.select.by.text", text); DoWithRetry(() => new SelectElement(GetElement()).SelectByText(text)); } public void SelectByValue(string value) { - LogElementAction("loc.selecting.value"); + LogElementAction("loc.selecting.value", value); DoWithRetry(() => new SelectElement(GetElement()).SelectByValue(value)); } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/Element.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/Element.cs index 3feb0268..a2499691 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/Element.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/Element.cs @@ -13,6 +13,8 @@ using ICoreElementFinder = Aquality.Selenium.Core.Elements.Interfaces.IElementFinder; using ICoreElementStateProvider = Aquality.Selenium.Core.Elements.Interfaces.IElementStateProvider; using Aquality.Selenium.Core.Configurations; +using System.Reflection; +using System.Linq; namespace Aquality.Selenium.Elements { @@ -25,7 +27,7 @@ protected Element(By locator, string name, ElementState state) : base(locator, n { } - public override ICoreElementStateProvider State => new ElementStateProvider(Locator, ConditionalWait, Finder); + public override ICoreElementStateProvider State => new ElementStateProvider(Locator, ConditionalWait, Finder, LogElementState); protected IBrowserProfile BrowserProfile => AqualityServices.Get(); @@ -49,7 +51,7 @@ protected Element(By locator, string name, ElementState state) : base(locator, n protected override ILocalizedLogger LocalizedLogger => AqualityServices.LocalizedLogger; - protected ILocalizationManager LocalizationManager => AqualityServices.Get(); + protected override ILocalizationManager LocalizationManager => AqualityServices.Get(); protected override IConditionalWait ConditionalWait => AqualityServices.ConditionalWait; @@ -82,21 +84,27 @@ public string GetAttribute(string attr, HighlightState highlightState = Highligh { LogElementAction("loc.el.getattr", attr); JsActions.HighlightElement(highlightState); - return DoWithRetry(() => GetElement().GetAttribute(attr)); + var value = DoWithRetry(() => GetElement().GetAttribute(attr)); + LogElementAction("loc.el.attr.value", attr, value); + return value; } public string GetCssValue(string propertyName, HighlightState highlightState = HighlightState.Default) { LogElementAction("loc.el.cssvalue", propertyName); JsActions.HighlightElement(highlightState); - return DoWithRetry(() => GetElement().GetCssValue(propertyName)); + var value = DoWithRetry(() => GetElement().GetCssValue(propertyName)); + LogElementAction("loc.el.attr.value", propertyName, value); + return value; } public string GetText(HighlightState highlightState = HighlightState.Default) { LogElementAction("loc.get.text"); JsActions.HighlightElement(highlightState); - return DoWithRetry(() => GetElement().Text); + var value = DoWithRetry(() => GetElement().Text); + LogElementAction("loc.text.value", value); + return value; } public void SetInnerHtml(string value) @@ -105,5 +113,14 @@ public void SetInnerHtml(string value) LogElementAction("loc.send.text", value); Browser.ExecuteScript(JavaScript.SetInnerHTML, GetElement(), value); } + + public void SendKey(Key key) + { + LogElementAction("loc.text.sending.key", key); + var keysString = typeof(Keys) + .GetFields(BindingFlags.Public | BindingFlags.Static) + .FirstOrDefault(field => field.Name == key.ToString())?.GetValue(null).ToString(); + DoWithRetry(() => GetElement().SendKeys(keysString)); + } } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/ElementStateProvider.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/ElementStateProvider.cs index 352a1c6c..0d4ad7c1 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/ElementStateProvider.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/ElementStateProvider.cs @@ -1,4 +1,5 @@ -using Aquality.Selenium.Core.Elements.Interfaces; +using Aquality.Selenium.Core.Elements; +using Aquality.Selenium.Core.Elements.Interfaces; using Aquality.Selenium.Core.Waitings; using OpenQA.Selenium; using CoreElementStateProvider = Aquality.Selenium.Core.Elements.ElementStateProvider; @@ -7,8 +8,8 @@ namespace Aquality.Selenium.Elements { public class ElementStateProvider : CoreElementStateProvider { - public ElementStateProvider(By elementLocator, IConditionalWait conditionalWait, IElementFinder elementFinder) - : base(elementLocator, conditionalWait, elementFinder) + public ElementStateProvider(By elementLocator, IConditionalWait conditionalWait, IElementFinder elementFinder, LogElementState logElementState) + : base(elementLocator, conditionalWait, elementFinder, logElementState) { } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/Interfaces/IElement.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/Interfaces/IElement.cs index 5187bc62..75255afa 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/Interfaces/IElement.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/Interfaces/IElement.cs @@ -66,5 +66,11 @@ public interface IElement : ICoreElement /// /// Value to set. void SetInnerHtml(string value); + + /// + /// Send key. + /// + /// Key for sending. + void SendKey(Key key); } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/Key.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/Key.cs new file mode 100644 index 00000000..917ce0ae --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/Key.cs @@ -0,0 +1,263 @@ +namespace Aquality.Selenium.Elements.Actions +{ + /// + /// Represents action keys which could be used to . + /// Used to enhance logging of SendKeys actions + /// Directly related to + /// + public enum Key + { + /// + /// Represents the NUL keystroke. + /// + Null, + /// + /// Represents the number pad 0 key. + /// + NumberPad0, + /// + /// Represents the number pad 1 key. + /// + NumberPad1, + /// + /// Represents the number pad 2 key. + /// + NumberPad2, + /// + /// Represents the number pad 3 key. + /// + NumberPad3, + /// + /// Represents the number pad 4 key. + /// + NumberPad4, + /// + /// Represents the number pad 5 key. + /// + NumberPad5, + /// + /// Represents the number pad 6 key. + /// + NumberPad6, + /// + /// Represents the number pad 7 key. + /// + NumberPad7, + /// + /// Represents the number pad 8 key. + /// + NumberPad8, + /// + /// Represents the number pad 9 key. + /// + NumberPad9, + /// + /// Represents the number pad multiplication key. + /// + Multiply, + /// + /// Represents the number pad addition key. + /// + Add, + /// + /// Represents the number pad thousands separator key. + /// + Separator, + /// + /// Represents the equal sign key. + /// + Equal, + /// + /// Represents the number pad subtraction key. + /// + Subtract, + /// + /// Represents the number pad division key. + /// + Divide, + /// + /// Represents the function key F1. + /// + F1, + /// + /// Represents the function key F2. + /// + F2, + /// + /// Represents the function key F3. + /// + F3, + /// + /// Represents the function key F4. + /// + F4, + /// + /// Represents the function key F5. + /// + F5, + /// + /// Represents the function key F6. + /// + F6, + /// + /// Represents the function key F7. + /// + F7, + /// + /// Represents the function key F8. + /// + F8, + /// + /// Represents the function key F9. + /// + F9, + /// + /// Represents the function key F10. + /// + F10, + /// + /// Represents the function key F11. + /// + F11, + /// + /// Represents the function key F12. + /// + F12, + /// + /// Represents the number pad decimal separator key. + /// + Decimal, + /// + /// Represents the function key META. + /// + Meta, + /// + /// Represents the semi-colon key. + /// + Semicolon, + /// + /// Represents the Insert key. + /// + Insert, + /// + /// Represents the Cancel keystroke. + /// + Cancel, + /// + /// Represents the Help keystroke. + /// + Help, + /// + /// Represents the Backspace key. + /// + Backspace, + /// + /// Represents the Tab key. + /// + Tab, + /// + /// Represents the Clear keystroke. + /// + Clear, + /// + /// Represents the Return key. + /// + Return, + /// + /// Represents the Enter key. + /// + Enter, + /// + /// Represents the Shift key. + /// + Shift, + /// + /// Represents the Shift key. + /// + LeftShift, + /// + /// Represents the Control key. + /// + Control, + /// + /// Represents the Control key. + /// + LeftControl, + /// + /// Represents the Alt key. + /// + Alt, + /// + /// Represents the Alt key. + /// + LeftAlt, + /// + /// Represents the Delete key. + /// + Delete, + /// + /// Represents the Pause key. + /// + Pause, + /// + /// Represents the Spacebar key. + /// + Space, + /// + /// Represents the Page Up key. + /// + PageUp, + /// + /// Represents the Page Down key. + /// + PageDown, + /// + /// Represents the End key. + /// + End, + /// + /// Represents the Home key. + /// + Home, + /// + /// Represents the left arrow key. + /// + Left, + /// + /// Represents the left arrow key. + /// + ArrowLeft, + /// + /// Represents the up arrow key. + /// + Up, + /// + /// Represents the up arrow key. + /// + ArrowUp, + /// + /// Represents the right arrow key. + /// + Right, + /// + /// Represents the right arrow key. + /// + ArrowRight, + /// + /// Represents the Left arrow key. + /// + Down, + /// + /// Represents the Left arrow key. + /// + ArrowDown, + /// + /// Represents the Escape key. + /// + Escape, + /// + /// Represents the function key COMMAND. + /// + Command + } +} \ No newline at end of file diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/RadioButton.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/RadioButton.cs index c61c4d99..1dcd7312 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/RadioButton.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/RadioButton.cs @@ -7,14 +7,12 @@ namespace Aquality.Selenium.Elements /// /// Defines RadioButton UI element. /// - public class RadioButton : Element, IRadioButton + public class RadioButton : CheckableElement, IRadioButton { protected internal RadioButton(By locator, string name, ElementState state) : base(locator, name, state) { } protected override string ElementType => LocalizationManager.GetLocalizedMessage("loc.radio"); - - public bool IsChecked => GetElement().Selected; } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Elements/TextBox.cs b/Aquality.Selenium/src/Aquality.Selenium/Elements/TextBox.cs index 6d700ece..3d23e058 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Elements/TextBox.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Elements/TextBox.cs @@ -40,11 +40,13 @@ public void ClearAndType(string value, bool secret = false) public void Submit() { + LogElementAction("loc.text.submitting"); DoWithRetry(() => GetElement().Submit()); } public new void Focus() { + LogElementAction("loc.focusing"); DoWithRetry(() => GetElement().SendKeys(string.Empty)); } } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json new file mode 100644 index 00000000..f9527d42 --- /dev/null +++ b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/be.json @@ -0,0 +1,76 @@ +{ + "loc.browser.arguments": "Атрымалі стартавыя аргументы браўзэра з settings файла: {0}", + "loc.browser.back": "Вяртаемся да папярэдняй старонкі", + "loc.browser.forward": "Пераходзім да наступнай старонкі", + "loc.browser.capabilities": "Атрымалі capabilities браўзэра з settings файла: {0}", + "loc.browser.options": "Атрымалі опцыі профіля браўзэра з settings файла: {0}", + "loc.browser.driver.quit": "Закрываем браўзэр", + "loc.browser.getUrl": "Атрымліваем адрас бягучай старонкі", + "loc.browser.url.value": "Адрас бягучай старонкі: [{0}]", + "loc.browser.grid": "Усталёўваем драйвэр для браўзэра з Selenium Grid hub", + "loc.browser.grid.fail": "Не ўдалося ўсталяваць драйвэр браўзэра з Selenium Grid hub", + "loc.browser.maximize": "Разгортваем акно браўзэра на ўвесь экран", + "loc.browser.navigate": "Пераходзім па адрасе - '{0}'", + "loc.browser.page.wait": "Чакаем загрузкі старонкі", + "loc.browser.page.timeout": "Таймаўт загрузкі старонкі", + "loc.browser.ready": "Браўзэр '{0}' гатовы...", + "loc.browser.refresh": "Абнаўляем старонку", + "loc.browser.alert.accept": "Пацвярджаем дзеянне ў акне апавяшчэння", + "loc.browser.alert.decline": "Адхіляем дзеянне ў акне апавяшчэння", + "loc.browser.alert.fail": "Памылка пры ўзаемадзеянні з акном апавяшчэння", + "loc.button": "Кнопка", + "loc.checkbox": "Чэкбокс", + "loc.checkable.get.state": "Атрымліваем стан", + "loc.checkable.state": "Стан: [{0}]", + "loc.clicking": "Націскаем", + "loc.clicking.double": "Падвойна націскаем", + "loc.clicking.js": "Націскаем праз Javascript", + "loc.clicking.right": "Націскаем правай кнопкай", + "loc.combobox": "Камбабокс", + "loc.combobox.getting.selected.text": "Атрымліваем выбраны тэкст", + "loc.combobox.getting.selected.value": "Атрымліваем выбранае значэнне", + "loc.combobox.selected.text": "Выбраны тэкст: [{0}]", + "loc.combobox.selected.value": "Выбранае значэнне: [{0}]", + "loc.combobox.select.by.text": "Выбіраем значэнне з тэкстам '{0}'", + "loc.combobox.select.by.text.js": "Выбіраем значэнне з тэкстам '{0}' праз JavaScript", + "loc.combobox.get.texts": "Атрымліваем спіс тэкстаў опцыяў", + "loc.combobox.get.texts.js": "Атрымліваем спіс тэкстаў опцыяў праз JavaScript", + "loc.combobox.get.values": "Атрымліваем спіс значэнняў", + "loc.combobox.get.text.js": "Атрымліваем выбраны тэкст праз JavaScript", + "loc.combobox.texts": "Спіс тэкстаў опцыяў: [{0}]", + "loc.combobox.values": "Спіс значэнняў: [{0}]", + "loc.el.getattr": "Атрымліваем атрыбут '{0}'", + "loc.el.attr.value": "Значэнне атрыбута '{0}': [{1}]", + "loc.el.cssvalue": "Атрымліваем значэнне css '{0}'", + "loc.focusing": "Факусуемся", + "loc.get.text": "Атрымліваем тэкст элемента", + "loc.text.value": "Тэкст элемента: [{0}]", + "loc.get.text.js": "Атрымліваем тэкст элемента праз Javascript", + "loc.hover.js": "Наводзім курсор мышы на элемент праз JavaScript", + "loc.is.present.js": "Вызначаем, ці прысутны элемент на экране, праз JavaScript", + "loc.is.present.value": "Ці прысутны элемент на экране: [{0}]", + "loc.get.xpath.js": "Атрымліваем XPath лакатар элемента праз JavaScript", + "loc.xpath.value": "XPath лакатар: [{0}]", + "loc.label": "Надпіс", + "loc.link": "Спасылка", + "loc.moving": "Наводзім курсор мышы на элемент", + "loc.movingFrom": "Адводзім курсор мышы ад элемента", + "loc.radio": "Радыёкнопка", + "loc.scrolling.center.js": "Пракручваем старонку да цэнтра элемента праз JavaScript", + "loc.scrolling.js": "Пракручваем старонку праз JavaScript", + "loc.selecting.value": "Выбіраем значэнне - '{0}'", + "loc.send.text": "Задаем тэкст - '{0}'", + "loc.setting.value": "Задаем значэнне - '{0}'", + "loc.text.clearing": "Ачышчаем", + "loc.text.submitting": "Адпраўляем", + "loc.text.field": "Тэкставае поле", + "loc.text.sending.key": "Націскаем клавішу '{0}'", + "loc.text.typing": "Уводзім '{0}'", + "loc.browser.switch.to.tab.handle": "Пераключэнне на новую ўкладку па дэскрыптару '{0}'", + "loc.browser.switch.to.tab.index": "Пераключэнне на новую ўкладку па індэксе '{0}'", + "loc.browser.switch.to.new.tab": "Пераключэнне на новую ўкладку", + "loc.browser.get.tab.handles": "Атрыманне спісу дэскрыптараў адкрытых укладак", + "loc.browser.get.tab.handle": "Атрыманне дэскрыптара бягучай укладкі", + "loc.browser.tab.open.new": "Адкрыццё новай укладкі", + "loc.browser.tab.close": "Закрыццё ўкладкі" +} diff --git a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json index 44c97a1e..41ffad0f 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json +++ b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json @@ -1,66 +1,71 @@ { - "loc.browser.arguments.setting": "Setting browser start arguments from JSON file: {0}", + "loc.browser.arguments": "Got browser start arguments from settings file: {0}", "loc.browser.back": "Return to previous page", "loc.browser.forward": "Proceed to the next page", - "loc.browser.caps.setting": "Setting browser capabilities from JSON file: {0}", - "loc.browser.config.setting": "Setting browser profile options from JSON file: {0}", + "loc.browser.capabilities": "Got browser capabilities from settings file: {0}", + "loc.browser.options": "Got browser profile options from settings file: {0}", "loc.browser.driver.quit": "Closing browser", "loc.browser.getUrl": "Getting current url", + "loc.browser.url.value": "Current url: [{0}]", "loc.browser.grid": "Setting webdriver from selenium grid hub", - "loc.browser.grid.fail": "Driver setting from Selenium Grid hub was failed", + "loc.browser.grid.fail": "Driver setting from Selenium Grid hub was failed", "loc.browser.maximize": "Maximizing browser window", - "loc.browser.name.wrong": "Browser name is wrong.", "loc.browser.navigate": "Navigate to url - '{0}'", + "loc.browser.page.wait": "Waiting for page to load", "loc.browser.page.timeout": "Page loading timed out", "loc.browser.ready": "Browser '{0}' ready...", "loc.browser.refresh": "Refreshing the page", + "loc.browser.alert.accept": "Accepting browser alert", + "loc.browser.alert.decline": "Dismissing browser alert", "loc.browser.alert.fail": "Failed while handling alert", "loc.button": "Button", "loc.checkbox": "CheckBox", - "loc.checkbox.get.state": "Getting state", + "loc.checkable.get.state": "Getting state", + "loc.checkable.state": "State: [{0}]", "loc.clicking": "Clicking", "loc.clicking.double": "Clicking double", "loc.clicking.js": "Clicking via Javascript", "loc.clicking.right": "Clicking right", "loc.combobox": "ComboBox", + "loc.combobox.getting.selected.text": "Getting selected text", + "loc.combobox.getting.selected.value": "Getting selected value", + "loc.combobox.selected.text": "Selected text: [{0}]", + "loc.combobox.selected.value": "Selected value: [{0}]", "loc.combobox.select.by.text": "Selecting value by text '{0}'", "loc.combobox.select.by.text.js": "Selecting value by text '{0}' via JavaScript", "loc.combobox.get.texts": "Getting option texts array", "loc.combobox.get.texts.js": "Getting option texts array via JavaScript", "loc.combobox.get.values": "Getting values array", "loc.combobox.get.text.js": "Getting selected text via JavaScript", + "loc.combobox.texts": "Option texts: [{0}]", + "loc.combobox.values": "Option values: [{0}]", "loc.el.getattr": "Getting attribute '{0}'", + "loc.el.attr.value": "Value of attribute '{0}': [{1}]", "loc.el.cssvalue": "Getting css value '{0}'", - "loc.file.reading_exception": "Exception while reading file: '{0}'", "loc.focusing": "Focusing", "loc.get.text": "Getting text from element", + "loc.text.value": "Element's text: [{0}]", "loc.get.text.js": "Getting text from element via Javascript", "loc.hover.js": "Hover mouse over element via JavaScript", "loc.is.present.js": "Is present via JavaScript", + "loc.is.present.value": "Is present on screen: [{0}]", "loc.get.xpath.js": "Getting XPath locator of element via JavaScript", + "loc.xpath.value": "XPath locator: [{0}]", "loc.label": "Label", "loc.link": "Link", - "loc.mouse.up": "Mouse Up", "loc.moving": "Moving mouse to element", + "loc.movingFrom": "Moving mouse from element", "loc.radio": "RadioButton", "loc.scrolling.center.js": "Scrolling to the center via JavaScript", "loc.scrolling.js": "Scrolling via JavaScript", - "loc.selecting.value": "Selecting value", + "loc.selecting.value": "Selecting value - '{0}'", "loc.send.text": "Setting text - '{0}'", "loc.setting.value": "Setting value - '{0}'", "loc.text.clearing": "Clearing", + "loc.text.submitting": "Submitting", "loc.text.field": "Text Field", - "loc.text.sending.keys": "Sending keys '{0}'", + "loc.text.sending.key": "Sending key '{0}'", "loc.text.typing": "Typing '{0}'", - "loc.waitexists": "Wait until element exists in DOM", - "loc.waitinstate": "Wait until is present in state {0} using locator: {1}", - "loc.waitinvisible": "Wait until element is not visible", - "loc.waitnotexists": "Wait until element does not exist in DOM during {0} seconds", - "loc.no.elements.found.in.state": "No elements with locator '{0}' found in {1} state", - "loc.no.elements.found.by.locator": "No elements were found by locator '{0}'", - "loc.elements.were.found.but.not.in.state": "Elements were found by locator '{0}' but not in desired state {1}", - "loc.elements.found.but.should.not": "No elements should be found by locator '{0}' in {1} state", - "loc.search.of.elements.failed": "Search of element by locator '{0}' failed", "loc.browser.switch.to.tab.handle": "Switching to tab by handle '{0}'", "loc.browser.switch.to.tab.index": "Switching to tab by index '{0}'", "loc.browser.switch.to.new.tab": "Switching to new tab", diff --git a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/ru.json b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/ru.json index 1f556fe7..1a01f83d 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/ru.json +++ b/Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/ru.json @@ -1,70 +1,76 @@ { - "loc.browser.arguments.setting": " JSON : {0}", - "loc.browser.back": " ", - "loc.browser.forward": " ", - "loc.browser.caps.setting": " capabilities JSON : {0}", - "loc.browser.config.setting": " JSON : {0}", - "loc.browser.driver.quit": " ", - "loc.browser.getUrl": " ", - "loc.browser.grid": " Selenium Grid ", - "loc.browser.grid.fail": " Selenium Grid ", - "loc.browser.maximize": " ", - "loc.browser.name.wrong": " .", - "loc.browser.navigate": " - '{0}'", - "loc.browser.page.timeout": " ", - "loc.browser.ready": " '{0}' ...", - "loc.browser.refresh": " ", - "loc.browser.alert.fail": " ", - "loc.element.wasnotfoundinstate": " '{0}' {1} {2} ", - "loc.button": "", - "loc.checkbox": "", - "loc.checkbox.get.state": " ", - "loc.clicking": "", - "loc.clicking.double": " ", - "loc.clicking.js": " JavaScript", - "loc.clicking.right": " ", - "loc.combobox": "", - "loc.combobox.select.by.text": " '{0}'", - "loc.combobox.select.by.text.js": " '{0}' JavaScript", - "loc.combobox.get.texts": " ", - "loc.combobox.get.texts.js": " JavaScript", - "loc.combobox.get.values": " ", - "loc.combobox.get.text.js": " JavaScript", - "loc.el.getattr": " '{0}'", - "loc.el.cssvalue": " css '{0}'", - "loc.file.reading_exception": " : '{0}'%n", - "loc.focusing": " ", - "loc.get.text": " ", - "loc.get.text.js": " JavaScript", - "loc.hover.js": " JavaScript", - "loc.is.present.js": " ( JavaScript)", - "loc.label": "", - "loc.link": "", - "loc.moving": " ", - "loc.radio": "", - "loc.scrolling.center.js": " JavaScript", - "loc.scrolling.js": " JavaScript", - "loc.selecting.value": " ", - "loc.send.text": " - '{0}'", - "loc.setting.value": " - '{0}'", - "loc.text.clearing": "", - "loc.text.field": " ", - "loc.text.sending.keys": " '{0}'", - "loc.text.typing": " '{0}'", - "loc.waitexists": " DOM", - "loc.waitinstate": " {0} : {1}", - "loc.waitinvisible": " ", - "loc.waitnotexists": " DOM {0}", - "loc.no.elements.found.in.state": " '{0}' {1} ", - "loc.no.elements.found.by.locator": " '{0}'", - "loc.elements.were.found.but.not.in.state": " '{0}', {1}", - "loc.elements.found.but.should.not": " '{0}' {1} ", - "loc.search.of.elements.failed": " '{0}' ", - "loc.browser.switch.to.tab.handle": " '{0}'", - "loc.browser.switch.to.tab.index": " '{0}'", - "loc.browser.switch.to.new.tab": " ", - "loc.browser.get.tab.handles": " ", - "loc.browser.get.tab.handle": " ", - "loc.browser.tab.open.new": " ", - "loc.browser.tab.close": " " -} \ No newline at end of file + "loc.browser.arguments": "Получили стартовые аргументы браузера из settings файла: {0}", + "loc.browser.back": "Возврат на предыдущую страницу", + "loc.browser.forward": "Перейти на следующую страницу", + "loc.browser.capabilities": "Получили capabilities браузера из settings файла: {0}", + "loc.browser.options": "Получили опции профиля браузера из settings файла: {0}", + "loc.browser.driver.quit": "Закрытие драйвера браузера", + "loc.browser.getUrl": "Получение адреса текущей страницы", + "loc.browser.url.value": "Адрес текущей страницы: [{0}]", + "loc.browser.grid": "Установка драйвера браузера из Selenium Grid хаба", + "loc.browser.grid.fail": "Ошибка при получении драйвера из Selenium Grid хаба", + "loc.browser.maximize": "Открытие браузера на всё окно", + "loc.browser.navigate": "Переход на страницу - '{0}'", + "loc.browser.page.wait": "Ожидание загрузки страницы", + "loc.browser.page.timeout": "Таймаут загрузки страницы", + "loc.browser.ready": "Браузер '{0}' готов...", + "loc.browser.refresh": "Обновление страницы", + "loc.browser.alert.accept": "Подтверждение действия во всплывающем окне", + "loc.browser.alert.decline": "Отклонение действия во всплывающем окне", + "loc.browser.alert.fail": "Не удалось обработать всплывающее окно", + "loc.button": "Кнопка", + "loc.checkbox": "Чекбокс", + "loc.checkable.get.state": "Получение состояния", + "loc.checkable.state": "Cостояние: [{0}]", + "loc.clicking": "Клик", + "loc.clicking.double": "Двойной Клик", + "loc.clicking.js": "Клик посредством JavaScript", + "loc.clicking.right": "Клик правой кнопкой", + "loc.combobox": "Комбобокс", + "loc.combobox.getting.selected.text": "Получаем выбранный текст", + "loc.combobox.getting.selected.value": "Получаем выбранное значение", + "loc.combobox.selected.text": "Выбранный текст: [{0}]", + "loc.combobox.selected.value": "Выбранное значение: [{0}]", + "loc.combobox.select.by.text": "Выбор значения с текстом '{0}'", + "loc.combobox.select.by.text.js": "Выбор значения с текстом '{0}' посредством JavaScript", + "loc.combobox.get.texts": "Получение списка текстов опций", + "loc.combobox.get.texts.js": "Получение списка текстов опций посредством JavaScript", + "loc.combobox.get.values": "Получение списка значений", + "loc.combobox.get.text.js": "Получение списка значений посредством JavaScript", + "loc.combobox.texts": "Список текстов опций: [{0}]", + "loc.combobox.values": "Список значений: [{0}]", + "loc.el.getattr": "Получение аттрибута '{0}'", + "loc.el.attr.value": "Значение аттрибута '{0}': [{1}]", + "loc.el.cssvalue": "Получение значения css '{0}'", + "loc.focusing": "Взятие элемента в фокус", + "loc.get.text": "Получение текста элемента", + "loc.text.value": "Текст элемента: [{0}]", + "loc.get.text.js": "Получение текста элемента посредством JavaScript", + "loc.hover.js": "Наведение курсора на элемент посредством JavaScript", + "loc.is.present.js": "Присутствует ли (посредством JavaScript)", + "loc.is.present.value": "Присутствует ли на экране: [{0}]", + "loc.get.xpath.js": "Получение XPath локатора элемента посредством JavaScrip", + "loc.xpath.value": "XPath локатор: [{0}]", + "loc.label": "Надпись", + "loc.link": "Ссылка", + "loc.moving": "Наведение курсора на элемент", + "loc.movingFrom": "Сдвиг курсора с элемента", + "loc.radio": "Радиокнопка", + "loc.scrolling.center.js": "Скроллинг в центр посредством JavaScript", + "loc.scrolling.js": "Скроллинг с помощью JavaScript", + "loc.selecting.value": "Выбор значения - '{0}'", + "loc.send.text": "Ввод текста - '{0}'", + "loc.setting.value": "Установка значения - '{0}'", + "loc.text.clearing": "Очистка", + "loc.text.submitting": "Отправка", + "loc.text.field": "Текстовое поле", + "loc.text.sending.key": "Нажатие клавиши '{0}'", + "loc.text.typing": "Ввод текста '{0}'", + "loc.browser.switch.to.tab.handle": "Переключение на новую вкладку по дескриптору '{0}'", + "loc.browser.switch.to.tab.index": "Переключение на новую вкладку по индексу '{0}'", + "loc.browser.switch.to.new.tab": "Переключение на новую вкладку", + "loc.browser.get.tab.handles": "Получение списка дескрипторов открытых вкладок", + "loc.browser.get.tab.handle": "Получение дескриптора текущей вкладки", + "loc.browser.tab.open.new": "Открытие новой вкладки", + "loc.browser.tab.close": "Закрытие вкладки" +} diff --git a/Aquality.Selenium/src/Aquality.Selenium/Resources/settings.json b/Aquality.Selenium/src/Aquality.Selenium/Resources/settings.json index 1001d7a2..7c78e7c3 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Resources/settings.json +++ b/Aquality.Selenium/src/Aquality.Selenium/Resources/settings.json @@ -101,7 +101,8 @@ "pollingInterval": 300 }, "logger": { - "language": "en" + "language": "en", + "logPageSource": true }, "elementCache": { "isEnabled": false diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Elements/ComboBoxTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Elements/ComboBoxTests.cs index 12ae492d..6d0bfc2a 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Elements/ComboBoxTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Elements/ComboBoxTests.cs @@ -63,7 +63,7 @@ public void Should_BePossibleTo_SelectByContainingValue() } [Test] - public void Should_BePossibleTo_GetValuesViaJsActions() + public void Should_BePossibleTo_GetTextsViaJsActions() { var comboBox = dropdownForm.ComboBox; CollectionAssert.AreEqual(comboBox.Texts, comboBox.JsActions.GetTexts()); diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Elements/TextBoxTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Elements/TextBoxTests.cs index 07357c36..5016f9e3 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Elements/TextBoxTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Elements/TextBoxTests.cs @@ -1,5 +1,6 @@ using Aquality.Selenium.Browsers; using Aquality.Selenium.Elements; +using Aquality.Selenium.Elements.Actions; using Aquality.Selenium.Tests.Integration.TestApp.TheInternet.Forms; using NUnit.Framework; using OpenQA.Selenium; @@ -38,13 +39,21 @@ public void Should_BePossibleTo_ClearAndType() } [Test] - public void Should_BePossibleTo_SendKeys() + public void Should_BePossibleTo_SendKey() { var passwordTxb = authForm.PasswordTextBox; - passwordTxb.SendKeys(Keys.NumberPad0); + passwordTxb.SendKey(Key.NumberPad0); Assert.AreEqual("0", passwordTxb.Value); } + [Test] + public void Should_BePossibleTo_SendKeys() + { + var passwordTxb = authForm.PasswordTextBox; + passwordTxb.SendKeys("00"); + Assert.AreEqual("00", passwordTxb.Value); + } + [Test] public void Should_BePossibleTo_Submit() { diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/UITest.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/UITest.cs index 8faffede..68fb1e75 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/UITest.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/UITest.cs @@ -11,7 +11,10 @@ internal class UITest [TearDown] public void CleanUp() { - AqualityServices.Browser.Quit(); + if (AqualityServices.IsBrowserStarted) + { + AqualityServices.Browser.Quit(); + } } } } diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Usecases/CustomBrowserFactoryTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Usecases/CustomBrowserFactoryTests.cs index 6d046b80..f07bc9ca 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Usecases/CustomBrowserFactoryTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/Usecases/CustomBrowserFactoryTests.cs @@ -6,10 +6,11 @@ using System; using WebDriverManager; using WebDriverManager.DriverConfigs.Impl; -using Microsoft.Extensions.DependencyInjection; using WebDriverManager.DriverConfigs; using WebDriverManager.Helpers; using System.IO; +using Aquality.Selenium.Core.Utilities; +using OpenQA.Selenium.Remote; namespace Aquality.Selenium.Tests.Integration.Usecases { @@ -48,21 +49,21 @@ public class CustomLocalBrowserFactory : BrowserFactory { private static readonly object WebDriverDownloadingLock = new object(); - public CustomLocalBrowserFactory() : base() + public CustomLocalBrowserFactory() : + base(AqualityServices.Get(), AqualityServices.Get(), AqualityServices.Get(), AqualityServices.LocalizedLogger) { } - public override Browser Browser => CreateBrowser(); - - private Browser CreateBrowser() + protected override RemoteWebDriver Driver { - var browserProfile = AqualityServices.Get(); - var driverSettings = browserProfile.DriverSettings; - SetUpDriver(new ChromeConfig(), driverSettings); - var driver = new ChromeDriver((ChromeOptions)driverSettings.DriverOptions); - return new Browser(driver); + get + { + var driverSettings = BrowserProfile.DriverSettings; + SetUpDriver(new ChromeConfig(), driverSettings); + return new ChromeDriver((ChromeOptions)driverSettings.DriverOptions); + } } - + private static void SetUpDriver(IDriverConfig driverConfig, IDriverSettings driverSettings) { var architecture = driverSettings.SystemArchitecture.Equals(Architecture.Auto) ? ArchitectureHelper.GetArchitecture() : driverSettings.SystemArchitecture; diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.azure.json b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.azure.json index 8c7d7cb7..650c50f9 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.azure.json +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.azure.json @@ -95,7 +95,8 @@ "pollingInterval": 300 }, "logger": { - "language": "en" + "language": "en", + "logPageSource": true }, "elementCache": { "isEnabled": false diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.json b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.json index 7c668c16..6172faaa 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.json +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.json @@ -94,7 +94,8 @@ "pollingInterval": 300 }, "logger": { - "language": "en" + "language": "en", + "logPageSource": true }, "elementCache": { "isEnabled": false diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.local.json b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.local.json index 9a44219c..ae24f1be 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.local.json +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Resources/settings.local.json @@ -98,7 +98,8 @@ "pollingInterval": 300 }, "logger": { - "language": "en" + "language": "en", + "logPageSource": true }, "elementCache": { "isEnabled": false diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Unit/Configuration/CustomConfigurationTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Unit/Configuration/CustomConfigurationTests.cs index c09c732d..7704b20d 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Unit/Configuration/CustomConfigurationTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Unit/Configuration/CustomConfigurationTests.cs @@ -48,6 +48,8 @@ public static void After() private class CustomLoggerConfiguration : ILoggerConfiguration { public string Language { get; } = SpecialLoggerLanguage; + + public bool LogPageSource => true; } private interface ICustomService