99 lines
3.0 KiB
TypeScript
99 lines
3.0 KiB
TypeScript
import { copyFile, mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { spawnSync } from "node:child_process";
|
|
|
|
import { afterEach, describe, expect, it } from "vitest";
|
|
|
|
const roots: string[] = [];
|
|
const script = join(process.cwd(), "scripts", "check-dependency-install.mjs");
|
|
|
|
afterEach(async () => {
|
|
await Promise.all(
|
|
roots.splice(0).map((root) => rm(root, { recursive: true })),
|
|
);
|
|
});
|
|
|
|
const fixture = async (
|
|
installedVersion?: string,
|
|
omitDevDependency = false,
|
|
) => {
|
|
const root = await mkdtemp(join(tmpdir(), "rea-deps-"));
|
|
roots.push(root);
|
|
await mkdir(join(root, "node_modules"));
|
|
await writeFile(
|
|
join(root, "package-lock.json"),
|
|
JSON.stringify({
|
|
packages: {
|
|
"": {
|
|
dependencies: { alpha: "1.0.0" },
|
|
devDependencies: { beta: "2.0.0" },
|
|
},
|
|
"node_modules/alpha": { version: "1.0.0" },
|
|
"node_modules/beta": { version: "2.0.0" },
|
|
},
|
|
}),
|
|
);
|
|
await writeFile(
|
|
join(root, "node_modules", ".package-lock.json"),
|
|
JSON.stringify({
|
|
packages: {
|
|
"node_modules/alpha": { version: installedVersion ?? "1.0.0" },
|
|
...(omitDevDependency
|
|
? {}
|
|
: { "node_modules/beta": { version: "2.0.0" } }),
|
|
"node_modules/unrelated": { version: "9.0.0" },
|
|
},
|
|
}),
|
|
);
|
|
return root;
|
|
};
|
|
|
|
describe("dependency install freshness", () => {
|
|
it("accepts matching direct packages and ignores extraneous packages", async () => {
|
|
const result = spawnSync(process.execPath, [script], {
|
|
cwd: await fixture(),
|
|
encoding: "utf8",
|
|
});
|
|
expect(result.status, result.stderr).toBe(0);
|
|
});
|
|
|
|
it("reports a direct version mismatch with one remediation", async () => {
|
|
const result = spawnSync(process.execPath, [script], {
|
|
cwd: await fixture("0.9.0"),
|
|
encoding: "utf8",
|
|
});
|
|
expect(result.status).toBe(1);
|
|
expect(result.stderr).toContain("alpha: installed 0.9.0, expected 1.0.0");
|
|
expect(result.stderr.match(/npm ci/gu)).toHaveLength(1);
|
|
});
|
|
|
|
it("reports a missing direct development dependency", async () => {
|
|
const result = spawnSync(process.execPath, [script], {
|
|
cwd: await fixture(undefined, true),
|
|
encoding: "utf8",
|
|
});
|
|
expect(result.status).toBe(1);
|
|
expect(result.stderr).toContain(
|
|
"beta: missing from the installed dependency lockfile",
|
|
);
|
|
expect(result.stderr.match(/npm ci/gu)).toHaveLength(1);
|
|
});
|
|
|
|
it("runs from a script path containing URL-escaped characters", async () => {
|
|
const root = await fixture("0.9.0");
|
|
const scriptDirectory = join(root, "path with spaces");
|
|
const copiedScript = join(scriptDirectory, "check-dependency-install.mjs");
|
|
await mkdir(scriptDirectory);
|
|
await copyFile(script, copiedScript);
|
|
|
|
const result = spawnSync(process.execPath, [copiedScript], {
|
|
cwd: root,
|
|
encoding: "utf8",
|
|
});
|
|
|
|
expect(result.status).toBe(1);
|
|
expect(result.stderr).toContain("alpha: installed 0.9.0, expected 1.0.0");
|
|
});
|
|
});
|