108 lines
3.8 KiB
JavaScript
108 lines
3.8 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
import { spawnSync } from "node:child_process";
|
|
import test from "node:test";
|
|
|
|
const repoRoot = path.resolve(import.meta.dirname, "../..");
|
|
const script = path.join(repoRoot, "scripts/release/npm-view-version.sh");
|
|
|
|
async function runView(mode) {
|
|
const fixtureDir = await mkdtemp(path.join(tmpdir(), "kandev-npm-view-"));
|
|
const npm = path.join(fixtureDir, "npm");
|
|
const sleep = path.join(fixtureDir, "sleep");
|
|
const countFile = path.join(fixtureDir, "attempts");
|
|
const sleepFile = path.join(fixtureDir, "sleeps");
|
|
await writeFile(
|
|
npm,
|
|
`#!/usr/bin/env bash
|
|
count=0
|
|
if [[ -f "$MOCK_NPM_COUNT_FILE" ]]; then read -r count < "$MOCK_NPM_COUNT_FILE"; fi
|
|
count=$((count + 1))
|
|
printf '%s\n' "$count" > "$MOCK_NPM_COUNT_FILE"
|
|
case "$MOCK_NPM_MODE" in
|
|
found) printf '%s\\n' '1.2.4-nightly.shaabc123def456' ;;
|
|
missing) printf '%s\\n' 'npm error code E404' 'npm error No match found for version nightly' >&2; exit 1 ;;
|
|
transient)
|
|
if (( count < 3 )); then
|
|
printf '%s\\n' 'npm error code EAI_AGAIN' >&2
|
|
exit 1
|
|
fi
|
|
printf '%s\\n' '1.2.4-nightly.shaabc123def456'
|
|
;;
|
|
failure) printf '%s\\n' 'npm error code EAI_AGAIN' 'registry-secret-detail' >&2; exit 1 ;;
|
|
misleading) printf '%s\\n' 'npm error code EAI_AGAIN' 'npm error request to https://registry.test/e404/404-Not-Found/is-not-in-this-registry failed' >&2; exit 1 ;;
|
|
esac
|
|
`,
|
|
);
|
|
await writeFile(sleepFile, "");
|
|
await writeFile(
|
|
sleep,
|
|
'#!/usr/bin/env bash\nprintf \'%s\\n\' "$1" >> "$MOCK_SLEEP_FILE"\n',
|
|
);
|
|
await chmod(npm, 0o755);
|
|
await chmod(sleep, 0o755);
|
|
try {
|
|
const result = spawnSync("bash", [script, "kandev@nightly"], {
|
|
encoding: "utf8",
|
|
env: {
|
|
...process.env,
|
|
MOCK_NPM_COUNT_FILE: countFile,
|
|
MOCK_NPM_MODE: mode,
|
|
MOCK_SLEEP_FILE: sleepFile,
|
|
PATH: `${fixtureDir}${path.delimiter}${process.env.PATH ?? ""}`,
|
|
},
|
|
});
|
|
result.attempts = Number(await readFile(countFile, "utf8"));
|
|
result.sleeps = (await readFile(sleepFile, "utf8"))
|
|
.trim()
|
|
.split("\n")
|
|
.filter(Boolean);
|
|
return result;
|
|
} finally {
|
|
await rm(fixtureDir, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
test("prints a resolved npm version", async () => {
|
|
const result = await runView("found");
|
|
assert.equal(result.status, 0);
|
|
assert.equal(result.stdout.trim(), "1.2.4-nightly.shaabc123def456");
|
|
assert.deepEqual(result.sleeps, []);
|
|
});
|
|
|
|
test("treats a missing version or dist-tag as an empty result", async () => {
|
|
const result = await runView("missing");
|
|
assert.equal(result.status, 0);
|
|
assert.equal(result.stdout, "");
|
|
assert.equal(result.stderr, "");
|
|
assert.equal(result.attempts, 1);
|
|
assert.deepEqual(result.sleeps, []);
|
|
});
|
|
|
|
test("retries transient registry failures before succeeding", async () => {
|
|
const result = await runView("transient");
|
|
assert.equal(result.status, 0);
|
|
assert.equal(result.stdout.trim(), "1.2.4-nightly.shaabc123def456");
|
|
assert.equal(result.attempts, 3);
|
|
assert.deepEqual(result.sleeps, ["2", "2"]);
|
|
});
|
|
|
|
test("fails closed on registry and network errors", async () => {
|
|
const result = await runView("failure");
|
|
assert.notEqual(result.status, 0);
|
|
assert.match(result.stderr, /npm view failed for kandev@nightly/);
|
|
assert.doesNotMatch(result.stderr, /registry-secret-detail/);
|
|
assert.equal(result.attempts, 3);
|
|
assert.deepEqual(result.sleeps, ["2", "2"]);
|
|
});
|
|
|
|
test("does not mistake missing-looking request URLs for npm E404 diagnostics", async () => {
|
|
const result = await runView("misleading");
|
|
assert.notEqual(result.status, 0);
|
|
assert.match(result.stderr, /npm view failed for kandev@nightly/);
|
|
assert.equal(result.attempts, 3);
|
|
assert.deepEqual(result.sleeps, ["2", "2"]);
|
|
});
|