XUnitAssured.Playwright
5.0.0
dotnet add package XUnitAssured.Playwright --version 5.0.0
NuGet\Install-Package XUnitAssured.Playwright -Version 5.0.0
<PackageReference Include="XUnitAssured.Playwright" Version="5.0.0" />
<PackageVersion Include="XUnitAssured.Playwright" Version="5.0.0" />
<PackageReference Include="XUnitAssured.Playwright" />
paket add XUnitAssured.Playwright --version 5.0.0
#r "nuget: XUnitAssured.Playwright, 5.0.0"
#:package XUnitAssured.Playwright@5.0.0
#addin nuget:?package=XUnitAssured.Playwright&version=5.0.0
#tool nuget:?package=XUnitAssured.Playwright&version=5.0.0
XUnitAssured.Playwright
Browser-based UI testing extensions for the XUnitAssured.Net framework. Write expressive end-to-end tests using a fluent Given().When().Then() DSL with multiple locator strategies, page interactions, screenshots, tracing, and rich assertions — built on Microsoft Playwright.
Installation
dotnet add package XUnitAssured.Playwright
After installing, run the Playwright browser install:
pwsh bin/Debug/net10.0/playwright.ps1 install
Quick Start
using XUnitAssured.Playwright.Extensions;
using XUnitAssured.Playwright.Testing;
public class LoginTests : PlaywrightTestBase<MyPlaywrightFixture>, IClassFixture<MyPlaywrightFixture>
{
public LoginTests(MyPlaywrightFixture fixture) : base(fixture) { }
[Fact]
public void Login_Should_Navigate_To_Dashboard()
{
Given()
.NavigateTo("/login")
.FillByLabel("Email", "user@test.com")
.FillByLabel("Password", "secret")
.ClickByRole(AriaRole.Button, "Sign in")
.When()
.Execute()
.Then()
.AssertSuccess()
.AssertUrl("/dashboard");
}
}
Fluent DSL Reference
Navigation
Given()
.NavigateTo("/login") // Navigate to relative or absolute URL
Click
.Click("#submit-btn") // CSS selector
.ClickByRole(AriaRole.Button, "Submit") // ARIA role + accessible name
.ClickByText("Sign in") // Visible text
.ClickByLabel("Remember me") // Associated label
.ClickByTestId("submit-btn") // data-testid attribute
.ClickByTitle("Close dialog") // title attribute
Double Click
.DoubleClick("#item") // CSS selector
.DoubleClickByRole(AriaRole.Row, "Item 1") // ARIA role
.DoubleClickByText("Edit") // Visible text
.DoubleClickByTestId("editable-cell") // data-testid
Fill (clears then types)
.Fill("#email", "user@test.com") // CSS selector
.FillByLabel("Email", "user@test.com") // Label text
.FillByPlaceholder("Enter email", "user@test.com") // Placeholder text
.FillByRole(AriaRole.Textbox, "Search", "playwright") // ARIA role + name
.FillByTestId("email-input", "user@test.com") // data-testid
Type (character by character)
.TypeText("#search", "playwright") // CSS selector
.TypeTextByLabel("Search", "playwright") // Label text
.TypeTextByPlaceholder("Search...", "playwright") // Placeholder text
.TypeTextByTestId("search-input", "playwright") // data-testid
.TypeTextByRole(AriaRole.Textbox, "Query", "pw") // ARIA role
Press (keyboard keys)
.Press("#input", "Enter") // Press Enter on element
.Press("#editor", "Control+A") // Keyboard shortcut
Check / Uncheck
.Check("#terms") // Check checkbox by CSS
.CheckByLabel("I agree") // Check by label
.CheckByRole(AriaRole.Checkbox, "Newsletter") // Check by role
.Uncheck("#newsletter") // Uncheck by CSS
.UncheckByLabel("Newsletter") // Uncheck by label
Select
.SelectOption("#country", "Brazil") // Select by CSS + value
.SelectOptionByLabel("Country", "Brazil") // Select by label
.SelectOptionByTestId("country-select", "BR") // Select by test ID
Hover / Focus
.Hover("#menu-item") // Hover by CSS
.HoverByRole(AriaRole.Link, "Settings") // Hover by role
.Focus("#input") // Focus by CSS
.FocusByTestId("search") // Focus by test ID
Screenshot
.Screenshot("login-page") // Capture named screenshot
Wait
.Wait(2000) // Wait 2 seconds
.WaitForSelector("#loading", visible: false) // Wait until element disappears
Advanced Interactions
.DragTo("#source", "#target") // Drag and drop
.ScrollIntoView("#footer") // Scroll element into view
.RightClick("#context-menu-target") // Right-click / context menu
.UploadFile("#file-input", "/path/to/file.pdf") // File upload
Playwright Inspector (Codegen)
.RecordAndPause() // Pause & open Playwright Inspector
Requires
Headless = false. Use this to record interactions via Codegen and then translate them into the XUnitAssured DSL.
Assertions
.When()
.Execute()
.Then()
.AssertSuccess() // Assert step succeeded
.AssertUrl("/dashboard") // Assert exact URL
.AssertUrlContains("/dash") // Assert URL contains
.AssertUrlEndsWith("/dashboard") // Assert URL ends with
.AssertTitle("Dashboard") // Assert page title
.AssertTitleContains("Dash") // Assert title contains
.AssertVisible("#welcome") // Element visible (CSS)
.AssertVisibleByRole(AriaRole.Heading, "Welcome") // Element visible (role)
.AssertVisibleByTestId("welcome-msg") // Element visible (test ID)
.AssertVisibleByText("Welcome back") // Element visible (text)
.AssertHidden("#spinner") // Element hidden (CSS)
.AssertHiddenByTestId("loader") // Element hidden (test ID)
.AssertHiddenByRole(AriaRole.Progressbar) // Element hidden (role)
.AssertText("#msg", "Success!") // Assert element text
.AssertTextByRole(AriaRole.Alert, "Saved") // Assert text by role
.AssertTextByTestId("status", "OK") // Assert text by test ID
.AssertScreenshot("login-page") // Capture assertion screenshot
Playwright Codegen Integration
Record tests with Playwright Inspector and translate to XUnitAssured DSL:
// Playwright Inspector output:
await page.GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();
await page.GetByLabel("Email").FillAsync("user@test.com");
await page.GetByPlaceholder("Search").FillAsync("test");
// XUnitAssured DSL (auto-translated via MCP or manually):
.ClickByRole(AriaRole.Button, "Click me")
.FillByLabel("Email", "user@test.com")
.FillByPlaceholder("Search", "test")
Configuration
Create a playwrightsettings.json in your test project:
{
"playwright": {
"baseUrl": "https://localhost:5001",
"browser": "Chromium",
"headless": true,
"slowMo": 0,
"defaultTimeout": 30000,
"navigationTimeout": 30000,
"viewportWidth": 1280,
"viewportHeight": 720,
"screenshotDirectory": "screenshots",
"tracingEnabled": false,
"traceDirectory": "traces"
}
}
Configuration Options
| Option | Default | Description |
|---|---|---|
baseUrl |
— | Base URL for navigation (relative paths resolve against it) |
browser |
Chromium |
Browser engine: Chromium, Firefox, or Webkit |
headless |
true |
Run browser in headless mode |
slowMo |
0 |
Slow down actions by N milliseconds (for debugging) |
defaultTimeout |
30000 |
Timeout for actions (clicks, fills, waits) |
navigationTimeout |
30000 |
Timeout for navigation operations |
viewportWidth |
1280 |
Browser viewport width |
viewportHeight |
720 |
Browser viewport height |
screenshotDirectory |
screenshots |
Directory for screenshot files |
tracingEnabled |
false |
Enable Playwright tracing per test |
traceDirectory |
traces |
Directory for trace files |
Test Fixture
using XUnitAssured.Playwright.Testing;
public class MyPlaywrightFixture : PlaywrightTestFixture
{
public MyPlaywrightFixture() : base() { }
}
The fixture manages browser lifecycle (one browser per test class) and creates isolated BrowserContext + Page per test.
Local Testing with Blazor (WebApplicationFactory)
public class BlazorFixture : PlaywrightTestFixture, IAsyncLifetime
{
private WebApplication? _app;
public override async Task InitializeAsync()
{
// Start local Blazor app
_app = WebApplication.Create();
_app.MapFallbackToFile("index.html");
await _app.StartAsync();
// Override base URL to local server
Settings.BaseUrl = _app.Urls.First();
await base.InitializeAsync();
}
public override async Task DisposeAsync()
{
await base.DisposeAsync();
if (_app != null) await _app.DisposeAsync();
}
}
Supported Frameworks
- .NET 7
- .NET 8
- .NET 9
- .NET 10
Dependencies
- XUnitAssured.Core — DSL infrastructure and abstractions
- Microsoft.Playwright — Browser automation engine
- Shouldly — Fluent assertions
Links
License
MIT — see LICENSE.md
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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
- Microsoft.Playwright (>= 1.52.0)
- Shouldly (>= 4.3.0)
- xunit.abstractions (>= 2.0.3)
- xunit.extensibility.core (>= 2.9.3)
- XUnitAssured.Core (>= 5.0.0)
-
net7.0
- Microsoft.Playwright (>= 1.52.0)
- Shouldly (>= 4.3.0)
- xunit.abstractions (>= 2.0.3)
- xunit.extensibility.core (>= 2.9.3)
- XUnitAssured.Core (>= 5.0.0)
-
net8.0
- Microsoft.Playwright (>= 1.52.0)
- Shouldly (>= 4.3.0)
- xunit.abstractions (>= 2.0.3)
- xunit.extensibility.core (>= 2.9.3)
- XUnitAssured.Core (>= 5.0.0)
-
net9.0
- Microsoft.Playwright (>= 1.52.0)
- Shouldly (>= 4.3.0)
- xunit.abstractions (>= 2.0.3)
- xunit.extensibility.core (>= 2.9.3)
- XUnitAssured.Core (>= 5.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.0.0 | 75 | 3/3/2026 |