diff --git a/test/packaging.test.js b/test/packaging.test.js index cf109e7..b463828 100644 --- a/test/packaging.test.js +++ b/test/packaging.test.js @@ -8,6 +8,7 @@ const os = require("node:os"); const path = require("node:path"); const { builtinModules } = require("node:module"); const { spawnSync } = require("node:child_process"); +const ts = require("typescript"); const pkg = require("alex2node/package.json"); const ROOT = path.join(__dirname, ".."); @@ -53,14 +54,17 @@ test("each build has its own declarations, and \"exports\" names them before the } }); -test("the builds import Node built-ins and the declared dependencies, nothing else", () => { +test("the builds and their declarations import Node built-ins and the declared dependencies, nothing else", () => { // "mqtt/lib/x" and "@scope/name/x" belong to the packages "mqtt" and "@scope/name" const packageOf = (specifier) => specifier.split("/").slice(0, specifier.startsWith("@") ? 2 : 1).join("/"); const imported = new Set(); - for (const file of files(DIST).filter((f) => f.endsWith(".js"))) { - const source = fs.readFileSync(path.join(DIST, file), "utf8"); - for (const [, specifier] of source.matchAll(/(?:\brequire\(|\bfrom\s+|\bimport\s+)"([^".][^"]*)"/g)) { - if (!builtinModules.includes(specifier.replace(/^node:/, ""))) imported.add(packageOf(specifier)); + for (const file of files(DIST).filter((f) => /\.(js|ts)$/.test(f))) { + // Read with the compiler's scanner: tsc keeps comments in its output, and an import in a usage example or in + // a string is not an import. + const { importedFiles } = ts.preProcessFile(fs.readFileSync(path.join(DIST, file), "utf8"), true, true); + for (const { fileName: specifier } of importedFiles) { + if (specifier.startsWith(".") || builtinModules.includes(specifier.replace(/^node:/, ""))) continue; + imported.add(packageOf(specifier)); } } assert.deepEqual([...imported].sort(), Object.keys(pkg.dependencies).sort());