rea/tests/dependencyInstall.test.ts

100 lines
3.1 KiB
TypeScript

import { copyFile, mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { spawnSync } from "node:child_process";
import { afterEach, describe, expect, it } from "vitest";
import { createTestTempDirectory } from "./fixtures/temporaryDirectory.js";
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 createTestTempDirectory("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");
});
});