diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..18beea4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+# Build output
+bin/
+obj/
+
+# .NET
+*.user
+*.suo
+.vs/
+
+# Reqnroll / SpecFlow generated files
+*.feature.cs
+
+# Playwright
+**/bin/**/playwright.ps1
+.playwright/
+
+# BrowserStack
+log/
+local.log
+.browserstack/
+
+# Environment
+.env
+
+# OS
+.DS_Store
diff --git a/README.md b/README.md
index 5025f0c..1879162 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,63 @@
-# nunit-csharp-reqnroll-playwright-browserstack
-Sample repo for customers
+# Reqnroll + NUnit + Playwright with BrowserStack
+
+Sample repository demonstrating how to run C# Reqnroll (NUnit runner) + Playwright tests on
+BrowserStack Automate using the [BrowserStack C# SDK](https://www.browserstack.com/docs/automate/selenium/sdk-overview).
+
+## Prerequisites
+
+- [.NET SDK](https://dotnet.microsoft.com/download) 6.0 or higher (8.0 recommended)
+- A [BrowserStack account](https://www.browserstack.com/users/sign_up) (username + access key)
+- Git
+
+## Setup
+
+1. Clone this repository and switch to the project directory:
+
+ ```bash
+ git clone https://github.com/browserstack/nunit-csharp-reqnroll-playwright-browserstack.git
+ cd nunit-csharp-reqnroll-playwright-browserstack/Reqnroll-Playwright-BrowserStack
+ ```
+
+2. Restore the BrowserStack SDK tool and project dependencies:
+
+ ```bash
+ dotnet tool restore
+ dotnet restore
+ ```
+
+3. Set your BrowserStack credentials as environment variables:
+
+ ```bash
+ export BROWSERSTACK_USERNAME="YOUR_USERNAME"
+ export BROWSERSTACK_ACCESS_KEY="YOUR_ACCESS_KEY"
+ ```
+
+ Alternatively, edit `browserstack.yml` and set the `userName` and `accessKey` values directly.
+
+## Run Sample Test
+
+Runs the BStack Demo "add to cart" scenario against the platforms configured in `browserstack.yml`:
+
+```bash
+dotnet test
+```
+
+To run only the sample (non-local) scenario, filter by its tag:
+
+```bash
+dotnet test --filter "TestCategory=sample-test"
+```
+
+## Run Local Test
+
+Runs the BrowserStack Local scenario (`browserstackLocal: true` is already enabled in `browserstack.yml`):
+
+```bash
+dotnet test --filter "TestCategory=sample-local-test"
+```
+
+## Notes
+
+- View your test results on the [BrowserStack Automate dashboard](https://automate.browserstack.com/).
+- The framework is detected as `nunit` because Reqnroll runs on the NUnit test runner.
+- Test Observability is enabled by default (`testObservability: true` in `browserstack.yml`).
diff --git a/Reqnroll-Playwright-BrowserStack.sln b/Reqnroll-Playwright-BrowserStack.sln
new file mode 100644
index 0000000..cae3efa
--- /dev/null
+++ b/Reqnroll-Playwright-BrowserStack.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reqnroll-Playwright-BrowserStack", "Reqnroll-Playwright-BrowserStack\Reqnroll-Playwright-BrowserStack.csproj", "{C3215C4E-FED4-47A9-9808-7B561D6A9F0B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C3215C4E-FED4-47A9-9808-7B561D6A9F0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C3215C4E-FED4-47A9-9808-7B561D6A9F0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C3215C4E-FED4-47A9-9808-7B561D6A9F0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C3215C4E-FED4-47A9-9808-7B561D6A9F0B}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Reqnroll-Playwright-BrowserStack/.config/dotnet-tools.json b/Reqnroll-Playwright-BrowserStack/.config/dotnet-tools.json
new file mode 100644
index 0000000..9800c45
--- /dev/null
+++ b/Reqnroll-Playwright-BrowserStack/.config/dotnet-tools.json
@@ -0,0 +1,12 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "browserstack-sdk": {
+ "version": "0.0.0",
+ "commands": [
+ "browserstack-sdk"
+ ]
+ }
+ }
+}
diff --git a/Reqnroll-Playwright-BrowserStack/Features/SampleLocalTest.feature b/Reqnroll-Playwright-BrowserStack/Features/SampleLocalTest.feature
new file mode 100644
index 0000000..d982da0
--- /dev/null
+++ b/Reqnroll-Playwright-BrowserStack/Features/SampleLocalTest.feature
@@ -0,0 +1,5 @@
+@sample-local-test
+Feature: BStack Local
+ Scenario: Open BrowserStack Local
+ Given I navigate to the local website
+ Then the page title should be "BrowserStack Local"
diff --git a/Reqnroll-Playwright-BrowserStack/Features/SampleTest.feature b/Reqnroll-Playwright-BrowserStack/Features/SampleTest.feature
new file mode 100644
index 0000000..641083a
--- /dev/null
+++ b/Reqnroll-Playwright-BrowserStack/Features/SampleTest.feature
@@ -0,0 +1,7 @@
+@sample-test
+Feature: BStack Sample
+ Scenario: Can add product to cart
+ Given I navigate to the StackDemo website
+ When I add the first product to the cart
+ And the cart pane is opened
+ Then the product in the cart matches the product on the page
diff --git a/Reqnroll-Playwright-BrowserStack/Reqnroll-Playwright-BrowserStack.csproj b/Reqnroll-Playwright-BrowserStack/Reqnroll-Playwright-BrowserStack.csproj
new file mode 100644
index 0000000..c39f0eb
--- /dev/null
+++ b/Reqnroll-Playwright-BrowserStack/Reqnroll-Playwright-BrowserStack.csproj
@@ -0,0 +1,25 @@
+
+
+
+ net6.0;net8.0
+ ReqnrollPlaywrightBrowserStack
+ ReqnrollPlaywrightBrowserStack
+ enable
+ enable
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Reqnroll-Playwright-BrowserStack/StepDefinitions/PlaywrightHooks.cs b/Reqnroll-Playwright-BrowserStack/StepDefinitions/PlaywrightHooks.cs
new file mode 100644
index 0000000..e232519
--- /dev/null
+++ b/Reqnroll-Playwright-BrowserStack/StepDefinitions/PlaywrightHooks.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.Playwright;
+using Reqnroll;
+
+namespace ReqnrollPlaywrightBrowserStack
+{
+ // Manages the Playwright browser/page lifecycle for each scenario.
+ // The BrowserStack SDK intercepts the Playwright connection and routes it
+ // to the BrowserStack cloud using the platforms defined in browserstack.yml.
+ [Binding]
+ public class PlaywrightHooks
+ {
+ private readonly ScenarioContext _scenarioContext;
+
+ private IPlaywright? _playwright;
+ private IBrowser? _browser;
+ private IBrowserContext? _context;
+ private IPage? _page;
+
+ public PlaywrightHooks(ScenarioContext scenarioContext)
+ {
+ _scenarioContext = scenarioContext;
+ }
+
+ [BeforeScenario]
+ public async Task InitializeAsync()
+ {
+ _playwright = await Playwright.CreateAsync();
+ _browser = await _playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
+ {
+ Headless = true
+ });
+ _context = await _browser.NewContextAsync();
+ _page = await _context.NewPageAsync();
+
+ // Expose the page to the step definitions via the scenario container.
+ _scenarioContext.ScenarioContainer.RegisterInstanceAs(_page);
+ }
+
+ [AfterScenario]
+ public async Task TearDownAsync()
+ {
+ if (_page != null)
+ {
+ await _page.CloseAsync();
+ }
+ if (_context != null)
+ {
+ await _context.CloseAsync();
+ }
+ if (_browser != null)
+ {
+ await _browser.CloseAsync();
+ }
+ _playwright?.Dispose();
+ }
+ }
+}
diff --git a/Reqnroll-Playwright-BrowserStack/StepDefinitions/SampleLocalTestSteps.cs b/Reqnroll-Playwright-BrowserStack/StepDefinitions/SampleLocalTestSteps.cs
new file mode 100644
index 0000000..0bfe8bb
--- /dev/null
+++ b/Reqnroll-Playwright-BrowserStack/StepDefinitions/SampleLocalTestSteps.cs
@@ -0,0 +1,31 @@
+using System.Threading.Tasks;
+using Microsoft.Playwright;
+using NUnit.Framework;
+using Reqnroll;
+
+namespace ReqnrollPlaywrightBrowserStack
+{
+ [Binding]
+ public class SampleLocalTestSteps
+ {
+ private readonly IPage _page;
+
+ public SampleLocalTestSteps(ScenarioContext scenarioContext)
+ {
+ _page = scenarioContext.ScenarioContainer.Resolve();
+ }
+
+ [Given(@"I navigate to the local website")]
+ public async Task GivenINavigateToTheLocalWebsite()
+ {
+ await _page.GotoAsync("http://bs-local.com:45454");
+ }
+
+ [Then(@"the page title should be ""(.*)""")]
+ public async Task ThenThePageTitleShouldBe(string expectedTitle)
+ {
+ string title = await _page.TitleAsync();
+ Assert.That(title, Is.EqualTo(expectedTitle));
+ }
+ }
+}
diff --git a/Reqnroll-Playwright-BrowserStack/StepDefinitions/SampleTestSteps.cs b/Reqnroll-Playwright-BrowserStack/StepDefinitions/SampleTestSteps.cs
new file mode 100644
index 0000000..d7428f8
--- /dev/null
+++ b/Reqnroll-Playwright-BrowserStack/StepDefinitions/SampleTestSteps.cs
@@ -0,0 +1,47 @@
+using System.Threading.Tasks;
+using Microsoft.Playwright;
+using NUnit.Framework;
+using Reqnroll;
+
+namespace ReqnrollPlaywrightBrowserStack
+{
+ [Binding]
+ public class SampleTestSteps
+ {
+ private readonly IPage _page;
+ private string? _productOnPageText;
+
+ public SampleTestSteps(ScenarioContext scenarioContext)
+ {
+ _page = scenarioContext.ScenarioContainer.Resolve();
+ }
+
+ [Given(@"I navigate to the StackDemo website")]
+ public async Task GivenINavigateToTheStackDemoWebsite()
+ {
+ await _page.GotoAsync("https://bstackdemo.com/");
+ }
+
+ [When(@"I add the first product to the cart")]
+ public async Task WhenIAddTheFirstProductToTheCart()
+ {
+ _productOnPageText = await _page.Locator("//*[@id=\"1\"]/p").InnerTextAsync();
+ await _page.Locator("//*[@id=\"1\"]/div[4]").ClickAsync();
+ }
+
+ [When(@"the cart pane is opened")]
+ public async Task WhenTheCartPaneIsOpened()
+ {
+ await _page.Locator(".float-cart__content").WaitForAsync();
+ }
+
+ [Then(@"the product in the cart matches the product on the page")]
+ public async Task ThenTheProductInTheCartMatchesTheProductOnThePage()
+ {
+ string productInCartText = await _page
+ .Locator("//*[@id=\"__next\"]/div/div/div[2]/div[2]/div[2]/div/div[3]/p[1]")
+ .InnerTextAsync();
+ Assert.That(productInCartText, Is.EqualTo(_productOnPageText));
+ }
+ }
+}
diff --git a/Reqnroll-Playwright-BrowserStack/browserstack.yml b/Reqnroll-Playwright-BrowserStack/browserstack.yml
new file mode 100644
index 0000000..4b4e564
--- /dev/null
+++ b/Reqnroll-Playwright-BrowserStack/browserstack.yml
@@ -0,0 +1,26 @@
+userName: YOUR_USERNAME
+accessKey: YOUR_ACCESS_KEY
+projectName: BrowserStack Samples
+buildName: browserstack build
+buildIdentifier: '#${BUILD_NUMBER}'
+framework: nunit
+platforms:
+ - os: OS X
+ osVersion: Big Sur
+ browserName: Chrome
+ browserVersion: latest
+ - os: Windows
+ osVersion: 10
+ browserName: Edge
+ browserVersion: latest
+ - deviceName: Samsung Galaxy S22 Ultra
+ browserName: chrome
+ osVersion: 12.0
+parallelsPerPlatform: 1
+browserstackAutomation: true
+browserstackLocal: true
+source: nunit-csharp-reqnroll-playwright-browserstack:sample-sdk:v1.0
+testObservability: true
+debug: false
+networkLogs: false
+consoleLogs: errors