From 007b0e8fbf4aa2d0404b8d4c3ffcf92d18b9aa90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alaksiej=20Miale=C5=A1ka?= Date: Wed, 6 Sep 2023 14:12:00 +0200 Subject: [PATCH] [Enhancement] Use native function to open new tab (#237) * Use native function to open new tab - add functions ..ViaJs to access previous behavior - add overload accepting Uri parameter - fix typo in the documentation - refactor BrowserNavigation and BrowserTabNavigation initialization to allow inheritance - use native ExecuteScript functions instead of AqualityServices wrappers for correct constructor parameter usage - add tests for new functions closes #231 * Update Selenium package versions * Add retry on test task * Update TheInternetForm.cs to use https address * Restore theIntenetForm URL and rework the check in BrowserConcurrencyTests * Fix locator and change theInternet url once again * Change TheInternetForm URL to be HTTPS once again * Stabilize async actions in DevToolsEmulationTests * Update selenium version * Handle ChromeDriver session not created issue: https://groups.google.com/g/chromedriver-users/c/Dgv9xRHZf58 * Add temporary workaround to avoid navigation issue described at https://github.com/SeleniumHQ/selenium/issues/12277 * Try to stabilize Should_BePossibleTo_CheckThatHiddenElementsNotDisplayed * Use different vmImage: 'windows-2019' --------- Co-authored-by: Aliaksej Mialeshka --- .../Aquality.Selenium.csproj | 2 +- .../Aquality.Selenium/Aquality.Selenium.xml | 20 +++++++++- .../src/Aquality.Selenium/Browsers/Browser.cs | 4 +- .../Browsers/BrowserFactory.cs | 3 +- .../Browsers/BrowserNavigation.cs | 24 +++++++++-- .../Browsers/BrowserTabNavigation.cs | 34 +++++++++++++--- .../Browsers/IBrowserTabNavigation.cs | 23 ++++++++++- .../Aquality.Selenium.Tests.csproj | 2 +- .../Integration/BrowserTabsTests.cs | 37 ++++++++++++++++- .../Integration/DevToolsEmulationTests.cs | 39 +++++++++--------- .../Integration/DevToolsPerformanceTests.cs | 4 +- .../Integration/HiddenElementsTests.cs | 14 ++++++- .../Integration/JavaScriptHandlingTests.cs | 40 +++++++++---------- .../Integration/NetworkHandlingTests.cs | 14 +++---- .../TheInternet/Forms/JQueryMenuForm.cs | 2 +- .../TheInternet/Forms/TheInternetForm.cs | 2 +- azure-pipelines.yml | 3 +- 17 files changed, 196 insertions(+), 71 deletions(-) diff --git a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj index ba394f22..eb9b92cc 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj +++ b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj @@ -76,7 +76,7 @@ - + diff --git a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml index 08fc26ec..d5f0345e 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml +++ b/Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.xml @@ -680,7 +680,7 @@ - Closes curent tab. + Closes current tab. @@ -689,12 +689,30 @@ Switches to new tab if true and stays at current otherwise. + + + Opens new tab using JS function. + + Switches to new tab if true and stays at current otherwise. + Navigates to desired url in new tab. String representation of URL. + + + Navigates to desired url in new tab. + + target URL. + + + + Navigates to desired url in new tab using JS function. + + String representation of URL. + Predefined JS scripts. diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs index e35c40d4..1477ec24 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs @@ -216,7 +216,7 @@ public void Refresh() private INavigation Navigate() { - return new BrowserNavigation(Driver); + return new BrowserNavigation(Driver, Logger); } /// @@ -225,7 +225,7 @@ private INavigation Navigate() /// Instance of IBrowserTabNavigation. public IBrowserTabNavigation Tabs() { - return new BrowserTabNavigation(Driver); + return new BrowserTabNavigation(Driver, Logger); } /// diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserFactory.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserFactory.cs index 73e28f9f..c18823e8 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserFactory.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserFactory.cs @@ -2,6 +2,7 @@ using Aquality.Selenium.Core.Localization; using Aquality.Selenium.Core.Utilities; using OpenQA.Selenium; +using System; namespace Aquality.Selenium.Browsers { @@ -29,7 +30,7 @@ public virtual Browser Browser { get { - var browser = new Browser(ActionRetrier.DoWithRetry(() => Driver, new[] { typeof(WebDriverException) })); + var browser = new Browser(ActionRetrier.DoWithRetry(() => Driver, new[] { typeof(WebDriverException), typeof(InvalidOperationException) })); LocalizedLogger.Info("loc.browser.ready", BrowserProfile.BrowserName); return browser; } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserNavigation.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserNavigation.cs index 57343a1a..9693a674 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserNavigation.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserNavigation.cs @@ -11,12 +11,13 @@ public class BrowserNavigation : INavigation { private readonly WebDriver driver; - internal BrowserNavigation(WebDriver driver) + protected internal BrowserNavigation(WebDriver driver, ILocalizedLogger logger) { this.driver = driver; + Logger = logger; } - private ILocalizedLogger Logger => AqualityServices.LocalizedLogger; + private ILocalizedLogger Logger { get; } /// /// Navigates back. @@ -43,7 +44,15 @@ public void Forward() public void GoToUrl(string url) { InfoLocNavigate(url); - driver.Navigate().GoToUrl(url); + // temporary workaround to avoid issue described at https://github.com/SeleniumHQ/selenium/issues/12277 + try + { + driver.Navigate().GoToUrl(url); + } + catch (WebDriverException e) when (driver.Url == url) + { + Logger.Fatal($"Navigation error occurred: [{e.Message}], but successfully navigated to URL [{url}]", e); + } } /// @@ -53,7 +62,14 @@ public void GoToUrl(string url) public void GoToUrl(Uri url) { InfoLocNavigate(url.ToString()); - driver.Navigate().GoToUrl(url); + try + { + driver.Navigate().GoToUrl(url); + } + catch (WebDriverException e) when (driver.Url == url.ToString()) + { + Logger.Fatal($"Navigation error occurred: [{e.Message}], but successfully navigated to URL [{url}]", e); + } } /// diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserTabNavigation.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserTabNavigation.cs index 35b59dc3..2654a15e 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserTabNavigation.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/BrowserTabNavigation.cs @@ -10,12 +10,13 @@ public class BrowserTabNavigation : IBrowserTabNavigation { private readonly WebDriver driver; - internal BrowserTabNavigation(WebDriver driver) + protected internal BrowserTabNavigation(WebDriver driver, ILocalizedLogger logger) { this.driver = driver; + Logger = logger; } - private ILocalizedLogger Logger => AqualityServices.LocalizedLogger; + private ILocalizedLogger Logger { get; } public string CurrentTabHandle { @@ -44,7 +45,18 @@ public void CloseTab() public void OpenNewTab(bool switchToNew = true) { Logger.Info("loc.browser.tab.open.new"); - AqualityServices.Browser.ExecuteScript(JavaScript.OpenNewTab); + var currentHandle = switchToNew ? null : CurrentTabHandle; + driver.SwitchTo().NewWindow(WindowType.Tab); + if (!switchToNew) + { + CloseAndSwitch(currentHandle, closeCurrent: false); + } + } + + public void OpenNewTabViaJs(bool switchToNew = true) + { + Logger.Info("loc.browser.tab.open.new"); + driver.ExecuteScript(JavaScript.OpenNewTab.GetScript()); if (switchToNew) { SwitchToLastTab(); @@ -53,7 +65,19 @@ public void OpenNewTab(bool switchToNew = true) public void OpenInNewTab(string url) { - AqualityServices.Browser.ExecuteScript(JavaScript.OpenInNewTab, url); + OpenNewTab(switchToNew: true); + driver.Navigate().GoToUrl(url); + } + + public void OpenInNewTab(Uri url) + { + OpenNewTab(switchToNew: true); + driver.Navigate().GoToUrl(url); + } + + public void OpenInNewTabViaJs(string url) + { + driver.ExecuteScript(JavaScript.OpenInNewTab.GetScript(), url); } public void SwitchToLastTab(bool closeCurrent = false) @@ -78,7 +102,7 @@ public void SwitchToTab(int index, bool closeCurrent = false) $"Index of browser tab '{index}' you provided is out of range {0}..{names.Count}"); } - var newTab = names.ElementAt(index); + var newTab = names[index]; CloseAndSwitch(newTab, closeCurrent); } diff --git a/Aquality.Selenium/src/Aquality.Selenium/Browsers/IBrowserTabNavigation.cs b/Aquality.Selenium/src/Aquality.Selenium/Browsers/IBrowserTabNavigation.cs index e8dde20e..d54dbf40 100644 --- a/Aquality.Selenium/src/Aquality.Selenium/Browsers/IBrowserTabNavigation.cs +++ b/Aquality.Selenium/src/Aquality.Selenium/Browsers/IBrowserTabNavigation.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Aquality.Selenium.Browsers { @@ -40,7 +41,7 @@ public interface IBrowserTabNavigation void SwitchToLastTab(bool closeCurrent = false); /// - /// Closes curent tab. + /// Closes current tab. /// void CloseTab(); @@ -50,10 +51,28 @@ public interface IBrowserTabNavigation /// Switches to new tab if true and stays at current otherwise. void OpenNewTab(bool switchToNew = true); + /// + /// Opens new tab using JS function. + /// + /// Switches to new tab if true and stays at current otherwise. + void OpenNewTabViaJs(bool switchToNew = true); + /// /// Navigates to desired url in new tab. /// /// String representation of URL. void OpenInNewTab(string url); + + /// + /// Navigates to desired url in new tab. + /// + /// target URL. + void OpenInNewTab(Uri url); + + /// + /// Navigates to desired url in new tab using JS function. + /// + /// String representation of URL. + void OpenInNewTabViaJs(string url); } } diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Aquality.Selenium.Tests.csproj b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Aquality.Selenium.Tests.csproj index 6d7531ce..4c6210c3 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Aquality.Selenium.Tests.csproj +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Aquality.Selenium.Tests.csproj @@ -34,7 +34,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/BrowserTabsTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/BrowserTabsTests.cs index 5c45335f..9f23e6c0 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/BrowserTabsTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/BrowserTabsTests.cs @@ -22,10 +22,29 @@ public void Should_BePossibleTo_OpenUrlInNewTab() var url = new WelcomeForm().Url; var browser = AqualityServices.Browser; browser.Tabs().OpenInNewTab(url); - browser.Tabs().SwitchToLastTab(); Assert.AreEqual(2, browser.Tabs().TabHandles.Count); Assert.AreEqual(browser.Driver.Url, url); } + + [Test] + public void Should_BePossibleTo_OpenUrlInNewTab_ViaJs() + { + var url = new WelcomeForm().Url; + var browser = AqualityServices.Browser; + browser.Tabs().OpenInNewTabViaJs(url); + Assert.AreEqual(2, browser.Tabs().TabHandles.Count); + Assert.AreEqual(browser.Driver.Url, url); + } + + [Test] + public void Should_BePossibleTo_OpenUriInNewTab() + { + var url = new Uri(new WelcomeForm().Url); + var browser = AqualityServices.Browser; + browser.Tabs().OpenInNewTab(url); + Assert.AreEqual(2, browser.Tabs().TabHandles.Count); + Assert.AreEqual(new Uri(browser.Driver.Url), url); + } [Test] public void Should_BePossibleTo_HandleTab() @@ -60,6 +79,22 @@ public void Should_BePossibleTo_OpenNewTab() Assert.AreEqual(newTabHandle, browser.Tabs().CurrentTabHandle, "Browser should not be switched to new tab"); } + [Test] + public void Should_BePossibleTo_OpenNewTab_ViaJs() + { + var browser = AqualityServices.Browser; + var tabHandle = browser.Tabs().CurrentTabHandle; + + browser.Tabs().OpenNewTabViaJs(); + var newTabHandle = browser.Tabs().CurrentTabHandle; + Assert.AreEqual(2, browser.Tabs().TabHandles.Count, "New tab should be opened"); + Assert.AreNotEqual(tabHandle, newTabHandle, "Browser should be switched to new tab"); + + browser.Tabs().OpenNewTabViaJs(false); + Assert.AreEqual(3, browser.Tabs().TabHandles.Count, "New tab should be opened"); + Assert.AreEqual(newTabHandle, browser.Tabs().CurrentTabHandle, "Browser should not be switched to new tab"); + } + [Test] public void Should_BePossibleTo_CloseTab() { diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsEmulationTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsEmulationTests.cs index 373b8047..15d810d9 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsEmulationTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsEmulationTests.cs @@ -50,7 +50,7 @@ public void Should_BePossibleTo_CheckThatBrowserCanEmulate() public void Should_BePossibleTo_SetAndClearDeviceMetricsOverride() { CheckDeviceMetricsOverride((width, height, isMobile, scaleFactor) => Assert.DoesNotThrowAsync( - () => DevTools.SetDeviceMetricsOverride(width, height, isMobile), "Should be possible to set device metrics override")); + async () => await DevTools.SetDeviceMetricsOverride(width, height, isMobile), "Should be possible to set device metrics override")); } [Test] @@ -58,18 +58,18 @@ public void Should_BePossibleTo_SetAndClearDeviceMetricsOverride_WithVersionSpec { void setAction(long width, long height, bool isMobile, double scaleFactor) { - var parameters = new OpenQA.Selenium.DevTools.V108.Emulation.SetDeviceMetricsOverrideCommandSettings + var parameters = new OpenQA.Selenium.DevTools.V116.Emulation.SetDeviceMetricsOverrideCommandSettings { - DisplayFeature = new OpenQA.Selenium.DevTools.V108.Emulation.DisplayFeature + DisplayFeature = new OpenQA.Selenium.DevTools.V116.Emulation.DisplayFeature { - Orientation = OpenQA.Selenium.DevTools.V108.Emulation.DisplayFeatureOrientationValues.Horizontal + Orientation = OpenQA.Selenium.DevTools.V116.Emulation.DisplayFeatureOrientationValues.Horizontal }, Width = width, Height = height, Mobile = isMobile, DeviceScaleFactor = scaleFactor }; - Assert.DoesNotThrowAsync(() => DevTools.SetDeviceMetricsOverride(parameters), + Assert.DoesNotThrowAsync(async () => await DevTools.SetDeviceMetricsOverride(parameters), "Should be possible to set device metrics override with version-specific parameters, even if the version doesn't match"); } @@ -79,15 +79,16 @@ void setAction(long width, long height, bool isMobile, double scaleFactor) private static void CheckDeviceMetricsOverride(Action setAction) { static long getWindowHeight() => AqualityServices.Browser.ExecuteScriptFromFile("Resources.GetWindowSize.js"); + var welcomeForm = new WelcomeForm(); + welcomeForm.Open(); var initialValue = getWindowHeight(); Assume.That(initialValue, Is.Not.EqualTo(DeviceModeSettingHeight), "To check that override works, initial value should differ from the new one"); setAction(DeviceModeSettingWidth, DeviceModeSettingHeight, DeviceModeSettingMobile, DeviceModeSettingDeviceScaleFactor); - var welcomeForm = new WelcomeForm(); - welcomeForm.Open(); Assert.AreEqual(DeviceModeSettingHeight, getWindowHeight(), "Browser height should match to override value"); - Assert.DoesNotThrowAsync(() => DevTools.ClearDeviceMetricsOverride(), "Should be possible to clear device metrics override"); + Assert.DoesNotThrowAsync(async () => await DevTools.ClearDeviceMetricsOverride(), "Should be possible to clear device metrics override"); AqualityServices.Browser.Refresh(); + AqualityServices.Browser.WaitForPageToLoad(); Assert.AreEqual(initialValue, getWindowHeight(), "Browser height should match to initial value after clear"); } @@ -96,8 +97,8 @@ public void Should_BePossibleTo_SetAndClearGeoLocationOverride() { CheckGeolocationOverride( (latitude, longitude, accuracy) => - Assert.DoesNotThrowAsync(() => DevTools.SetGeoLocationOverride(latitude, longitude, accuracy), "Should be possible to override geoLocation"), - () => Assert.DoesNotThrowAsync(() => DevTools.ClearGeolocationOverride(), "Should be possible to clear geoLocation")); + Assert.DoesNotThrowAsync(async () => await DevTools.SetGeoLocationOverride(latitude, longitude, accuracy), "Should be possible to override geoLocation"), + () => Assert.DoesNotThrowAsync(async () => await DevTools.ClearGeolocationOverride(), "Should be possible to clear geoLocation")); } [Test] @@ -150,7 +151,7 @@ public void Should_BePossibleTo_SetUserAgentAndLanguageOverride() Assume.That(defaultLanguage, Is.Not.EqualTo(CustomAcceptLanguage), "Default accept-language header should be different from the custom one to check override"); Assume.That(defaultUserAgent, Is.Not.EqualTo(CustomUserAgent), "Default user agent header should be different from the custom one to check override"); - Assert.DoesNotThrowAsync(() => DevTools.SetUserAgentOverride(CustomUserAgent, CustomAcceptLanguage), "Should be possible to set user agent override"); + Assert.DoesNotThrowAsync(async () => await DevTools.SetUserAgentOverride(CustomUserAgent, CustomAcceptLanguage), "Should be possible to set user agent override"); StringAssert.Contains(CustomAcceptLanguage, new BrowserLanguageForm().Open().Value, "Accept-language header should match to value set"); Assert.AreEqual(CustomUserAgent, new UserAgentForm().Open().Value, "User agent should match to value set"); } @@ -163,11 +164,11 @@ public void Should_BePossibleTo_SetScriptExecutionDisabled_AndEnableAgain() alertsForm.JsAlertButton.Click(); Assert.DoesNotThrow(() => AqualityServices.Browser.HandleAlert(AlertAction.Accept), "Alert should appear and be handled"); - Assert.DoesNotThrowAsync(() => DevTools.SetScriptExecutionDisabled(), "Should be possible to set script execution disabled"); + Assert.DoesNotThrowAsync(async () => await DevTools.SetScriptExecutionDisabled(), "Should be possible to set script execution disabled"); alertsForm.JsAlertButton.Click(); Assert.Throws(() => AqualityServices.Browser.HandleAlert(AlertAction.Accept), "Alert should not appear as JS scripts disabled"); - Assert.DoesNotThrowAsync(() => DevTools.SetScriptExecutionDisabled(false), "Should be possible to set script execution enabled"); + Assert.DoesNotThrowAsync(async () => await DevTools.SetScriptExecutionDisabled(false), "Should be possible to set script execution enabled"); alertsForm.JsAlertButton.Click(); Assert.DoesNotThrow(() => AqualityServices.Browser.HandleAlert(AlertAction.Accept), "Alert should appear and be handled as JS scripts are enabled again"); } @@ -178,9 +179,9 @@ public void Should_BePossibleTo_SetTouchEmulationEnabled_AndDisabled() static bool isTouchEnabled() => AqualityServices.Browser.ExecuteScriptFromFile("Resources.IsTouchEnabled.js"); Assume.That(isTouchEnabled, Is.False, "Touch should be initially disabled"); - Assert.DoesNotThrowAsync(() => DevTools.SetTouchEmulationEnabled(true), "Should be possible to enable touch emulation"); + Assert.DoesNotThrowAsync(async () => await DevTools.SetTouchEmulationEnabled(true), "Should be possible to enable touch emulation"); Assert.IsTrue(isTouchEnabled(), "Touch should be enabled"); - Assert.DoesNotThrowAsync(() => DevTools.SetTouchEmulationEnabled(new SetTouchEmulationEnabledCommandSettings { Enabled = false }), + Assert.DoesNotThrowAsync(async () => await DevTools.SetTouchEmulationEnabled(new SetTouchEmulationEnabledCommandSettings { Enabled = false }), "Should be possible to disable touch emulation"); Assert.IsFalse(isTouchEnabled(), "Touch should be disabled"); } @@ -194,19 +195,19 @@ public void Should_BePossibleTo_SetEmulatedMedia() var initialValue = getMediaType(); Assume.That(initialValue, Does.Not.Contain(emulatedMedia), "Initial media type should differ from value to be set"); - Assert.DoesNotThrowAsync(() => DevTools.SetEmulatedMedia(emulatedMedia, new Dictionary { { "width", DeviceModeSettingWidth.ToString() } }), + Assert.DoesNotThrowAsync(async () => await DevTools.SetEmulatedMedia(emulatedMedia, new Dictionary { { "width", DeviceModeSettingWidth.ToString() } }), "Should be possible to set emulated media"); Assert.AreEqual(emulatedMedia, getMediaType(), "Media type should equal to emulated"); - Assert.DoesNotThrowAsync(() => DevTools.DisableEmulatedMediaOverride(), "Should be possible to disable emulated media override"); + Assert.DoesNotThrowAsync(async () => await DevTools.DisableEmulatedMediaOverride(), "Should be possible to disable emulated media override"); Assert.AreEqual(initialValue, getMediaType(), "Media type should equal to initial after disabling the override"); } [Test] public void Should_BePossibleTo_SetDefaultBackgroundColorOverride() { - Assert.DoesNotThrowAsync(() => DevTools.SetDefaultBackgroundColorOverride(0, 255, 38, 0.25), + Assert.DoesNotThrowAsync(async () => await DevTools.SetDefaultBackgroundColorOverride(0, 255, 38, 0.25), "Should be possible to set default background color override"); - Assert.DoesNotThrowAsync(() => DevTools.ClearDefaultBackgroundColorOverride(), + Assert.DoesNotThrowAsync(async () => await DevTools.ClearDefaultBackgroundColorOverride(), "Should be possible to clear default background color override"); } } diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsPerformanceTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsPerformanceTests.cs index 0fd30e4d..4db4b426 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsPerformanceTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/DevToolsPerformanceTests.cs @@ -11,7 +11,7 @@ internal class DevToolsPerformanceTests : UITest [Test] public void Should_BePossibleTo_CollectPerformanceMetrics() { - Assert.DoesNotThrowAsync(() => DevTools.EnablePerfomanceMonitoring(), "Should be possible to enable performance monitoring"); + Assert.DoesNotThrowAsync(async () => await DevTools.EnablePerfomanceMonitoring(), "Should be possible to enable performance monitoring"); AqualityServices.Browser.GoTo("http://www.google.com"); IDictionary metrics = null; @@ -22,7 +22,7 @@ public void Should_BePossibleTo_CollectPerformanceMetrics() IDictionary otherMetrics = DevTools.GetPerformanceMetrics().GetAwaiter().GetResult(); CollectionAssert.AreNotEqual(otherMetrics, metrics, "Some additional metrics should have been collected"); - Assert.DoesNotThrowAsync(() => DevTools.DisablePerfomanceMonitoring(), "Should be possible to disable performance monitoring"); + Assert.DoesNotThrowAsync(async () => await DevTools.DisablePerfomanceMonitoring(), "Should be possible to disable performance monitoring"); AqualityServices.Browser.Refresh(); metrics = DevTools.GetPerformanceMetrics().GetAwaiter().GetResult(); CollectionAssert.IsEmpty(metrics, "Metrics should have not been collected after performance monitoring have been disabled"); diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/HiddenElementsTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/HiddenElementsTests.cs index ee5ae220..94802e76 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/HiddenElementsTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/HiddenElementsTests.cs @@ -1,4 +1,5 @@ -using Aquality.Selenium.Core.Elements; +using Aquality.Selenium.Browsers; +using Aquality.Selenium.Core.Elements; using Aquality.Selenium.Elements.Interfaces; using Aquality.Selenium.Tests.Integration.TestApp.TheInternet.Forms; using NUnit.Framework; @@ -56,7 +57,16 @@ public void Should_BePossibleTo_CheckThatHiddenElementsNotDisplayed( Assert.Multiple(() => { Assert.IsTrue(elements.Any()); - Assert.IsTrue(elements.All(element => element.State.WaitForNotDisplayed())); + Assert.IsTrue(elements.All(element => + { + var result = element.State.WaitForNotDisplayed(); + if (!result) + { + AqualityServices.Browser.Refresh(); + result = element.State.WaitForNotDisplayed(); + } + return result; + })); }); } } diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/JavaScriptHandlingTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/JavaScriptHandlingTests.cs index c74e1ec2..c0399250 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/JavaScriptHandlingTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/JavaScriptHandlingTests.cs @@ -24,11 +24,11 @@ public void Should_BePossibleTo_SubscribeToDomMutationEvent_AndUnsubscribeFromIt var attributeValueChanges = new List(); void eventHandler(object sender, DomMutatedEventArgs e) => attributeValueChanges.Add(e.AttributeData); JavaScriptEngine.DomMutated += eventHandler; - Assert.DoesNotThrowAsync(() => JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); + Assert.DoesNotThrowAsync(async() => await JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); welcomeForm.Open(); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.EnableDomMutationMonitoring(), "Should be possible to enable DOM mutation monitoring"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.EnableDomMutationMonitoring(), "Should be possible to enable DOM mutation monitoring"); welcomeForm.SubTitleLabel.JsActions.SetAttribute(attributeName, attributeValue); AqualityServices.ConditionalWait.WaitForTrue(() => attributeValueChanges.Count > 0, @@ -43,7 +43,7 @@ public void Should_BePossibleTo_SubscribeToDomMutationEvent_AndUnsubscribeFromIt AqualityServices.ConditionalWait.WaitFor(() => attributeValueChanges.Count > 1, timeout: NegativeConditionTimeout); Assert.AreEqual(1, attributeValueChanges.Count, "No more changes in DOM is expected, should be possible to unsubscribe from DOM mutation event"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.DisableDomMutationMonitoring(), "Should be possible to disable DOM mutation monitoring"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.DisableDomMutationMonitoring(), "Should be possible to disable DOM mutation monitoring"); Assert.DoesNotThrow(() => JavaScriptEngine.StopEventMonitoring(), "Should be possible to stop event monitoring"); } @@ -61,11 +61,11 @@ public void Should_BePossibleTo_PinScript_AndUnpinIt() var expectedValue = welcomeForm.SubTitleLabel.JsActions.GetXPath(); Assert.AreEqual(expectedValue, xpath, "Pinned script should return the same value"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.UnpinScript(pinnedScript), "Should be possible to unpin the script"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.UnpinScript(pinnedScript), "Should be possible to unpin the script"); Assert.Throws( () => pinnedScript.ExecuteScript(welcomeForm.SubTitleLabel), "Unpinned script should not return the value"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.Reset(), "Should be possible to reset JavaScript monitoring"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.Reset(), "Should be possible to reset JavaScript monitoring"); } [Test] @@ -83,7 +83,7 @@ public void Should_BePossibleTo_PinScript_WithoutReturnedValue_AndUnpinIt() var actualText = keyPressesForm.InputTextBox.Value; Assert.AreEqual(text, actualText, $"Text should be '{text}' after setting value via pinned JS"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.UnpinScript(pinnedScript), "Should be possible to unpin the script"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.UnpinScript(pinnedScript), "Should be possible to unpin the script"); Assert.Throws(() => pinnedScript.ExecuteScript(keyPressesForm.InputTextBox, text), "Unpinned script should not be executed"); } @@ -94,7 +94,7 @@ public void Should_BePossibleTo_SubscribeToJavaScriptConsoleApiCalledEvent_AndUn var apiCalledMessages = new List(); void eventHandler(object sender, JavaScriptConsoleApiCalledEventArgs e) => apiCalledMessages.Add(e.MessageContent); JavaScriptEngine.JavaScriptConsoleApiCalled += eventHandler; - Assert.DoesNotThrowAsync(() => JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); AqualityServices.Browser.ExecuteScript(consoleApiScript); @@ -115,7 +115,7 @@ public void Should_BePossibleTo_SubscribeToJavaScriptExceptionThrownEvent_AndUns var errorMessages = new List(); void eventHandler(object sender, JavaScriptExceptionThrownEventArgs e) => errorMessages.Add(e.Message); JavaScriptEngine.JavaScriptExceptionThrown += eventHandler; - Assert.DoesNotThrowAsync(() => JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); welcomeForm.Open(); welcomeForm.SubTitleLabel.JsActions.SetAttribute("onclick", "throw new Error('Hello, world!')"); welcomeForm.SubTitleLabel.Click(); @@ -140,30 +140,30 @@ public void Should_BePossibleTo_AddInitializationScript_GetIt_ThenRemove_OrClear Assert.AreEqual(script, initScript.ScriptSource, "Saved script source should match to expected"); Assert.AreEqual(name, initScript.ScriptName, "Saved script name should match to expected"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); + Assert.DoesNotThrowAsync(async() => await JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); AqualityServices.Browser.Refresh(); Assert.DoesNotThrow(() => AqualityServices.Browser.HandleAlert(AlertAction.Accept), "Alert should appear and be possible to handle"); Assert.DoesNotThrow(() => AqualityServices.Browser.RefreshPageWithAlert(AlertAction.Accept), "Alert should appear after the refresh and be possible to handle"); Assert.That(JavaScriptEngine.InitializationScripts, Has.Member(initScript), "Should be possible to read initialization scripts"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.RemoveInitializationScript(name), "Should be possible to remove initialization script"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.RemoveInitializationScript(name), "Should be possible to remove initialization script"); AqualityServices.Browser.Refresh(); Assert.Throws(() => AqualityServices.Browser.HandleAlert(AlertAction.Accept), "Initialization script should not be executed after the remove"); Assert.That(JavaScriptEngine.InitializationScripts, Is.Empty, "Should be possible to read initialization scripts after remove"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.AddInitializationScript(name, script), "Should be possible to add the same initialization script again"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.AddInitializationScript(name, script), "Should be possible to add the same initialization script again"); Assert.DoesNotThrow(() => AqualityServices.Browser.RefreshPageWithAlert(AlertAction.Accept), "Alert should appear and be possible to handle"); Assert.That(JavaScriptEngine.InitializationScripts, Has.One.Items, "Exactly one script should be among initialization scripts"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.ClearInitializationScripts(), "Should be possible to clear initialization scripts"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.ClearInitializationScripts(), "Should be possible to clear initialization scripts"); Assert.Throws(() => AqualityServices.Browser.RefreshPageWithAlert(AlertAction.Accept), "Initialization script should not be executed after the clear"); Assert.That(JavaScriptEngine.InitializationScripts, Is.Empty, "Should be possible to read initialization scripts after clear"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.AddInitializationScript(name, script), "Should be possible to add the same initialization script again"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.AddInitializationScript(name, script), "Should be possible to add the same initialization script again"); Assert.DoesNotThrow(() => AqualityServices.Browser.RefreshPageWithAlert(AlertAction.Accept), "Alert should appear and be possible to handle"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.ClearAll(), "Should be possible to clear all JavaScript monitoring"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.ClearAll(), "Should be possible to clear all JavaScript monitoring"); Assert.Throws(() => AqualityServices.Browser.RefreshPageWithAlert(AlertAction.Accept), "Initialization script should not be executed after the clear all"); Assert.That(JavaScriptEngine.InitializationScripts, Is.Empty, "Should be possible to read initialization scripts after clear all"); @@ -178,11 +178,11 @@ public void Should_BePossibleTo_AddScriptCallbackBinding_SubscribeAndUnsubscribe var executedBindings = new List(); void eventHandler(object sender, JavaScriptCallbackExecutedEventArgs e) => executedBindings.Add(e.BindingName); JavaScriptEngine.JavaScriptCallbackExecuted += eventHandler; - Assert.DoesNotThrowAsync(() => JavaScriptEngine.AddInitializationScript(scriptName, script), "Should be possible to add initialization script"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.AddInitializationScript(scriptName, script), "Should be possible to add initialization script"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.StartEventMonitoring(), "Should be possible to start event monitoring"); Assert.DoesNotThrow(() => AqualityServices.Browser.RefreshPageWithAlert(AlertAction.Accept), "Alert should appear and be possible to handle"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.AddScriptCallbackBinding(scriptName), "Should be possible to add script callback binding"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.AddScriptCallbackBinding(scriptName), "Should be possible to add script callback binding"); Assert.Throws(() => AqualityServices.Browser.RefreshPageWithAlert(AlertAction.Accept), "Callback binding should prevent from initialization script execution"); AqualityServices.ConditionalWait.WaitForTrue(() => executedBindings.Contains(scriptName), message: "Subscription to JavaScriptCallbackExecuted event should work"); @@ -192,11 +192,11 @@ public void Should_BePossibleTo_AddScriptCallbackBinding_SubscribeAndUnsubscribe Assert.That(JavaScriptEngine.ScriptCallbackBindings, Has.Member(scriptName), "Should be possible to read script callback bindings"); oldCount = executedBindings.Count; - Assert.DoesNotThrowAsync(() => JavaScriptEngine.RemoveScriptCallbackBinding(scriptName), "Should be possible to remove script callback binding"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.RemoveScriptCallbackBinding(scriptName), "Should be possible to remove script callback binding"); Assert.That(JavaScriptEngine.ScriptCallbackBindings, Is.Empty, "Should be possible to read script callback bindings after remove"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.AddScriptCallbackBinding(scriptName), "Should be possible to add script callback binding again"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.AddScriptCallbackBinding(scriptName), "Should be possible to add script callback binding again"); Assert.That(JavaScriptEngine.ScriptCallbackBindings, Has.Member(scriptName), "Should be possible to read script callback bindings"); - Assert.DoesNotThrowAsync(() => JavaScriptEngine.ClearScriptCallbackBindings(), "Should be possible to clear script callback bindings"); + Assert.DoesNotThrowAsync(async () => await JavaScriptEngine.ClearScriptCallbackBindings(), "Should be possible to clear script callback bindings"); Assert.That(JavaScriptEngine.ScriptCallbackBindings, Is.Empty, "Should be possible to read script callback bindings after remove"); JavaScriptEngine.JavaScriptCallbackExecuted -= eventHandler; diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/NetworkHandlingTests.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/NetworkHandlingTests.cs index a05cf219..982d2d6f 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/NetworkHandlingTests.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/NetworkHandlingTests.cs @@ -17,7 +17,7 @@ public void Should_BePossibleTo_SetBasicAuthentication() var welcomeForm = new WelcomeForm(); welcomeForm.Open(); var basicAuthForm = new BasicAuthForm(); - Assert.DoesNotThrowAsync(() => AqualityServices.Browser.RegisterBasicAuthenticationAndStartMonitoring(BasicAuthForm.Domain, BasicAuthForm.User, BasicAuthForm.Password), + Assert.DoesNotThrowAsync(async () => await AqualityServices.Browser.RegisterBasicAuthenticationAndStartMonitoring(BasicAuthForm.Domain, BasicAuthForm.User, BasicAuthForm.Password), "Should be possible to set basic authentication async"); basicAuthForm.Open(); Assert.IsTrue(basicAuthForm.IsCongratulationsPresent, "Basic authentication should work"); @@ -29,12 +29,12 @@ public void Should_BePossibleTo_ClearBasicAuthentication() var welcomeForm = new WelcomeForm(); welcomeForm.Open(); var basicAuthForm = new BasicAuthForm(); - Assert.DoesNotThrowAsync(() => AqualityServices.Browser.RegisterBasicAuthenticationAndStartMonitoring(BasicAuthForm.Domain, BasicAuthForm.User, BasicAuthForm.Password), + Assert.DoesNotThrowAsync(async () => await AqualityServices.Browser.RegisterBasicAuthenticationAndStartMonitoring(BasicAuthForm.Domain, BasicAuthForm.User, BasicAuthForm.Password), "Should be possible to set basic authentication async"); AqualityServices.Browser.Network.ClearAuthenticationHandlers(); basicAuthForm.Open(); Assert.IsFalse(basicAuthForm.IsCongratulationsPresent, "Basic authentication should not work after the handler is cleared"); - Assert.DoesNotThrowAsync(() => AqualityServices.Browser.Network.StopMonitoring(), "Should be possible to stop network monitoring"); + Assert.DoesNotThrowAsync(async () => await AqualityServices.Browser.Network.StopMonitoring(), "Should be possible to stop network monitoring"); } [Test] @@ -66,7 +66,7 @@ public void Should_BePossibleTo_AddAndClearResponseHandler() ResponseMatcher = res => true, ResponseTransformer = res => new HttpResponseData { Body = somePhrase, StatusCode = 200 } }); - Assert.DoesNotThrowAsync(() => AqualityServices.Browser.Network.StartMonitoring()); + Assert.DoesNotThrowAsync(async() => await AqualityServices.Browser.Network.StartMonitoring()); var welcomeForm = new WelcomeForm(); welcomeForm.Open(); StringAssert.Contains(somePhrase, AqualityServices.Browser.Driver.PageSource, "Response should be intercepted"); @@ -83,7 +83,7 @@ public void Should_BePossibleTo_SubscribeToRequestSentEvent_AndUnsubscribeFromIt var counter = 0; void eventHandler(object sender, NetworkRequestSentEventArgs args) => ++counter; AqualityServices.Browser.Network.NetworkRequestSent += eventHandler; - Assert.DoesNotThrowAsync(() => AqualityServices.Browser.Network.StartMonitoring()); + Assert.DoesNotThrowAsync(async () => await AqualityServices.Browser.Network.StartMonitoring()); welcomeForm.Open(); Assert.That(counter, Is.GreaterThan(0), "Should be possible to subscribe to Request Sent event"); var oldValue = counter; @@ -100,7 +100,7 @@ public void Should_BePossibleTo_SubscribeToResponseReceivedEvent_AndUnsubscribeF var counter = 0; void eventHandler(object sender, NetworkResponseReceivedEventArgs args) => ++counter; AqualityServices.Browser.Network.NetworkResponseReceived += eventHandler; - Assert.DoesNotThrowAsync(() => AqualityServices.Browser.Network.StartMonitoring()); + Assert.DoesNotThrowAsync(async () => await AqualityServices.Browser.Network.StartMonitoring()); welcomeForm.Open(); Assert.That(counter, Is.GreaterThan(0), "Should be possible to subscribe to Response Received event"); var oldValue = counter; @@ -117,7 +117,7 @@ public void Should_BePossibleTo_EnableHttpExchangeLogging_AndDisableIt() someForm.Open(); var logMessage1 = File.ReadAllLines(LogPath).LastOrDefault(); Assert.IsFalse(string.IsNullOrEmpty(logMessage1), "Some message should appear in log file and should not be empty"); - Assert.DoesNotThrowAsync(() => AqualityServices.Browser.EnableHttpExchangeLoggingAndStartMonitoring(), "Should be possible to enable HTTP exchange logging"); + Assert.DoesNotThrowAsync(async () => await AqualityServices.Browser.EnableHttpExchangeLoggingAndStartMonitoring(), "Should be possible to enable HTTP exchange logging"); AqualityServices.Browser.Driver.Navigate().Refresh(); var logMessage2 = File.ReadAllLines(LogPath).LastOrDefault(); Assert.IsFalse(string.IsNullOrEmpty(logMessage2), "Some message should appear in log file and should not be empty"); diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/TestApp/TheInternet/Forms/JQueryMenuForm.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/TestApp/TheInternet/Forms/JQueryMenuForm.cs index 5d2b42c1..0e7361a0 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/TestApp/TheInternet/Forms/JQueryMenuForm.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/TestApp/TheInternet/Forms/JQueryMenuForm.cs @@ -9,7 +9,7 @@ public JQueryMenuForm() : base(By.Id("menu"), "JQueryUI menu") { } - public static IButton EnabledButton => ElementFactory.GetButton(By.Id("ui-id-2"), "Enabled"); + public static IButton EnabledButton => ElementFactory.GetButton(By.XPath("//*[@id='ui-id-2' or @id='ui-id-3']"), "Enabled"); public static bool IsEnabledButtonFocused => EnabledButton.GetAttribute("class").Contains("focus"); diff --git a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/TestApp/TheInternet/Forms/TheInternetForm.cs b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/TestApp/TheInternet/Forms/TheInternetForm.cs index 73f88eab..7bf1c956 100644 --- a/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/TestApp/TheInternet/Forms/TheInternetForm.cs +++ b/Aquality.Selenium/tests/Aquality.Selenium.Tests/Integration/TestApp/TheInternet/Forms/TheInternetForm.cs @@ -8,7 +8,7 @@ namespace Aquality.Selenium.Tests.Integration.TestApp.TheInternet.Forms internal abstract class TheInternetForm : Form { private ILink ElementalSeleniumLink => ElementFactory.GetLink(By.XPath("//a[contains(@href,'elementalselenium')]"), "Elemental Selenium"); - private const string BaseUrl = "http://the-internet.herokuapp.com/"; + private const string BaseUrl = "https://the-internet.herokuapp.com/"; protected TheInternetForm(By locator, string name) : base(locator, name) { diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8651f7d0..45946920 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -2,7 +2,7 @@ trigger: - master pool: - vmImage: 'windows-latest' + vmImage: 'windows-2019' variables: buildConfiguration: 'Release' @@ -63,6 +63,7 @@ stages: - task: DotNetCoreCLI@2 displayName: 'Run tests' + retryCountOnTaskFailure: 1 inputs: command: 'test' projects: '**/*Tests*/*.csproj'