Skip to content

Commit 4bac526

Browse files
committed
WIP #250 Initial work towards testing with BrowserStack
Right now this is just one browser, with a first stab at the CI logic and test logic to do this. I've not tried any of this out locally yet but conceptually everything's here.
1 parent 2180c30 commit 4bac526

37 files changed

Lines changed: 407 additions & 33 deletions
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
name: Cross-browser testing
2+
3+
on:
4+
push:
5+
branches: [ "master" ]
6+
pull_request:
7+
branches: [ "master" ]
8+
schedule:
9+
- cron: "27 20 * * 0"
10+
11+
jobs:
12+
13+
# Summary:
14+
#
15+
# * Installs and configures the environment
16+
# * Builds the solution in Debug configuration
17+
# * Runs just the Selenium tests
18+
# * In Debug configuration (.NET tests)
19+
# * Using the BrowserStack browser configuration
20+
21+
browser_tests:
22+
23+
strategy:
24+
matrix:
25+
include:
26+
- browserName: Chrome
27+
browserVersion: latest-50
28+
os: Windows
29+
osVersion: 11
30+
# - browserName: Chrome
31+
# browserVersion: latest
32+
# os: Windows
33+
# osVersion: 11
34+
# - browserName: Edge
35+
# browserVersion: latest
36+
# os: Windows
37+
# osVersion: 11
38+
# - browserName: Firefox
39+
# browserVersion: latest
40+
# os: Windows
41+
# osVersion: 11
42+
# - browserName: Firefox
43+
# browserVersion: latest-40
44+
# os: Windows
45+
# osVersion: 11
46+
# - browserName: Safari
47+
# browserVersion: 17.3
48+
# os: OS X
49+
# osVersion: Sonoma
50+
# - browserName: Safari
51+
# browserVersion: 26.2
52+
# os: OS X
53+
# osVersion: Tahoe
54+
55+
name: Build, test & package
56+
runs-on: ubuntu-24.04
57+
timeout-minutes: 30
58+
59+
env:
60+
RunNumber: ${{ github.run_number }}.${{ github.run_attempt }}
61+
VersionSuffix: crossbrowser.${{ github.run_number }}
62+
Configuration: Release
63+
Tfm: net8.0
64+
DotnetVersion: 8.0.x
65+
"WebDriverFactory::SelectedConfiguration": BrowserStack
66+
BSbrowserName: ${{ matrix.browserName }}
67+
BSbrowserVersion: ${{ matrix.browserVersion }}
68+
BSos: ${{ matrix.os }}
69+
BSosVersion: ${{ matrix.osVersion }}
70+
BSuserName: ${{ secrets.BROWSERSTACK_USERNAME }}
71+
BSaccessKey: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
72+
BSprojectName: CSF.Screenplay
73+
BSbuildName: ghActionsRun.${{ github.run_number }}.${{ github.run_attempt }}_${{ matrix.browserName }}:${{ matrix.browserVersion }}_${{ matrix.os }}:${{ matrix.osVersion }}
74+
75+
steps:
76+
- name: Checkout
77+
uses: actions/checkout@v4
78+
79+
# Install build dependencies
80+
81+
- name: Install .NET
82+
uses: actions/setup-dotnet@v4
83+
with:
84+
dotnet-version: ${{ env.DotnetVersion }}
85+
- name: Install Node.js for building JSON-to-HTML report converter
86+
uses: actions/setup-node@v6.2.0
87+
88+
# Environment setup pre-build
89+
90+
- name: Restore .NET packages
91+
run: dotnet restore
92+
- name: Restore Node modules
93+
run: |
94+
cd CSF.Screenplay.JsonToHtmlReport.Template/src
95+
npm ci
96+
cd ../..
97+
98+
# Build and test the solution
99+
100+
- name: Build the solution
101+
run: dotnet build -c ${{ env.Configuration }}
102+
- name: Run .NET tests with coverage
103+
id: dotnet_tests
104+
run: dotnet test -c ${{ env.Configuration }} --no-build Tests/CSF.Screenplay.Selenium.Tests -- NumberOfTestWorkers=5
105+
continue-on-error: true
106+
107+
# Post-test tasks (artifacts, overall status)
108+
- name: Upload .NET test results artifacts
109+
uses: actions/upload-artifact@v4
110+
with:
111+
name: NUnit test results
112+
path: Tests/CSF.Screenplay.Selenium.Tests/**/TestResults.xml
113+
- name: Upload Screenplay JSON report artifact
114+
uses: actions/upload-artifact@v4
115+
with:
116+
name: Screenplay JSON reports
117+
path: Tests/CSF.Screenplay.Selenium.Tests/**/ScreenplayReport_*.json
118+
- name: Convert Screenplay reports to HTML
119+
continue-on-error: true
120+
run: |
121+
for report in $(find Tests/CSF.Screenplay.Selenium.Tests/ -type f -name "ScreenplayReport_*.json")
122+
do
123+
reportDir=$(dirname "$report")
124+
outputFile="$reportDir/ScreenplayReport.html"
125+
dotnet run --no-build --framework $Tfm -c {{ env.Configuration }} --project CSF.Screenplay.JsonToHtmlReport --ReportPath "$report" --OutputPath "$outputFile"
126+
done
127+
- name: Upload Screenplay HTML report artifact
128+
uses: actions/upload-artifact@v4
129+
with:
130+
name: Screenplay HTML reports
131+
path: Tests/**/ScreenplayReport.html
132+
- name: Fail the build if any test failures
133+
if: steps.dotnet_tests.outputs.failures == 'true'
134+
run: |
135+
echo "Failing the build due to test failures"
136+
exit 1

