Type to search pages and rules.

Browse pages

Web Testing

Web frontends prove pure logic in Vitest beside the module it covers and navigation and integration in Playwright against the running system. The testing principles live in Frontend Testing; this page names the runners, libraries, and commands one web frontend uses for them, and refuses a test with no assertion. A team that applies it while writing tests keeps fast tests fast and proves every address and every declared refusal, each named way a use case, one user task, says no, in a browser.

Markdown1 rule

Stack: any

Layer: tests

Concepts#

Test Kinds#

Each kind of test runs in one place on the web stacks:

KindWhere it runs
LogicVitest beside the module
StructureVitest beside the suite
Route contractPlaywright against a running stack
EvidencePlaywright against a running stack

What each kind proves is stated on Frontend Testing.

Runners and Libraries#

Pure logic runs in Vitest beside its module, navigation and integration run in Playwright against a running stack, and the route contract visits every address, per litespec/frontend/testing#match-test-level-to-risk. Browser suites run through the Playwright CLI, addressable per route and per file, per litespec/frontend/testing#run-browser-checks-through-the-command-line:

Text
pnpm --filter @claimwick/web exec playwright test --project=routes --grep "expenses list keeps the route contract"

Component and logic tests needing HTTP answer through msw handlers generated from the published OpenAPI document, running in the browser worker and the Node server alike, per litespec/frontend/testing#use-network-mocks-for-component-tests. The workspace keeps one mock-generation command that regenerates them. Each stack page names the libraries tests keep, per litespec/frontend/testing#keep-mocks-at-owned-boundaries. The module mirror check runs as a Vitest structure test resolving each folder against the backend module tree, per litespec/frontend/testing#prove-the-module-mirror-in-a-structure-test:

TypeScript
test("every module folder names a backend use case, and no folder is named for nothing", () => {
  expect(checkModuleStructure(appRoot, applicationRoot)).toEqual([]);
});

A declared refusal is reached and asserted by its result code through the refusal helper, per litespec/frontend/testing#assert-each-declared-refusal-by-its-code:

TypeScript
await expect(refusalFor(page, "expenses.not-found")).toBeVisible({ timeout: AFTER_ACTION });

Changed TypeScript lines run under StrykerJS in incremental mode, per litespec/backend/testing#refuse-surviving-mutants-on-changed-lines, and calculation properties run on fast-check inside Vitest with seed cases from the examples table, per litespec/backend/testing#prove-every-calculation-with-property-tests. Element queries follow the Testing Library guiding principles: role, label, name, or visible text first, scoped to one floorplan through its data-floorplan attribute.

Standards#

Refuse a Test Without an Assertion#

rulerulecheckable
litespec/frontend/web/testing#refuse-a-test-without-an-assertion
Statement

Lint MUST fail a Vitest or Playwright test that contains no expect assertion, through the expect-expect rule.

Why

A test that calls code and asserts nothing passes unless something throws, so it raises coverage while proving nothing. The expect-expect rule of the Vitest ESLint plugin reports each such test before it runs, at no measurable cost. The rule is free and maintained under MIT.

Checkchecked by a tool

Checked bypnpm eslint reports vitest/expect-expect for each test that contains no assertion.

Marked checkable: the tool named here checks it.

Conventions#

None.