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}