Testing
The test suite’s shape mirrors the product: numbered pre-flight checks, then per-feature files, plus regression suites tied to specific issue numbers, adversarial “exploit” tests for past vulnerabilities, and the separate MCP suite. This page maps the coverage.
The pre-flight files
00-compile.t— the whole application compiles (skips cleanly if Mojolicious/DBI aren’t installed, since it is a smoke check, not a dependency installer).01-schema.t— the schema itself is what migrations then reproduce; this test validates the schema file.02-media-sniff.t— media upload sniffing behavior.03-util.t,04-webhook.t— utility-layer and webhook-dispatch unit suites.
Per-feature suites
Each API-managed entity gets a suite of its own, usually one per area: pages, posts, blocks (incl. per-type helpers and the block-type palette), snippets, categories, media, documents, nav, redirects, themes, users, audit, drafts_restore, library, health, i18n, settings. Forms and submissions are also their own area (forms.t, submissions.t, submission_values.t), including the file-upload restrictions and quota tests.
Security and adversarial regressions
A dedicated exploit_… family of tests re-creates historically reported exploits as tests, each with a comment describing the vulnerability fixed:
- Read-only API keys bypassing write gates (#4827) — the session-gate accepted read-scope API keys on mutating routes; the test forces the gate to require write scope for POST/PUT/PATCH/DELETE.
- API nav privilege escalation — mutating navigation entries (and the admin 404-log intake) with a too-scoped key is rejected.
- API rate-limit double counting — the per-key rate counter must increment once per HTTP request (a regression previously counted it per auth layer).
- Documents path traversal — crafted filenames attempting to escape the documents directory.
- Forms mass-assignment — POSTing values for fields the form never declared is rejected.
- Theme file dot-placeholder injection — the theme file editor’s path handling blocks crafted paths.
- A security-regression sweep (
exploit_security_regression.t) — a broad adversarial suite.
The naming convention (exploit_issue_tag.t) makes every vulnerability “regression-testable”: each is labeled with a specific issue number so future changes know the fix they must not break.
A whole suite for backup subsystem behaviors
Several separate files cover the backup and restore machinery (backup_*.t): snapshot creation, retention, restore dry-run previews and confirmation, manifest validation, retention, API restores.
Build behavior suites
- Minimum test:
build_helpers run per-language render waves with the Hunni microscopy check (the review-api builds). - build_speed_4636/4637/4638: the parallel-build performance test series; a per-build “timings” suite validates per-phase times against fixture tests; incremental builds assert in a mixed-mode test.
- Build suites measure on a small corpus asserting code paths (fingerprint, minification, link scans, schema) and confirm data races/wall-time conditions (via
build_speed_4637-examples — the multiple-speed regression ideas).
Air-gap and platform behaviors
- Email-when-airgap disabled behaviors (
admin_email_airgap.t), SMTP-failure paths (admin_email_smtp.t,form_email_smtp_fail.t) and forced SMTP-hand-rolled CRLF checks (form_email_crlf.t). - Turnstile gate: behind
turnstile_*settings, verify panels as a separate suite (turnstile_gate.t). - Upward-facing ports of URL routing, XML escaping (sitemap/feed safety), and statement-checking in route shadow guards.
The miscellany of suites worth knowing about
- The migrations suite verifies each migration file’s uniqueness when re-run on a temp DB (idempotency/safe re-run) and cross-checks migration vs schema so schema.sql and migrations can’t drift (migrations_lint.t, migrations_has_table.t, migrations_helpers.t).
- Installation testing (installer-install.t, installer-bundle.t) covers the offline bundle install path.
zz_phase80_verify.truns late (alphabetically last) as a verify layer crossing multiple areas.