dotnet/aspnetcore · Archived

validate-blazor-feature

>- Validate a Blazor feature or behavior interactively in a browser using the canonical Components samples in this repo, before writing E2E tests. USE FOR exercising a Blazor change in src/Components (a render-mode behavior, an interactive component, enhanced navigation, forms, streaming, prerendering), deciding which sample to use, where to add a test page, how to set the render mode (Server/WebAssembly/Auto/static SSR), how to confirm the app is actually interactive (not just static SSR), and…

First seen Aug 12, 2026

Installation

$ npx skills add dotnet/aspnetcore --skill validate-blazor-feature

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from dotnet/aspnetcore.

npx skills add dotnet/aspnetcore

Browse all from dotnet/aspnetcore

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 38.4K
License LICENSE.txt
Default branch main
Open issues 3,805
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,839 B
  • docs SUMMARY.md 1,037 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Validate a Blazor feature with the Components samples

Workflow: pick a sample, add a scenario page, set the render mode, build, launch, drive it in a browser, and check for errors. Validate behavior before writing E2E tests; remove the sample code afterward (git checkout/git clean) once the E2E test covers it.

1. Pick the sample and where the page goes

Samples live in src/Components/Samples (Blazor Web Apps) and src/Components/WebAssembly/Samples (standalone). Each is a full checkout against the in-tree framework.

Sample Use it to test Add your page in
BlazorWebAppPerPage (+ .Client) Most features: mix static SSR with per-page interactivity; switch one page's mode independently .Client/Pages/ for WebAssembly/Auto-capable pages; host Components/Pages/ for Server-only or static SSR pages
BlazorWebAppGlobal (+ .Client) Root/global interactivity concerns (whole app one mode) .Client/Pages/ (all routable pages live there)
BlazorWebAssemblyStandalone Pure client WebAssembly behavior, no server host Pages/

A WebAssembly or Auto component must live in the .Client project so it compiles into the client assembly. A page placed in the server host can only run Server or static SSR. Routable pages need @page "/your-route".

2. Set the render mode

The two Web App samples express interactivity differently:

  • Per-page (BlazorWebAppPerPage): put the directive at the top of the page/component. Omit it for static SSR.

``razor @rendermode InteractiveServer @ or InteractiveWebAssembly, or InteractiveAuto @ ``

  • Global (BlazorWebAppGlobal): change the single value on <Routes> and <HeadOutlet> in host Components/App.razor:

``razor <HeadOutlet @rendermode="InteractiveAuto" /> ... <Routes @rendermode="InteractiveAuto" /> ``

  • Disable prerendering (to test the no-prerender path):

``razor @rendermode @(new InteractiveServerRenderMode(prerender: false)) ``

  • Static SSR / None: omit the render mode entirely (per-page sample). Static SSR emits the same markup as interactive, so it is not interactive on its own.

InteractiveAuto runs on the Server circuit on first load while the WebAssembly assets download, then uses WebAssembly on later visits. To force one platform, name it explicitly.

3. Build, then launch

The samples reference the in-tree framework, so the framework and the Blazor JS must be built first:

  • Framework assemblies: run eng\build.cmd once (look for artifacts\bin).
  • Blazor JS: src/Components/Web.JS/dist/Debug/_framework/blazor.web.js must exist; if not, run npm run build in src/Components/Web.JS. Without it the page serves no blazor.web.js and interactivity never starts.

Then activate the repo SDK and run the sample:

. ./activate.ps1
# Per-page Blazor Web App
dotnet run --project src/Components/Samples/BlazorWebAppPerPage/BlazorWebAppPerPage.csproj --no-restore
# Global Blazor Web App
dotnet run --project src/Components/Samples/BlazorWebAppGlobal/BlazorWebAppGlobal.csproj --no-restore
# Standalone WebAssembly
dotnet run --project src/Components/WebAssembly/Samples/BlazorWebAssemblyStandalone/BlazorWebAssemblyStandalone.csproj --no-restore

Read the launch URL from stdout: Web App hosts print Now listening on: http://localhost:<port>;; the standalone (WasmAppHost) prints App url: http://localhost:<port>/. Do not assume a port; parse that line.

4. Drive it in the browser (Playwright MCP)

Use the playwright-browser_* tools. For an interactive behavior, prove it behaviorally; rendered markup alone is a false positive (static SSR emits the same HTML).

For transient DOM or browser-state behavior, first run the probe against the unmodified baseline and confirm that it detects the reported transition. A passing probe that cannot observe the known failure is not evidence for the fix. Choose instrumentation whose timing matches the behavior: MutationObserver callbacks run after synchronous mutations, so reading live DOM state in the callback may expose only the final state. Inspect the mutation records or instrument the exact operation when an intermediate synchronous state matters.

  1. playwright-browser_navigate to <base>/<route>.
  2. For WebAssembly/Auto/standalone, the runtime boots asynchronously: playwright-browserwaitfor the expected text (e.g. Current count) before interacting. First paint can take many seconds.
  3. playwright-browser_snapshot to read current state.
  4. playwright-browserclick (or type, fillform) to interact.
  5. playwright-browser_snapshot again and assert the state changed (e.g. Current count: 01). No change after interaction means the component is static, not interactive: the render mode was not applied or the component is in the wrong project.

Confirm the runtime attached:

  • Interactive Server: console logs Information: WebSocket connected to ws://<host>/_blazor?....
  • Interactive WebAssembly/standalone: the page becomes responsive after the runtime boots; no _blazor WebSocket is required.

5. Check the console and network for errors

After interacting, inspect the console. Scope it to the current page: call playwright-browserconsolemessages with level: error and do not set all: true. The all-history form returns errors from the whole session, including stale failures from a server you already stopped on another port (see [references/error-checks.md](references/error-checks.md#false-positives-to-ignore) for which to ignore).

  • playwright-browserconsolemessages with level: error: expect zero real errors on the page under test.
  • playwright-browsernetworkrequests: check blazor.web.js (Web App) or blazor.webassembly.js (standalone) and _framework/* assets return 200, not 404.

See [references/error-checks.md](references/error-checks.md) for the catalog of common failures, the symptom each produces, and the fix.

6. Finish

  • Stop the sample server by its specific PID.
  • Remove the Playwright artifacts folder (.playwright-mcp/) it drops into the working directory.
  • Per the Components workflow, once an E2E test covers the behavior, remove the sample scenario code: git checkout -- src/Components/Samples src/Components/WebAssembly/Samples and git clean -df -- src/Components/Samples src/Components/WebAssembly/Samples.

Completion criteria

The validation is done when: the page loaded (200, framework JS served), the behavior was exercised by a real interaction, the resulting state change was observed in a snapshot, and the console shows no real errors for the page under test. Only then move on to writing the E2E test.