// testing.md

This page is its own test report.

Every number below comes from the same data and CI signals the site ships with. Nothing here is mocked.

repo
timjstacey/resume-static-site
stack
astro · tailwind · catppuccin
runner
vitest + playwright
policy
green gates every merge
branch
main passing
latest commit · 9h ago
#50dcd28 chore: set playwright and k6 docs as higher priority (#195)
last 10 runs
9/10 clean
p50 · p95
41s ▾ -1s
49s ▴ +1s
01_
315
unit specs
02_
232
E2E flows
03_
7
playwright projects
04_
3
browser engines
// two-layer pyramid

Cheap where we can. Browser where we must.

spec counts · relative 547 specs total
vitest · cheap checks 315 specs · 3s
playwright · rendered surface 232 specs · 1m46s
vitest 315 specs
  • → schema validation
  • → pure helpers
  • → data loaders
  • → nav + format logic
playwright 232 specs
  • → page content per route
  • → keyboard + focus a11y
  • → responsive layout
  • → theme switching
// project routing

Split by spec type. Skip the duplicates.

917 → 232
runs · -75%

Content renders identically across engines, so it runs once. Only keyboard, focus, and viewport behaviour fan out across browsers.

content
device
Desktop Chrome
engine
chromium
specs
homejobsprojectsresumea11y
a11y-chromium
device
Desktop Chrome
engine
chromium
specs
navtheme-picker
a11y-firefox
device
Desktop Firefox
engine
firefox
specs
navtheme-picker
a11y-webkit
device
Desktop Safari
engine
webkit
specs
navtheme-picker
responsive-mobile-chrome
device
Pixel 5
engine
chromium
specs
responsive
responsive-mobile-safari
device
iPhone 13
engine
webkit
specs
responsive
responsive-tablet-safari
device
iPad Pro 11
engine
webkit
specs
responsive
// ci gates

Two pipelines. Two minutes between green and merged.

ci.yml on: push · pull_request
step 1
check-claude-md
✓ 0s
step 2
pnpm lint
✓ 4s
step 3
pnpm test
✓ 3s
step 4
pnpm typecheck
✓ 9s
step 5
pnpm build
✓ 6s
playwright.yml on: after preview deploy
step 1
wait-for-preview
✓ 0s
step 2
run E2E vs preview URL
✓ 1m46s
// data-driven everything

One YAML. The site renders it. The tests assert against it.

resume.yml → getResume() → resume.spec.ts
jobs.yml → getJobs() → jobs.spec.ts
projects.yml → getProjects() → projects.spec.ts
loaders live in src/lib/, imported by both components and specs.
jobs.spec.ts UTF-8 · typescript
import { getJobs } from '../src/lib/data';
import { withKeys } from '../src/lib/jobhunt';
const jobs = withKeys(getJobs());
for (const job of jobs) {
test(job.company, async ({ page }) => {
await page.goto('/job-hunt');
await expect(card(job)).toBeVisible();
});
}
// source

Everything on this page is in the repo.

timjstacey/resume-static-site →