Skip to content

Commit bfc93d3

Browse files
authored
Merge pull request #152 from quantori/feature/add_button_click_test_case
Feature/add button click test case
2 parents 3b0a4fc + 88d8aee commit bfc93d3

File tree

13 files changed

+224
-3
lines changed

13 files changed

+224
-3
lines changed

Behavioral.Automation.Playwright/Behavioral.Automation.Playwright/Behavioral.Automation.Playwright.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
</ItemGroup>
4242

4343
<ItemGroup>
44+
<ProjectReference Include="..\..\Behavioral.Automation.AsyncAbstractions.UI\Behavioral.Automation.AsyncAbstractions.UI.csproj" />
4445
<ProjectReference Include="..\..\Behavioral.Automation.Configs\Behavioral.Automation.Configs.csproj" />
4546
</ItemGroup>
4647

Behavioral.Automation.Playwright/Behavioral.Automation.Playwright/ElementTransformations/ElementTransformations.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Behavioral.Automation.Playwright.Context;
1+
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
2+
using Behavioral.Automation.Playwright.Context;
3+
using Behavioral.Automation.Playwright.Selectors;
24
using Behavioral.Automation.Playwright.Services;
35
using Behavioral.Automation.Playwright.Services.ElementSelectors;
46
using Behavioral.Automation.Playwright.Utils;

Behavioral.Automation.Playwright/Behavioral.Automation.Playwright/Hooks.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Behavioral.Automation.Configs;
66
using Behavioral.Automation.Playwright.Configs;
77
using Behavioral.Automation.Playwright.Context;
8+
using Behavioral.Automation.Playwright.WebElementsWrappers;
89
using BoDi;
910
using Microsoft.Playwright;
1011
using NUnit.Framework;
@@ -17,6 +18,7 @@ public class Hooks
1718
{
1819
private readonly IObjectContainer _objectContainer;
1920
private readonly WebContext _webContext;
21+
private readonly AsyncAbstractions.UI.BasicImplementations.WebContext _newWebContext;
2022
private static IPlaywright? _playwright;
2123
private static IBrowser? _browser;
2224
private readonly ScenarioContext _scenarioContext;
@@ -25,12 +27,13 @@ public class Hooks
2527
private static readonly bool RecordVideo = ConfigManager.GetConfig<Config>().RecordVideo;
2628
private readonly TestServicesBuilder _testServicesBuilder;
2729

28-
public Hooks(WebContext webContext, ScenarioContext scenarioContext, IObjectContainer objectContainer)
30+
public Hooks(AsyncAbstractions.UI.BasicImplementations.WebContext newWebContext, WebContext webContext, ScenarioContext scenarioContext, IObjectContainer objectContainer)
2931
{
3032
_objectContainer = objectContainer;
3133
_webContext = webContext;
3234
_scenarioContext = scenarioContext;
3335
_testServicesBuilder = new TestServicesBuilder(objectContainer);
36+
_newWebContext = newWebContext;
3437
}
3538

3639
[BeforeTestRun]
@@ -61,6 +64,7 @@ public async Task CreateContextAsync()
6164
: await _browser.NewContextAsync();
6265

6366
_webContext.Page = await _webContext.Context.NewPageAsync();
67+
_newWebContext.Page = new Page(_webContext.Page);
6468
}
6569

6670
[AfterScenario]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
using Behavioral.Automation.Configs;
22
using Behavioral.Automation.Playwright.Configs;
3+
using Behavioral.Automation.Playwright.Selectors;
34
using Behavioral.Automation.Playwright.Services.ElementSelectors;
45

56
namespace Behavioral.Automation.Playwright.Pages;
67

