// tests/kb-update/test-excluded-terms.test.mjs // Preventive gate: no tracked text file may contain a term from the // maintainer's excluded-terms list. Examples, fixtures and placeholders use // generic, fictitious material instead. // // The list lives in `tests/.excluded-terms.local.json` (gitignored via // `*.local.json`) and holds `pattern`, `flags`, `positives` and `negatives`. // Without that file the gate is skipped with a message, so a fresh clone runs // green; with it, the known positives prove the pattern can find before the // empty result over the tree is trusted. // // Population: `git ls-files` (tracked files only). Binary files (NUL byte in // the first 8000 bytes, as git decides) are skipped: text in a screenshot is // rendered pixels, so a byte match there says nothing about what it shows. import { test } from 'node:test'; import assert from 'node:assert/strict'; import { execFileSync } from 'node:child_process'; import { existsSync, readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; const pluginRoot = fileURLToPath(new URL('../../', import.meta.url)); const listPath = fileURLToPath(new URL('../.excluded-terms.local.json', import.meta.url)); const skip = existsSync(listPath) ? false : 'tests/.excluded-terms.local.json not present (local-only list) — gate skipped'; function loadList() { const list = JSON.parse(readFileSync(listPath, 'utf8')); return { ...list, regex: new RegExp(list.pattern, list.flags ?? '') }; } function trackedFiles() { return execFileSync('git', ['ls-files', '-z'], { cwd: pluginRoot, encoding: 'utf8' }) .split('\0') .filter(Boolean); } function isBinary(buf) { return buf.subarray(0, 8000).includes(0); } test('pattern matches every known positive and no known negative', { skip }, () => { const { regex, positives = [], negatives = [] } = loadList(); assert.ok(positives.length > 0, 'the list must carry known positives'); for (const s of positives) assert.match(s, regex, s); for (const s of negatives) assert.doesNotMatch(s, regex, s); }); test('no tracked text file contains an excluded term', { skip }, () => { const { regex } = loadList(); const files = trackedFiles(); assert.ok(files.length > 500, `git ls-files returned ${files.length} files — population too small to trust`); const hits = []; for (const rel of files) { let buf; try { buf = readFileSync(pluginRoot + rel); } catch { continue; } if (isBinary(buf)) continue; buf.toString('utf8').split('\n').forEach((line, i) => { if (regex.test(line)) hits.push(`${rel}:${i + 1}`); }); } assert.deepEqual(hits, [], `excluded terms in tracked files:\n ${hits.join('\n ')}`); });