118 lines
3.5 KiB
TypeScript
118 lines
3.5 KiB
TypeScript
import { promises as fs } from "node:fs"
|
|
import os from "node:os"
|
|
import path from "node:path"
|
|
import { describe, expect, it } from "vitest"
|
|
|
|
import { getDryRunEnvironment, runLocalCliDryRun } from "./dry-run"
|
|
import { REGISTRY_DRY_RUN_FAILURE_MESSAGE_MAX_LENGTH } from "./schema"
|
|
|
|
describe("getDryRunEnvironment", () => {
|
|
it("allowlists process variables and excludes credentials", () => {
|
|
const environment = getDryRunEnvironment("/tmp/registry-health-test")
|
|
|
|
expect(environment).toMatchObject({
|
|
CI: "1",
|
|
NO_COLOR: "1",
|
|
XDG_CACHE_HOME: "/tmp/registry-health-test",
|
|
XDG_CONFIG_HOME: "/tmp/registry-health-test",
|
|
})
|
|
expect(environment).not.toHaveProperty("BLOB_READ_WRITE_TOKEN")
|
|
expect(environment).not.toHaveProperty("GITHUB_TOKEN")
|
|
expect(environment).not.toHaveProperty("GH_TOKEN")
|
|
})
|
|
})
|
|
|
|
describe("runLocalCliDryRun", () => {
|
|
it("creates a TypeScript project the CLI can load", async () => {
|
|
const directory = await fs.mkdtemp(
|
|
path.join(os.tmpdir(), "registry-health-cli-test-")
|
|
)
|
|
const cliPath = path.join(directory, "cli.mjs")
|
|
await fs.writeFile(
|
|
cliPath,
|
|
`
|
|
import { readFileSync } from "node:fs"
|
|
|
|
const tsconfig = JSON.parse(readFileSync("tsconfig.json", "utf8"))
|
|
if (tsconfig.compilerOptions.paths["@/*"][0] !== "./*") {
|
|
process.exit(1)
|
|
}
|
|
`
|
|
)
|
|
|
|
try {
|
|
await expect(
|
|
runLocalCliDryRun({
|
|
namespace: "@acme",
|
|
item: "button",
|
|
registryUrl: "https://acme.example.com/r/{name}.json",
|
|
cliPath,
|
|
})
|
|
).resolves.toMatchObject({ success: true })
|
|
} finally {
|
|
await fs.rm(directory, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
it("captures bounded sanitized CLI errors", async () => {
|
|
const directory = await fs.mkdtemp(
|
|
path.join(os.tmpdir(), "registry-health-cli-test-")
|
|
)
|
|
const cliPath = path.join(directory, "cli.mjs")
|
|
await fs.writeFile(
|
|
cliPath,
|
|
'process.stderr.write("\\u001b[31m" + "x".repeat(1500) + " useful failure\\u001b[0m"); process.exit(1)'
|
|
)
|
|
|
|
try {
|
|
const result = await runLocalCliDryRun({
|
|
namespace: "@acme",
|
|
item: "button",
|
|
registryUrl: "https://acme.example.com/r/{name}.json",
|
|
cliPath,
|
|
})
|
|
|
|
expect(result).toMatchObject({
|
|
success: false,
|
|
failureCode: "exit_1",
|
|
})
|
|
expect(result.failureMessage).toContain("useful failure")
|
|
expect(result.failureMessage).not.toContain("\u001b")
|
|
expect(result.failureMessage?.length).toBeLessThanOrEqual(
|
|
REGISTRY_DRY_RUN_FAILURE_MESSAGE_MAX_LENGTH
|
|
)
|
|
} finally {
|
|
await fs.rm(directory, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
it("force kills a CLI process that ignores SIGTERM", async () => {
|
|
const directory = await fs.mkdtemp(
|
|
path.join(os.tmpdir(), "registry-health-cli-test-")
|
|
)
|
|
const cliPath = path.join(directory, "cli.mjs")
|
|
await fs.writeFile(
|
|
cliPath,
|
|
'process.on("SIGTERM", () => {}); setInterval(() => {}, 1000)'
|
|
)
|
|
|
|
try {
|
|
const result = await runLocalCliDryRun({
|
|
namespace: "@acme",
|
|
item: "button",
|
|
registryUrl: "https://acme.example.com/r/{name}.json",
|
|
cliPath,
|
|
timeoutMs: 25,
|
|
killGraceMs: 25,
|
|
})
|
|
|
|
expect(result).toMatchObject({
|
|
success: false,
|
|
failureCode: "timeout",
|
|
})
|
|
} finally {
|
|
await fs.rm(directory, { recursive: true, force: true })
|
|
}
|
|
})
|
|
})
|