Files
siftlode/frontend/src/components/ui/uiI18n.contract.test.ts
T
peter d44d8d6dda fix(gate): knip sees the watch entry, the build must emit watch.html, and two hand copies are held
- The raw-source contract tests read files from disk (rawSources.testkit)
  instead of import.meta.glob, which knip counted as importing every src file —
  its unused-files lane could never name an orphan. knip now names
  src/watchMain.tsx as an entry (registered in docs/gates.md).
- vite build fails when index.html or watch.html is not emitted.
- The watch-entry import walk follows dynamic import() too.
- audit_metrics.py's plan-code patterns are held equal to the guard's.
- CrashBoundary is domain-free: it moves into components/ui.
2026-10-06 03:19:33 +02:00

42 lines
1.6 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { readSources } from "../../lib/rawSources.testkit";
// The platform layer (`components/ui/`) may not import a feature component or a domain API slice —
// eslint's `no-restricted-imports` enforces that. It cannot see an i18n KEY, though, and two
// primitives spoke domain vocabulary through one: `PriorityStepper` labelled itself with
// `channels.row.*` (and told every caller that it orders the Feed), `Combobox` said `plex.loading`
// and `plex.filter.moreRefine` on the feed sidebar. A primitive's strings live in a platform
// namespace; what a value MEANS where it is used arrives as a prop.
const PLATFORM_NAMESPACES = new Set([
"common",
"errors",
"datatable",
"keys",
"palette",
"sidebar",
"notifications",
"time",
]);
const files = readSources(__dirname, "./**/*.{ts,tsx}");
// `t("ns.…")` and `t(\`ns.…\`)` — the namespace is everything before the first dot.
const KEY = /\bt\(\s*["`]([A-Za-z]+)\./g;
describe("components/ui/ speaks only platform i18n namespaces", () => {
it("names no feature namespace", () => {
const sources = Object.entries(files).filter(([p]) => !/\.test\.tsx?$/.test(p));
expect(sources.length).toBeGreaterThan(20); // the glob matched the layer
const offenders = sources.flatMap(([p, src]) =>
[...String(src).matchAll(KEY)]
.map((m) => m[1]!)
.filter((ns) => !PLATFORM_NAMESPACES.has(ns))
.map((ns) => `${p}: ${ns}.*`),
);
expect(offenders).toEqual([]);
});
it("sees a feature namespace when one is used", () => {
expect([...'t("plex.loading")'.matchAll(KEY)].map((m) => m[1])).toEqual(["plex"]);
});
});