// 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 · 22h ago
#e58ceae chore(ci): refresh ci-snapshot.json
last 10 runs
10/10 clean
p50 · p95
42s ▾ +1s
48s ▴ +2s
01_
247
unit specs
02_
213
E2E flows
03_
7
playwright projects
04_
3
browser engines
// two-layer pyramid

Cheap where we can. Browser where we must.

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

Split by spec type. Skip the duplicates.

784 213
runs · -73%

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
✓ 5s
step 3
pnpm test
✓ 3s
step 4
pnpm typecheck
✓ 10s
step 5
pnpm build
✓ 6s
playwright.yml on: after preview deploy
step 1
wait-for-preview
✓ 1s
step 2
run E2E vs preview URL
✓ 1m26s
// 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 →