test.build/core/resolvers/binding.resolver.test.ts
test.build/core/resolvers/binding.resolver.test.ts is a file in Codebase Testing. 52 lines of code and 0 definitions.
import { describe, expect, it } from "vitest";
import { mkdtempSync, rmSync } from "node:fs";
import { bindingResolverOf } from "@banes-lab/build-scripts/core/resolvers/binding.resolver.ts";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { writeVerbatim } from "@govlab/canonical-write";
const CONFIG = JSON.stringify({
compilerOptions: { allowImportingTsExtensions: true, module: "ESNext", moduleResolution: "Bundler", noEmit: true },
});
const B = "export const beta = 1;\nexport default function gamma() {\n return beta;\n}\n";
const IMPORTS = 'import gamma, { beta as renamed } from "./b.ts";';
const NAMESPACE = 'import * as space from "./b.ts";';
const BODY = "const local = (value: number) => value + renamed + space.beta;";
const TAIL = 'export { beta } from "./b.ts";\nconst lazy = import("./b.ts");\nlocal(gamma());\nvoid lazy;\n';
const A = [IMPORTS, NAMESPACE, BODY, TAIL].join("\n");
describe("bindingResolverOf", () => {
it("binds every identifier to its declaration through the compiler, across import forms and scopes", () => {
const root = mkdtempSync(join(tmpdir(), "binding-"));
writeVerbatim(join(root, "tsconfig.json"), CONFIG);
writeVerbatim(join(root, "a.ts"), A);
writeVerbatim(join(root, "b.ts"), B);
const resolve = bindingResolverOf(
[
{ absolute: join(root, "a.ts"), path: "a.ts" },
{ absolute: join(root, "b.ts"), path: "b.ts" },
{ absolute: join(root, "c.md"), path: "c.md" },
],
root,
);
const bindings = resolve("a.ts") ?? [];
const other = resolve("b.ts") ?? [];
const prose = resolve("c.md");
rmSync(root, { force: true, recursive: true });
const at = (line: number, column: number): (typeof bindings)[number] | undefined =>
bindings.find((binding) => binding.line === line && binding.column === column);
const beta = { file: "b.ts", module: false, name: "beta", target: 1 };
expect(at(1, IMPORTS.indexOf("gamma"))).toMatchObject({ file: "b.ts", name: "gamma", target: 2 });
expect(at(1, IMPORTS.indexOf("renamed"))).toMatchObject(beta);
expect(at(1, IMPORTS.indexOf('"'))).toMatchObject({ file: "b.ts", module: true });
expect(at(2, NAMESPACE.indexOf("space"))).toMatchObject({ file: "b.ts", module: true });
expect(at(3, BODY.lastIndexOf("value"))).toMatchObject({ file: "a.ts", name: "value", target: 3 });
expect(at(3, BODY.indexOf("renamed"))).toMatchObject(beta);
expect(at(3, BODY.indexOf("space."))).toMatchObject({ file: "b.ts", module: true });
expect(at(3, BODY.indexOf("beta"))).toMatchObject(beta);
expect(at(4, "export { ".length)).toMatchObject(beta);
expect(at(5, "const lazy = import(".length)).toMatchObject({ file: "b.ts", module: true });
expect(at(6, 0)).toMatchObject({ file: "a.ts", name: "local", target: 3 });
expect(at(3, "const ".length)).toBeUndefined();
expect(other.find((binding) => binding.line === 3)).toMatchObject({ file: "b.ts", name: "beta", target: 1 });
expect(prose).toBeNull();
});
});