import assert from "node:assert/strict"; import { mkdtemp, writeFile, rm } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import test from "node:test"; import { checkComponentTypes } from "./component-types.mjs"; const tsc = process.env.QUIXOS_TYPESCRIPT; if (!tsc) throw Error("Pass the selected TypeScript compiler path"); async function fixture(context, left, right) { const work = await mkdtemp(path.join(os.tmpdir(), "component-types-")); context.after(() => rm(work, { recursive: true, force: true })); await Promise.all( Object.entries({ "left.ts": left, "right.ts": right, "assets.d.ts": "", "props.d.ts": "" }).map(([file, source]) => writeFile(path.join(work, file), source), ), ); return { node: process.execPath, tsc, work, witnesses: ["left.ts", "right.ts"], assets: "assets.d.ts", props: "props.d.ts", packageRevision: "test", }; } test("shared component typechecking accepts all valid witnesses", async (context) => { checkComponentTypes(await fixture(context, "export const left: string = 'ok';", "export const right: number = 1;")); }); test("independently valid ambient declarations use the full individual check fallback", async (context) => { checkComponentTypes( await fixture( context, "export {}; declare global { interface Application { value: string; } }", "export {}; declare global { interface Application { value: number; } }", ), ); }); test("a type error in any witness still rejects the artifact", async (context) => { const input = await fixture(context, "export const left: string = 'ok';", "export const right: string = 1;"); assert.throws(() => checkComponentTypes(input)); }); test("one witness's globals cannot make an independently invalid witness pass", async (context) => { const input = await fixture( context, "export {}; declare global { interface Application { value: string; } }", "export const right: Application = {value: 'ok'};", ); assert.throws(() => checkComponentTypes(input)); }); test("an ambient module from another source closure cannot resolve a missing import", async (context) => { const input = await fixture( context, "declare module 'missing-component-package' { export const value: string; }", "import {value} from 'missing-component-package'; export const right = value;", ); assert.throws(() => checkComponentTypes(input)); });