Files
jb fd63b0ccec
fast-browser scenarios / Offline scenario contract tests (push) Failing after 44s
fast-browser scenarios / Local Chromium headless scenarios (push) Failing after 23s
fast-browser-with-jev
2026-09-20 12:24:08 -04:00

85 lines
4.2 KiB
TypeScript

import assert from "node:assert/strict";
import { mkdtemp, writeFile, rm, mkdir } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import { createCredentialResolver } from "./credentials.ts";
import type { CredentialBindings } from "./contracts.ts";
const signal = () => new AbortController().signal;
async function fixture(fn: (cwd: string) => Promise<void>) {
const cwd = await mkdtemp(join(tmpdir(), "fast-browser-credentials-"));
try { await fn(cwd); } finally { await rm(cwd, { recursive: true, force: true }); }
}
test("literals and explicit environment sources resolve without trimming or process-env fallback", async () => {
const resolve = createCredentialResolver({ literal: " test-value\n", environment: { env: "TEST_PASSWORD" }, blank: "" }, {
cwd: "/unused", env: { TEST_PASSWORD: "another-value" },
});
assert.equal(await resolve("literal", signal()), " test-value\n");
assert.equal(await resolve("environment", signal()), "another-value");
assert.equal(await resolve("blank", signal()), "");
await assert.rejects(resolve("missing", signal()), /not supplied/);
});
test("plain file and exact JSON key sources resolve relative to the caller cwd", async () => {
await fixture(async (cwd) => {
await writeFile(join(cwd, "password.txt"), "plain-secret\n", { mode: 0o600 });
await writeFile(join(cwd, "accounts.json"), JSON.stringify({ "test.password": "json-secret", user: "demo" }), { mode: 0o600 });
const resolve = createCredentialResolver({
plain: { file: "password.txt" },
json: { file: "accounts.json", key: "test.password" },
}, { cwd, env: {} });
assert.equal(await resolve("plain", signal()), "plain-secret\n");
assert.equal(await resolve("json", signal()), "json-secret");
});
});
test("files are read lazily and malformed/missing values never appear in errors", async () => {
await fixture(async (cwd) => {
const resolve = createCredentialResolver({ secret: { file: "accounts.json", key: "password" } }, { cwd, env: {} });
await writeFile(join(cwd, "accounts.json"), "private-secret-is-not-json");
await assert.rejects(resolve("secret", signal()), (error: Error) => {
assert.match(error.message, /not valid JSON/);
assert.doesNotMatch(error.message, /private-secret/);
return true;
});
await writeFile(join(cwd, "accounts.json"), JSON.stringify({ password: "new-value" }));
assert.equal(await resolve("secret", signal()), "new-value");
await writeFile(join(cwd, "accounts.json"), JSON.stringify({ elsewhere: "private-value" }));
await assert.rejects(resolve("secret", signal()), /entry is missing/);
});
});
test("missing environment and oversized values fail closed", async () => {
const resolve = createCredentialResolver({ p: { env: "PRIVATE_VALUE" } }, { cwd: "/unused", env: {} });
await assert.rejects(resolve("p", signal()), /bounded string/);
assert.throws(() => createCredentialResolver({ p: "x".repeat(8001) }, { cwd: "/unused" }), /too long/);
});
test("unknown source fields and ambiguous bindings are rejected before any IO", () => {
for (const bindings of [
{ p: { env: "A", file: "x" } }, { p: { command: "print-secret" } }, { p: { env: "A B" } },
{ p: { file: "x", key: 2 } }, { "bad name": "value" }, { p: null },
]) {
assert.throws(() => createCredentialResolver(bindings as unknown as CredentialBindings, { cwd: "/unused" }));
}
});
test("non-regular and oversized files are rejected", async () => {
await fixture(async (cwd) => {
await mkdir(join(cwd, "directory"));
await writeFile(join(cwd, "large"), "x".repeat(65537));
for (const file of ["directory", "large"]) {
const resolve = createCredentialResolver({ p: { file } }, { cwd, env: {} });
await assert.rejects(resolve("p", signal()), /bounded regular file/);
}
});
});
test("pre-aborted credential resolution does not read the source", async () => {
const resolve = createCredentialResolver({ p: { file: "/nonexistent" } }, { cwd: "/unused", env: {} });
const abort = new AbortController(); abort.abort(new Error("test cancellation"));
await assert.rejects(resolve("p", abort.signal), /test cancellation/);
});