From 1abb77764278567de622f09ef64440f72dd9ce1d Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:13:37 +0400 Subject: [PATCH 01/32] Added first code to test poc --- ....Automation.Implementation.Selenium.csproj | 38 +++++ .../Bindings/NavigationBInding.cs | 142 ++++++++++++++++++ Behavioral.Automation.sln | 19 +++ 3 files changed, 199 insertions(+) create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj create mode 100644 Behavioral.Automation.Implementation.Selenium/Bindings/NavigationBInding.cs diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj new file mode 100644 index 0000000..aa35da8 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -0,0 +1,38 @@ + + + + net6.0 + enable + enable + Behavioral.Automation.Implementation.Selenium + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Behavioral.Automation.Implementation.Selenium/Bindings/NavigationBInding.cs b/Behavioral.Automation.Implementation.Selenium/Bindings/NavigationBInding.cs new file mode 100644 index 0000000..ebef3fb --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Bindings/NavigationBInding.cs @@ -0,0 +1,142 @@ +namespace SpecFlowProject1.Bindings +{ + /// + /// Bindings for URL navigation and testing + /// + [Binding] + public sealed class NavigationBinding + { + private readonly IDriverService _driverService; + private readonly IScopeContextManager _scopeContextManager; + + public NavigationBinding([NotNull] IDriverService driverService, + [NotNull] IScopeContextManager scopeContextManager) + { + _driverService = driverService; + _scopeContextManager = scopeContextManager; + } + + /// + /// Open URL + /// + /// URL to open + /// Given URL "http://test" is opened + [Given("URL \"(.*)\" is opened")] + [When("user opens URL \"(.*)\"")] + public void Navigate([NotNull] string url) + { + if(IsAbsoluteUrl(url)) + { + _driverService.Navigate(url); + return; + } + _driverService.Navigate(ConfigServiceBase.BaseUrl + url); + } + + /// + /// Open Base URL from config + /// + /// When user opens application URL + [Given("application URL is opened")] + [When("user opens application URL")] + public void NavigateToBaseUrl() + { + _driverService.Navigate(ConfigServiceBase.BaseUrl); + } + + /// + /// Open URL which is relative to the Base URL + /// + /// Relative URL to be opened + /// When user opens relative URL "/test-url" + [Given("relative URL \"(.*)\" is opened")] + [When("user opens relative URL \"(.*)\"")] + public void NavigateToRelativeUrl([NotNull] string url) + { + _driverService.NavigateToRelativeUrl(url); + } + + /// + /// Check full page URL + /// + /// Expected URL + /// Assertion behavior (instant or continuous) + /// Then page "http://test" should become opened + [Given("page \"(.*)\" (is|is not|become|become not) opened")] + [Then("page \"(.*)\" should (be|be not|become|become not) opened")] + public void CheckUrl([NotNull] string url, [NotNull] AssertionBehavior behavior) + { + Assert.ShouldBecome(() => _driverService.CurrentUrl, url, behavior, + $"current URL is {_driverService.CurrentUrl}"); + } + + /// + /// Check URL which is relative to Base URL + /// + /// Expected URL + /// Assertion behavior (instant or continuous) + /// Then relative URL should become "/test-page" + [Given("relative URL (is|is not|become|become not) \"(.*)\"")] + [Then("relative URL should (be|be not|become|become not) \"(.*)\"")] + public void CheckRelativeUrl([NotNull] AssertionBehavior behavior, [NotNull] string url) + { + Assert.ShouldBecome(() => new Uri(_driverService.CurrentUrl).PathAndQuery, url, behavior, + $"relative URL is {new Uri(_driverService.CurrentUrl).PathAndQuery}"); + } + + /// + /// Check that page URL contains specific string + /// + /// Assertion behavior (instant or continuous) + /// Expected URL substring + /// Then page should contain "test" URL + [Given("page (contains|not contains) \"(.*)\" URL")] + [Then("page (should|should not) contain \"(.*)\" URL")] + public void CheckUrlContains(string behavior, [NotNull] string url) + { + Assert.ShouldBecome(() => _driverService.CurrentUrl.Contains(url), !behavior.Contains("not"), $"current URL is {_driverService.CurrentUrl}"); + } + + /// + /// Check title of the page + /// + /// Assertion behavior (instant or continuous) + /// Expected title of the page + /// Then page title should be "Test page" + [Given("page title (is|is not|become|become not) \"(.*)\"")] + [Then("page title should (be|be not|become|become not) \"(.*)\"")] + public void CheckPageTitle([NotNull] AssertionBehavior behavior, [CanBeNull] string title) + { + Assert.ShouldBecome(() => _driverService.Title, title, behavior, + $"page title is {_driverService.Title}"); + } + + /// + /// Resize opened browser window + /// + /// Desired window height + /// Desired window width + /// When user resize window to 480 height and 640 width + [Given("user resized window to (.*) height and (.*) width")] + [When("user resizes window to (.*) height and (.*) width")] + public void CheckOpened([NotNull] int pageHeight, [NotNull] int pageWidth) + { + _driverService.ResizeWindow(pageHeight, pageWidth); + } + + /// + /// Refresh the page + /// + [Given("user reloaded current page")] + [When("user reloads current page")] + public void ReloadCurrentPage() + { + _driverService.Refresh(); + } + + private static bool IsAbsoluteUrl(string url) + { + return Uri.IsWellFormedUriString(url, UriKind.Absolute); + } + } +} \ No newline at end of file diff --git a/Behavioral.Automation.sln b/Behavioral.Automation.sln index be4a136..d66f7c1 100644 --- a/Behavioral.Automation.sln +++ b/Behavioral.Automation.sln @@ -30,6 +30,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Behavioral.Automation.Async EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Behavioral.Automation.AsyncAbstractions.UI", "Behavioral.Automation.AsyncAbstractions.UI", "{C6D1A214-4D90-4973-83A0-4D1D1EA5DE30}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Behavioral.Automation.Implementation.Selenium", "Behavioral.Automation.Implementation.Selenium", "{1878BA03-4371-4FB3-B6BF-D649846308E3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Behavioral.Automation.Implementation.Selenium", "Behavioral.Automation.Implementation.Selenium\Behavioral.Automation.Implementation.Selenium.csproj", "{320A43D2-1B5C-4613-8615-BB4DB86A1C3B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{765191A2-9E83-41A8-AFC4-55005123DF6F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UITests", "Behavioral.Automation.Implementation.Selenium\UITests\UITests.csproj", "{98BC0E30-D7A0-488C-B731-EBFCBE08AC43}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -72,6 +80,14 @@ Global {DB675416-81CA-40EA-A1D9-F45E75248F74}.Debug|Any CPU.Build.0 = Debug|Any CPU {DB675416-81CA-40EA-A1D9-F45E75248F74}.Release|Any CPU.ActiveCfg = Release|Any CPU {DB675416-81CA-40EA-A1D9-F45E75248F74}.Release|Any CPU.Build.0 = Release|Any CPU + {320A43D2-1B5C-4613-8615-BB4DB86A1C3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {320A43D2-1B5C-4613-8615-BB4DB86A1C3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {320A43D2-1B5C-4613-8615-BB4DB86A1C3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {320A43D2-1B5C-4613-8615-BB4DB86A1C3B}.Release|Any CPU.Build.0 = Release|Any CPU + {98BC0E30-D7A0-488C-B731-EBFCBE08AC43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {98BC0E30-D7A0-488C-B731-EBFCBE08AC43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {98BC0E30-D7A0-488C-B731-EBFCBE08AC43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {98BC0E30-D7A0-488C-B731-EBFCBE08AC43}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -86,6 +102,9 @@ Global {FA8E07DE-0779-44A0-AFF2-2C2573DD6611} = {2A26C467-6A03-4942-9F9B-62F77F992F70} {1498E9EA-13DE-4C6A-AB63-960D226F6FCE} = {FA8E07DE-0779-44A0-AFF2-2C2573DD6611} {DB675416-81CA-40EA-A1D9-F45E75248F74} = {C6D1A214-4D90-4973-83A0-4D1D1EA5DE30} + {320A43D2-1B5C-4613-8615-BB4DB86A1C3B} = {1878BA03-4371-4FB3-B6BF-D649846308E3} + {765191A2-9E83-41A8-AFC4-55005123DF6F} = {1878BA03-4371-4FB3-B6BF-D649846308E3} + {98BC0E30-D7A0-488C-B731-EBFCBE08AC43} = {765191A2-9E83-41A8-AFC4-55005123DF6F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {724FD185-E1F2-44BD-89EA-DFD1DBF6453A} From 8c7d44150d0695e9a10e0705057b729c0a19d0c6 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:18:32 +0400 Subject: [PATCH 02/32] small adjustment --- ....Automation.Implementation.Selenium.csproj | 4 + .../Bindings/NavigationBInding.cs | 142 ------------------ .../UITests/Drivers/Driver.cs | 8 + .../UITests/Features/Calculator.feature | 13 ++ .../UITests/Hooks/Hook.cs | 10 ++ .../Steps/CalculatorStepDefinitions.cs | 54 +++++++ .../UITests/UITests.csproj | 22 +++ Behavioral.Automation.sln | 12 +- 8 files changed, 117 insertions(+), 148 deletions(-) delete mode 100644 Behavioral.Automation.Implementation.Selenium/Bindings/NavigationBInding.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Drivers/Driver.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Features/Calculator.feature create mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Hooks/Hook.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Steps/CalculatorStepDefinitions.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index aa35da8..3e48055 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -35,4 +35,8 @@ + + + + diff --git a/Behavioral.Automation.Implementation.Selenium/Bindings/NavigationBInding.cs b/Behavioral.Automation.Implementation.Selenium/Bindings/NavigationBInding.cs deleted file mode 100644 index ebef3fb..0000000 --- a/Behavioral.Automation.Implementation.Selenium/Bindings/NavigationBInding.cs +++ /dev/null @@ -1,142 +0,0 @@ -namespace SpecFlowProject1.Bindings -{ - /// - /// Bindings for URL navigation and testing - /// - [Binding] - public sealed class NavigationBinding - { - private readonly IDriverService _driverService; - private readonly IScopeContextManager _scopeContextManager; - - public NavigationBinding([NotNull] IDriverService driverService, - [NotNull] IScopeContextManager scopeContextManager) - { - _driverService = driverService; - _scopeContextManager = scopeContextManager; - } - - /// - /// Open URL - /// - /// URL to open - /// Given URL "http://test" is opened - [Given("URL \"(.*)\" is opened")] - [When("user opens URL \"(.*)\"")] - public void Navigate([NotNull] string url) - { - if(IsAbsoluteUrl(url)) - { - _driverService.Navigate(url); - return; - } - _driverService.Navigate(ConfigServiceBase.BaseUrl + url); - } - - /// - /// Open Base URL from config - /// - /// When user opens application URL - [Given("application URL is opened")] - [When("user opens application URL")] - public void NavigateToBaseUrl() - { - _driverService.Navigate(ConfigServiceBase.BaseUrl); - } - - /// - /// Open URL which is relative to the Base URL - /// - /// Relative URL to be opened - /// When user opens relative URL "/test-url" - [Given("relative URL \"(.*)\" is opened")] - [When("user opens relative URL \"(.*)\"")] - public void NavigateToRelativeUrl([NotNull] string url) - { - _driverService.NavigateToRelativeUrl(url); - } - - /// - /// Check full page URL - /// - /// Expected URL - /// Assertion behavior (instant or continuous) - /// Then page "http://test" should become opened - [Given("page \"(.*)\" (is|is not|become|become not) opened")] - [Then("page \"(.*)\" should (be|be not|become|become not) opened")] - public void CheckUrl([NotNull] string url, [NotNull] AssertionBehavior behavior) - { - Assert.ShouldBecome(() => _driverService.CurrentUrl, url, behavior, - $"current URL is {_driverService.CurrentUrl}"); - } - - /// - /// Check URL which is relative to Base URL - /// - /// Expected URL - /// Assertion behavior (instant or continuous) - /// Then relative URL should become "/test-page" - [Given("relative URL (is|is not|become|become not) \"(.*)\"")] - [Then("relative URL should (be|be not|become|become not) \"(.*)\"")] - public void CheckRelativeUrl([NotNull] AssertionBehavior behavior, [NotNull] string url) - { - Assert.ShouldBecome(() => new Uri(_driverService.CurrentUrl).PathAndQuery, url, behavior, - $"relative URL is {new Uri(_driverService.CurrentUrl).PathAndQuery}"); - } - - /// - /// Check that page URL contains specific string - /// - /// Assertion behavior (instant or continuous) - /// Expected URL substring - /// Then page should contain "test" URL - [Given("page (contains|not contains) \"(.*)\" URL")] - [Then("page (should|should not) contain \"(.*)\" URL")] - public void CheckUrlContains(string behavior, [NotNull] string url) - { - Assert.ShouldBecome(() => _driverService.CurrentUrl.Contains(url), !behavior.Contains("not"), $"current URL is {_driverService.CurrentUrl}"); - } - - /// - /// Check title of the page - /// - /// Assertion behavior (instant or continuous) - /// Expected title of the page - /// Then page title should be "Test page" - [Given("page title (is|is not|become|become not) \"(.*)\"")] - [Then("page title should (be|be not|become|become not) \"(.*)\"")] - public void CheckPageTitle([NotNull] AssertionBehavior behavior, [CanBeNull] string title) - { - Assert.ShouldBecome(() => _driverService.Title, title, behavior, - $"page title is {_driverService.Title}"); - } - - /// - /// Resize opened browser window - /// - /// Desired window height - /// Desired window width - /// When user resize window to 480 height and 640 width - [Given("user resized window to (.*) height and (.*) width")] - [When("user resizes window to (.*) height and (.*) width")] - public void CheckOpened([NotNull] int pageHeight, [NotNull] int pageWidth) - { - _driverService.ResizeWindow(pageHeight, pageWidth); - } - - /// - /// Refresh the page - /// - [Given("user reloaded current page")] - [When("user reloads current page")] - public void ReloadCurrentPage() - { - _driverService.Refresh(); - } - - private static bool IsAbsoluteUrl(string url) - { - return Uri.IsWellFormedUriString(url, UriKind.Absolute); - } - } -} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Drivers/Driver.cs b/Behavioral.Automation.Implementation.Selenium/UITests/Drivers/Driver.cs new file mode 100644 index 0000000..ad9da2f --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Drivers/Driver.cs @@ -0,0 +1,8 @@ +using System; + +namespace UITests.Drivers +{ + public class Driver + { + } +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Calculator.feature b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Calculator.feature new file mode 100644 index 0000000..75b5b2b --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Calculator.feature @@ -0,0 +1,13 @@ +Feature: Calculator +![Calculator](https://specflow.org/wp-content/uploads/2020/09/calculator.png) +Simple calculator for adding **two** numbers + +Link to a feature: [Calculator]($projectname$/Features/Calculator.feature) +***Further read***: **[Learn more about how to generate Living Documentation](https://docs.specflow.org/projects/specflow-livingdoc/en/latest/LivingDocGenerator/Generating-Documentation.html)** + +@mytag +Scenario: Add two numbers + Given the first number is 50 + And the second number is 70 + When the two numbers are added + Then the result should be 120 \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Hooks/Hook.cs b/Behavioral.Automation.Implementation.Selenium/UITests/Hooks/Hook.cs new file mode 100644 index 0000000..c92b3ca --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Hooks/Hook.cs @@ -0,0 +1,10 @@ +using System; +using TechTalk.SpecFlow; + +namespace UITests.Hooks +{ + [Binding] + public class Hooks + { + } +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Steps/CalculatorStepDefinitions.cs b/Behavioral.Automation.Implementation.Selenium/UITests/Steps/CalculatorStepDefinitions.cs new file mode 100644 index 0000000..f6ed05f --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Steps/CalculatorStepDefinitions.cs @@ -0,0 +1,54 @@ +namespace UITests.Steps; + +[Binding] +public sealed class CalculatorStepDefinitions +{ + // For additional details on SpecFlow step definitions see https://go.specflow.org/doc-stepdef + + private readonly ScenarioContext _scenarioContext; + + public CalculatorStepDefinitions(ScenarioContext scenarioContext) + { + _scenarioContext = scenarioContext; + } + + [Given("the first number is (.*)")] + public void GivenTheFirstNumberIs(int number) + { + //TODO: implement arrange (precondition) logic + // For storing and retrieving scenario-specific data see https://go.specflow.org/doc-sharingdata + // To use the multiline text or the table argument of the scenario, + // additional string/Table parameters can be defined on the step definition + // method. + + _scenarioContext.Pending(); + } + + [Given("the second number is (.*)")] + public void GivenTheSecondNumberIs(int number) + { + //TODO: implement arrange (precondition) logic + // For storing and retrieving scenario-specific data see https://go.specflow.org/doc-sharingdata + // To use the multiline text or the table argument of the scenario, + // additional string/Table parameters can be defined on the step definition + // method. + + _scenarioContext.Pending(); + } + + [When("the two numbers are added")] + public void WhenTheTwoNumbersAreAdded() + { + //TODO: implement act (action) logic + + _scenarioContext.Pending(); + } + + [Then("the result should be (.*)")] + public void ThenTheResultShouldBe(int result) + { + //TODO: implement assert (verification) logic + + _scenarioContext.Pending(); + } +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj new file mode 100644 index 0000000..21d74cc --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj @@ -0,0 +1,22 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + + + + + diff --git a/Behavioral.Automation.sln b/Behavioral.Automation.sln index d66f7c1..3ec17ac 100644 --- a/Behavioral.Automation.sln +++ b/Behavioral.Automation.sln @@ -36,7 +36,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Behavioral.Automation.Imple EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{765191A2-9E83-41A8-AFC4-55005123DF6F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UITests", "Behavioral.Automation.Implementation.Selenium\UITests\UITests.csproj", "{98BC0E30-D7A0-488C-B731-EBFCBE08AC43}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UITests", "Behavioral.Automation.Implementation.Selenium\UITests\UITests.csproj", "{B68D63F0-BDBC-4F35-B0DE-6459B27B0F96}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -84,10 +84,10 @@ Global {320A43D2-1B5C-4613-8615-BB4DB86A1C3B}.Debug|Any CPU.Build.0 = Debug|Any CPU {320A43D2-1B5C-4613-8615-BB4DB86A1C3B}.Release|Any CPU.ActiveCfg = Release|Any CPU {320A43D2-1B5C-4613-8615-BB4DB86A1C3B}.Release|Any CPU.Build.0 = Release|Any CPU - {98BC0E30-D7A0-488C-B731-EBFCBE08AC43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {98BC0E30-D7A0-488C-B731-EBFCBE08AC43}.Debug|Any CPU.Build.0 = Debug|Any CPU - {98BC0E30-D7A0-488C-B731-EBFCBE08AC43}.Release|Any CPU.ActiveCfg = Release|Any CPU - {98BC0E30-D7A0-488C-B731-EBFCBE08AC43}.Release|Any CPU.Build.0 = Release|Any CPU + {B68D63F0-BDBC-4F35-B0DE-6459B27B0F96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B68D63F0-BDBC-4F35-B0DE-6459B27B0F96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B68D63F0-BDBC-4F35-B0DE-6459B27B0F96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B68D63F0-BDBC-4F35-B0DE-6459B27B0F96}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -104,7 +104,7 @@ Global {DB675416-81CA-40EA-A1D9-F45E75248F74} = {C6D1A214-4D90-4973-83A0-4D1D1EA5DE30} {320A43D2-1B5C-4613-8615-BB4DB86A1C3B} = {1878BA03-4371-4FB3-B6BF-D649846308E3} {765191A2-9E83-41A8-AFC4-55005123DF6F} = {1878BA03-4371-4FB3-B6BF-D649846308E3} - {98BC0E30-D7A0-488C-B731-EBFCBE08AC43} = {765191A2-9E83-41A8-AFC4-55005123DF6F} + {B68D63F0-BDBC-4F35-B0DE-6459B27B0F96} = {765191A2-9E83-41A8-AFC4-55005123DF6F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {724FD185-E1F2-44BD-89EA-DFD1DBF6453A} From 73721794bfc63a290c02ccfebb848ce5ecbdfd95 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:19:48 +0400 Subject: [PATCH 03/32] first selenium case --- .../UITests/Drivers/Driver.cs | 8 --- .../UITests/Features/Calculator.feature | 13 ----- .../UITests/Features/Tests.feature | 5 ++ .../UITests/Hooks/Hook.cs | 10 ---- .../Steps/CalculatorStepDefinitions.cs | 54 ------------------- .../UITests/UITests.csproj | 14 ++--- 6 files changed, 12 insertions(+), 92 deletions(-) delete mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Drivers/Driver.cs delete mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Features/Calculator.feature create mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature delete mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Hooks/Hook.cs delete mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Steps/CalculatorStepDefinitions.cs diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Drivers/Driver.cs b/Behavioral.Automation.Implementation.Selenium/UITests/Drivers/Driver.cs deleted file mode 100644 index ad9da2f..0000000 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Drivers/Driver.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace UITests.Drivers -{ - public class Driver - { - } -} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Calculator.feature b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Calculator.feature deleted file mode 100644 index 75b5b2b..0000000 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Calculator.feature +++ /dev/null @@ -1,13 +0,0 @@ -Feature: Calculator -![Calculator](https://specflow.org/wp-content/uploads/2020/09/calculator.png) -Simple calculator for adding **two** numbers - -Link to a feature: [Calculator]($projectname$/Features/Calculator.feature) -***Further read***: **[Learn more about how to generate Living Documentation](https://docs.specflow.org/projects/specflow-livingdoc/en/latest/LivingDocGenerator/Generating-Documentation.html)** - -@mytag -Scenario: Add two numbers - Given the first number is 50 - And the second number is 70 - When the two numbers are added - Then the result should be 120 \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature new file mode 100644 index 0000000..8fc36e6 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature @@ -0,0 +1,5 @@ +Feature: Tests for Bahavioral.Automation.Playwright project + + Scenario: Visibility binding check + Given application URL is opened + Then the "Demo label" should be visible \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Hooks/Hook.cs b/Behavioral.Automation.Implementation.Selenium/UITests/Hooks/Hook.cs deleted file mode 100644 index c92b3ca..0000000 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Hooks/Hook.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using TechTalk.SpecFlow; - -namespace UITests.Hooks -{ - [Binding] - public class Hooks - { - } -} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Steps/CalculatorStepDefinitions.cs b/Behavioral.Automation.Implementation.Selenium/UITests/Steps/CalculatorStepDefinitions.cs deleted file mode 100644 index f6ed05f..0000000 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Steps/CalculatorStepDefinitions.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace UITests.Steps; - -[Binding] -public sealed class CalculatorStepDefinitions -{ - // For additional details on SpecFlow step definitions see https://go.specflow.org/doc-stepdef - - private readonly ScenarioContext _scenarioContext; - - public CalculatorStepDefinitions(ScenarioContext scenarioContext) - { - _scenarioContext = scenarioContext; - } - - [Given("the first number is (.*)")] - public void GivenTheFirstNumberIs(int number) - { - //TODO: implement arrange (precondition) logic - // For storing and retrieving scenario-specific data see https://go.specflow.org/doc-sharingdata - // To use the multiline text or the table argument of the scenario, - // additional string/Table parameters can be defined on the step definition - // method. - - _scenarioContext.Pending(); - } - - [Given("the second number is (.*)")] - public void GivenTheSecondNumberIs(int number) - { - //TODO: implement arrange (precondition) logic - // For storing and retrieving scenario-specific data see https://go.specflow.org/doc-sharingdata - // To use the multiline text or the table argument of the scenario, - // additional string/Table parameters can be defined on the step definition - // method. - - _scenarioContext.Pending(); - } - - [When("the two numbers are added")] - public void WhenTheTwoNumbersAreAdded() - { - //TODO: implement act (action) logic - - _scenarioContext.Pending(); - } - - [Then("the result should be (.*)")] - public void ThenTheResultShouldBe(int result) - { - //TODO: implement assert (verification) logic - - _scenarioContext.Pending(); - } -} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj index 21d74cc..b952ff7 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj +++ b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj @@ -7,16 +7,16 @@ - + - - - - - - + + + + + + From 20899fd70b93af0f7b54da9e647a61d0476b9d90 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:21:36 +0400 Subject: [PATCH 04/32] reference added --- .../UITests/UITests.csproj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj index b952ff7..a9e8e5b 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj +++ b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj @@ -12,11 +12,14 @@ - + + + + From b367a4a0c58e798c474ac5c73cda2d3f3c1cc8c0 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:22:36 +0400 Subject: [PATCH 05/32] changed test case --- .../UITests/Features/Tests.feature | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature index 8fc36e6..56f68dd 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature @@ -1,5 +1,5 @@ Feature: Tests for Bahavioral.Automation.Playwright project - Scenario: Visibility binding check - Given application URL is opened - Then the "Demo label" should be visible \ No newline at end of file + Scenario: Button click binding test + Given application URL was opened + When user clicks the "test" button From b952d3dc3715d55cc4cd111d8059a0ba4f9d0a49 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:25:56 +0400 Subject: [PATCH 06/32] small changes --- ...ioral.Automation.Implementation.Selenium.csproj | 14 -------------- .../Bindings/TestClass.cs | 6 ++++++ 2 files changed, 6 insertions(+), 14 deletions(-) create mode 100644 Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index 3e48055..01d8ad8 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -25,18 +25,4 @@ - - - - - - - - - - - - - - diff --git a/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs b/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs new file mode 100644 index 0000000..7a2ec65 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs @@ -0,0 +1,6 @@ +namespace Behavioral.Automation.Implementation.Selenium.Bindings; + +public class TestClass +{ + +} \ No newline at end of file From 7e07887de487e9e2e57c291cc58fa27529bfedad Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:30:26 +0400 Subject: [PATCH 07/32] changed project path --- .../Behavioral.Automation.Implementation.Selenium.csproj | 0 .../Bindings/TestClass.cs | 0 .../CHANGELOG.md | 9 +++++++++ Behavioral.Automation.Implementation.Selenium/README.md | 1 + Behavioral.Automation.sln | 2 +- 5 files changed, 11 insertions(+), 1 deletion(-) rename Behavioral.Automation.Implementation.Selenium/{ => Behavioral.Automation.Implementation.Selenium}/Behavioral.Automation.Implementation.Selenium.csproj (100%) rename Behavioral.Automation.Implementation.Selenium/{ => Behavioral.Automation.Implementation.Selenium}/Bindings/TestClass.cs (100%) create mode 100644 Behavioral.Automation.Implementation.Selenium/CHANGELOG.md create mode 100644 Behavioral.Automation.Implementation.Selenium/README.md diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj similarity index 100% rename from Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj rename to Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj diff --git a/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs similarity index 100% rename from Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs rename to Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs diff --git a/Behavioral.Automation.Implementation.Selenium/CHANGELOG.md b/Behavioral.Automation.Implementation.Selenium/CHANGELOG.md new file mode 100644 index 0000000..5a83288 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +[0.1] - 2022-06-03 +### Added +- Added basic folder structure and browser launch methods for Playwright framework \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/README.md b/Behavioral.Automation.Implementation.Selenium/README.md new file mode 100644 index 0000000..2fd9f95 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/README.md @@ -0,0 +1 @@ +TBD \ No newline at end of file diff --git a/Behavioral.Automation.sln b/Behavioral.Automation.sln index 3ec17ac..1329635 100644 --- a/Behavioral.Automation.sln +++ b/Behavioral.Automation.sln @@ -32,7 +32,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Behavioral.Automation.Async EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Behavioral.Automation.Implementation.Selenium", "Behavioral.Automation.Implementation.Selenium", "{1878BA03-4371-4FB3-B6BF-D649846308E3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Behavioral.Automation.Implementation.Selenium", "Behavioral.Automation.Implementation.Selenium\Behavioral.Automation.Implementation.Selenium.csproj", "{320A43D2-1B5C-4613-8615-BB4DB86A1C3B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Behavioral.Automation.Implementation.Selenium", "Behavioral.Automation.Implementation.Selenium\Behavioral.Automation.Implementation.Selenium\Behavioral.Automation.Implementation.Selenium.csproj", "{320A43D2-1B5C-4613-8615-BB4DB86A1C3B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{765191A2-9E83-41A8-AFC4-55005123DF6F}" EndProject From 1ad00280288cfdcbf9f4113971770031cd30004d Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:35:26 +0400 Subject: [PATCH 08/32] project structure change --- .../Behavioral.Automation.Implementation.Selenium.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index 01d8ad8..47e0fab 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -17,11 +17,10 @@ - - + From 47c1f81bf2a6c5fdbeb9c3c286891a4204ae009a Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:36:22 +0400 Subject: [PATCH 09/32] structure --- .../UITests/UITests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj index a9e8e5b..c2d12ef 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj +++ b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj @@ -19,7 +19,7 @@ - + From d30a9c44e151386062deffa07e33528c2d9cbd0c Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:38:48 +0400 Subject: [PATCH 10/32] simplify dependepcies --- ....Automation.Implementation.Selenium.csproj | 5 ----- .../Bindings/TestClass.cs | 21 ++++++++++++++++--- .../UITests/Features/Tests.feature | 1 + 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index 47e0fab..7812ecf 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -7,13 +7,8 @@ Behavioral.Automation.Implementation.Selenium - - - - - diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs index 7a2ec65..7967845 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs @@ -1,6 +1,21 @@ -namespace Behavioral.Automation.Implementation.Selenium.Bindings; +using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; -public class TestClass +namespace Behavioral.Automation.Implementation.Selenium.Bindings; + +public class TestClass : IPage { - + public Task GoToUrlAsync(string url) + { + throw new NotImplementedException(); + } + + public Task GoToApplicationUrlAsync() + { + throw new NotImplementedException(); + } + + public Task HaveTitleAsync(string title) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature index 56f68dd..81b3136 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature @@ -1,5 +1,6 @@ Feature: Tests for Bahavioral.Automation.Playwright project Scenario: Button click binding test + Given application URL was opened When user clicks the "test" button From 747ed1c0624986a56b5cfb9fbecde211c4cc444b Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:40:33 +0400 Subject: [PATCH 11/32] small changes --- .../UITests/Features/Tests.feature | 1 - .../UITests/UITests.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature index 81b3136..56f68dd 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature @@ -1,6 +1,5 @@ Feature: Tests for Bahavioral.Automation.Playwright project Scenario: Button click binding test - Given application URL was opened When user clicks the "test" button diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj index c2d12ef..c3c372d 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj +++ b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj @@ -15,7 +15,6 @@ - From 8d19410e0f8526344f4f3340245d734fd8c3127e Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:44:01 +0400 Subject: [PATCH 12/32] versions update --- .../Behavioral.Automation.DemoBindings.csproj | 2 +- .../Behavioral.Automation.DemoScenarios.csproj | 2 +- .../Behavioral.Automation/Behavioral.Automation.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Behavioral.Automation.Selenium/Behavioral.Automation.DemoBindings/Behavioral.Automation.DemoBindings.csproj b/Behavioral.Automation.Selenium/Behavioral.Automation.DemoBindings/Behavioral.Automation.DemoBindings.csproj index 8cdd4fb..5c32f42 100644 --- a/Behavioral.Automation.Selenium/Behavioral.Automation.DemoBindings/Behavioral.Automation.DemoBindings.csproj +++ b/Behavioral.Automation.Selenium/Behavioral.Automation.DemoBindings/Behavioral.Automation.DemoBindings.csproj @@ -12,7 +12,7 @@ - + diff --git a/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj b/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj index 4062b6d..42d31df 100644 --- a/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj +++ b/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj @@ -11,7 +11,7 @@ - + diff --git a/Behavioral.Automation.Selenium/Behavioral.Automation/Behavioral.Automation.csproj b/Behavioral.Automation.Selenium/Behavioral.Automation/Behavioral.Automation.csproj index b71a85c..499d0e3 100644 --- a/Behavioral.Automation.Selenium/Behavioral.Automation/Behavioral.Automation.csproj +++ b/Behavioral.Automation.Selenium/Behavioral.Automation/Behavioral.Automation.csproj @@ -38,7 +38,7 @@ The whole automation code is divided into the following parts: - + all runtime; build; native; contentfiles; analyzers; buildtransitive From ae29a6dcc6dfd78e9b04e16d7fffbecced3afd89 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:44:57 +0400 Subject: [PATCH 13/32] fix config project reference --- .../Behavioral.Automation.Implementation.Selenium.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index 7812ecf..f4a3a30 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -16,7 +16,7 @@ - + From 0cd2f5822a960d81e6243810df2f1a9767e6ac06 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:46:53 +0400 Subject: [PATCH 14/32] use the same version for different projects --- .../Behavioral.Automation.Implementation.Selenium.csproj | 2 +- .../UITests/UITests.csproj | 2 +- .../Behavioral.Automation.DemoScenarios.csproj | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index f4a3a30..306e76f 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -9,7 +9,7 @@ - + diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj index c3c372d..5c728a9 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj +++ b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj b/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj index 42d31df..6e0e658 100644 --- a/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj +++ b/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj @@ -12,8 +12,8 @@ - - + + From 7dcd2b2022a65467fcfc16539a2c7beb92111d5c Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:51:41 +0400 Subject: [PATCH 15/32] Added configuration --- .../UITests/AutomationConfig.json | 18 ++++++++++++++++++ .../UITests/Features/Tests.feature | 2 +- .../UITests/UITests.csproj | 9 +++++++++ .../UITests/specflow.json | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json create mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/specflow.json diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json b/Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json new file mode 100644 index 0000000..d314d71 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json @@ -0,0 +1,18 @@ +{ + "BASE_URL": "http://localhost:4200", + "TEST_EMAIL": "", + "TEST_PASSWORD": "", + "BASE_AUTH_URL": "", + "BROWSER_PARAMS": "--window-size=1920,1080", + "ACCESS_CLIPBOARD": false, + "DOWNLOAD_PATH": "", + "SEARCH_ATTRIBUTE": "data-automation-id", + "BAUTH_LOGIN": "", + "BAUTH_PWD": "", + "BAUTH_IGNORE": "true", + "BROWSER_BINARY_LOCATION": "", + "ASSERT_TIMEOUT_MILLISECONDS": 40000, + "SLOW_MO_MILLISECONDS": 50, + "HEADLESS": true, + "RECORD_VIDEO": false +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature index 56f68dd..5214f9a 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature @@ -1,4 +1,4 @@ -Feature: Tests for Bahavioral.Automation.Playwright project +Feature: Tests for Bahavioral.Automation.Selenium project Scenario: Button click binding test Given application URL was opened diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj index 5c728a9..b72ff83 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj +++ b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj @@ -21,4 +21,13 @@ + + + Always + + + Always + + + diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json b/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json new file mode 100644 index 0000000..d529ef5 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json @@ -0,0 +1,16 @@ +{ + "bindingCulture": { + "language": "en-us" + }, + "language": { + "feature": "en-us" + }, + "runtime": { + "missingOrPendingStepsOutcome": "Error" + }, + "stepAssemblies": [ + { + "assembly": "Behavioral.Automation.Playwright" + } + ] +} From e776d6fc60ac7e1987cb7685d76164d393b87abd Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 22:52:41 +0400 Subject: [PATCH 16/32] fixed config --- .../UITests/specflow.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json b/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json index d529ef5..721eefc 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json +++ b/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json @@ -10,7 +10,10 @@ }, "stepAssemblies": [ { - "assembly": "Behavioral.Automation.Playwright" + "assembly": "Behavioral.Automation.asyncAbstractions.UI" + }, + { + "assembly": "Behavioral.Automation.Implementation.Selenium" } ] } From ff1265974fb99e268427cb853d1a82a2b0f9e2e1 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 23:15:49 +0400 Subject: [PATCH 17/32] Some initial configuration without specific purpose --- .../Bindings/BrowserRunner.cs | 100 ++++++++++++++++++ .../Bindings/TestClass.cs | 2 +- 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs new file mode 100644 index 0000000..64b2796 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs @@ -0,0 +1,100 @@ +namespace Behavioral.Automation.Implementation.Selenium.Bindings; + +public class BrowserRunner + { + public IWebDriver Driver; + + /// + /// Driver initialization + /// + /// IWebDriver object + public void OpenBrowser([NotNull] IWebDriver driver) + { + Driver = driver; + } + + + /// + /// Driver disposal + /// + public void CloseBrowser() + { + Driver.Dispose(); + } + + /// + /// Open and configure Google Chrome browser + /// + /// Browser parameters + public void OpenChrome(ChromeOptions options = null) + { + var downloadPath = ConfigServiceBase.DownloadPath ?? Environment.CurrentDirectory; + + if (options == null) + { + options = new ChromeOptions(); + options.AddArguments(new List( + ConfigServiceBase.BrowserParameters.Split(" ", StringSplitOptions.RemoveEmptyEntries))); + if (ConfigServiceBase.BrowserParameters.Contains("headless")) + { + ConfigureChromeHeadlessDownload(options, downloadPath); + } + if (ConfigServiceBase.AccessClipboard) + { + ConfigureClipboardAccess(options); + } + options.AddUserProfilePreference("intl.accept_languages", "en,en_US"); + options.AcceptInsecureCertificates = ConfigServiceBase.AcceptInsecureCertificates; + options.SetLoggingPreference(LogType.Browser, LogLevel.All); + if (!string.IsNullOrWhiteSpace(ConfigServiceBase.BrowserBinaryLocation)) + { + options.BinaryLocation = Environment.ExpandEnvironmentVariables(ConfigServiceBase.BrowserBinaryLocation); + } + if (!string.IsNullOrWhiteSpace(ConfigServiceBase.UnhandledPromptBehavior)) + { + options.UnhandledPromptBehavior = ConfigServiceBase.UnhandledPromptBehavior switch + { + "Accept" => UnhandledPromptBehavior.Accept, + "Dismiss" => UnhandledPromptBehavior.Dismiss, + "Ignore" => UnhandledPromptBehavior.Ignore, + _ => options.UnhandledPromptBehavior + }; + } + } + + var driver = new ChromeDriver(options); + var param = new Dictionary + { + {"behavior", "allow"}, + {"downloadPath", downloadPath} + }; + driver.ExecuteCdpCommand("Page.setDownloadBehavior", param); + OpenBrowser(driver); + } + + /// + /// Configure Google Chrome downloads to work correctly in headless mode + /// + /// Chrome configuration parameters + /// Directory to download files to + private void ConfigureChromeHeadlessDownload(ChromeOptions options, string downloadPath) + { + options.AddUserProfilePreference("download.prompt_for_download", "false"); + options.AddUserProfilePreference("download.directory_upgrade", "true"); + options.AddUserProfilePreference("download.default_directory", downloadPath); + } + + private void ConfigureClipboardAccess(ChromeOptions options) + { + var clipboardExceptionSettings = new Dictionary { + {ConfigServiceBase.BaseUrl, + new Dictionary { + {"last_modified", DateTimeOffset.Now.ToUnixTimeMilliseconds()}, + {"setting", 1} + } + } + }; + options.AddUserProfilePreference("profile.content_settings.exceptions.clipboard", clipboardExceptionSettings); + } + } +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs index 7967845..c47298a 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs @@ -6,7 +6,7 @@ public class TestClass : IPage { public Task GoToUrlAsync(string url) { - throw new NotImplementedException(); + return new Task(() => { Driver.Navigate().GoToUrl(url); }); } public Task GoToApplicationUrlAsync() From fa93ac50c8e51be4c58dbf738583c51e0693a426 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sat, 13 Apr 2024 23:58:37 +0400 Subject: [PATCH 18/32] Added configs to selenium project --- .../Bindings/Hooks.cs | 89 +++++++++++++++++++ .../Configs/Config.cs | 12 +++ 2 files changed, 101 insertions(+) create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Configs/Config.cs diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs new file mode 100644 index 0000000..5fdedb4 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs @@ -0,0 +1,89 @@ +using System.Diagnostics; +using System.Net; +using Behavioral.Automation.Configs; +using Behavioral.Automation.Implementation.Selenium.Configs; +using BoDi; +using NUnit.Framework; +using TechTalk.SpecFlow; + +namespace Behavioral.Automation.Implementation.Selenium.Bindings; + +[Binding] +public class Hooks +{ + private readonly IObjectContainer _objectContainer; + private readonly ITestRunner _runner; + private readonly BrowserRunner _browserRunner; + private static Process _coreRunProcess; + + public Hooks(IObjectContainer objectContainer, ITestRunner runner, BrowserRunner browserRunner) + { + _objectContainer = objectContainer; + _runner = runner; + _browserRunner = browserRunner; + } + + private static bool IsConnectionEstablished() + { + try + { + WebRequest.CreateHttp(ConfigManager.GetConfig().BaseUrl).GetResponse(); + return true; + } + catch (WebException) + { + return false; + } + } + + private static void RunTestApp() + { + string testAppPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "..", "..", "src", + "BlazorApp"); + + _coreRunProcess = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "cmd.exe", + Arguments = "/c dotnet run", + WorkingDirectory = testAppPath + } + }; + _coreRunProcess.Start(); + } + + [BeforeTestRun] + public static void StartDemoApp() + { + if (!IsConnectionEstablished()) + RunTestApp(); + } + + [AfterTestRun] + public static void StopDemoApp() + { + if (_coreRunProcess != null) + { + _coreRunProcess.Kill(true); + _coreRunProcess.Dispose(); + } + } + + [AfterScenario] + public void CloseBrowser() + { + _browserRunner.CloseBrowser(); + + } + + [BeforeScenario(Order = 0)] + public void Bootstrap() + { + Assert.SetRunner(_runner); + _objectContainer.RegisterTypeAs(); + _servicesBuilder.Build(); + _browserRunner.OpenChrome(); + } + } +} diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Configs/Config.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Configs/Config.cs new file mode 100644 index 0000000..28e7b6e --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Configs/Config.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.Configuration; + +namespace Behavioral.Automation.Implementation.Selenium.Configs; + +public class Config +{ + [ConfigurationKeyName("BASE_URL")] + public string BaseUrl { get; set; } + + [ConfigurationKeyName("SEARCH_ATTRIBUTE")] + public string SearchAttribute { get; set; } +} \ No newline at end of file From 39c4c0de748a0e99c9c2746e82131268d247d4ed Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 00:00:47 +0400 Subject: [PATCH 19/32] import selenium web driver to selenium project --- ....Automation.Implementation.Selenium.csproj | 1 + .../Bindings/BrowserRunner.cs | 6 +- .../Bindings/Hooks.cs | 120 +++++++++--------- 3 files changed, 65 insertions(+), 62 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index 306e76f..2deaf3f 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -9,6 +9,7 @@ + diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs index 64b2796..0b924b1 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs @@ -1,4 +1,8 @@ -namespace Behavioral.Automation.Implementation.Selenium.Bindings; +using System.Diagnostics.CodeAnalysis; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; + +namespace Behavioral.Automation.Implementation.Selenium.Bindings; public class BrowserRunner { diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs index 5fdedb4..0a5d899 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs @@ -11,79 +11,77 @@ namespace Behavioral.Automation.Implementation.Selenium.Bindings; [Binding] public class Hooks { - private readonly IObjectContainer _objectContainer; - private readonly ITestRunner _runner; - private readonly BrowserRunner _browserRunner; - private static Process _coreRunProcess; - - public Hooks(IObjectContainer objectContainer, ITestRunner runner, BrowserRunner browserRunner) - { - _objectContainer = objectContainer; - _runner = runner; - _browserRunner = browserRunner; - } + private readonly IObjectContainer _objectContainer; + private readonly ITestRunner _runner; + private readonly BrowserRunner _browserRunner; + private static Process _coreRunProcess; - private static bool IsConnectionEstablished() - { - try - { - WebRequest.CreateHttp(ConfigManager.GetConfig().BaseUrl).GetResponse(); - return true; - } - catch (WebException) - { - return false; - } - } + public Hooks(IObjectContainer objectContainer, ITestRunner runner, BrowserRunner browserRunner) + { + _objectContainer = objectContainer; + _runner = runner; + _browserRunner = browserRunner; + } - private static void RunTestApp() + private static bool IsConnectionEstablished() + { + try { - string testAppPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "..", "..", "src", - "BlazorApp"); - - _coreRunProcess = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = "cmd.exe", - Arguments = "/c dotnet run", - WorkingDirectory = testAppPath - } - }; - _coreRunProcess.Start(); + WebRequest.CreateHttp(ConfigManager.GetConfig().BaseUrl).GetResponse(); + return true; } - - [BeforeTestRun] - public static void StartDemoApp() + catch (WebException) { - if (!IsConnectionEstablished()) - RunTestApp(); + return false; } + } + + private static void RunTestApp() + { + string testAppPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "..", "..", "src", + "BlazorApp"); - [AfterTestRun] - public static void StopDemoApp() + _coreRunProcess = new Process { - if (_coreRunProcess != null) + StartInfo = new ProcessStartInfo { - _coreRunProcess.Kill(true); - _coreRunProcess.Dispose(); + FileName = "cmd.exe", + Arguments = "/c dotnet run", + WorkingDirectory = testAppPath } - } + }; + _coreRunProcess.Start(); + } - [AfterScenario] - public void CloseBrowser() - { - _browserRunner.CloseBrowser(); - - } + [BeforeTestRun] + public static void StartDemoApp() + { + if (!IsConnectionEstablished()) + RunTestApp(); + } - [BeforeScenario(Order = 0)] - public void Bootstrap() + [AfterTestRun] + public static void StopDemoApp() + { + if (_coreRunProcess != null) { - Assert.SetRunner(_runner); - _objectContainer.RegisterTypeAs(); - _servicesBuilder.Build(); - _browserRunner.OpenChrome(); + _coreRunProcess.Kill(true); + _coreRunProcess.Dispose(); } } -} + + [AfterScenario] + public void CloseBrowser() + { + _browserRunner.CloseBrowser(); + } + + [BeforeScenario(Order = 0)] + public void Bootstrap() + { + //Assert.SetRunner(_runner); + //_objectContainer.RegisterTypeAs(); + //_servicesBuilder.Build(); + _browserRunner.OpenChrome(); + } +} \ No newline at end of file From 0546bc14b848226f598d17af272703f80e4363c3 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 00:17:14 +0400 Subject: [PATCH 20/32] small changes --- .../Bindings/BrowserRunner.cs | 164 +++++++++--------- .../Configs/Config.cs | 28 ++- 2 files changed, 110 insertions(+), 82 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs index 0b924b1..02e3037 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs @@ -1,104 +1,112 @@ using System.Diagnostics.CodeAnalysis; +using Behavioral.Automation.Configs; +using Behavioral.Automation.Implementation.Selenium.Configs; using OpenQA.Selenium; using OpenQA.Selenium.Chrome; namespace Behavioral.Automation.Implementation.Selenium.Bindings; public class BrowserRunner +{ + public IWebDriver Driver; + + /// + /// Driver initialization + /// + /// IWebDriver object + public void OpenBrowser([NotNull] IWebDriver driver) { - public IWebDriver Driver; + Driver = driver; + } - /// - /// Driver initialization - /// - /// IWebDriver object - public void OpenBrowser([NotNull] IWebDriver driver) - { - Driver = driver; - } + /// + /// Driver disposal + /// + public void CloseBrowser() + { + Driver.Dispose(); + } - /// - /// Driver disposal - /// - public void CloseBrowser() - { - Driver.Dispose(); - } + /// + /// Open and configure Google Chrome browser + /// + /// Browser parameters + public void OpenChrome(ChromeOptions options = null) + { + var downloadPath = ConfigManager.GetConfig().DownloadPath ?? Environment.CurrentDirectory; - /// - /// Open and configure Google Chrome browser - /// - /// Browser parameters - public void OpenChrome(ChromeOptions options = null) + if (options == null) { - var downloadPath = ConfigServiceBase.DownloadPath ?? Environment.CurrentDirectory; + options = new ChromeOptions(); + options.AddArguments(new List( + ConfigManager.GetConfig().BrowserParameters.Split(" ", StringSplitOptions.RemoveEmptyEntries))); + if (ConfigManager.GetConfig().BrowserParameters.Contains("headless")) + { + ConfigureChromeHeadlessDownload(options, downloadPath); + } - if (options == null) + if (ConfigManager.GetConfig().AccessClipboard) { - options = new ChromeOptions(); - options.AddArguments(new List( - ConfigServiceBase.BrowserParameters.Split(" ", StringSplitOptions.RemoveEmptyEntries))); - if (ConfigServiceBase.BrowserParameters.Contains("headless")) - { - ConfigureChromeHeadlessDownload(options, downloadPath); - } - if (ConfigServiceBase.AccessClipboard) - { - ConfigureClipboardAccess(options); - } - options.AddUserProfilePreference("intl.accept_languages", "en,en_US"); - options.AcceptInsecureCertificates = ConfigServiceBase.AcceptInsecureCertificates; - options.SetLoggingPreference(LogType.Browser, LogLevel.All); - if (!string.IsNullOrWhiteSpace(ConfigServiceBase.BrowserBinaryLocation)) - { - options.BinaryLocation = Environment.ExpandEnvironmentVariables(ConfigServiceBase.BrowserBinaryLocation); - } - if (!string.IsNullOrWhiteSpace(ConfigServiceBase.UnhandledPromptBehavior)) - { - options.UnhandledPromptBehavior = ConfigServiceBase.UnhandledPromptBehavior switch - { - "Accept" => UnhandledPromptBehavior.Accept, - "Dismiss" => UnhandledPromptBehavior.Dismiss, - "Ignore" => UnhandledPromptBehavior.Ignore, - _ => options.UnhandledPromptBehavior - }; - } + ConfigureClipboardAccess(options); + } + + options.AddUserProfilePreference("intl.accept_languages", "en,en_US"); + options.AcceptInsecureCertificates = ConfigServiceBase.AcceptInsecureCertificates; + options.SetLoggingPreference(LogType.Browser, LogLevel.All); + if (!string.IsNullOrWhiteSpace(ConfigServiceBase.BrowserBinaryLocation)) + { + options.BinaryLocation = + Environment.ExpandEnvironmentVariables(ConfigServiceBase.BrowserBinaryLocation); } - var driver = new ChromeDriver(options); - var param = new Dictionary + if (!string.IsNullOrWhiteSpace(ConfigServiceBase.UnhandledPromptBehavior)) { - {"behavior", "allow"}, - {"downloadPath", downloadPath} - }; - driver.ExecuteCdpCommand("Page.setDownloadBehavior", param); - OpenBrowser(driver); + options.UnhandledPromptBehavior = ConfigServiceBase.UnhandledPromptBehavior switch + { + "Accept" => UnhandledPromptBehavior.Accept, + "Dismiss" => UnhandledPromptBehavior.Dismiss, + "Ignore" => UnhandledPromptBehavior.Ignore, + _ => options.UnhandledPromptBehavior + }; + } } - /// - /// Configure Google Chrome downloads to work correctly in headless mode - /// - /// Chrome configuration parameters - /// Directory to download files to - private void ConfigureChromeHeadlessDownload(ChromeOptions options, string downloadPath) + var driver = new ChromeDriver(options); + var param = new Dictionary { - options.AddUserProfilePreference("download.prompt_for_download", "false"); - options.AddUserProfilePreference("download.directory_upgrade", "true"); - options.AddUserProfilePreference("download.default_directory", downloadPath); - } + {"behavior", "allow"}, + {"downloadPath", downloadPath} + }; + driver.ExecuteCdpCommand("Page.setDownloadBehavior", param); + OpenBrowser(driver); + } - private void ConfigureClipboardAccess(ChromeOptions options) + /// + /// Configure Google Chrome downloads to work correctly in headless mode + /// + /// Chrome configuration parameters + /// Directory to download files to + private void ConfigureChromeHeadlessDownload(ChromeOptions options, string downloadPath) + { + options.AddUserProfilePreference("download.prompt_for_download", "false"); + options.AddUserProfilePreference("download.directory_upgrade", "true"); + options.AddUserProfilePreference("download.default_directory", downloadPath); + } + + private void ConfigureClipboardAccess(ChromeOptions options) + { + var clipboardExceptionSettings = new Dictionary { - var clipboardExceptionSettings = new Dictionary { - {ConfigServiceBase.BaseUrl, - new Dictionary { - {"last_modified", DateTimeOffset.Now.ToUnixTimeMilliseconds()}, - {"setting", 1} - } + { + ConfigServiceBase.BaseUrl, + new Dictionary + { + {"last_modified", DateTimeOffset.Now.ToUnixTimeMilliseconds()}, + {"setting", 1} } - }; - options.AddUserProfilePreference("profile.content_settings.exceptions.clipboard", clipboardExceptionSettings); - } + } + }; + options.AddUserProfilePreference("profile.content_settings.exceptions.clipboard", clipboardExceptionSettings); } } \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Configs/Config.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Configs/Config.cs index 28e7b6e..0c16628 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Configs/Config.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Configs/Config.cs @@ -4,9 +4,29 @@ namespace Behavioral.Automation.Implementation.Selenium.Configs; public class Config { - [ConfigurationKeyName("BASE_URL")] - public string BaseUrl { get; set; } - - [ConfigurationKeyName("SEARCH_ATTRIBUTE")] + [ConfigurationKeyName("BASE_URL")] public string BaseUrl { get; set; } + + [ConfigurationKeyName("BROWSER_PARAMS")] + public string BrowserParameters { get; set; } + + [ConfigurationKeyName("DOWNLOAD_PATH")] + public string DownloadPath { get; set; } = AppContext.BaseDirectory; + + [ConfigurationKeyName("ACCEPT_INSECURE_CERTIFICATES")] + public bool AcceptInsecureCertificates { get; set; } = true; + + [ConfigurationKeyName("SEARCH_ATTRIBUTE")] public string SearchAttribute { get; set; } + + [ConfigurationKeyName("ACCESS_CLIPBOARD")] + public bool AccessClipboard { get; set; } = false; + + [ConfigurationKeyName("BROWSER_BINARY_LOCATION")] + public string BrowserBinaryLocation { get; set; } + + [ConfigurationKeyName("UNHANDLED_PROMPT_BEHAVIOR")] + public string UnhandledPromptBehavior { get; set; } + + [ConfigurationKeyName("ASSERT_ATTEMPTS")] + public int? AssertAttempts { get; set; } = 30; } \ No newline at end of file From 92427f5cbe478f0ea9b7cd7e2e2b7a2ad1c8eb55 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 00:20:00 +0400 Subject: [PATCH 21/32] Added hooks --- .../Bindings/BrowserRunner.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs index 02e3037..06f9ddf 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs @@ -52,17 +52,17 @@ public void OpenChrome(ChromeOptions options = null) } options.AddUserProfilePreference("intl.accept_languages", "en,en_US"); - options.AcceptInsecureCertificates = ConfigServiceBase.AcceptInsecureCertificates; + options.AcceptInsecureCertificates = ConfigManager.GetConfig().AcceptInsecureCertificates; options.SetLoggingPreference(LogType.Browser, LogLevel.All); - if (!string.IsNullOrWhiteSpace(ConfigServiceBase.BrowserBinaryLocation)) + if (!string.IsNullOrWhiteSpace(ConfigManager.GetConfig().BrowserBinaryLocation)) { options.BinaryLocation = - Environment.ExpandEnvironmentVariables(ConfigServiceBase.BrowserBinaryLocation); + Environment.ExpandEnvironmentVariables(ConfigManager.GetConfig().BrowserBinaryLocation); } - if (!string.IsNullOrWhiteSpace(ConfigServiceBase.UnhandledPromptBehavior)) + if (!string.IsNullOrWhiteSpace(ConfigManager.GetConfig().UnhandledPromptBehavior)) { - options.UnhandledPromptBehavior = ConfigServiceBase.UnhandledPromptBehavior switch + options.UnhandledPromptBehavior = ConfigManager.GetConfig().UnhandledPromptBehavior switch { "Accept" => UnhandledPromptBehavior.Accept, "Dismiss" => UnhandledPromptBehavior.Dismiss, @@ -99,7 +99,7 @@ private void ConfigureClipboardAccess(ChromeOptions options) var clipboardExceptionSettings = new Dictionary { { - ConfigServiceBase.BaseUrl, + ConfigManager.GetConfig().BaseUrl, new Dictionary { {"last_modified", DateTimeOffset.Now.ToUnixTimeMilliseconds()}, From cea0a07768a19798a9f297d48de8658d960e009c Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 00:26:05 +0400 Subject: [PATCH 22/32] Added first poc --- .../Bindings/Hooks.cs | 6 +++++- .../Bindings/{TestClass.cs => Page.cs} | 10 +++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) rename Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/{TestClass.cs => Page.cs} (50%) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs index 0a5d899..5b544fa 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Net; +using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; using Behavioral.Automation.Configs; using Behavioral.Automation.Implementation.Selenium.Configs; using BoDi; @@ -15,12 +16,14 @@ public class Hooks private readonly ITestRunner _runner; private readonly BrowserRunner _browserRunner; private static Process _coreRunProcess; + private readonly IPage _page; - public Hooks(IObjectContainer objectContainer, ITestRunner runner, BrowserRunner browserRunner) + public Hooks(IObjectContainer objectContainer, ITestRunner runner, BrowserRunner browserRunner, IPage page) { _objectContainer = objectContainer; _runner = runner; _browserRunner = browserRunner; + _page = page; } private static bool IsConnectionEstablished() @@ -83,5 +86,6 @@ public void Bootstrap() //_objectContainer.RegisterTypeAs(); //_servicesBuilder.Build(); _browserRunner.OpenChrome(); + ((Page) _page).driver = _browserRunner.Driver; } } \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs similarity index 50% rename from Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs rename to Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs index c47298a..850f499 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/TestClass.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs @@ -1,17 +1,21 @@ using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; +using Behavioral.Automation.Configs; +using Behavioral.Automation.Implementation.Selenium.Configs; +using OpenQA.Selenium; namespace Behavioral.Automation.Implementation.Selenium.Bindings; -public class TestClass : IPage +public class Page : IPage { + public IWebDriver driver; public Task GoToUrlAsync(string url) { - return new Task(() => { Driver.Navigate().GoToUrl(url); }); + return new Task(() => { driver.Navigate().GoToUrl(url); }); } public Task GoToApplicationUrlAsync() { - throw new NotImplementedException(); + return new Task(() => { driver.Navigate().GoToUrl(ConfigManager.GetConfig().BaseUrl); }); } public Task HaveTitleAsync(string title) From a030c6a9d51d5a33e37bc3f5912f00a7c535af84 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 00:36:07 +0400 Subject: [PATCH 23/32] changed version --- ...ehavioral.Automation.Implementation.Selenium.csproj | 1 + .../Bindings/Hooks.cs | 10 ++++++---- .../UITests/Configuration/Configuration.cs | 7 +++++++ .../UITests/specflow.json | 3 +++ 4 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 Behavioral.Automation.Implementation.Selenium/UITests/Configuration/Configuration.cs diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index 2deaf3f..a2b4614 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -9,6 +9,7 @@ + diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs index 5b544fa..62ee6c9 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Net; +using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; using Behavioral.Automation.Configs; using Behavioral.Automation.Implementation.Selenium.Configs; @@ -16,14 +17,14 @@ public class Hooks private readonly ITestRunner _runner; private readonly BrowserRunner _browserRunner; private static Process _coreRunProcess; - private readonly IPage _page; + private readonly WebContext _webContext; - public Hooks(IObjectContainer objectContainer, ITestRunner runner, BrowserRunner browserRunner, IPage page) + public Hooks(IObjectContainer objectContainer, ITestRunner runner, BrowserRunner browserRunner, WebContext webContext) { _objectContainer = objectContainer; _runner = runner; _browserRunner = browserRunner; - _page = page; + _webContext = webContext; } private static bool IsConnectionEstablished() @@ -86,6 +87,7 @@ public void Bootstrap() //_objectContainer.RegisterTypeAs(); //_servicesBuilder.Build(); _browserRunner.OpenChrome(); - ((Page) _page).driver = _browserRunner.Driver; + _webContext.Page = new Page(); + ((Page) _webContext.Page).driver = _browserRunner.Driver; } } \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Configuration/Configuration.cs b/Behavioral.Automation.Implementation.Selenium/UITests/Configuration/Configuration.cs new file mode 100644 index 0000000..ababbea --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Configuration/Configuration.cs @@ -0,0 +1,7 @@ +namespace UITests.Configuration; + +[Binding] +public class Configuration +{ + +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json b/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json index 721eefc..63c260b 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json +++ b/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json @@ -14,6 +14,9 @@ }, { "assembly": "Behavioral.Automation.Implementation.Selenium" + }, + { + "assembly": "UITests" } ] } From 38591a5a4fd1427da827c6aee7c595b3a6954b2f Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 00:49:04 +0400 Subject: [PATCH 24/32] update configs --- .../Behavioral.Automation.Implementation.Selenium.csproj | 1 + .../UITests/AutomationConfig.json | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index a2b4614..a80d8d6 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -11,6 +11,7 @@ + diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json b/Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json index d314d71..01701a2 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json +++ b/Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json @@ -14,5 +14,9 @@ "ASSERT_TIMEOUT_MILLISECONDS": 40000, "SLOW_MO_MILLISECONDS": 50, "HEADLESS": true, - "RECORD_VIDEO": false + "RECORD_VIDEO": false, + "BAUTH_URL": "", + "BAUTH_PASSWORD": "", + "UNHANDLED_PROMPT_BEHAVIOR" : "", + "ASSERT_ATTEMPTS" : 30 } \ No newline at end of file From dd645c5a9d499363c3b765c3f614e864e6ccf763 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 01:04:46 +0400 Subject: [PATCH 25/32] added dependencies --- .../Behavioral.Automation.Implementation.Selenium.csproj | 1 - .../Bindings/BrowserRunner.cs | 2 ++ .../Bindings/Hooks.cs | 1 + .../UITests/UITests.csproj | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj index a80d8d6..a2b4614 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -11,7 +11,6 @@ - diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs index 06f9ddf..1a35140 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs @@ -34,6 +34,8 @@ public void CloseBrowser() /// Browser parameters public void OpenChrome(ChromeOptions options = null) { + // new DriverManager().SetUpDriver(new ChromeConfig(), VersionResolveStrategy.MatchingBrowser); + var downloadPath = ConfigManager.GetConfig().DownloadPath ?? Environment.CurrentDirectory; if (options == null) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs index 62ee6c9..6fbac0d 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs @@ -86,6 +86,7 @@ public void Bootstrap() //Assert.SetRunner(_runner); //_objectContainer.RegisterTypeAs(); //_servicesBuilder.Build(); + _browserRunner.OpenChrome(); _webContext.Page = new Page(); ((Page) _webContext.Page).driver = _browserRunner.Driver; diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj index b72ff83..0b95a8f 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj +++ b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj @@ -12,6 +12,7 @@ + From 18f2aa2711f99f17cceee77fe2f009ad6ff6c814 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 01:20:04 +0400 Subject: [PATCH 26/32] Added first code to switch application page --- .../Bindings/Page.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs index 850f499..9830141 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs @@ -15,7 +15,7 @@ public Task GoToUrlAsync(string url) public Task GoToApplicationUrlAsync() { - return new Task(() => { driver.Navigate().GoToUrl(ConfigManager.GetConfig().BaseUrl); }); + return Task.Run(() => { driver.Navigate().GoToUrl(ConfigManager.GetConfig().BaseUrl); }); } public Task HaveTitleAsync(string title) From fd84df1ffe933359ffea0b4251ee3759789b000a Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 16:26:06 +0400 Subject: [PATCH 27/32] small changes to bring button binding --- .../Pages/ISelectorStorage.cs | 6 ++++++ .../Pages/MainPage.cs | 13 ++++++++++++ .../WebElements/ButtonElement.cs | 20 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/ISelectorStorage.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/MainPage.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/ISelectorStorage.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/ISelectorStorage.cs new file mode 100644 index 0000000..79cf899 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/ISelectorStorage.cs @@ -0,0 +1,6 @@ +namespace Behavioral.Automation.Playwright.Pages; + +public interface ISelectorStorage +{ + +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/MainPage.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/MainPage.cs new file mode 100644 index 0000000..72c784f --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/MainPage.cs @@ -0,0 +1,13 @@ +using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; +using Behavioral.Automation.Configs; +using Behavioral.Automation.Implementation.Selenium.Configs; +using Behavioral.Automation.Playwright.Pages; + +namespace Behavioral.Automation.Implementation.Selenium.Pages; + +class MainPageExample : ISelectorStorage +{ + private static readonly string Id = ConfigManager.GetConfig().SearchAttribute; + + public ElementSelector DemoLabel = new() {IdSelector = "label-simple-text"}; +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs new file mode 100644 index 0000000..96afcc1 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs @@ -0,0 +1,20 @@ +using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; +using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; + +namespace Behavioral.Automation.Implementation.Selenium.WebElements; + +public class ButtonElement : IButtonElement +{ + public WebContext WebContext { get; } + public ElementSelector ElementSelector { get; } + public string? Description { get; set; } + public Task ShouldBecomeVisibleAsync() + { + throw new NotImplementedException(); + } + + public Task ClickAsync() + { + throw new NotImplementedException(); + } +} \ No newline at end of file From 3b9d6d5afa22191c1318a607be75db0d833055c1 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 16:44:52 +0400 Subject: [PATCH 28/32] added first configuration of web elements --- .../UITests/Configuration/Configuration.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Configuration/Configuration.cs b/Behavioral.Automation.Implementation.Selenium/UITests/Configuration/Configuration.cs index ababbea..4f6ba00 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Configuration/Configuration.cs +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Configuration/Configuration.cs @@ -1,7 +1,15 @@ -namespace UITests.Configuration; +using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; +using Behavioral.Automation.Implementation.Selenium.WebElements; + +namespace UITests.Configuration; [Binding] public class Configuration { - + // Configuration of DI and Factories should be done with order 0 + [BeforeTestRun(Order = 0)] + public static void ConfigureUiImplementations() + { + IWebElementStorageService.RegisterWebElementImplementationAs(); + } } \ No newline at end of file From 17b4a47c36bef860c7ea8dcde528323566e5327c Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 17:04:17 +0400 Subject: [PATCH 29/32] Added basis for interacting with web elements --- .../Pages/MainPage.cs | 3 + .../Selectors/ButtonSelector.cs | 8 +++ .../Services/Hooks.cs | 24 +++++++ .../Services/WebElementStorageService.cs | 63 +++++++++++++++++++ .../WebElements/ButtonElement.cs | 14 ++--- .../WebElements/SeleniumWebElement.cs | 35 +++++++++++ .../UITests/Features/Tests.feature | 2 +- src/BlazorApp/Pages/Counter.razor | 2 +- 8 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Selectors/ButtonSelector.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Services/Hooks.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Services/WebElementStorageService.cs create mode 100644 Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/MainPage.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/MainPage.cs index 72c784f..c93b219 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/MainPage.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/MainPage.cs @@ -1,6 +1,7 @@ using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; using Behavioral.Automation.Configs; using Behavioral.Automation.Implementation.Selenium.Configs; +using Behavioral.Automation.Implementation.Selenium.Selectors; using Behavioral.Automation.Playwright.Pages; namespace Behavioral.Automation.Implementation.Selenium.Pages; @@ -10,4 +11,6 @@ class MainPageExample : ISelectorStorage private static readonly string Id = ConfigManager.GetConfig().SearchAttribute; public ElementSelector DemoLabel = new() {IdSelector = "label-simple-text"}; + public ButtonSelector IncrementCountButton = new() {XpathSelector = "//button[@data-automation-id='increment-count-button']"}; + } \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Selectors/ButtonSelector.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Selectors/ButtonSelector.cs new file mode 100644 index 0000000..945b663 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Selectors/ButtonSelector.cs @@ -0,0 +1,8 @@ +using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; + +namespace Behavioral.Automation.Implementation.Selenium.Selectors; + +public class ButtonSelector : ElementSelector +{ + +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Services/Hooks.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Services/Hooks.cs new file mode 100644 index 0000000..a26bdb9 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Services/Hooks.cs @@ -0,0 +1,24 @@ +using System.Runtime.ConstrainedExecution; +using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; +using BoDi; +using TechTalk.SpecFlow; + +namespace Behavioral.Automation.Implementation.Selenium.Services; + +[Binding] +public class Hooks +{ + private readonly ObjectContainer _objectContainer; + + public Hooks(ObjectContainer objectContainer) + { + _objectContainer = objectContainer; + } + + // Configuration of DI and Factories should be done with order 0 + [BeforeScenario(Order = 0)] + public void ConfigureUiImplementations() + { + _objectContainer.RegisterTypeAs(); + } +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Services/WebElementStorageService.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Services/WebElementStorageService.cs new file mode 100644 index 0000000..bb42b78 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Services/WebElementStorageService.cs @@ -0,0 +1,63 @@ +using System.Text.RegularExpressions; +using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; +using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; +using Behavioral.Automation.Playwright.Pages; +using BoDi; + +namespace Behavioral.Automation.Implementation.Selenium.Services; + +public class WebElementStorageService : IWebElementStorageService +{ + private readonly WebContext _webContext; + private readonly IObjectContainer _objectContainer; + + public WebElementStorageService(WebContext webContext, IObjectContainer objectContainer) + { + _webContext = webContext; + _objectContainer = objectContainer; + } + + //TODO: Impl factory + public T Get(string elementName) where T : IWebElement + { + var pages = GetAllPagesWithElements(); + var elementSelector = GetElementSelector(pages, elementName); + + // Select proper realisation for element according to registered class in DI framework: + var classType = IWebElementStorageService.RegisteredElements[typeof(T)]; + var element = (IWebElement) Activator.CreateInstance(classType, _webContext, elementSelector); + element.Description = elementName; + return (T) element; + } + + private IEnumerable GetAllPagesWithElements() + { + var type = typeof(ISelectorStorage); + return AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(s => s.GetTypes()) + .Where(p => type.IsAssignableFrom(p) && p.IsClass); + } + + private ElementSelector GetElementSelector(IEnumerable pages, string elementName) + { + ElementSelector elementSelector = null; + var camelCaseElementName = ToCamelCase(elementName); + + foreach (var pageType in pages) + { + var pageTemp = Activator.CreateInstance(pageType); + var temp = (ElementSelector) pageType.GetField(camelCaseElementName)?.GetValue(pageTemp)!; + if (elementSelector != null && temp != null) + throw new Exception($"found the same selector '{elementName}' in different classes"); + elementSelector ??= temp; + } + + if (elementSelector == null) throw new Exception($"'{elementName}' transformed to '{camelCaseElementName}' selectors not found."); + return elementSelector; + } + + private string ToCamelCase(string originalString) + { + return Regex.Replace(originalString, @"[ ](\w)", m => m.Groups[1].Value.ToUpper()); + } +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs index 96afcc1..f8fe493 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs @@ -1,20 +1,18 @@ using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; +using Behavioral.Automation.Implementation.Selenium.Selectors; namespace Behavioral.Automation.Implementation.Selenium.WebElements; -public class ButtonElement : IButtonElement +public class ButtonElement: SeleniumWebElement, IButtonElement { - public WebContext WebContext { get; } - public ElementSelector ElementSelector { get; } - public string? Description { get; set; } - public Task ShouldBecomeVisibleAsync() + + public ButtonElement(WebContext webContext, ButtonSelector selector) : base(webContext, selector) { - throw new NotImplementedException(); } - public Task ClickAsync() + public async Task ClickAsync() { - throw new NotImplementedException(); + await Locator.ClickAsync(); } } \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs new file mode 100644 index 0000000..1ce4c3c --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs @@ -0,0 +1,35 @@ +using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; +using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; +using Behavioral.Automation.Implementation.Selenium.Bindings; + +namespace Behavioral.Automation.Implementation.Selenium.WebElements; + +public class SeleniumWebElement: IWebElement +{ + public WebContext WebContext { get; } + public ElementSelector ElementSelector { get; } + public string? Description { get; set; } + public async Task ShouldBecomeVisibleAsync() + { + await Assertions.Expect(Locator).ToBeVisibleAsync(); + } + + protected PlaywrightWebElement(WebContext webContext, ElementSelector baseSelector) + { + ElementSelector = baseSelector; + WebContext = webContext; + } + + public ILocator Locator + { + get + { + if (WebContext is null) throw new NullReferenceException("Please set web context."); + // Locator for Playwright can be retrieved from Page element: + var selector = (ElementSelector.XpathSelector != null) + ? ElementSelector.XpathSelector + : ElementSelector.IdSelector; + return ((Page) WebContext.Page).GetPlaywrightPage().Locator(selector); + } + } +} \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature index 5214f9a..95921e1 100644 --- a/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature @@ -2,4 +2,4 @@ Scenario: Button click binding test Given application URL was opened - When user clicks the "test" button + When user clicks the "Increment count" button diff --git a/src/BlazorApp/Pages/Counter.razor b/src/BlazorApp/Pages/Counter.razor index 4315314..acf2173 100644 --- a/src/BlazorApp/Pages/Counter.razor +++ b/src/BlazorApp/Pages/Counter.razor @@ -6,7 +6,7 @@

Current count: @currentCount

- + @code { private int currentCount = 0; From 4a0474419216a503164af475ba06648eef29baa0 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 17:10:28 +0400 Subject: [PATCH 30/32] moved implementation to SeleniumWebElement --- .../WebElements/ButtonElement.cs | 4 ++-- .../WebElements/SeleniumWebElement.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs index f8fe493..704cba0 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs @@ -11,8 +11,8 @@ public ButtonElement(WebContext webContext, ButtonSelector selector) : base(webC { } - public async Task ClickAsync() + public Task ClickAsync() { - await Locator.ClickAsync(); + return new Task(() => { Locator.Click(); }); } } \ No newline at end of file diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs index 1ce4c3c..261c2db 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs @@ -14,13 +14,13 @@ public async Task ShouldBecomeVisibleAsync() await Assertions.Expect(Locator).ToBeVisibleAsync(); } - protected PlaywrightWebElement(WebContext webContext, ElementSelector baseSelector) + protected SeleniumWebElement(WebContext webContext, ElementSelector baseSelector) { ElementSelector = baseSelector; WebContext = webContext; } - public ILocator Locator + public OpenQA.Selenium.IWebElement Locator { get { From ebea0efa042ed87861015450a09ff6d5ec87beb5 Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 17:23:09 +0400 Subject: [PATCH 31/32] added poc for finnd element --- .../Bindings/Page.cs | 2 +- .../WebElements/SeleniumWebElement.cs | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs index 9830141..af61573 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs @@ -10,7 +10,7 @@ public class Page : IPage public IWebDriver driver; public Task GoToUrlAsync(string url) { - return new Task(() => { driver.Navigate().GoToUrl(url); }); + return Task.Run(() => { driver.Navigate().GoToUrl(url); }); } public Task GoToApplicationUrlAsync() diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs index 261c2db..62eae52 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs @@ -1,6 +1,8 @@ using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; -using Behavioral.Automation.AsyncAbstractions.UI.Interfaces; using Behavioral.Automation.Implementation.Selenium.Bindings; +using NUnit.Framework; +using OpenQA.Selenium; +using IWebElement = Behavioral.Automation.AsyncAbstractions.UI.Interfaces.IWebElement; namespace Behavioral.Automation.Implementation.Selenium.WebElements; @@ -9,9 +11,9 @@ public class SeleniumWebElement: IWebElement public WebContext WebContext { get; } public ElementSelector ElementSelector { get; } public string? Description { get; set; } - public async Task ShouldBecomeVisibleAsync() + public Task ShouldBecomeVisibleAsync() { - await Assertions.Expect(Locator).ToBeVisibleAsync(); + return Locator.Displayed ? Task.Run(() => { }) : Task.Run(() => { Assert.Fail("Element is not visible"); }); } protected SeleniumWebElement(WebContext webContext, ElementSelector baseSelector) @@ -25,11 +27,12 @@ public OpenQA.Selenium.IWebElement Locator get { if (WebContext is null) throw new NullReferenceException("Please set web context."); - // Locator for Playwright can be retrieved from Page element: - var selector = (ElementSelector.XpathSelector != null) - ? ElementSelector.XpathSelector - : ElementSelector.IdSelector; - return ((Page) WebContext.Page).GetPlaywrightPage().Locator(selector); + if (ElementSelector.XpathSelector != null) + { + return ((Page) WebContext.Page).driver.FindElement(By.XPath(ElementSelector.XpathSelector)); + } + + throw new Exception("Currently only search by Xpath selector is implemented"); } } } \ No newline at end of file From b3b120ab00751b2f693772c4b248925cd9c4b09e Mon Sep 17 00:00:00 2001 From: OlegMozhey Date: Sun, 14 Apr 2024 17:26:50 +0400 Subject: [PATCH 32/32] Finished poc for selenium interraction --- .../WebElements/ButtonElement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs index 704cba0..132d5ee 100644 --- a/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs @@ -13,6 +13,6 @@ public ButtonElement(WebContext webContext, ButtonSelector selector) : base(webC public Task ClickAsync() { - return new Task(() => { Locator.Click(); }); + return Task.Run(() => { Locator.Click(); }); } } \ No newline at end of file