117 lines
3.8 KiB
TypeScript
117 lines
3.8 KiB
TypeScript
/**
|
|
* Spec-conformance: pins the dual-runner conditional-exports shape
|
|
* declared in `package.json`. A regression that flips the `bun`
|
|
* condition to a vitest-only barrel (or vice versa) would silently
|
|
* break consumers running under `bun test`; this test catches it at
|
|
* the JSON-shape level rather than at integration time.
|
|
*/
|
|
import { readFile } from "node:fs/promises";
|
|
import { dirname, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { describe, expect, it } from "../src/runner/index.js";
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
const pkgPath = resolve(here, "..", "package.json");
|
|
|
|
interface ExportTarget {
|
|
readonly types?: string;
|
|
readonly default?: string;
|
|
}
|
|
|
|
interface ExportsMap {
|
|
readonly "."?: {
|
|
readonly vitest?: ExportTarget;
|
|
readonly bun?: ExportTarget;
|
|
readonly default?: ExportTarget;
|
|
};
|
|
readonly "./polyfills"?: string | ExportTarget;
|
|
readonly "./matchers"?: string | ExportTarget;
|
|
readonly "./config"?: string | ExportTarget;
|
|
readonly "./errors"?: string | ExportTarget;
|
|
readonly "./render"?: string | ExportTarget;
|
|
readonly "./queries"?: string | ExportTarget;
|
|
readonly "./user"?: string | ExportTarget;
|
|
readonly "./package.json"?: string;
|
|
}
|
|
|
|
interface MinimalPkg {
|
|
exports?: ExportsMap;
|
|
}
|
|
|
|
async function loadPkg(): Promise<MinimalPkg> {
|
|
return JSON.parse(await readFile(pkgPath, "utf8")) as MinimalPkg;
|
|
}
|
|
|
|
describe("dual-runner conditional exports", () => {
|
|
it("routes vitest + default to the index barrel", {
|
|
timeout: 5000,
|
|
}, async () => {
|
|
const pkg = await loadPkg();
|
|
const root = pkg.exports?.["."];
|
|
expect(root, "exports['.'] missing").toBeDefined();
|
|
expect(root?.vitest?.default).toBe("./dist/index.js");
|
|
expect(root?.default?.default).toBe("./dist/index.js");
|
|
});
|
|
|
|
it("routes the bun condition to the bun-test barrel", {
|
|
timeout: 5000,
|
|
}, async () => {
|
|
const pkg = await loadPkg();
|
|
const root = pkg.exports?.["."];
|
|
expect(root?.bun?.default).toBe("./dist/runner/bun-test.js");
|
|
});
|
|
|
|
it("vitest and default conditions share the same types entry", {
|
|
timeout: 5000,
|
|
}, async () => {
|
|
const pkg = await loadPkg();
|
|
const root = pkg.exports?.["."];
|
|
expect(root?.vitest?.types).toBe("./dist/index.d.ts");
|
|
expect(root?.default?.types).toBe("./dist/index.d.ts");
|
|
});
|
|
|
|
it("bun condition has its own types entry", { timeout: 5000 }, async () => {
|
|
const pkg = await loadPkg();
|
|
const root = pkg.exports?.["."];
|
|
expect(root?.bun?.types).toBe("./dist/runner/bun-test.d.ts");
|
|
});
|
|
});
|
|
|
|
describe("subpath exports presence", () => {
|
|
const REQUIRED_SUBPATHS = [
|
|
"./polyfills",
|
|
"./matchers",
|
|
"./config",
|
|
"./errors",
|
|
"./render",
|
|
"./queries",
|
|
"./user",
|
|
] as const;
|
|
|
|
it("declares every required subpath", { timeout: 5000 }, async () => {
|
|
const pkg = await loadPkg();
|
|
const exportsMap = pkg.exports ?? {};
|
|
for (const sub of REQUIRED_SUBPATHS) {
|
|
expect(
|
|
Object.hasOwn(exportsMap, sub),
|
|
`package.json#exports is missing "${sub}"`
|
|
).toBe(true);
|
|
}
|
|
});
|
|
|
|
it("polyfills + matchers resolve to side-effecting dist files", {
|
|
timeout: 5000,
|
|
}, async () => {
|
|
const pkg = await loadPkg();
|
|
const exportsMap = pkg.exports ?? {};
|
|
const polyfills = exportsMap["./polyfills"];
|
|
const matchers = exportsMap["./matchers"];
|
|
expect(
|
|
typeof polyfills === "string" ? polyfills : polyfills?.default
|
|
).toBe("./dist/setup/polyfills.js");
|
|
expect(
|
|
typeof matchers === "string" ? matchers : matchers?.default
|
|
).toBe("./dist/matchers/matchers.js");
|
|
});
|
|
});
|