test: share cli and channel setup fixtures

This commit is contained in:
Peter Steinberger
2026-03-26 18:13:22 +00:00
parent 02cf12371f
commit 1f740ff099
9 changed files with 353 additions and 513 deletions

View File

@@ -1,20 +1,10 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { registerBrowserManageCommands } from "./browser-cli-manage.js";
import { createBrowserProgram } from "./browser-cli-test-helpers.js";
import type { CliRuntimeCapture } from "./test-runtime-capture.js";
const runtimeState = vi.hoisted(() => ({ capture: null as CliRuntimeCapture | null }));
function getRuntimeCapture(): CliRuntimeCapture {
if (!runtimeState.capture) {
throw new Error("runtime capture not initialized");
}
return runtimeState.capture;
}
function getRuntime() {
return getRuntimeCapture().defaultRuntime;
}
import {
createBrowserProgram,
getBrowserCliRuntime,
getBrowserCliRuntimeCapture,
} from "./browser-cli-test-helpers.js";
const mocks = vi.hoisted(() => {
return {
@@ -32,19 +22,15 @@ vi.mock("./browser-cli-shared.js", () => ({
callBrowserRequest: mocks.callBrowserRequest,
}));
vi.mock("./cli-utils.js", () => ({
runCommandWithRuntime: async (
_runtime: unknown,
action: () => Promise<void>,
onError: (err: unknown) => void,
) => await action().catch(onError),
vi.mock("./cli-utils.js", async () => ({
...(await (await import("./browser-cli-test-helpers.js")).createBrowserCliUtilsMockModule()),
}));
vi.mock("../runtime.js", async () => {
const { createCliRuntimeCapture } = await import("./test-runtime-capture.js");
runtimeState.capture ??= createCliRuntimeCapture();
return { defaultRuntime: runtimeState.capture.defaultRuntime };
});
vi.mock(
"../runtime.js",
async () =>
await (await import("./browser-cli-test-helpers.js")).createBrowserCliRuntimeMockModule(),
);
function createProgram() {
const { program, browser, parentOpts } = createBrowserProgram();
@@ -55,7 +41,7 @@ function createProgram() {
describe("browser manage output", () => {
beforeEach(() => {
mocks.callBrowserRequest.mockClear();
getRuntimeCapture().resetRuntimeCapture();
getBrowserCliRuntimeCapture().resetRuntimeCapture();
});
it("shows chrome-mcp transport for existing-session status without fake CDP fields", async () => {
@@ -88,7 +74,7 @@ describe("browser manage output", () => {
from: "user",
});
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
const output = getBrowserCliRuntime().log.mock.calls.at(-1)?.[0] as string;
expect(output).toContain("transport: chrome-mcp");
expect(output).not.toContain("cdpPort:");
expect(output).not.toContain("cdpUrl:");
@@ -124,7 +110,7 @@ describe("browser manage output", () => {
from: "user",
});
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
const output = getBrowserCliRuntime().log.mock.calls.at(-1)?.[0] as string;
expect(output).toContain(
"userDataDir: /Users/test/Library/Application Support/BraveSoftware/Brave-Browser",
);
@@ -155,7 +141,7 @@ describe("browser manage output", () => {
const program = createProgram();
await program.parseAsync(["browser", "profiles"], { from: "user" });
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
const output = getBrowserCliRuntime().log.mock.calls.at(-1)?.[0] as string;
expect(output).toContain("chrome-live: running (2 tabs) [existing-session]");
expect(output).toContain("transport: chrome-mcp");
expect(output).not.toContain("port: 0");
@@ -183,7 +169,7 @@ describe("browser manage output", () => {
{ from: "user" },
);
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
const output = getBrowserCliRuntime().log.mock.calls.at(-1)?.[0] as string;
expect(output).toContain('Created profile "chrome-live"');
expect(output).toContain("transport: chrome-mcp");
expect(output).not.toContain("port: 0");
@@ -220,7 +206,7 @@ describe("browser manage output", () => {
from: "user",
});
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
const output = getBrowserCliRuntime().log.mock.calls.at(-1)?.[0] as string;
expect(output).toContain("cdpUrl: https://example.com/chrome?token=supers…7890");
expect(output).not.toContain("alice");
expect(output).not.toContain("supersecretpasswordvalue1234");

View File

@@ -1,16 +1,6 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { registerBrowserManageCommands } from "./browser-cli-manage.js";
import { createBrowserProgram } from "./browser-cli-test-helpers.js";
import type { CliRuntimeCapture } from "./test-runtime-capture.js";
const runtimeState = vi.hoisted(() => ({ capture: null as CliRuntimeCapture | null }));
function getRuntimeCapture(): CliRuntimeCapture {
if (!runtimeState.capture) {
throw new Error("runtime capture not initialized");
}
return runtimeState.capture;
}
import { createBrowserProgram, getBrowserCliRuntimeCapture } from "./browser-cli-test-helpers.js";
const mocks = vi.hoisted(() => {
return {
@@ -36,19 +26,15 @@ vi.mock("./browser-cli-shared.js", () => ({
callBrowserRequest: mocks.callBrowserRequest,
}));
vi.mock("./cli-utils.js", () => ({
runCommandWithRuntime: async (
_runtime: unknown,
action: () => Promise<void>,
onError: (err: unknown) => void,
) => await action().catch(onError),
vi.mock("./cli-utils.js", async () => ({
...(await (await import("./browser-cli-test-helpers.js")).createBrowserCliUtilsMockModule()),
}));
vi.mock("../runtime.js", async () => {
const { createCliRuntimeCapture } = await import("./test-runtime-capture.js");
runtimeState.capture ??= createCliRuntimeCapture();
return { defaultRuntime: runtimeState.capture.defaultRuntime };
});
vi.mock(
"../runtime.js",
async () =>
await (await import("./browser-cli-test-helpers.js")).createBrowserCliRuntimeMockModule(),
);
describe("browser manage start timeout option", () => {
function createProgram() {
@@ -60,7 +46,7 @@ describe("browser manage start timeout option", () => {
beforeEach(() => {
mocks.callBrowserRequest.mockClear();
getRuntimeCapture().resetRuntimeCapture();
getBrowserCliRuntimeCapture().resetRuntimeCapture();
});
it("uses parent --timeout for browser start instead of hardcoded 15s", async () => {

View File

@@ -1,20 +1,10 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { registerBrowserStateCommands } from "./browser-cli-state.js";
import { createBrowserProgram as createBrowserProgramShared } from "./browser-cli-test-helpers.js";
import type { CliRuntimeCapture } from "./test-runtime-capture.js";
const runtimeState = vi.hoisted(() => ({ capture: null as CliRuntimeCapture | null }));
function getRuntimeCapture(): CliRuntimeCapture {
if (!runtimeState.capture) {
throw new Error("runtime capture not initialized");
}
return runtimeState.capture;
}
function getRuntime() {
return getRuntimeCapture().defaultRuntime;
}
import {
createBrowserProgram as createBrowserProgramShared,
getBrowserCliRuntime,
getBrowserCliRuntimeCapture,
} from "./browser-cli-test-helpers.js";
const mocks = vi.hoisted(() => ({
callBrowserRequest: vi.fn(async (..._args: unknown[]) => ({ ok: true })),
@@ -29,11 +19,11 @@ vi.mock("./browser-cli-resize.js", () => ({
runBrowserResizeWithOutput: mocks.runBrowserResizeWithOutput,
}));
vi.mock("../runtime.js", async () => {
const { createCliRuntimeCapture } = await import("./test-runtime-capture.js");
runtimeState.capture ??= createCliRuntimeCapture();
return { defaultRuntime: runtimeState.capture.defaultRuntime };
});
vi.mock(
"../runtime.js",
async () =>
await (await import("./browser-cli-test-helpers.js")).createBrowserCliRuntimeMockModule(),
);
describe("browser state option collisions", () => {
const createStateProgram = ({ withGatewayUrl = false } = {}) => {
@@ -64,8 +54,8 @@ describe("browser state option collisions", () => {
beforeEach(() => {
mocks.callBrowserRequest.mockClear();
mocks.runBrowserResizeWithOutput.mockClear();
getRuntimeCapture().resetRuntimeCapture();
getRuntime().exit.mockImplementation(() => {});
getBrowserCliRuntimeCapture().resetRuntimeCapture();
getBrowserCliRuntime().exit.mockImplementation(() => {});
});
it("forwards parent-captured --target-id on `browser cookies set`", async () => {
@@ -145,37 +135,39 @@ describe("browser state option collisions", () => {
await runBrowserCommand(["set", "offline", "maybe"]);
expect(mocks.callBrowserRequest).not.toHaveBeenCalled();
expect(getRuntime().error).toHaveBeenCalledWith(expect.stringContaining("Expected on|off"));
expect(getRuntime().exit).toHaveBeenCalledWith(1);
expect(getBrowserCliRuntime().error).toHaveBeenCalledWith(
expect.stringContaining("Expected on|off"),
);
expect(getBrowserCliRuntime().exit).toHaveBeenCalledWith(1);
});
it("errors when set media receives an invalid value", async () => {
await runBrowserCommand(["set", "media", "sepia"]);
expect(mocks.callBrowserRequest).not.toHaveBeenCalled();
expect(getRuntime().error).toHaveBeenCalledWith(
expect(getBrowserCliRuntime().error).toHaveBeenCalledWith(
expect.stringContaining("Expected dark|light|none"),
);
expect(getRuntime().exit).toHaveBeenCalledWith(1);
expect(getBrowserCliRuntime().exit).toHaveBeenCalledWith(1);
});
it("errors when headers JSON is missing", async () => {
await runBrowserCommand(["set", "headers"]);
expect(mocks.callBrowserRequest).not.toHaveBeenCalled();
expect(getRuntime().error).toHaveBeenCalledWith(
expect(getBrowserCliRuntime().error).toHaveBeenCalledWith(
expect.stringContaining("Missing headers JSON"),
);
expect(getRuntime().exit).toHaveBeenCalledWith(1);
expect(getBrowserCliRuntime().exit).toHaveBeenCalledWith(1);
});
it("errors when headers JSON is not an object", async () => {
await runBrowserCommand(["set", "headers", "--json", "[]"]);
expect(mocks.callBrowserRequest).not.toHaveBeenCalled();
expect(getRuntime().error).toHaveBeenCalledWith(
expect(getBrowserCliRuntime().error).toHaveBeenCalledWith(
expect.stringContaining("Headers JSON must be a JSON object"),
);
expect(getRuntime().exit).toHaveBeenCalledWith(1);
expect(getBrowserCliRuntime().exit).toHaveBeenCalledWith(1);
});
});

View File

@@ -1,5 +1,7 @@
import { Command } from "commander";
import type { BrowserParentOpts } from "./browser-cli-shared.js";
import { createCliRuntimeCapture } from "./test-runtime-capture.js";
import type { CliRuntimeCapture } from "./test-runtime-capture.js";
export function createBrowserProgram(params?: { withGatewayUrl?: boolean }): {
program: Command;
@@ -17,3 +19,37 @@ export function createBrowserProgram(params?: { withGatewayUrl?: boolean }): {
const parentOpts = (cmd: Command) => cmd.parent?.opts?.() as BrowserParentOpts;
return { program, browser, parentOpts };
}
const browserCliRuntimeState = { capture: null as CliRuntimeCapture | null };
export function getBrowserCliRuntimeCapture(): CliRuntimeCapture {
if (!browserCliRuntimeState.capture) {
throw new Error("runtime capture not initialized");
}
return browserCliRuntimeState.capture;
}
export function getBrowserCliRuntime() {
return getBrowserCliRuntimeCapture().defaultRuntime;
}
export async function mockBrowserCliDefaultRuntime() {
browserCliRuntimeState.capture ??= createCliRuntimeCapture();
return { defaultRuntime: browserCliRuntimeState.capture.defaultRuntime };
}
export async function runCommandWithRuntimeMock(
_runtime: unknown,
action: () => Promise<void>,
onError: (err: unknown) => void,
) {
return await action().catch(onError);
}
export async function createBrowserCliUtilsMockModule() {
return { runCommandWithRuntime: runCommandWithRuntimeMock };
}
export async function createBrowserCliRuntimeMockModule() {
return await mockBrowserCliDefaultRuntime();
}

View File

@@ -45,6 +45,78 @@ vi.mock("@clack/prompts", () => ({
const { registerSecretsCli } = await import("./secrets-cli.js");
function createManualSecretsPlan() {
return {
version: 1,
protocolVersion: 1,
generatedAt: "2026-02-26T00:00:00.000Z",
generatedBy: "manual",
targets: [],
};
}
function createConfigureInteractiveResult(options?: {
targets?: unknown[];
changed?: boolean;
resolvabilityComplete?: boolean;
}) {
return {
plan: {
version: 1,
protocolVersion: 1,
generatedAt: "2026-02-26T00:00:00.000Z",
generatedBy: "openclaw secrets configure",
targets: options?.targets ?? [],
},
preflight: {
mode: "dry-run" as const,
changed: options?.changed ?? false,
changedFiles: options?.changed ? ["/tmp/openclaw.json"] : [],
checks: {
resolvability: true,
resolvabilityComplete: options?.resolvabilityComplete ?? true,
},
refsChecked: 0,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
},
};
}
function createSecretsApplyResult(options?: {
mode?: "dry-run" | "write";
changed?: boolean;
resolvabilityComplete?: boolean;
}) {
return {
mode: options?.mode ?? "dry-run",
changed: options?.changed ?? false,
changedFiles: options?.changed ? ["/tmp/openclaw.json"] : [],
checks: {
resolvability: true,
resolvabilityComplete: options?.resolvabilityComplete ?? true,
},
refsChecked: 0,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
};
}
async function withPlanFile(run: (planPath: string) => Promise<void>) {
const planPath = path.join(
os.tmpdir(),
`openclaw-secrets-cli-test-${Date.now()}-${Math.random().toString(16).slice(2)}.json`,
);
await fs.writeFile(planPath, `${JSON.stringify(createManualSecretsPlan())}\n`, "utf8");
try {
await run(planPath);
} finally {
await fs.rm(planPath, { force: true });
}
}
describe("secrets CLI", () => {
const createProgram = () => {
const program = new Command();
@@ -142,12 +214,9 @@ describe("secrets CLI", () => {
});
it("runs secrets configure then apply when confirmed", async () => {
runSecretsConfigureInteractive.mockResolvedValue({
plan: {
version: 1,
protocolVersion: 1,
generatedAt: "2026-02-26T00:00:00.000Z",
generatedBy: "openclaw secrets configure",
runSecretsConfigureInteractive.mockResolvedValue(
createConfigureInteractiveResult({
changed: true,
targets: [
{
type: "skills.entries.apiKey",
@@ -160,35 +229,10 @@ describe("secrets CLI", () => {
},
},
],
},
preflight: {
mode: "dry-run",
changed: true,
changedFiles: ["/tmp/openclaw.json"],
checks: {
resolvability: true,
resolvabilityComplete: true,
},
refsChecked: 1,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
},
});
}),
);
confirm.mockResolvedValue(true);
runSecretsApply.mockResolvedValue({
mode: "write",
changed: true,
changedFiles: ["/tmp/openclaw.json"],
checks: {
resolvability: true,
resolvabilityComplete: true,
},
refsChecked: 1,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
});
runSecretsApply.mockResolvedValue(createSecretsApplyResult({ mode: "write", changed: true }));
await createProgram().parseAsync(["secrets", "configure"], { from: "user" });
expect(runSecretsConfigureInteractive).toHaveBeenCalled();
@@ -209,28 +253,7 @@ describe("secrets CLI", () => {
});
it("forwards --agent to secrets configure", async () => {
runSecretsConfigureInteractive.mockResolvedValue({
plan: {
version: 1,
protocolVersion: 1,
generatedAt: "2026-02-26T00:00:00.000Z",
generatedBy: "openclaw secrets configure",
targets: [],
},
preflight: {
mode: "dry-run",
changed: false,
changedFiles: [],
checks: {
resolvability: true,
resolvabilityComplete: true,
},
refsChecked: 0,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
},
});
runSecretsConfigureInteractive.mockResolvedValue(createConfigureInteractiveResult());
confirm.mockResolvedValue(false);
await createProgram().parseAsync(["secrets", "configure", "--agent", "ops"], { from: "user" });
@@ -243,154 +266,57 @@ describe("secrets CLI", () => {
});
it("forwards --allow-exec to secrets apply dry-run", async () => {
const planPath = path.join(
os.tmpdir(),
`openclaw-secrets-cli-test-${Date.now()}-${Math.random().toString(16).slice(2)}.json`,
);
await fs.writeFile(
planPath,
`${JSON.stringify({
version: 1,
protocolVersion: 1,
generatedAt: new Date().toISOString(),
generatedBy: "manual",
targets: [],
})}\n`,
"utf8",
);
runSecretsApply.mockResolvedValue({
mode: "dry-run",
changed: false,
changedFiles: [],
checks: {
resolvability: true,
resolvabilityComplete: true,
},
refsChecked: 0,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
});
await withPlanFile(async (planPath) => {
runSecretsApply.mockResolvedValue(createSecretsApplyResult());
await createProgram().parseAsync(
["secrets", "apply", "--from", planPath, "--dry-run", "--allow-exec"],
{
from: "user",
},
);
expect(runSecretsApply).toHaveBeenCalledWith(
expect.objectContaining({
write: false,
allowExec: true,
}),
);
await fs.rm(planPath, { force: true });
await createProgram().parseAsync(
["secrets", "apply", "--from", planPath, "--dry-run", "--allow-exec"],
{
from: "user",
},
);
expect(runSecretsApply).toHaveBeenCalledWith(
expect.objectContaining({
write: false,
allowExec: true,
}),
);
});
});
it("forwards --allow-exec to secrets apply write mode", async () => {
const planPath = path.join(
os.tmpdir(),
`openclaw-secrets-cli-test-${Date.now()}-${Math.random().toString(16).slice(2)}.json`,
);
await fs.writeFile(
planPath,
`${JSON.stringify({
version: 1,
protocolVersion: 1,
generatedAt: new Date().toISOString(),
generatedBy: "manual",
targets: [],
})}\n`,
"utf8",
);
runSecretsApply.mockResolvedValue({
mode: "write",
changed: false,
changedFiles: [],
checks: {
resolvability: true,
resolvabilityComplete: true,
},
refsChecked: 0,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
});
await withPlanFile(async (planPath) => {
runSecretsApply.mockResolvedValue(createSecretsApplyResult({ mode: "write" }));
await createProgram().parseAsync(["secrets", "apply", "--from", planPath, "--allow-exec"], {
from: "user",
await createProgram().parseAsync(["secrets", "apply", "--from", planPath, "--allow-exec"], {
from: "user",
});
expect(runSecretsApply).toHaveBeenCalledWith(
expect.objectContaining({
write: true,
allowExec: true,
}),
);
});
expect(runSecretsApply).toHaveBeenCalledWith(
expect.objectContaining({
write: true,
allowExec: true,
}),
);
await fs.rm(planPath, { force: true });
});
it("does not print skipped-exec note when apply dry-run skippedExecRefs is zero", async () => {
const planPath = path.join(
os.tmpdir(),
`openclaw-secrets-cli-test-${Date.now()}-${Math.random().toString(16).slice(2)}.json`,
);
await fs.writeFile(
planPath,
`${JSON.stringify({
version: 1,
protocolVersion: 1,
generatedAt: new Date().toISOString(),
generatedBy: "manual",
targets: [],
})}\n`,
"utf8",
);
runSecretsApply.mockResolvedValue({
mode: "dry-run",
changed: false,
changedFiles: [],
checks: {
resolvability: true,
resolvabilityComplete: false,
},
refsChecked: 0,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
});
await withPlanFile(async (planPath) => {
runSecretsApply.mockResolvedValue(createSecretsApplyResult({ resolvabilityComplete: false }));
await createProgram().parseAsync(["secrets", "apply", "--from", planPath, "--dry-run"], {
from: "user",
await createProgram().parseAsync(["secrets", "apply", "--from", planPath, "--dry-run"], {
from: "user",
});
expect(runtimeLogs.some((line) => line.includes("Secrets apply dry-run note: skipped"))).toBe(
false,
);
});
expect(runtimeLogs.some((line) => line.includes("Secrets apply dry-run note: skipped"))).toBe(
false,
);
await fs.rm(planPath, { force: true });
});
it("does not print skipped-exec note when configure preflight skippedExecRefs is zero", async () => {
runSecretsConfigureInteractive.mockResolvedValue({
plan: {
version: 1,
protocolVersion: 1,
generatedAt: "2026-02-26T00:00:00.000Z",
generatedBy: "openclaw secrets configure",
targets: [],
},
preflight: {
mode: "dry-run",
changed: false,
changedFiles: [],
checks: {
resolvability: true,
resolvabilityComplete: false,
},
refsChecked: 0,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
},
});
runSecretsConfigureInteractive.mockResolvedValue(
createConfigureInteractiveResult({ resolvabilityComplete: false }),
);
confirm.mockResolvedValue(false);
await createProgram().parseAsync(["secrets", "configure"], { from: "user" });
@@ -398,41 +324,8 @@ describe("secrets CLI", () => {
});
it("forwards --allow-exec to configure preflight and apply", async () => {
runSecretsConfigureInteractive.mockResolvedValue({
plan: {
version: 1,
protocolVersion: 1,
generatedAt: "2026-02-26T00:00:00.000Z",
generatedBy: "openclaw secrets configure",
targets: [],
},
preflight: {
mode: "dry-run",
changed: false,
changedFiles: [],
checks: {
resolvability: true,
resolvabilityComplete: true,
},
refsChecked: 0,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
},
});
runSecretsApply.mockResolvedValue({
mode: "write",
changed: false,
changedFiles: [],
checks: {
resolvability: true,
resolvabilityComplete: true,
},
refsChecked: 0,
skippedExecRefs: 0,
warningCount: 0,
warnings: [],
});
runSecretsConfigureInteractive.mockResolvedValue(createConfigureInteractiveResult());
runSecretsApply.mockResolvedValue(createSecretsApplyResult({ mode: "write" }));
await createProgram().parseAsync(["secrets", "configure", "--apply", "--yes", "--allow-exec"], {
from: "user",

View File

@@ -45,6 +45,22 @@ function createProgram() {
return program;
}
function primeDeepAuditConfig(sourceConfig = { gateway: { mode: "local" } }) {
loadConfig.mockReturnValue(sourceConfig);
resolveCommandSecretRefsViaGateway.mockResolvedValue({
resolvedConfig: sourceConfig,
diagnostics: [],
targetStatesByPath: {},
hadUnresolvedTargets: false,
});
runSecurityAudit.mockResolvedValue({
ts: 0,
summary: { critical: 0, warn: 0, info: 0 },
findings: [],
});
return sourceConfig;
}
describe("security CLI", () => {
beforeEach(() => {
resetRuntimeCapture();
@@ -131,27 +147,31 @@ describe("security CLI", () => {
]);
});
it("forwards --token to deep probe auth without altering command-level resolver mode", async () => {
const sourceConfig = { gateway: { mode: "local" } };
loadConfig.mockReturnValue(sourceConfig);
resolveCommandSecretRefsViaGateway.mockResolvedValue({
resolvedConfig: sourceConfig,
diagnostics: [],
targetStatesByPath: {},
hadUnresolvedTargets: false,
});
runSecurityAudit.mockResolvedValue({
ts: 0,
summary: { critical: 0, warn: 0, info: 0 },
findings: [],
});
await createProgram().parseAsync(
["security", "audit", "--deep", "--token", "explicit-token", "--json"],
{
from: "user",
it.each([
{
title: "forwards --token to deep probe auth without altering command-level resolver mode",
argv: ["--token", "explicit-token"],
deepProbeAuth: { token: "explicit-token" },
},
{
title: "forwards --password to deep probe auth without altering command-level resolver mode",
argv: ["--password", "explicit-password"],
deepProbeAuth: { password: "explicit-password" },
},
{
title: "forwards both --token and --password to deep probe auth",
argv: ["--token", "explicit-token", "--password", "explicit-password"],
deepProbeAuth: {
token: "explicit-token",
password: "explicit-password",
},
);
},
])("$title", async ({ argv, deepProbeAuth }) => {
primeDeepAuditConfig();
await createProgram().parseAsync(["security", "audit", "--deep", ...argv, "--json"], {
from: "user",
});
expect(resolveCommandSecretRefsViaGateway).toHaveBeenCalledWith(
expect.objectContaining({
@@ -161,84 +181,7 @@ describe("security CLI", () => {
expect(runSecurityAudit).toHaveBeenCalledWith(
expect.objectContaining({
deep: true,
deepProbeAuth: { token: "explicit-token" },
}),
);
});
it("forwards --password to deep probe auth without altering command-level resolver mode", async () => {
const sourceConfig = { gateway: { mode: "local" } };
loadConfig.mockReturnValue(sourceConfig);
resolveCommandSecretRefsViaGateway.mockResolvedValue({
resolvedConfig: sourceConfig,
diagnostics: [],
targetStatesByPath: {},
hadUnresolvedTargets: false,
});
runSecurityAudit.mockResolvedValue({
ts: 0,
summary: { critical: 0, warn: 0, info: 0 },
findings: [],
});
await createProgram().parseAsync(
["security", "audit", "--deep", "--password", "explicit-password", "--json"],
{
from: "user",
},
);
expect(resolveCommandSecretRefsViaGateway).toHaveBeenCalledWith(
expect.objectContaining({
mode: "read_only_status",
}),
);
expect(runSecurityAudit).toHaveBeenCalledWith(
expect.objectContaining({
deep: true,
deepProbeAuth: { password: "explicit-password" },
}),
);
});
it("forwards both --token and --password to deep probe auth", async () => {
const sourceConfig = { gateway: { mode: "local" } };
loadConfig.mockReturnValue(sourceConfig);
resolveCommandSecretRefsViaGateway.mockResolvedValue({
resolvedConfig: sourceConfig,
diagnostics: [],
targetStatesByPath: {},
hadUnresolvedTargets: false,
});
runSecurityAudit.mockResolvedValue({
ts: 0,
summary: { critical: 0, warn: 0, info: 0 },
findings: [],
});
await createProgram().parseAsync(
[
"security",
"audit",
"--deep",
"--token",
"explicit-token",
"--password",
"explicit-password",
"--json",
],
{
from: "user",
},
);
expect(runSecurityAudit).toHaveBeenCalledWith(
expect.objectContaining({
deep: true,
deepProbeAuth: {
token: "explicit-token",
password: "explicit-password",
},
deepProbeAuth,
}),
);
});