86 lines
2.7 KiB
TypeScript
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);
|
|
}
|
|
}
|
|
});
|
|
});
|