78
class MainPageExample : ISelectorStorage
89
{
910
private static readonly string Id = ConfigManager.GetConfig<Config>().SearchAttribute;
11+
12+
public ButtonSelector IncrementCountButton = new() {XpathSelector = "//button[@data-automation-id='increment-count-button']"};
1013

1114
public ElementSelector DemoLabel = new() {IdSelector = "label-simple-text"};
1215
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations;
2+
3+
namespace Behavioral.Automation.Playwright.Selectors;
4+
5+
public class ButtonSelector : ElementSelector
6+
{
7+
8+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations;
5+
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
6+
using Behavioral.Automation.Playwright.Pages;
7+
using Behavioral.Automation.Playwright.Utils;
8+
using BoDi;
9+
10+
namespace Behavioral.Automation.Playwright.Services;
11+
12+
public class WebElementStorageService : IWebElementStorageService
13+
{
14+
private readonly WebContext _webContext;
15+
private readonly IObjectContainer _objectContainer;
16+
17+
public WebElementStorageService(WebContext webContext, IObjectContainer objectContainer)
18+
{
19+
_webContext = webContext;
20+
_objectContainer = objectContainer;
21+
}
22+
23+
//TODO: Impl factory
24+
public T Get<T>(string elementName) where T : IWebElement
25+
{
26+
var pages = GetAllPagesWithElements();
27+
var elementSelector = GetElementSelector(pages, elementName);
28+
29+
// Select proper realisation for element according to registered class in DI framework:
30+
var classType = IWebElementStorageService.RegisteredElements[typeof(T)];
31+
var element = (IWebElement) Activator.CreateInstance(classType, _webContext, elementSelector);
32+
element.Description = elementName;
33+
return (T) element;
34+
}
35+
36+
private IEnumerable<Type> GetAllPagesWithElements()
37+
{
38+
var type = typeof(ISelectorStorage);
39+
return AppDomain.CurrentDomain.GetAssemblies()
40+
.SelectMany(s => s.GetTypes())
41+
.Where(p => type.IsAssignableFrom(p) && p.IsClass);
42+
}
43+
44+
private ElementSelector GetElementSelector(IEnumerable<Type> pages, string elementName)
45+
{
46+
ElementSelector elementSelector = null;
47+
var camelCaseElementName = elementName.ToCamelCase();
48+
49+
foreach (var pageType in pages)
50+
{
51+
var pageTemp = Activator.CreateInstance(pageType);
52+
var temp = (ElementSelector) pageType.GetField(camelCaseElementName)?.GetValue(pageTemp)!;
53+
if (elementSelector != null && temp != null)
54+
throw new Exception($"found the same selector '{elementName}' in different classes");
55+
elementSelector ??= temp;
56+
}
57+
58+
if (elementSelector == null) throw new Exception($"'{elementName}' transformed to '{camelCaseElementName}' selectors not found.");
59+
return elementSelector;
60+
}
61+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Threading.Tasks;
2+
using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations;
3+
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
4+
using Behavioral.Automation.Playwright.Selectors;
5+
6+
namespace Behavioral.Automation.Playwright.WebElementsWrappers;
7+
8+
public class ButtonElement: PlaywrightWebElement, IButtonElement
9+
{
10+
11+
public ButtonElement(WebContext webContext, ButtonSelector selector) : base(webContext, selector)
12+
{
13+
}
14+
15+
public async Task ClickAsync()
16+
{
17+
await Locator.ClickAsync();
18+
}
19+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Behavioral.Automation.Configs;
4+
using Behavioral.Automation.Playwright.Configs;
5+
using Microsoft.Playwright;
6+
using IPage = Behavioral.Automation.AsyncAbstractions.UI.Interfaces.IPage;
7+
8+
namespace Behavioral.Automation.Playwright.WebElementsWrappers;
9+
10+
public class Page: IPage
11+
{
12+
private readonly Microsoft.Playwright.IPage _playwrightPage;
13+
14+
15+
public Page(Microsoft.Playwright.IPage playwrightPage)
16+
{
17+
_playwrightPage = playwrightPage;
18+
}
19+
20+
public Task GoToUrlAsync(string url)
21+
{
22+
throw new NotImplementedException();
23+
}
24+
25+
public Task GoToApplicationUrlAsync()
26+
{
27+
return _playwrightPage.GotoAsync(ConfigManager.GetConfig<Config>().BaseUrl,
28+
new PageGotoOptions { WaitUntil = WaitUntilState.NetworkIdle, Timeout = 300000 });
29+
}
30+
31+
public Task HaveTitleAsync(string title)
32+
{
33+
throw new NotImplementedException();
34+
}
35+
36+
public Microsoft.Playwright.IPage GetPlaywrightPage()
37+
{
38+
return _playwrightPage;
39+
}
40+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Behavioral.Automation.AsyncAbstractions.UI.BasicImplementations;
4+
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
5+
using Microsoft.Playwright;
6+
7+
namespace Behavioral.Automation.Playwright.WebElementsWrappers;
8+
9+
public abstract class PlaywrightWebElement : IWebElement
10+
{
11+
public WebContext WebContext { get; }
12+
public ElementSelector ElementSelector { get; }
13+
public string? Description { get; set; }
14+
public async Task ShouldBecomeVisibleAsync()
15+
{
16+
await Assertions.Expect(Locator).ToBeVisibleAsync();
17+
}
18+
19+
protected PlaywrightWebElement(WebContext webContext, ElementSelector baseSelector)
20+
{
21+
ElementSelector = baseSelector;
22+
WebContext = webContext;
23+
}
24+
25+
public ILocator Locator
26+
{
27+
get
28+
{
29+
if (WebContext is null) throw new NullReferenceException("Please set web context.");
30+
// Locator for Playwright can be retrieved from Page element:
31+
var selector = (ElementSelector.XpathSelector != null)
32+
? ElementSelector.XpathSelector
33+
: ElementSelector.IdSelector;
34+
return ((Page) WebContext.Page).GetPlaywrightPage().Locator(selector);
35+
}
36+
}
37+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Behavioral.Automation.AsyncAbstractions.UI.Interfaces;
2+
using Behavioral.Automation.Playwright.Services;
3+
using Behavioral.Automation.Playwright.WebElementsWrappers;
4+
using BoDi;
5+
using TechTalk.SpecFlow;
6+
7+
namespace Behavioral.Automation.Playwright.Tests.Configurations;
8+
9+
[Binding]
10+
public class Configurations
11+
{
12+
private readonly ObjectContainer _objectContainer;
13+
14+
/// <summary>
15+
/// According to our convention Configuration of DI and Factories should be done with order 0
16+
/// </summary>
17+
public Configurations(ObjectContainer objectContainer)
18+
{
19+
_objectContainer = objectContainer;
20+
}
21+
22+
[BeforeTestRun(Order = 0)]
23+
public static void ConfigureUiImplementations()
24+
{
25+
IWebElementStorageService.RegisterWebElementImplementationAs<ButtonElement, IButtonElement>();
26+
}
27+
28+
/// <summary>
29+
/// According to our convention all interfaces registrations should go with 0 order
30+
/// </summary>
31+
[BeforeScenario(Order = 0)]
32+
public void Bootstrap()
33+
{
34+
_objectContainer.RegisterTypeAs<WebElementStorageService, IWebElementStorageService>();
35+
}
36+
}

0 commit comments

Comments
 (0)