diff --git a/Behavioral.Automation.Template/.template.config/template.json b/Behavioral.Automation.Template/.template.config/template.json
new file mode 100644
index 00000000..0358ab26
--- /dev/null
+++ b/Behavioral.Automation.Template/.template.config/template.json
@@ -0,0 +1,25 @@
+{
+ "$schema": "http://json.schemastore.org/template",
+ "author": "Quantori LLC",
+ "classifications": [
+ "BDD",
+ "Automation"
+ ],
+ "identity": "BDDTemplate",
+ "name": "Template for Behavioral Automation Framework",
+ "sourceName": "Behavioral.Automation.Template",
+ "shortName": "bddautomation",
+ "tags": {
+ "language": "C#",
+ "type": "project"
+ },
+ "sources": [
+ {
+ "modifiers": [
+ {
+ "exclude": [ ".vs/**", "**/**.feature.cs", "**.nuspec" ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/AutomationConfig.json b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/AutomationConfig.json
new file mode 100644
index 00000000..e2d76509
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/AutomationConfig.json
@@ -0,0 +1,14 @@
+{
+ "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": "id",
+ "BAUTH_LOGIN": "",
+ "BAUTH_PWD": "",
+ "BAUTH_IGNORE": "true",
+ "BROWSER_BINARY_LOCATION" : ""
+}
\ No newline at end of file
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/Behavioral.Automation.Template.Bindings.csproj b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/Behavioral.Automation.Template.Bindings.csproj
new file mode 100644
index 00000000..5fcba859
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/Behavioral.Automation.Template.Bindings.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net6.0
+ false
+ Quantori Inc.
+ Demo project that can be used as example of test configuration.
+ https://github.com/quantori/Behavioral.Automation
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementStorage/UserInterfaceBuilder.cs b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementStorage/UserInterfaceBuilder.cs
new file mode 100644
index 00000000..2673f456
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementStorage/UserInterfaceBuilder.cs
@@ -0,0 +1,29 @@
+using Behavioral.Automation.Services;
+using Behavioral.Automation.Services.Mapping.Contract;
+
+namespace Behavioral.Automation.Template.Bindings.ElementStorage
+{
+ public class UserInterfaceBuilder : UserInterfaceBuilderBase
+ {
+ public UserInterfaceBuilder(IScopeMarkupMapper mapper)
+ : base(mapper)
+ {
+
+ }
+
+ public override void Build()
+ {
+ using (var mappingPipe = Mapper.GetGlobalMappingPipe())
+ {
+ mappingPipe.Register("input").Alias("input")
+ .With("searchInput").As("Search");
+
+ mappingPipe.Register("input").Alias("button")
+ .With("searchButton").As("Magnifying glass");
+
+ mappingPipe.Register("h1")
+ .With("firstHeading").As("Page header");
+ }
+ }
+ }
+}
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/TextElementWrapper.cs b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/TextElementWrapper.cs
new file mode 100644
index 00000000..bcdc8a9d
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/TextElementWrapper.cs
@@ -0,0 +1,37 @@
+using System.Diagnostics.CodeAnalysis;
+using Behavioral.Automation.Elements;
+using Behavioral.Automation.FluentAssertions;
+using Behavioral.Automation.Model;
+using Behavioral.Automation.Services;
+using OpenQA.Selenium;
+
+namespace Behavioral.Automation.Template.Bindings.ElementWrappers
+{
+ public sealed class TextElementWrapper : WebElementWrapper, ITextElementWrapper
+ {
+ public TextElementWrapper([NotNull] IWebElementWrapper wrapper, string caption, [NotNull] IDriverService driverService)
+ : base(() => wrapper.Element, caption, driverService) { }
+
+ public void EnterString(string input)
+ {
+ Assert.ShouldBecome(() => Enabled, true,
+ new AssertionBehavior(AssertionType.Continuous, false),
+ $"{Caption} is not enabled");
+ Element.SendKeys(input);
+ Driver.RemoveFocusFromActiveElement();
+ }
+
+ public void ClearInput()
+ {
+ Assert.ShouldBecome(() => Enabled, true,
+ new AssertionBehavior(AssertionType.Continuous, false),
+ $"{Caption} is not enabled");
+
+ while (Element.GetAttribute("value").Length > 0)
+ {
+ Element.SendKeys(Keys.Backspace);
+ }
+ Driver.RemoveFocusFromActiveElement();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/WebElementWrapper.cs b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/WebElementWrapper.cs
new file mode 100644
index 00000000..27e19e7b
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/ElementWrappers/WebElementWrapper.cs
@@ -0,0 +1,122 @@
+using Behavioral.Automation.Elements;
+using Behavioral.Automation.FluentAssertions;
+using Behavioral.Automation.Services;
+using OpenQA.Selenium;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Behavioral.Automation.Template.Bindings.ElementWrappers
+{
+ public class WebElementWrapper : IWebElementWrapper
+ {
+ private readonly Func _elementSelector;
+ private readonly IDriverService _driverService;
+
+ public WebElementWrapper([NotNull] Func elementSelector, [NotNull] string caption, [NotNull] IDriverService driverService)
+ {
+ _elementSelector = elementSelector;
+ _driverService = driverService;
+ Caption = caption;
+ }
+
+ public string Caption { get; }
+
+ public IWebElement Element => _elementSelector();
+
+ public string Text => Element.Text;
+
+ public string GetAttribute(string attribute) => Element.GetAttribute(attribute);
+
+ public void Click()
+ {
+ MouseHover();
+ Assert.ShouldGet(() => Enabled);
+ _driverService.MouseClick();
+ }
+
+ public void MouseHover()
+ {
+ Assert.ShouldBecome(() => Enabled, true, $"{Caption} is disabled");
+ _driverService.ScrollTo(Element);
+ }
+
+ public void SendKeys(string text)
+ {
+ Assert.ShouldBecome(() => Enabled, true, $"{Caption} is disabled");
+ Element.SendKeys(text);
+ }
+
+ public bool Displayed => Element != null && Element.Displayed;
+
+ public bool Enabled => Displayed && Element.Enabled && AriaEnabled;
+
+ public string Tooltip
+ {
+ get
+ {
+ var matTooltip = GetAttribute("matTooltip");
+ if (matTooltip != null)
+ {
+ return matTooltip;
+ }
+ var ngReflectTip = GetAttribute("ng-reflect-message"); //some elements have their tooltips' texts stored inside 'ng-reflect-message' attribute
+ if (ngReflectTip != null)
+ {
+ return ngReflectTip;
+ }
+
+ return GetAttribute("aria-label"); //some elements have their tooltips' texts stored inside 'aria-label' attribute
+ }
+ }
+
+ public bool Stale
+ {
+ get
+ {
+ try
+ {
+ // Calling any method forces a staleness check
+ var elementEnabled = Element.Enabled;
+ return false;
+ }
+ catch (StaleElementReferenceException)
+ {
+ return true;
+ }
+ }
+ }
+
+ public IEnumerable FindSubElements(By locator, string caption)
+ {
+ var elements = Assert.ShouldGet(() => Element.FindElements(locator));
+ return ElementsToWrappers(elements, caption);
+ }
+
+ private IEnumerable ElementsToWrappers(IEnumerable elements, string caption)
+ {
+ foreach (var element in elements)
+ {
+ var wrapper = new WebElementWrapper(() => element, caption, _driverService);
+ yield return wrapper;
+ }
+ }
+
+ protected IDriverService Driver => _driverService;
+
+ private bool AriaEnabled
+ {
+ get
+ {
+ switch (Element.GetAttribute("aria-disabled"))
+ {
+ case null:
+ case "false":
+ return true;
+ }
+
+ return false;
+ }
+ }
+ }
+}
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/Hooks/Bootstrapper.cs b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/Hooks/Bootstrapper.cs
new file mode 100644
index 00000000..6c0dfc34
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/Hooks/Bootstrapper.cs
@@ -0,0 +1,42 @@
+using Behavioral.Automation.FluentAssertions;
+using Behavioral.Automation.Services;
+using Behavioral.Automation.Template.Bindings.ElementStorage;
+using BoDi;
+using TechTalk.SpecFlow;
+using Behavioral.Automation;
+using Behavioral.Automation.Template.Bindings.Services;
+
+namespace Behavioral.Automation.Template.Bindings.Hooks
+{
+ [Binding]
+ public class Bootstrapper
+ {
+ private readonly IObjectContainer _objectContainer;
+ private readonly ITestRunner _runner;
+ private readonly DemoTestServicesBuilder _servicesBuilder;
+ private readonly BrowserRunner _browserRunner;
+
+ public Bootstrapper(IObjectContainer objectContainer, ITestRunner runner, BrowserRunner browserRunner)
+ {
+ _objectContainer = objectContainer;
+ _runner = runner;
+ _browserRunner = browserRunner;
+ _servicesBuilder = new DemoTestServicesBuilder(objectContainer, new TestServicesBuilder(_objectContainer));
+ }
+
+ [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.Template/Behavioral.Automation.Template.Bindings/Services/DemoTestServicesBuilder.cs b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/Services/DemoTestServicesBuilder.cs
new file mode 100644
index 00000000..59026254
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/Services/DemoTestServicesBuilder.cs
@@ -0,0 +1,22 @@
+using BoDi;
+using Behavioral.Automation;
+
+namespace Behavioral.Automation.Template.Bindings.Services
+{
+ internal class DemoTestServicesBuilder
+ {
+ private readonly IObjectContainer _objectContainer;
+ private readonly TestServicesBuilder _servicesBuilder;
+
+ internal DemoTestServicesBuilder(IObjectContainer objectContainer, TestServicesBuilder servicesBuilder)
+ {
+ _objectContainer = objectContainer;
+ _servicesBuilder = servicesBuilder;
+ }
+
+ internal void Build()
+ {
+ _servicesBuilder.Build();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/StepArgumentTransformations/ElementTransformations.cs b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/StepArgumentTransformations/ElementTransformations.cs
new file mode 100644
index 00000000..cc181a23
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Bindings/StepArgumentTransformations/ElementTransformations.cs
@@ -0,0 +1,37 @@
+using Behavioral.Automation.Template.Bindings.ElementWrappers;
+using Behavioral.Automation.Elements;
+using Behavioral.Automation.Services;
+using JetBrains.Annotations;
+using TechTalk.SpecFlow;
+
+namespace Behavioral.Automation.Template.Bindings.StepArgumentTransformations
+{
+ [Binding]
+ class ElementTransformations
+ {
+ private readonly IDriverService _driverService;
+ private readonly IElementSelectionService _selectionService;
+
+ public ElementTransformations(
+ [NotNull] IDriverService driverService,
+ [NotNull] IElementSelectionService selectionService)
+ {
+ _driverService = driverService;
+ _selectionService = selectionService;
+ }
+
+ [StepArgumentTransformation]
+ public IWebElementWrapper FindElement([NotNull] string caption)
+ {
+ return new WebElementWrapper(() => _selectionService.Find(caption),
+ caption,
+ _driverService);
+ }
+
+ [StepArgumentTransformation("(.*)")]
+ public ITextElementWrapper FindTextElement([NotNull] IWebElementWrapper element)
+ {
+ return new TextElementWrapper(element, element.Caption, _driverService);
+ }
+ }
+}
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/Behavioral.Automation.Template.Scenarios.csproj b/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/Behavioral.Automation.Template.Scenarios.csproj
new file mode 100644
index 00000000..be043f26
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/Behavioral.Automation.Template.Scenarios.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net6.0
+ Quantori Inc.
+ Specflow scenarios for demonstration of Behavioral.Automation framework features and testing.
+ Quantori Inc.
+ https://github.com/quantori/Behavioral.Automation
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/Features/Examples.feature b/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/Features/Examples.feature
new file mode 100644
index 00000000..65166345
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/Features/Examples.feature
@@ -0,0 +1,13 @@
+Feature: Examples
+
+@Automated
+Scenario: Open Google page
+ When user opens URL "https://www.google.com/"
+ Then page title should become "Google"
+
+@Automated
+Scenario: Find something on Wikipedia
+ When user opens URL "https://en.wikipedia.org/"
+ And user enters "French bulldog" into "Search" input
+ And user clicks on "Magnifying glass" button
+ Then the "Page header" text should become "French Bulldog"
\ No newline at end of file
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/Properties/AssemblyInfo.cs b/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..98c5f084
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/Properties/AssemblyInfo.cs
@@ -0,0 +1,6 @@
+using NUnit.Framework;
+
+[assembly: Parallelizable(ParallelScope.Fixtures)]
+
+//edit if more threads are needed
+[assembly: LevelOfParallelism(1)]
\ No newline at end of file
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/specflow.json b/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/specflow.json
new file mode 100644
index 00000000..797f0043
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.Scenarios/specflow.json
@@ -0,0 +1,19 @@
+{
+ "bindingCulture": {
+ "language": "en-us"
+ },
+ "language": {
+ "feature": "en-us"
+ },
+ "runtime": {
+ "missingOrPendingStepsOutcome": "Error"
+ },
+ "stepAssemblies": [
+ {
+ "assembly": "Behavioral.Automation.Template.Bindings"
+ },
+ {
+ "assembly": "Behavioral.Automation"
+ }
+ ]
+}
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.Template.sln b/Behavioral.Automation.Template/Behavioral.Automation.Template.sln
new file mode 100644
index 00000000..8e1669d3
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.Template.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Behavioral.Automation.Template.Bindings", "Behavioral.Automation.Template.Bindings\Behavioral.Automation.Template.Bindings.csproj", "{97A76E21-F1E4-49D8-B419-BAFD89B565BD}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Behavioral.Automation.Template.Scenarios", "Behavioral.Automation.Template.Scenarios\Behavioral.Automation.Template.Scenarios.csproj", "{0958EBF8-72A6-45DA-A552-C9B18F6A1695}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {97A76E21-F1E4-49D8-B419-BAFD89B565BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {97A76E21-F1E4-49D8-B419-BAFD89B565BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {97A76E21-F1E4-49D8-B419-BAFD89B565BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {97A76E21-F1E4-49D8-B419-BAFD89B565BD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0958EBF8-72A6-45DA-A552-C9B18F6A1695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0958EBF8-72A6-45DA-A552-C9B18F6A1695}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0958EBF8-72A6-45DA-A552-C9B18F6A1695}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0958EBF8-72A6-45DA-A552-C9B18F6A1695}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {762FF955-CF9D-4647-87C5-7F974941573C}
+ EndGlobalSection
+EndGlobal
diff --git a/Behavioral.Automation.Template/Behavioral.Automation.nuspec b/Behavioral.Automation.Template/Behavioral.Automation.nuspec
new file mode 100644
index 00000000..0c93f776
--- /dev/null
+++ b/Behavioral.Automation.Template/Behavioral.Automation.nuspec
@@ -0,0 +1,19 @@
+
+
+
+ Behavioral.Automation.Template
+ 1.7.0
+
+ Template for easy start with Behavioral.Automation framework
+
+ Quantori LLC
+
+
+
+ readme.md
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Behavioral.Automation.Template/readme.md b/Behavioral.Automation.Template/readme.md
new file mode 100644
index 00000000..3a083e2f
--- /dev/null
+++ b/Behavioral.Automation.Template/readme.md
@@ -0,0 +1,13 @@
+# Quantori Behavioral Automation Testing System
+Copyright (c) 2022 Quantori.
+
+Quantori Behavioral Automation is an open-source framework for UI testing automation based on Selenium and Specflow which incorporates good portability and ability to be integrated into a custom web-application. Quantori Behavioral Automation is designed to be used by both manual and automation QA engineers in projects which are built based on Behaviour Driven Development approach.
+
+## KEY FEATURES
+* Allows to create project for BDD Automation needs using Behavioral.Automation framework
+
+## Build instructions
+TBD
+
+## License
+Quantori Behavioral Automation Testing System is released under [Apache License, Version 2.0](LICENSE)