Skip to content

Commit

Permalink
Add click button test
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleg-Mozhey committed Apr 9, 2024
1 parent 9cfacb5 commit f92ebe2
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Behavioral.Automation.AsyncAbstractions.UI\Behavioral.Automation.AsyncAbstractions.UI.csproj" />
<ProjectReference Include="..\..\Behavioral.Automation.Configs\Behavioral.Automation.Configs.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Behavioral.Automation.Playwright.Context;
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
using Behavioral.Automation.Playwright.Context;
using Behavioral.Automation.Playwright.Selectors;
using Behavioral.Automation.Playwright.Services;
using Behavioral.Automation.Playwright.Services.ElementSelectors;
using Behavioral.Automation.Playwright.Utils;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Behavioral.Automation.Configs;
using Behavioral.Automation.Playwright.Configs;
using Behavioral.Automation.Playwright.Context;
using Behavioral.Automation.Playwright.WebElementsWrappers;
using BoDi;
using Microsoft.Playwright;
using NUnit.Framework;
Expand All @@ -17,6 +18,7 @@ public class Hooks
{
private readonly IObjectContainer _objectContainer;
private readonly WebContext _webContext;
private readonly AsyncAbstractions.UI.BasicImplementations.WebContext _newWebContext;
private static IPlaywright? _playwright;
private static IBrowser? _browser;
private readonly ScenarioContext _scenarioContext;
Expand All @@ -25,12 +27,13 @@ public class Hooks
private static readonly bool RecordVideo = ConfigManager.GetConfig<Config>().RecordVideo;
private readonly TestServicesBuilder _testServicesBuilder;

public Hooks(WebContext webContext, ScenarioContext scenarioContext, IObjectContainer objectContainer)
public Hooks(AsyncAbstractions.UI.BasicImplementations.WebContext newWebContext, WebContext webContext, ScenarioContext scenarioContext, IObjectContainer objectContainer)
{
_objectContainer = objectContainer;
_webContext = webContext;
_scenarioContext = scenarioContext;
_testServicesBuilder = new TestServicesBuilder(objectContainer);
_newWebContext = newWebContext;
}

[BeforeTestRun]
Expand Down Expand Up @@ -61,6 +64,7 @@ public async Task CreateContextAsync()
: await _browser.NewContextAsync();

_webContext.Page = await _webContext.Context.NewPageAsync();
_newWebContext.Page = new Page(_webContext.Page);
}

[AfterScenario]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using Behavioral.Automation.Configs;
using Behavioral.Automation.Playwright.Configs;
using Behavioral.Automation.Playwright.Selectors;
using Behavioral.Automation.Playwright.Services.ElementSelectors;

namespace Behavioral.Automation.Playwright.Pages;

class MainPageExample : ISelectorStorage
{
private static readonly string Id = ConfigManager.GetConfig<Config>().SearchAttribute;

public ButtonSelector IncrementCountButton = new() {XpathSelector = "//button[@data-automation-id='increment-count-button']"};

public ElementSelector DemoLabel = new() {IdSelector = "label-simple-text"};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations;

namespace Behavioral.Automation.Playwright.Selectors;

public class ButtonSelector : ElementSelector
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations;
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
using Behavioral.Automation.Playwright.Pages;
using Behavioral.Automation.Playwright.Utils;
using BoDi;

namespace Behavioral.Automation.Playwright.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<T>(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<Type> GetAllPagesWithElements()
{
var type = typeof(ISelectorStorage);
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p) && p.IsClass);
}

private ElementSelector GetElementSelector(IEnumerable<Type> pages, string elementName)
{
ElementSelector elementSelector = null;
var camelCaseElementName = elementName.ToCamelCase();

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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Threading.Tasks;
using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations;
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
using Behavioral.Automation.Playwright.Selectors;

namespace Behavioral.Automation.Playwright.WebElementsWrappers;

public class ButtonElement: PlaywrightWebElement, IButtonElement
{

public ButtonElement(WebContext webContext, ButtonSelector selector) : base(webContext, selector)
{
}

public async Task ClickAsync()
{
await Locator.ClickAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Threading.Tasks;
using Behavioral.Automation.Configs;
using Behavioral.Automation.Playwright.Configs;
using Microsoft.Playwright;
using IPage = Behavioral.Automation.AsyncAbstractions.UI.Interfaces.IPage;

namespace Behavioral.Automation.Playwright.WebElementsWrappers;

public class Page: IPage
{
private readonly Microsoft.Playwright.IPage _playwrightPage;


public Page(Microsoft.Playwright.IPage playwrightPage)
{
_playwrightPage = playwrightPage;
}

public Task GoToUrlAsync(string url)
{
throw new NotImplementedException();
}

public Task GoToApplicationUrlAsync()
{
return _playwrightPage.GotoAsync(ConfigManager.GetConfig<Config>().BaseUrl,
new PageGotoOptions { WaitUntil = WaitUntilState.NetworkIdle, Timeout = 300000 });
}

public Task HaveTitleAsync(string title)
{
throw new NotImplementedException();
}

public Microsoft.Playwright.IPage GetPlaywrightPage()
{
return _playwrightPage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Threading.Tasks;
using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations;
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
using Microsoft.Playwright;

namespace Behavioral.Automation.Playwright.WebElementsWrappers;

public abstract class PlaywrightWebElement : 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);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
using Behavioral.Automation.Playwright.Services;
using Behavioral.Automation.Playwright.WebElementsWrappers;
using BoDi;
using TechTalk.SpecFlow;

namespace Behavioral.Automation.Playwright.Tests.Configurations;

[Binding]
public class Configurations
{
private readonly ObjectContainer _objectContainer;

// Configuration of DI and Factories should be done with order 0
public Configurations(ObjectContainer objectContainer)
{
_objectContainer = objectContainer;
}

[BeforeTestRun(Order = 0)]
public static void ConfigureUiImplementations()
{
// IWebElementStorageService.RegisterWebElementImplementationAs<InputElement, IInputWebElement>();
IWebElementStorageService.RegisterWebElementImplementationAs<ButtonElement, IButtonElement>();
}

/// <summary>
/// According to our convention all interfaces registrations should go with 0 order
/// </summary>
[BeforeScenario(Order = 0)]
public void Bootstrap()
{
_objectContainer.RegisterTypeAs<WebElementStorageService, IWebElementStorageService>();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
Feature: Tests for Bahavioral.Automation.Playwright project
Feature: Button step definition tests

Scenario: Check button click
Given application URL is opened
When user clicks the "Increment count" button

Scenario: Visibility binding check
Given application URL is opened
Expand Down
6 changes: 6 additions & 0 deletions Behavioral.Automation.Playwright/UITests/specflow.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
"missingOrPendingStepsOutcome": "Error"
},
"stepAssemblies": [
{
"assembly": "Behavioral.Automation.AsyncAbstractions.UI"
},
{
"assembly": "Behavioral.Automation.Playwright"
},
{
"assembly": "UITests"
}
]
}
2 changes: 1 addition & 1 deletion src/BlazorApp/Pages/Counter.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
<button data-automation-id="increment-count-button" class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;
Expand Down

0 comments on commit f92ebe2

Please sign in to comment.