Files
suaveplan/packages/money/finance/cryptocurrency/tests/exports.test.ts
2026-05-27 23:47:53 +01:00

86 lines
2.7 KiB
TypeScript

import { describe, expect, it } from "@suaveplan/testing/runner";
/**
* Asserts that every subpath advertised in `package.json` `exports`
* resolves at runtime. This catches drift between the manifest and the
* actual file layout (rename a file, forget the export entry, and this
* test fails).
*
* We exercise the in-source TypeScript modules via relative imports
* because `bun test` runs against `src/` directly — the `dist/`
* subpaths would only resolve after `vite build`, which is a separate
* pipeline stage. The structural shape is the same.
*/
const MODULES: ReadonlyArray<{
subpath: string;
loader: () => Promise<unknown>;
}> = [
{
subpath: "./address/validator",
loader: () => import("../src/address/validator.js"),
},
{
subpath: "./chains/chain-data",
loader: () => import("../src/chains/chain-data.js"),
},
{
subpath: "./chains/chain-registry",
loader: () => import("../src/chains/chain-registry.js"),
},
{
subpath: "./chains/registry",
loader: () => import("../src/chains/registry.js"),
},
{
subpath: "./error-codes/error-codes",
loader: () => import("../src/error-codes/error-codes.js"),
},
{
subpath: "./gas/gas-estimator",
loader: () => import("../src/gas/gas-estimator.js"),
},
{
subpath: "./tokens/token-data",
loader: () => import("../src/tokens/token-data.js"),
},
{
subpath: "./tokens/token-registry",
loader: () => import("../src/tokens/token-registry.js"),
},
{
subpath: "./transaction/tx-decoder",
loader: () => import("../src/transaction/tx-decoder.js"),
},
{
subpath: "./types/crypto.types",
loader: () => import("../src/types/crypto.types.js"),
},
{
subpath: "./units/converter",
loader: () => import("../src/units/converter.js"),
},
];
describe("subpath exports", () => {
it("every package.json subpath export resolves to a real module", {
timeout: 30000,
}, async () => {
for (const { subpath, loader } of MODULES) {
const mod = await loader();
expect(
mod,
`expected ${subpath} to resolve to a module record`
).toBeTruthy();
// The types subpath is pure types — it compiles to an empty module record.
// Every other subpath must have at least one runtime export.
if (subpath !== "./types/crypto.types") {
expect(
Object.keys(mod as Record<string, unknown>).length,
`expected ${subpath} to have at least one named export`
).toBeGreaterThan(0);
}
}
});
});