Chapter 18Operate
Checks and tests
Four checks that block the branch, and a test suite that calls the routes for real. What each one catches, and why it exists.
Two commands
npm run check # four checks on the built site
npm test # the full suite, which builds along the wayThese are exactly the ones CI runs, and they block the branch. A check that does not block gets bypassed, then disabled, then removed.
The four checks
check-html — is the content in the raw HTML?
This is the project's safety net. It verifies three things on the actually built HTML:
- every text value from the JSON is present in the HTML source;
- every
data-cmsin the HTML points at a key that exists in the JSON; - no editable zone sits inside a hydrated island.
| Check | What it catches |
|---|---|
| 1 | client:only — the content is in no served HTML, therefore in no index. |
| 2 | A stale path after a key was renamed. |
| 3 | client:load around an editable zone — the framework re-renders it on load and wipes the client's edits in progress. Invisible in the source. |
The script enumerates the pages to check explicitly, one entry per page and per language. Adding a page or a language without completing that list leaves a check that passes while verifying nothing.
const PAGES = [
{ content: 'src/content/pages/fr/home.json', html: 'dist/fr/index.html' },
{ content: 'src/content/pages/en/home.json', html: 'dist/en/index.html' },
];check-locales — do the languages say the same thing?
Fails on any key present in one language and absent from another, in both directions: a translated key that does not exist in the reference language would never be displayed, and that is wasted work better seen straight away.
check-logs — can a secret leak through a log?
Refuses a console.* that would evaluate a token, a hash, a cookie, a session, or an
object containing them (env, headers, payload).
Accepted
console.error('[save] write failed (key missing)');
console.warn('[auth] rate exceeded');Strings are removed before analysis: a message mentioning “key” is not a leak.
Refused
console.error(key);
console.log(env);
console.error(error); // may contain an API responseThat is the line added six months later to debug, and forgotten afterwards.
check-secrets — does the build contain a secret?
Scans the build folder for hashes, tokens and secret patterns. It does not replace the “no secret in the repository” rule: it verifies no accident bypassed it — an exposed build variable, a value copied into a component.
The test suite
| Command | What it exercises |
|---|---|
npm run test:git | The Git provider: read, write, conflict, error translation. Offline by default, real with --online. |
npm run test:auth | Hashing, constant-time comparison, session signature and lifetime, cookies. |
npm run test:guard | Rate, caps, paths, and the order of checks — by calling the routes directly. |
npm run test:sanitize | The same corpus submitted to both sanitisers — browser and server — and compared. |
npm run test:media | Format recognition from the bytes, dimension reading, name rewriting. |
npm run test:heic | HEIC recognition; decoding is skipped for lack of a sample, unless INLINE_HEIC_SAMPLE is provided. |
npm run test:bootstrap | Bootstrapping on a versioned annotated page, refusals included. |
npm run test:locales | The translation fallback and the marking of untranslated fields. |
npm run test:editor | Overlay logic: path resolution, item reconciliation, drafts. |
npm run test:scaffold | A site created from scratch, installed, built, checked. |
test:guard calls the routes
A size cap placed after reading the body protects nothing, and an identity check placed before rate counting lets the route be hammered. Testing rules in isolation says nothing about their order: hence a test that goes through the real routes.
Testing what would ship to a registry
Two commands answering different questions.
npm run test:scaffold
Does the code work? Creates a site, installs the package by its path in the repository, builds, checks.
npm run test:pack
Does what would ship to the registry work? Same thing, but through npm pack: the exact archives a publication would produce.
The second is the only mode that catches a file forgotten in files or a path
missing from exports — errors invisible while installing from a folder, and which
break the first third-party site. Run it before any publication.
In continuous integration
The shipped workflow runs npm test then npm run check, on every push
and every merge request. No secret is needed: the checks touch neither the content repository
nor the write token — they build the site and inspect it.
The reference repository adds a second job, kept separate because it installs a fresh project
and takes a few minutes: without it, the template embedded in create-inline
diverges silently from the reference repository, and you only find out with the next client.
Adding a check
A useful check has three properties:
- it blocks — otherwise it only provides comfort;
- it examines the result, not the intent: the built HTML, the build folder, a route's response;
- it fails with a message that says what to do, not merely what is wrong.
A site-specific check goes in scripts/ and is added to check. A check
that would hold for every client goes into the package — and becomes a versioned change.
Before every commit
npm test && npm run checkTwo minutes. That is the price of a fix found before the merge rather than after it goes live at a client's.