// No tracked file may carry a term from a LOCAL, untracked term list - not in // its content and not in its path. The list itself is deliberately kept out of // the repository (tests/excluded-terms.local.md, covered by `*.local.md` in // .gitignore): a check that spelled its own pattern out would be a tracked file // carrying exactly what it forbids. // // Absent list = SKIPPED, loudly, never passed: a check that could not run must // not read as a check that found nothing. // // Format: one case-insensitive regex per line; `#` lines and blank lines are // ignored; `sample: ` lines are known-positive controls. Every sample // must match some term and every term must be matched by some sample, so a // term that can no longer find anything fails here instead of passing vacuously. import { test } from 'node:test'; import assert from 'node:assert'; import { execFileSync } from 'node:child_process'; import { existsSync, readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; const root = join(dirname(fileURLToPath(import.meta.url)), '..'); const listFile = join(root, 'tests', 'excluded-terms.local.md'); // Named exceptions: tracked path -> reason. Empty on purpose; an entry needs a // stated reason, never a silent widening. const EXEMPT = new Map(); function loadList() { const terms = []; const samples = []; for (const raw of readFileSync(listFile, 'utf8').split('\n')) { const line = raw.trim(); if (line === '' || line.startsWith('#')) continue; if (line.startsWith('sample:')) samples.push(line.slice('sample:'.length).trim()); else terms.push(new RegExp(line, 'i')); } return { terms, samples }; } function hitsIn(text, terms) { return terms.filter((re) => re.test(text)).map((re) => re.source); } test('no tracked file carries a term from the local term list', (t) => { if (!existsSync(listFile)) { t.skip(`SKIPPED, not passed: ${listFile} is absent, so nothing was checked`); return; } const { terms, samples } = loadList(); assert.ok(terms.length > 0, 'term list holds no terms'); // Known-positive controls, before anything depends on the matcher. for (const s of samples) { assert.ok(hitsIn(s, terms).length > 0, `control sample matches no term: ${s}`); } for (const re of terms) { assert.ok(samples.some((s) => re.test(s)), `term /${re.source}/ has no matching sample`); } const files = execFileSync('git', ['ls-files', '-z'], { cwd: root, encoding: 'utf8' }) .split('\0') .filter((p) => p !== '' && !EXEMPT.has(p)); assert.ok(files.length > 0, 'git ls-files listed no tracked files'); const found = []; for (const path of files) { for (const term of hitsIn(path, terms)) found.push(`${path} (path): /${term}/`); const lines = readFileSync(join(root, path), 'latin1').split('\n'); lines.forEach((line, i) => { for (const term of hitsIn(line, terms)) found.push(`${path}:${i + 1}: /${term}/`); }); } t.diagnostic(`scanned ${files.length} tracked files against ${terms.length} terms`); assert.deepStrictEqual(found, [], `${found.length} hit(s):\n${found.join('\n')}`); });