feat: add repeatable Web UX inspection workbench

This commit is contained in:
2026-09-01 22:48:26 +09:00
parent 409245cb52
commit 4a4a01b730
20 changed files with 2307 additions and 0 deletions
+75
View File
@@ -0,0 +1,75 @@
import { assertEquals, assertRejects, assertStringIncludes } from "@std/assert";
import { join } from "@std/path";
import {
assertBundleIsSecretFree,
redactText,
safeUrl,
writePrivateJson,
} from "../src/artifacts.ts";
import { startOwnedProcesses, stopOwnedProcesses } from "../src/processes.ts";
Deno.test("redaction removes common credentials and query values", () => {
const redacted = redactText(
"Authorization: Bearer abc.def cookie=session-value token=secret-value",
["abc.def"],
);
assertStringIncludes(redacted, "[REDACTED]");
assertEquals(redacted.includes("abc.def"), false);
assertEquals(redacted.includes("session-value"), false);
assertEquals(
safeUrl("https://user:pass@example.test/path?token=secret#fragment"),
"https://example.test/path?token=%5BREDACTED%5D",
);
assertRejects(
async () => assertBundleIsSecretFree('{"authorization":"Bearer abc"}'),
Error,
"forbidden secret marker",
);
});
Deno.test("private JSON state uses owner-only permissions", async () => {
const directory = await Deno.makeTempDir();
try {
const path = join(directory, "state", "owner.json");
await writePrivateJson(path, { cookies: [], origins: [] });
assertEquals(JSON.parse(await Deno.readTextFile(path)), { cookies: [], origins: [] });
if (Deno.build.os !== "windows") assertEquals((await Deno.stat(path)).mode! & 0o777, 0o600);
} finally {
await Deno.remove(directory, { recursive: true });
}
});
Deno.test("owned process is terminated and its logs are redacted", async () => {
const directory = await Deno.makeTempDir();
const scenario = join(directory, "scenario.json");
await Deno.writeTextFile(scenario, "{}");
try {
const processes = await startOwnedProcesses(
[{
id: "fixture",
command: Deno.execPath(),
args: ["eval", 'console.log("authorization: secret-value"); setInterval(() => {}, 1000)'],
}],
scenario,
join(directory, "logs"),
["secret-value"],
);
assertEquals(processes.length, 1);
const logPath = join(directory, "logs", "fixture.stdout.log");
for (let attempt = 0; attempt < 20; attempt++) {
try {
if ((await Deno.readTextFile(logPath)).length > 0) break;
} catch {
// The output pump creates the file asynchronously.
}
await new Promise((resolve) => setTimeout(resolve, 10));
}
const diagnostics = await stopOwnedProcesses(processes);
assertEquals(diagnostics, []);
const log = await Deno.readTextFile(logPath);
assertEquals(log.includes("secret-value"), false);
assertStringIncludes(log, "[REDACTED]");
} finally {
await Deno.remove(directory, { recursive: true });
}
});