Web
WebEngine drives Chromium through Microsoft.Playwright. The first launch in a process installs the headless shell, so the first run needs network access. Set E2E_SKIP_BROWSER_INSTALL=1 when the browser is already installed.
1. Create the test project
Section titled “1. Create the test project”dotnet new nunit -n MyApp.E2ETestscd MyApp.E2ETestsdotnet add package E2Edotnet add package E2E.NUnit # or E2E.XUnit.V3 for xUnit v3Add E2E to the implicit usings, so tests need no using E2E;:
<ItemGroup> <Using Include="E2E" /> <Using Include="NUnit.Framework" /></ItemGroup>2. Point at your app
Section titled “2. Point at your app”{ "targets": [{ "name": "web", "platform": "web", "app": { "url": "http://localhost:3000" } }], "actionTimeout": 15000, "assertionTimeout": 10000, "agents": { "default": { "provider": "copilot", "model": "claude-sonnet-5.5", "context": "MyApp is a project tracker. Never delete data." } }, "cache": { "dir": ".e2e/cache" }}Copy the file to the output folder:
<ItemGroup> <None Update="e2e.config.json" CopyToOutputDirectory="PreserveNewest" /></ItemGroup>Start your app at that address before the run. App.OpenAsync("/path") opens a path on app.url.
3. Write a test
Section titled “3. Write a test”The steps below are placeholders for a signup flow. Replace the headings, goals, and checks with your own app’s. To run a finished web test right away, use the Dariten sample.
Derive from E2ETest. It starts a WebEngine session for each test.
using E2E.NUnit;
public sealed class SignupTests : E2ETest{ [Test] public async Task The_home_page_opens() { await App.OpenAsync("/"); await Expect.That(Screen.GetByRole("heading", "Welcome")).ToBeVisibleAsync(); }
[Test] [Category("RealModel")] public async Task A_visitor_signs_up_for_a_trial() { await App.OpenAsync("/");
await Agent.ActAsync("sign up for a free trial as {name} with email {email}", new ActOptions { Params = new Dictionary<string, object?> { ["name"] = "Ada Lovelace", ["email"] = "ada@example.test", }, });
await Agent.AssertAsync("the welcome screen greets Ada by name"); await Expect.That(Screen.GetByRole("status")).ToContainTextAsync("trial"); }}- Give
ActAsyncone atomic goal per call.Paramsfills the placeholders. AssertAsyncasks the model to judge the screen.Expect.That(...)checks an exact value with no model call, so pair each agent step with one.- Tag tests that call a model, for example
[Category("RealModel")], so CI can skip them with--filter "TestCategory!=RealModel".
4. Run
Section titled “4. Run”dotnet test --project .E2E_HEADLESS=0 dotnet test --project . # watch the browserThe first run asks the model to perform each ActAsync. A passing run records each verified step in .e2e/cache, and the next run replays it with no model call.