.github/workflows/dotnetCi.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ jobs:
4040
BranchParam: ${{ github.event_name == 'pull_request' && 'sonar.pullrequest.branch' || 'sonar.branch.name' }}
4141
PullRequestParam: ${{ github.event_name == 'pull_request' && format('/d:sonar.pullrequest.key={0}', github.event.number) || '' }}
4242
DISPLAY: :99
43+
# Change selected factory to VerboseChrome to debug Chrome-related issues
44+
"WebDriverFactory::SelectedConfiguration": DefaultChrome
4345

4446
steps:
4547
- name: Checkout
@@ -171,7 +173,7 @@ jobs:
171173
do
172174
reportDir=$(dirname "$report")
173175
outputFile="$reportDir/ScreenplayReport.html"
174-
dotnet run --no-build --framework $Tfm --project CSF.Screenplay.JsonToHtmlReport --ReportPath "$report" --OutputPath "$outputFile"
176+
dotnet run --no-build --framework $Tfm -c ${{ env.Configuration }} --project CSF.Screenplay.JsonToHtmlReport --ReportPath "$report" --OutputPath "$outputFile"
175177
done
176178
- name: Upload Screenplay HTML report artifact
177179
uses: actions/upload-artifact@v4
@@ -202,6 +204,3 @@ jobs:
202204
with:
203205
name: Docs website
204206
path: docs/**/*
205-
206-
# runBrowserTests:
207-
# TODO: Use build-results artifacts and run tests on matrix of browsers

CSF.Screenplay/ScreenplayExtensions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,19 @@ public static ScopeAndPerformance CreateScopedPerformance(this Screenplay screen
208208
return new ScopeAndPerformance(performance, scope);
209209
}
210210

211+
/// <summary>
212+
/// Gets the event bus from the screenplay's service provider.
213+
/// </summary>
214+
/// <param name="screenplay">The screenplay from which to retrieve the event bus.</param>
215+
/// <returns>The <see cref="IHasPerformanceEvents"/> event bus instance.</returns>
216+
/// <exception cref="ArgumentNullException">If <paramref name="screenplay"/> is <see langword="null" />.</exception>
217+
public static IHasPerformanceEvents GetEventBus(this Screenplay screenplay)
218+
{
219+
if (screenplay is null)
220+
throw new ArgumentNullException(nameof(screenplay));
221+
return screenplay.ServiceProvider.GetRequiredService<IHasPerformanceEvents>();
222+
}
223+
211224
static AsyncPerformanceLogic GetAsyncPerformanceLogic(SyncPerformanceLogic syncPerformanceLogic)
212225
{
213226
return (services, token) =>

Tests/CSF.Screenplay.Selenium.Tests/Actions/ClearCookiesTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace CSF.Screenplay.Selenium.Actions;
77

8-
[TestFixture]
8+
[TestFixture, Parallelizable]
99
public class ClearCookiesTests
1010
{
1111
static readonly ITarget

Tests/CSF.Screenplay.Selenium.Tests/Actions/ClearLocalStorageTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace CSF.Screenplay.Selenium.Actions;
1313

14-
[TestFixture]
14+
[TestFixture, Parallelizable]
1515
public class ClearLocalStorageTests
1616
{
1717
static readonly ITarget

Tests/CSF.Screenplay.Selenium.Tests/Actions/ClearTheContentsTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace CSF.Screenplay.Selenium.Actions;
77

8-
[TestFixture]
8+
[TestFixture, Parallelizable]
99
public class ClearTheContentsTests
1010
{
1111
static readonly ITarget

Tests/CSF.Screenplay.Selenium.Tests/Actions/ClickTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace CSF.Screenplay.Selenium.Actions;
77

8-
[TestFixture]
8+
[TestFixture, Parallelizable]
99
public class ClickTests
1010
{
1111
static readonly ITarget

Tests/CSF.Screenplay.Selenium.Tests/Actions/DeleteTheCookieTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace CSF.Screenplay.Selenium.Actions;
77

8-
[TestFixture]
8+
[TestFixture, Parallelizable]
99
public class DeleteTheCookieTests
1010
{
1111
static readonly ITarget

Tests/CSF.Screenplay.Selenium.Tests/Actions/DeselectAllTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace CSF.Screenplay.Selenium.Actions;
77

8-
[TestFixture]
8+
[TestFixture, Parallelizable]
99
public class DeselectAllTests
1010
{
1111
static readonly ITarget

Tests/CSF.Screenplay.Selenium.Tests/Actions/DeselectByIndexTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace CSF.Screenplay.Selenium.Actions;
77

8-
[TestFixture]
8+
[TestFixture, Parallelizable]
99
public class DeselectByIndexTests
1010
{
1111
static readonly ITarget

0 commit comments

Comments
 (0)