Files
2026-07-13 13:39:12 +08:00

192 lines
5.9 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import {
parseEnvExampleVars,
parseEnvDocVars,
runEnvDocSync,
} from "../../scripts/check/check-env-doc-sync.mjs";
test("parseEnvExampleVars: extracts uncommented assignments", () => {
const text = `
JWT_SECRET=abc123
FOO_BAR=baz
# SKIPPED_VAR=leading whitespace before hash is rejected
`;
const vars = parseEnvExampleVars(text);
assert.ok(vars.has("JWT_SECRET"));
assert.ok(vars.has("FOO_BAR"));
// The regex anchors `^#?` so leading whitespace before `#` prevents a match.
assert.equal(vars.has("SKIPPED_VAR"), false);
});
test("parseEnvExampleVars: extracts commented examples", () => {
const text = `
#OPTIONAL_KEY=value
# OPTIONAL_OTHER=value-with-space
ACTIVE=1
`;
const vars = parseEnvExampleVars(text);
assert.ok(vars.has("OPTIONAL_KEY"));
assert.ok(vars.has("OPTIONAL_OTHER"));
assert.ok(vars.has("ACTIVE"));
});
test("parseEnvExampleVars: ignores prose", () => {
const text = `
# This file documents env vars. Don't put values here.
Some narrative paragraph mentions PORT and DATA_DIR in passing.
PORT=20128
`;
const vars = parseEnvExampleVars(text);
assert.deepEqual([...vars].sort(), ["PORT"]);
});
test("parseEnvDocVars: extracts SHOUTY_NAMES from inline backticks", () => {
const md = "Set `FOO_BAR` to enable the thing. Defaults to `BAR_BAZ_QUX`.";
const vars = parseEnvDocVars(md);
assert.deepEqual([...vars].sort(), ["BAR_BAZ_QUX", "FOO_BAR"]);
});
test("parseEnvDocVars: ignores values like `7s` or two-letter codes", () => {
const md = "TTL is `60s` and the type is `JSON`. Real var: `OMNIROUTE_TTL_MS`.";
const vars = parseEnvDocVars(md);
assert.deepEqual([...vars].sort(), ["JSON", "OMNIROUTE_TTL_MS"]);
});
test("runEnvDocSync: matched fixture passes", () => {
const envExampleText = `
JWT_SECRET=secret
#OPTIONAL_VAR=value
ANOTHER_VAR=1
`;
const envDocText = `
# Reference
| Variable | Default | Description |
| --- | --- | --- |
| \`JWT_SECRET\` | _(none)_ | required |
| \`OPTIONAL_VAR\` | _(unset)_ | optional |
| \`ANOTHER_VAR\` | 1 | enabled by default |
`;
const codeVars = new Set(["JWT_SECRET", "OPTIONAL_VAR", "ANOTHER_VAR"]);
const result = runEnvDocSync({
envExampleText,
envDocText,
codeVars,
ignore: new Set(),
docOnlyAllowlist: new Set(),
envOnlyAllowlist: new Set(),
});
assert.equal(result.ok, true);
assert.deepEqual(result.problems.codeMissingEnv, []);
assert.deepEqual(result.problems.envMissingDoc, []);
assert.deepEqual(result.problems.docMissingEnv, []);
});
test("runEnvDocSync: drift in code is flagged", () => {
const envExampleText = `JWT_SECRET=secret\n`;
const envDocText = "| `JWT_SECRET` | _(none)_ | required |";
const result = runEnvDocSync({
envExampleText,
envDocText,
codeVars: new Set(["JWT_SECRET", "NEW_VAR"]),
ignore: new Set(),
docOnlyAllowlist: new Set(),
envOnlyAllowlist: new Set(),
});
assert.equal(result.ok, false);
assert.deepEqual(result.problems.codeMissingEnv, ["NEW_VAR"]);
});
test("runEnvDocSync: drift in doc is flagged", () => {
const envExampleText = `JWT_SECRET=secret\nNEW_VAR=value\n`;
const envDocText = "| `JWT_SECRET` | _(none)_ | required |";
const result = runEnvDocSync({
envExampleText,
envDocText,
codeVars: new Set(["JWT_SECRET", "NEW_VAR"]),
ignore: new Set(),
docOnlyAllowlist: new Set(),
envOnlyAllowlist: new Set(),
});
assert.equal(result.ok, false);
assert.deepEqual(result.problems.envMissingDoc, ["NEW_VAR"]);
});
test("runEnvDocSync: drift in env (doc-only var) is flagged", () => {
const envExampleText = `JWT_SECRET=secret\n`;
const envDocText = `
| \`JWT_SECRET\` | _(none)_ | required |
| \`OBSOLETE_VAR\` | _(unset)_ | docs-only legacy |
`;
const result = runEnvDocSync({
envExampleText,
envDocText,
codeVars: new Set(["JWT_SECRET"]),
ignore: new Set(),
docOnlyAllowlist: new Set(),
envOnlyAllowlist: new Set(),
});
assert.equal(result.ok, false);
assert.deepEqual(result.problems.docMissingEnv, ["OBSOLETE_VAR"]);
});
test("runEnvDocSync: docOnlyAllowlist absolves doc-only entries", () => {
const envExampleText = `JWT_SECRET=secret\n`;
const envDocText = `
| \`JWT_SECRET\` | _(none)_ | required |
| \`LEGACY_ALIAS\` | _(unset)_ | documented but not in env.example |
`;
const result = runEnvDocSync({
envExampleText,
envDocText,
codeVars: new Set(["JWT_SECRET"]),
ignore: new Set(),
docOnlyAllowlist: new Set(["LEGACY_ALIAS"]),
envOnlyAllowlist: new Set(),
});
assert.equal(result.ok, true);
assert.deepEqual(result.problems.docMissingEnv, []);
});
test("runEnvDocSync: envOnlyAllowlist absolves env-only entries", () => {
const envExampleText = `JWT_SECRET=secret\nFOO_BAR=bar\n`;
const envDocText = "| `JWT_SECRET` | _(none)_ | required |";
const result = runEnvDocSync({
envExampleText,
envDocText,
codeVars: new Set(["JWT_SECRET", "FOO_BAR"]),
ignore: new Set(),
docOnlyAllowlist: new Set(),
envOnlyAllowlist: new Set(["FOO_BAR"]),
});
assert.equal(result.ok, true);
assert.deepEqual(result.problems.envMissingDoc, []);
});
test("runEnvDocSync: ignore set skips a code-referenced var", () => {
const envExampleText = `JWT_SECRET=secret\n`;
const envDocText = "| `JWT_SECRET` | _(none)_ | required |";
const result = runEnvDocSync({
envExampleText,
envDocText,
codeVars: new Set(["JWT_SECRET", "PATH", "HOME"]),
ignore: new Set(["PATH", "HOME"]),
docOnlyAllowlist: new Set(),
envOnlyAllowlist: new Set(),
});
assert.equal(result.ok, true);
});
test("repository contract is in sync (live data)", () => {
// Uses the real .env.example, docs/ENVIRONMENT.md, and the bundled
// allowlists. This is the same check that runs in pre-commit / CI.
const result = runEnvDocSync();
if (!result.ok) {
const summary = JSON.stringify(result.problems, null, 2);
assert.fail(`Env/docs contract drift detected:\n${summary}`);
}
assert.equal(result.ok, true);
});