Ctrl K
ComunidadGuías…

scripts/check-ui-wildcard-exports.test.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// The check guards a blind spot that is invisible by construction: a component
// under a wildcard export registers as a knip entry point, so knip reports it
// as used no matter what. A guard for an invisible failure is worth exactly as
// much as its proof that it still fires.
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import test from "node:test";

const script = resolve(import.meta.dirname, "check-ui-wildcard-exports.mjs");

// Keep fixture imports and wildcard exports shaped like the real workspaces.
function fixture(t) {
  const root = mkdtempSync(join(tmpdir(), "ui-exports-"));
  t.after(() => rmSync(root, { recursive: true, force: true }));
  const write = (rel, text) => {
    mkdirSync(dirname(join(root, rel)), { recursive: true });
    writeFileSync(join(root, rel), text);
  };
  const remove = (rel) => rmSync(join(root, rel));
  write("packages/ui/package.json", JSON.stringify({
    name: "@multica/ui",
    exports: {
      "./components/ui/*": "./components/ui/*.tsx",
      "./components/common/*": "./components/common/*.tsx",
      "./markdown/*": "./markdown/*.tsx",
      "./hooks/*": "./hooks/*.ts",
    },
  }));
  mkdirSync(join(root, "packages/views"), { recursive: true });
  const check = () => {
    const result = spawnSync(process.execPath, [script, root], { encoding: "utf8" });
    return { status: result.status, output: result.stdout + result.stderr };
  };
  const passes = (message) => {
    const { status, output } = check();
    assert.equal(status, 0, `${message}\n${output}`);
  };
  const failsNaming = (names, message) => {
    const { status, output } = check();
    assert.equal(status, 1, `${message}\n${output}`);
    for (const name of names) assert.ok(output.includes(name), `should name ${name}\n${output}`);
  };
  return { write, remove, passes, failsNaming };
}

const importer = "packages/views/zz-probe-importer.tsx";

test("an unimported component fails and is named until a consumer imports it", (t) => {
  const { write, passes, failsNaming } = fixture(t);
  passes("a clean tree should pass");
  write("packages/ui/components/ui/zz-unused-export-probe.tsx", "export function UnusedExportProbe() { return null; }\n");
  failsNaming(["zz-unused-export-probe.tsx"], "a zero-reference component should fail");
  write(importer, 'export { UnusedExportProbe } from "@multica/ui/components/ui/zz-unused-export-probe";\n');
  passes("a real consumer should make the component live");
});

test("a relative import of a same-named file outside UI cannot vouch for it", (t) => {
  const { write, failsNaming } = fixture(t);
  write("packages/views/onboarding/components/option-card.tsx", "export function OptionCard() { return null; }\n");
  write("packages/views/onboarding/steps/welcome.tsx", 'export { OptionCard } from "../components/option-card";\n');
  write("packages/ui/components/ui/option-card.tsx", "export function OptionCard() { return null; }\n");
  failsNaming(["components/ui/option-card.tsx"], "basename matching must not mark a dead component as used");
});

// Liveness is reachability from outside the guarded directories, not a
// reference count.
test("an unreachable import chain or cycle stays dead until something outside reaches it", (t) => {
  const { write, passes, failsNaming } = fixture(t);
  write("packages/ui/components/ui/zz-cycle-a.tsx", 'import { CycleB } from "./zz-cycle-b";\nexport const CycleA = () => CycleB();\n');
  write("packages/ui/components/ui/zz-cycle-b.tsx", "export const CycleB = () => null;\n");
  failsNaming(["zz-cycle-a.tsx", "zz-cycle-b.tsx"], "an A -> B chain must not vouch for itself");
  write("packages/ui/components/ui/zz-cycle-b.tsx", 'import { CycleA } from "./zz-cycle-a";\nexport const CycleB = () => CycleA;\n');
  failsNaming(["zz-cycle-a.tsx", "zz-cycle-b.tsx"], "an A <-> B cycle must not vouch for itself");
  write(importer, 'export { CycleA } from "@multica/ui/components/ui/zz-cycle-a";\n');
  passes("an external consumer should make both halves live");
});

// A component passes through this state the moment its last real importer is
// deleted, so a text scan would keep vouching for it exactly when it stops
// being used.
test("commented-out, stringified and mock-only mentions are not imports", (t) => {
  const { write, remove, failsNaming } = fixture(t);
  write("packages/ui/components/ui/zz-comment-probe.tsx", "export function CommentProbe() { return null; }\n");
  write(importer, [
    '// import { CommentProbe } from "@multica/ui/components/ui/zz-comment-probe";',
    'export const note = \'import { CommentProbe } from "@multica/ui/components/ui/zz-comment-probe"\';',
  ].join("\n"));
  failsNaming(["zz-comment-probe.tsx"], "a comment or string must not count as an edge");
  remove("packages/ui/components/ui/zz-comment-probe.tsx");
  write("packages/ui/components/ui/zz-mock-only.tsx", "export function MockOnly() { return null; }\n");
  write(importer, 'import { vi } from "vitest"; vi.mock("@multica/ui/components/ui/zz-mock-only");\n');
  failsNaming(["zz-mock-only.tsx"], "a mock-only mention must not vouch for a product");
});

// Vitest discovers *.test.{ts,tsx} without product imports. Such files in
// wildcard directories are exempt from reporting, but cannot vouch for unused
// production files. Non-contract *.spec files remain guarded.
for (const [dir, ext] of [["components/ui", "tsx"], ["components/common", "tsx"], ["markdown", "tsx"], ["hooks", "ts"]]) {
  test(`colocated tests in ${dir} are exempt but cannot vouch for a product`, (t) => {
    const { write, remove, passes, failsNaming } = fixture(t);
    const testFile = `packages/ui/${dir}/zz-unused-runtime.test.${ext}`;
    write(testFile, 'import { it } from "vitest";\nit("discovered", () => {});\n');
    passes(`a Vitest-discovered test in ${dir} should not need a product import`);
    write(`packages/ui/${dir}/zz-unused-runtime.${ext}`, "export function RuntimeProbe() { return null; }\n");
    write(testFile, 'import { RuntimeProbe } from "./zz-unused-runtime";\nimport { it } from "vitest";\nit("probe", () => RuntimeProbe());\n');
    failsNaming([`${dir}/zz-unused-runtime.${ext}`], `a colocated test in ${dir} must not vouch for an unused product`);
    write(importer, `export { RuntimeProbe } from "@multica/ui/${dir}/zz-unused-runtime";\n`);
    passes(`a real consumer should make the product in ${dir} live`);
    for (const rel of [importer, testFile, `packages/ui/${dir}/zz-unused-runtime.${ext}`]) remove(rel);
    write(`packages/ui/${dir}/zz-not-discovered.spec.${ext}`, "export function StillGuarded() { return null; }\n");
    failsNaming([`${dir}/zz-not-discovered.spec.${ext}`], `a spec file in ${dir} must remain guarded`);
  });
}