Docs
Browse documentation

Testing and quality checks

On this page

Choose validation around the behavior a change can break. This repository combines strict source checks, content-generation tests, Angular unit tests, and production browser regressions; each catches a different class of failure.

Required commands

bash
pnpm check
pnpm test --watch=false

Run these sequentially. Their lifecycle hooks write shared generated files. Before every push, run both check and noninteractive unit tests after the final change. If anything changes afterward, run them again. For changes that need browser validation, run pnpm test:e2e locally; it builds production output before launching Playwright.

pnpm check includes Biome formatting, Angular application and strict-template compilation, strict tooling and E2E typechecks, ESLint, and article MDX/BibTeX checks. Documentation structure, internal links, and anchors are validated by its generation hook. It does not execute tests or build production pages.

pnpm test --watch=false runs Node content/tooling tests followed by Angular unit tests. If the host's CPU count causes Vitest worker failures, use VITEST_MAX_WORKERS=2 pnpm test --watch=false.

Match tests to changes

Change Useful evidence
Prose or handbook wording Generation and link checks; inspect the relevant rendered page
Parser, compiler, cache, or publication Small input fixtures, invalid inputs, no-op behavior, failure recovery, removed outputs
Angular state or lifecycle User-visible state changes, dependency overrides, teardown and late asynchronous completion
Routes or metadata Prerendered HTML, direct visits, client navigation, canonical and noindex behavior
Search Chinese/English queries, ranking, real keyboard events, focus containment/restoration, cold and warm loading
Formula, diagram, or reading layout Real MathJax plus Chromium/WebKit at narrow and desktop widths, both themes
Hosting or Markdown Actual Cloudflare Worker requests, negotiation, MIME, redirects, direct exports, missing routes
Performance Served production resources including lazy chunks and worker requests

Do not add a test that merely repeats a constant from the implementation or checks incidental markup. Regression tests should fail for the underlying bug: for example, removing cleanup, loading the full search index eagerly, or serving an HTML 404 with a Markdown MIME type.

Unit-test conventions

Tooling tests live beside helpers as scripts/lib/*.spec.mts and run through tsx. Use temporary directories for file-generation tests and dispose them. Verify that failed generation preserves the prior successful published outputs and that removed sources prune derived files.

Angular tests live beside application code. Override injectable services with TestBed; the Angular unit-test builder does not support vi.mock for relative imports. Use controlled promises and observable effects for lifecycle tests instead of arbitrary delays. Verify listeners, views, observers, timers, and late imports are released on navigation.

Browser setup and focused runs

Install the matching browser versions after dependency upgrades:

bash
pnpm exec playwright install --with-deps chromium webkit
pnpm build
pnpm exec playwright test e2e/docs.spec.ts --project=desktop --project=mobile

Calling Playwright directly reuses existing production output, so build after changing source. BLOG_PREVIEW_PORT and BLOG_CLOUDFLARE_PORT select isolated server ports when defaults are occupied. Playwright owns its servers and does not reuse an existing development server. See host troubleshooting for Linux library, font, and workerd issues. The Playwright configuration starts the preview and Wrangler Node entrypoints directly so their server processes exit when the test run finishes under native pnpm.

Shared browser fixtures stub third-party analytics/comments and external webfonts. Generated formulas are already static; reading/scroll tests must not load a browser math engine. Real-rendering tests verify static output, retained-TeX copying, stable right-click geometry, and dynamic TeX views using pinned MathJax and local fonts. The dynamic renderer's custom context menu must remain disabled. Navigation tests wait for article/font readiness, not unrelated external images' load event. Do not use stubbed traffic as rendering evidence.

Wait for .post-body[data-rendered="true"] before testing attached article controls. This marker does not await lazy article-specific enhancements or MathJax; those have their own readiness conditions. Scroll offscreen controls into view before focusing them to avoid smooth-scroll races with the next navigation.

CI and performance evidence

The quality workflow runs source checks and unit tests. The quality job generates once and uses *:generated commands afterward; the final required check status depends only on that job. Browser tests are not run in GitHub CI; run them locally when relevant. Keep generated and normal commands aligned when adding checks.

Resource budgets cover representative production pages and cold search with worker traffic included. Warm queries must add no resources. Use the per-request reports to explain changes rather than increasing a threshold without investigation. Local browser runs retain reports and visual diagnostics, including successful rendering captures; screenshots are diagnostic artifacts rather than pixel baselines. See performance records. The long-article Chromium diagnostic applies fourfold CPU throttling and waits for article font/layout readiness before sampling; its host timings are diagnostic, while engine loading and body growth remain assertions.