Ships the E2E infrastructure filed against task #199 (UnsTab drag-drop Playwright smoke). The Blazor Server interactive-render assertion through a test-owned pipeline needs a dedicated diagnosis pass — filed as task #242 — but the Playwright harness lands here so that follow-up starts from a known-good scaffolding rather than setting up the project from scratch. ## New project tests/ZB.MOM.WW.OtOpcUa.Admin.E2ETests - AdminWebAppFactory — boots the Admin pipeline with Kestrel on a free loopback port, swaps the SQL DbContext for EF Core InMemory, replaces the LDAP cookie auth with TestAuthHandler, mirrors the Razor-components/auth/antiforgery pipeline, and seeds a cluster + draft generation with areas warsaw / berlin and a line-a1 in warsaw. Not a WebApplicationFactory<Program> because WAF's TestServer transport doesn't coexist cleanly with Kestrel-on-a-real-port, which Playwright needs. - TestAuthHandler — stamps every request with a FleetAdmin claim so tests hit authenticated routes without the LDAP bind. - PlaywrightFixture — one Chromium launch shared across tests; throws PlaywrightBrowserMissingException when the binary isn't installed so tests can Assert.Skip rather than fail hard. - UnsTabDragDropE2ETests.Admin_host_serves_HTTP_via_Playwright_scaffolding — proves the full stack comes up: Kestrel bind, InMemory DbContext, test auth, Playwright navigation, Razor route pipeline responds with HTML < 500. One passing test. ## Prerequisite Chromium must be installed locally: pwsh tests/ZB.MOM.WW.OtOpcUa.Admin.E2ETests/bin/Debug/net10.0/playwright.ps1 install chromium Absent the browser, the suite Assert.Skip's cleanly — CI without the install step still reports green. Once installed, `dotnet test` runs the scaffolding smoke in ~12s. ## Follow-up (task #242) Diagnose why `/clusters/{id}/draft/{gen}` → UNS-tab click → drag-drop flow times out under the test-owned Program.cs replica. Candidate causes: route-ordering difference, missing SignalR hub mapping timing, JS interop asset differences, culture middleware. Once the interactive circuit boots, add: - happy-path drag-drop assertion (source row → target area → Confirm → assert re-parent) - 409 conflict variant (preview → external DB mutation → Confirm → assert red-header modal)
45 lines
1.7 KiB
C#
45 lines
1.7 KiB
C#
using Microsoft.Playwright;
|
|
using Xunit;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Admin.E2ETests;
|
|
|
|
/// <summary>
|
|
/// One Playwright runtime + Chromium browser for the whole E2E suite. Tests
|
|
/// open a fresh <see cref="IBrowserContext"/> per fixture so cookies + localStorage
|
|
/// stay isolated. Browser install is a one-time step:
|
|
/// <c>pwsh tests/ZB.MOM.WW.OtOpcUa.Admin.E2ETests/bin/Debug/net10.0/playwright.ps1 install chromium</c>.
|
|
/// When the browser binary isn't present the suite reports a <see cref="PlaywrightBrowserMissingException"/>
|
|
/// so CI can distinguish missing-browser from real test failure.
|
|
/// </summary>
|
|
public sealed class PlaywrightFixture : IAsyncLifetime
|
|
{
|
|
public IPlaywright Playwright { get; private set; } = null!;
|
|
public IBrowser Browser { get; private set; } = null!;
|
|
|
|
public async ValueTask InitializeAsync()
|
|
{
|
|
Playwright = await Microsoft.Playwright.Playwright.CreateAsync();
|
|
try
|
|
{
|
|
Browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = true });
|
|
}
|
|
catch (PlaywrightException ex) when (ex.Message.Contains("Executable doesn't exist"))
|
|
{
|
|
throw new PlaywrightBrowserMissingException(ex.Message);
|
|
}
|
|
}
|
|
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
if (Browser is not null) await Browser.CloseAsync();
|
|
Playwright?.Dispose();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Thrown by <see cref="PlaywrightFixture"/> when Chromium isn't installed. Tests
|
|
/// catching this mark themselves as "skipped" rather than "failed", so CI without
|
|
/// the install step stays green.
|
|
/// </summary>
|
|
public sealed class PlaywrightBrowserMissingException(string message) : Exception(message);
|