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 new file mode 100644 index 0000000..a2b4614 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium.csproj @@ -0,0 +1,24 @@ + + + + net6.0 + enable + enable + Behavioral.Automation.Implementation.Selenium + + + + + + + + + + + + + + + + + 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..1a35140 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/BrowserRunner.cs @@ -0,0 +1,114 @@ +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) + { + Driver = driver; + } + + + /// + /// Driver disposal + /// + public void CloseBrowser() + { + Driver.Dispose(); + } + + /// + /// Open and configure Google Chrome browser + /// + /// 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) + { + options = new ChromeOptions(); + options.AddArguments(new List( + ConfigManager.GetConfig().BrowserParameters.Split(" ", StringSplitOptions.RemoveEmptyEntries))); + if (ConfigManager.GetConfig().BrowserParameters.Contains("headless")) + { + ConfigureChromeHeadlessDownload(options, downloadPath); + } + + if (ConfigManager.GetConfig().AccessClipboard) + { + ConfigureClipboardAccess(options); + } + + options.AddUserProfilePreference("intl.accept_languages", "en,en_US"); + options.AcceptInsecureCertificates = ConfigManager.GetConfig().AcceptInsecureCertificates; + options.SetLoggingPreference(LogType.Browser, LogLevel.All); + if (!string.IsNullOrWhiteSpace(ConfigManager.GetConfig().BrowserBinaryLocation)) + { + options.BinaryLocation = + Environment.ExpandEnvironmentVariables(ConfigManager.GetConfig().BrowserBinaryLocation); + } + + if (!string.IsNullOrWhiteSpace(ConfigManager.GetConfig().UnhandledPromptBehavior)) + { + options.UnhandledPromptBehavior = ConfigManager.GetConfig().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 + { + { + ConfigManager.GetConfig().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/Hooks.cs b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs new file mode 100644 index 0000000..6fbac0d --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Hooks.cs @@ -0,0 +1,94 @@ +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; +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; + private readonly WebContext _webContext; + + public Hooks(IObjectContainer objectContainer, ITestRunner runner, BrowserRunner browserRunner, WebContext webContext) + { + _objectContainer = objectContainer; + _runner = runner; + _browserRunner = browserRunner; + _webContext = webContext; + } + + 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(); + _webContext.Page = new Page(); + ((Page) _webContext.Page).driver = _browserRunner.Driver; + } +} \ No newline at end of file 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 new file mode 100644 index 0000000..af61573 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Bindings/Page.cs @@ -0,0 +1,25 @@ +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 Page : IPage +{ + public IWebDriver driver; + public Task GoToUrlAsync(string url) + { + return Task.Run(() => { driver.Navigate().GoToUrl(url); }); + } + + public Task GoToApplicationUrlAsync() + { + return Task.Run(() => { driver.Navigate().GoToUrl(ConfigManager.GetConfig().BaseUrl); }); + } + + public Task HaveTitleAsync(string title) + { + throw new NotImplementedException(); + } +} \ 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 new file mode 100644 index 0000000..0c16628 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Configs/Config.cs @@ -0,0 +1,32 @@ +using Microsoft.Extensions.Configuration; + +namespace Behavioral.Automation.Implementation.Selenium.Configs; + +public class Config +{ + [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 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..c93b219 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/Pages/MainPage.cs @@ -0,0 +1,16 @@ +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; + +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 new file mode 100644 index 0000000..132d5ee --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/ButtonElement.cs @@ -0,0 +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: SeleniumWebElement, IButtonElement +{ + + public ButtonElement(WebContext webContext, ButtonSelector selector) : base(webContext, selector) + { + } + + public Task ClickAsync() + { + return Task.Run(() => { 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 new file mode 100644 index 0000000..62eae52 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/Behavioral.Automation.Implementation.Selenium/WebElements/SeleniumWebElement.cs @@ -0,0 +1,38 @@ +using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations; +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; + +public class SeleniumWebElement: IWebElement +{ + public WebContext WebContext { get; } + public ElementSelector ElementSelector { get; } + public string? Description { get; set; } + public Task ShouldBecomeVisibleAsync() + { + return Locator.Displayed ? Task.Run(() => { }) : Task.Run(() => { Assert.Fail("Element is not visible"); }); + } + + protected SeleniumWebElement(WebContext webContext, ElementSelector baseSelector) + { + ElementSelector = baseSelector; + WebContext = webContext; + } + + public OpenQA.Selenium.IWebElement Locator + { + get + { + if (WebContext is null) throw new NullReferenceException("Please set web context."); + 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 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.Implementation.Selenium/UITests/AutomationConfig.json b/Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json new file mode 100644 index 0000000..01701a2 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/AutomationConfig.json @@ -0,0 +1,22 @@ +{ + "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, + "BAUTH_URL": "", + "BAUTH_PASSWORD": "", + "UNHANDLED_PROMPT_BEHAVIOR" : "", + "ASSERT_ATTEMPTS" : 30 +} \ 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..4f6ba00 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Configuration/Configuration.cs @@ -0,0 +1,15 @@ +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 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..95921e1 --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/Features/Tests.feature @@ -0,0 +1,5 @@ +Feature: Tests for Bahavioral.Automation.Selenium project + + Scenario: Button click binding test + Given application URL was opened + When user clicks the "Increment count" button diff --git a/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj new file mode 100644 index 0000000..0b95a8f --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/UITests.csproj @@ -0,0 +1,34 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + 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..63c260b --- /dev/null +++ b/Behavioral.Automation.Implementation.Selenium/UITests/specflow.json @@ -0,0 +1,22 @@ +{ + "bindingCulture": { + "language": "en-us" + }, + "language": { + "feature": "en-us" + }, + "runtime": { + "missingOrPendingStepsOutcome": "Error" + }, + "stepAssemblies": [ + { + "assembly": "Behavioral.Automation.asyncAbstractions.UI" + }, + { + "assembly": "Behavioral.Automation.Implementation.Selenium" + }, + { + "assembly": "UITests" + } + ] +} 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..6e0e658 100644 --- a/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj +++ b/Behavioral.Automation.Selenium/Behavioral.Automation.DemoScenarios/Behavioral.Automation.DemoScenarios.csproj @@ -11,9 +11,9 @@ - - - + + + 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 diff --git a/Behavioral.Automation.sln b/Behavioral.Automation.sln index be4a136..1329635 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\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", "{B68D63F0-BDBC-4F35-B0DE-6459B27B0F96}" +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 + {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 @@ -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} + {B68D63F0-BDBC-4F35-B0DE-6459B27B0F96} = {765191A2-9E83-41A8-AFC4-55005123DF6F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {724FD185-E1F2-44BD-89EA-DFD1DBF6453A}