STAF.Playwright
3.1.0
dotnet add package STAF.Playwright --version 3.1.0
NuGet\Install-Package STAF.Playwright -Version 3.1.0
<PackageReference Include="STAF.Playwright" Version="3.1.0" />
<PackageVersion Include="STAF.Playwright" Version="3.1.0" />
<PackageReference Include="STAF.Playwright" />
paket add STAF.Playwright --version 3.1.0
#r "nuget: STAF.Playwright, 3.1.0"
#:package STAF.Playwright@3.1.0
#addin nuget:?package=STAF.Playwright&version=3.1.0
#tool nuget:?package=STAF.Playwright&version=3.1.0
STAF.Playwright

Enterprise test engineering platform for Playwright .NET — v3.1.0
Build production-ready Playwright automation with multi-runner support (MSTest, NUnit, xUnit), HTML reporting, API testing, browser-state authentication, test data, OpenAPI contracts, and Phase 2 AI/MCP (generate, analyze, repair).
Keywords: Playwright C#, Playwright .NET framework, Playwright MSTest, Playwright NUnit, Playwright xUnit, page object model C#, API testing .NET, Playwright reporting, Playwright authentication, OpenAPI contract testing, Playwright MCP, AI Playwright C#, STAF Playwright.
Why STAF?
| Raw Playwright | STAF |
|---|---|
| You build infrastructure | Enterprise infrastructure included |
| You build reporting | HTML reports + screenshots |
| You pick one runner | MSTest, NUnit, and xUnit |
| You wire config/CI | runsettings + STAF_ env overrides |
| You add auth/API/data yourself | Browser state, API client, Excel, SQL, OpenAPI |
Install
dotnet add package STAF.Playwright --version 3.1.0
Requirements
- .NET 8, 9, or 10
- A test SDK + runner of your choice (MSTest, NUnit, or xUnit)
- Playwright browsers:
playwright install(from a project that references Microsoft.Playwright)
Your test project still needs the runner packages (for example MSTest, NUnit + adapter, or xunit). The STAF library includes the shared framework and thin base classes for each runner.
Quick start — MSTest
using Microsoft.VisualStudio.TestTools.UnitTesting;
using STAF.Playwright.Framework;
[TestClass]
public class LoginTests : BaseTest
{
[TestMethod]
public async Task Home_Loads()
{
await Page.GotoAsync(ConfigManager.GetParameter("BaseUrl"));
await ReportResult.ReportResultPass(Page, TestContext, "Smoke", "Page loaded");
}
}
Add assembly bootstrap in the test project (required for HTML report rollup):
[TestClass]
public class AssemblyInit
{
[AssemblyInitialize]
public static void Init(TestContext tc) =>
STAF.Playwright.Framework.AssemblyInit.AssemblyInitialize(tc);
[AssemblyCleanup]
public static void Cleanup() =>
STAF.Playwright.Framework.AssemblyInit.AssemblyCleanUp();
}
Page objects
public class LoginPage : BasePage
{
public LoginPage(IPage page, TestContext ctx) : base(page, ctx) { }
public async Task LoginAsync(string user, string password)
{
await EnterTextAsync("#username", user);
await EnterTextAsync("#password", password);
await ClickAsync("button[type=submit]");
}
}
BasePage also accepts IStafTestContext for NUnit/xUnit.
API tests (MSTest)
[TestClass]
public class ApiTests : TestBaseAPI
{
[TestMethod]
public async Task Pets_Available_ReturnsOk()
{
var response = await ApiClient.GetAsync("pet/findByStatus?status=available");
Assert.IsTrue(response.IsSuccessStatusCode);
}
}
Set ApiBaseUrl in testsetting.runsettings (for example https://petstore.swagger.io/v2). Endpoints may be written with or without a leading /; STAF preserves the base path (e.g. /v2).
Quick start — NUnit
using NUnit.Framework;
using STAF.Playwright.Framework;
using STAF.Playwright.Framework.Runners.NUnit;
[SetUpFixture]
public class GlobalSetup
{
[OneTimeSetUp]
public void OneTimeSetUp() => AssemblyInit.EnsureReportInfrastructure();
[OneTimeTearDown]
public void OneTimeTearDown() => AssemblyInit.AssemblyCleanUp();
}
public class LoginTests : NUnitBaseTest
{
[Test]
public async Task Home_Loads()
{
await Page.GotoAsync(ConfigManager.GetParameter("BaseUrl"));
await ReportResult.ReportResultPass(Page, StafContext, "Smoke", "Page loaded");
}
}
API: inherit NUnitApiBaseTest.
Quick start — xUnit
using STAF.Playwright.Framework;
using STAF.Playwright.Framework.Runners.Xunit;
using Xunit;
public class LoginTests : XunitBaseTest
{
protected override string ResolveTestName() => nameof(Home_Loads);
[Fact]
public async Task Home_Loads()
{
await Page.GotoAsync(ConfigManager.GetParameter("BaseUrl"));
await ReportResult.ReportResultPass(Page, StafContext, "Smoke", "Page loaded");
}
}
API: inherit XunitApiBaseTest. Report infrastructure initializes lazily; call AssemblyInit.AssemblyCleanUp() from a collection fixture if you need a final HTML rollup.
Features
| Area | What you get |
|---|---|
| Multi-target | net8.0, net9.0, net10.0 |
| Multi-runner | BaseTest, NUnitBaseTest, XunitBaseTest (+ API bases) |
| HTML reporting | Steps, screenshots on failure, files under TestResults |
| Config | testsetting.runsettings, testdata.json, STAF_* env overrides |
| Auth | Browser-state session reuse, login helpers, MFA pause (local) |
| API | ApiClient, OpenAPI contract testing with schema $ref resolution |
| Data | ExcelDriver, SqlDbClient |
| Phase 2 AI/MCP | Providers, discovery, generate/analyze/repair, permissioned MCP tools — see docs/AI.md |
Key components
| Component | Purpose |
|---|---|
BaseTest / NUnitBaseTest / XunitBaseTest |
Browser/context/page lifecycle + config + optional login/state |
TestBaseAPI / NUnitApiBaseTest / XunitApiBaseTest |
API + optional SQL client |
BasePage |
Page objects with automatic step reporting |
ConfigManager |
Runsettings + testdata + STAF_ overrides |
ReportResult / ReportResultAPI / HtmlResult |
Manual and automatic HTML reporting |
ApiClient |
REST helpers with optional auto-report |
OpenApiContractTestBase |
MSTest OpenAPI contract base |
IStafTestContext |
Runner-agnostic context for reporting and page objects |
UiTestSession / ApiTestSession |
Shared lifecycle used by all runners |
Reporting
Automatic
- UI:
BasePagemethods (ClickAsync,EnterTextAsync,PressAsync, …) - API:
ApiClientwhen constructed with a test context
Manual
// MSTest
await ReportResult.ReportResultPass(Page, TestContext, "Module", "Details");
await ReportResultAPI.ReportResultPass(TestContext, "API/Health", "OK");
// NUnit / xUnit
await ReportResult.ReportResultPass(Page, StafContext, "Module", "Details");
await ReportResultAPI.ReportResultPass(StafContext, "API/Health", "OK");
Configuration
- Run settings:
testsetting.runsettings(BaseUrl,ApiBaseUrl,Browser,Headless, auth, browser state, …) - Test data:
testdata.json/testdata.{Environment}.json - CI overrides: any parameter via
STAF_<Name>(for exampleSTAF_Headless=true,STAF_BaseUrl=...)
Full reference: CONFIGURATION.md.
Browser state (summary)
When BrowserStateEnabled=true, STAF can reuse browserstate_<username>.json across tests. Use a non-MFA account in CI (MFAEnabled=false). Local MFA pause is supported for interactive runs only.
Compatibility matrix
| .NET 8 | .NET 9 | .NET 10 | |
|---|---|---|---|
| MSTest | yes | yes | yes |
| NUnit | yes | yes | yes |
| xUnit | yes | yes | yes |
Migrating from 2.x
STAF 3.0 keeps the same package id and MSTest public API. See MIGRATION.md.
Notable 3.0 consumer notes:
- Target frameworks expanded to net8/net9/net10
- Library depends on
MSTest.TestFramework(not the adapter); your test project still references MSTest/NUnit/xUnit as usual ApiClientbase-path handling fixed (relative endpoints no longer drop/v2-style paths)- OpenAPI schema validation resolves component
$refs
Project template
dotnet new install ./templates/staf-playwright # from repo
dotnet new staf-playwright -n MyTests
MCP / AI (Phase 2)
STAF 3.1 includes AI providers (OpenAI / Azure OpenAI / Ollama), application discovery, test generation, failure analysis, and reviewable repair proposals — plus a permissioned MCP tool surface.
staf generate "login and verify inventory" --runner mstest
staf analyze --test MyTest --error "Locator timeout"
staf mcp list
Full guide: docs/AI.md.
License
MIT — Copyright © 2026 Sooraj Ramachandran
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- ClosedXML (>= 0.105.1)
- Microsoft.Data.SqlClient (>= 7.0.2)
- Microsoft.OpenApi (>= 3.9.0)
- Microsoft.Playwright (>= 1.61.0)
- MSTest.TestFramework (>= 4.3.3)
- NJsonSchema (>= 11.6.1)
- NUnit (>= 4.6.1)
- xunit.assert (>= 2.9.3)
- xunit.core (>= 2.9.3)
-
net8.0
- ClosedXML (>= 0.105.1)
- Microsoft.Data.SqlClient (>= 7.0.2)
- Microsoft.OpenApi (>= 3.9.0)
- Microsoft.Playwright (>= 1.61.0)
- MSTest.TestFramework (>= 4.3.3)
- NJsonSchema (>= 11.6.1)
- NUnit (>= 4.6.1)
- xunit.assert (>= 2.9.3)
- xunit.core (>= 2.9.3)
-
net9.0
- ClosedXML (>= 0.105.1)
- Microsoft.Data.SqlClient (>= 7.0.2)
- Microsoft.OpenApi (>= 3.9.0)
- Microsoft.Playwright (>= 1.61.0)
- MSTest.TestFramework (>= 4.3.3)
- NJsonSchema (>= 11.6.1)
- NUnit (>= 4.6.1)
- xunit.assert (>= 2.9.3)
- xunit.core (>= 2.9.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
STAF 3.1.0 Phase 2: AI providers (OpenAI/Azure/Ollama), MCP tools with permissions, app discovery, test generation, failure analysis, reviewable repair proposals, staf CLI.