test.rules/codemods/analyzers/vocabulary.analyzer.test.ts
test.rules/codemods/analyzers/vocabulary.analyzer.test.ts is a file in Codebase Testing. 64 lines of code and 0 definitions.
import {
collectVocabularyFindings,
vocabularyFindingsIn,
} from "@ssot/govlab/codemods/analyzers/vocabulary.analyzer.ts";
import { describe, expect, it } from "vitest";
import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
import { join } from "node:path";
import { pathExclusion } from "@govlab/quality/config";
import { tmpdir } from "node:os";
import { writeVerbatim } from "@govlab/canonical-write";
const renamed = function renamed(fileName: string, content: string, wholeIds = false): string[] {
return vocabularyFindingsIn(fileName, content, wholeIds).map((finding) => `${finding.from}>${finding.to}`);
};
describe("vocabularyFindingsIn", () => {
it("renames a retired id in a reference, an anchor, a catalog path and a collection name", () => {
expect(renamed("probe.ts", 'const a = "arch:x"; const b = "#lex-y"; const c = "/records/algo/z.md";')).toEqual([
"arch>architecture",
"lex>lexicon",
"algo>algorithms",
]);
expect(renamed("probe.ts", 'const d = "The reason collection holds the loop.";')).toEqual(["reason>reasoning"]);
});
it("renames a renamed word in prose and keeps its case, only where the literal is prose", () => {
expect(renamed("probe.ts", 'const a = "Each face has a Markdown twin."; const b = "face";')).toEqual([
"face>collection",
"twin>alternate",
]);
});
it("renames a literal that is exactly an id only where whole ids are declared, and never a field name", () => {
const code = 'const a = { face: "arch" }; const b = x["arch"]; const c = "arch" in y;';
expect(renamed("probe.ts", code)).toEqual([]);
expect(renamed("probe.ts", code, true)).toEqual(["arch>architecture"]);
});
it("leaves module specifiers, JSON keys and the words of a hyphenated identifier as written", () => {
expect(renamed("probe.ts", 'import x from "./arch:y";')).toEqual([]);
expect(renamed("probe.json", '{ "arch:x": "lex:y" }')).toEqual(["lex>lexicon"]);
expect(renamed("probe.ts", 'const a = "the font-face rule and a face_value";')).toEqual([]);
});
it("reads shapes everywhere in Markdown and words only outside code", () => {
const content = "the `face` field and `arch:x`\n```\nface\n```\na face";
expect(renamed("probe.md", content)).toEqual(["arch>architecture", "face>collection"]);
});
});
describe("collectVocabularyFindings", () => {
it("walks the roots, skips excluded folders, skipped paths and generated files, and marks whole-id roots", () => {
const root = mkdtempSync(join(tmpdir(), "vocabulary-"));
mkdirSync(join(root, "excluded"));
mkdirSync(join(root, "ids"));
writeVerbatim(join(root, "a.ts"), 'const a = "arch";\n');
writeVerbatim(join(root, "ids", "b.ts"), 'const b = "arch";\n');
writeVerbatim(join(root, "c.generated.ts"), 'const c = "arch:x";\n');
writeVerbatim(join(root, "excluded", "d.ts"), 'const d = "arch:x";\n');
writeVerbatim(join(root, "e.ts"), 'const e = "arch:x";\n');
const found = collectVocabularyFindings({
extensions: [".ts"],
roots: [root],
skipped: pathExclusion(root, ["excluded", "*.generated.*"]),
skippedPaths: [join(root, "e.ts")],
wholeIdRoots: [join(root, "ids")],
}).map((finding) => finding.file.slice(finding.file.lastIndexOf("/") + 1));
rmSync(root, { force: true, recursive: true });
expect(found).toEqual(["b.ts"]);
});
});