


























@@ -239,6 +239,31 @@ function createAdvancedFinalizeArgs(params: AdvancedFinalizeArgs = {}) {
239239};
240240}
241241242+function requireMockArg<T>(mock: ReturnType<typeof vi.fn>, callIndex = 0, argIndex = 0): T {
243+const call = mock.mock.calls[callIndex];
244+if (!call) {
245+throw new Error(`expected mock call ${callIndex}`);
246+}
247+return call[argIndex] as T;
248+}
249+250+function expectNoteContains(
251+prompter: ReturnType<typeof buildWizardPrompter>,
252+expected: string,
253+title: string,
254+): void {
255+const calls = vi.mocked(prompter.note).mock.calls;
256+expect(calls.some((call) => String(call[0]).includes(expected) && call[1] === title)).toBe(true);
257+}
258+259+function expectNoteTitleNotCalled(
260+prompter: ReturnType<typeof buildWizardPrompter>,
261+title: string,
262+): void {
263+const calls = vi.mocked(prompter.note).mock.calls;
264+expect(calls.every((call) => call[1] !== title)).toBe(true);
265+}
266+242267describe("finalizeSetupWizard", () => {
243268beforeEach(() => {
244269launchTuiCli.mockClear();
@@ -339,12 +364,9 @@ describe("finalizeSetupWizard", () => {
339364}
340365}
341366342-expect(probeGatewayReachable).toHaveBeenCalledWith(
343-expect.objectContaining({
344-url: "ws://127.0.0.1:18789",
345-password: "resolved-gateway-password", // pragma: allowlist secret
346-}),
347-);
367+const probeParams = requireMockArg<{ url?: string; password?: string }>(probeGatewayReachable);
368+expect(probeParams.url).toBe("ws://127.0.0.1:18789");
369+expect(probeParams.password).toBe("resolved-gateway-password"); // pragma: allowlist secret
348370expect(launchTuiCli).toHaveBeenCalledWith({
349371local: true,
350372deliver: false,
@@ -547,8 +569,9 @@ describe("finalizeSetupWizard", () => {
547569}),
548570);
549571550-expect(prompter.note).toHaveBeenCalledWith(
551-expect.stringContaining("selected but unavailable under the current plugin policy"),
572+expectNoteContains(
573+prompter,
574+"selected but unavailable under the current plugin policy",
552575"Web search",
553576);
554577expect(resolveExistingKey).not.toHaveBeenCalled();
@@ -573,8 +596,9 @@ describe("finalizeSetupWizard", () => {
573596574597await finalizeSetupWizard(createAdvancedFinalizeArgs({ prompter }));
575598576-expect(prompter.note).toHaveBeenCalledWith(
577-expect.stringContaining("Web search is available via Perplexity Search (auto-detected)."),
599+expectNoteContains(
600+prompter,
601+"Web search is available via Perplexity Search (auto-detected).",
578602"Web search",
579603);
580604});
@@ -602,10 +626,9 @@ describe("finalizeSetupWizard", () => {
602626}),
603627);
604628605-expect(prompter.note).toHaveBeenCalledWith(
606-expect.stringContaining(
607-"Web search is enabled, so your agent can look things up online when needed.",
608-),
629+expectNoteContains(
630+prompter,
631+"Web search is enabled, so your agent can look things up online when needed.",
609632"Web search",
610633);
611634});
@@ -645,22 +668,18 @@ describe("finalizeSetupWizard", () => {
645668runtime: createRuntime(),
646669});
647670648-expect(healthCommand).toHaveBeenCalledWith(
649-expect.objectContaining({
650-json: false,
651-timeoutMs: 10_000,
652-token: "session-token",
653-config: expect.objectContaining({
654-gateway: expect.objectContaining({
655-auth: expect.objectContaining({
656-mode: "token",
657-token: "session-token",
658-}),
659-}),
660-}),
661-}),
662-expect.any(Object),
663-);
671+const healthArgs = requireMockArg<{
672+json?: boolean;
673+timeoutMs?: number;
674+token?: string;
675+config?: OpenClawConfig;
676+}>(healthCommand);
677+expect(healthArgs.json).toBe(false);
678+expect(healthArgs.timeoutMs).toBe(10_000);
679+expect(healthArgs.token).toBe("session-token");
680+expect(healthArgs.config?.gateway?.auth?.mode).toBe("token");
681+expect(healthArgs.config?.gateway?.auth?.token).toBe("session-token");
682+expect(requireMockArg<unknown>(healthCommand, 0, 1)).toBeTypeOf("object");
664683});
665684666685it("uses the resolved setup password for health checks", async () => {
@@ -703,29 +722,27 @@ describe("finalizeSetupWizard", () => {
703722runtime: createRuntime(),
704723});
705724706-expect(waitForGatewayReachable).toHaveBeenCalledWith(
707-expect.objectContaining({
708-url: "ws://127.0.0.1:18789",
709-token: undefined,
710-password: "session-password",
711-}),
712-);
713-expect(healthCommand).toHaveBeenCalledWith(
714-expect.objectContaining({
715-json: false,
716-timeoutMs: 10_000,
717-token: undefined,
718-password: "session-password",
719-config: expect.objectContaining({
720-gateway: expect.objectContaining({
721-auth: expect.objectContaining({
722-mode: "password",
723-}),
724-}),
725-}),
726-}),
727-expect.any(Object),
728-);
725+const waitArgs = requireMockArg<{
726+url?: string;
727+token?: string;
728+password?: string;
729+}>(waitForGatewayReachable);
730+expect(waitArgs.url).toBe("ws://127.0.0.1:18789");
731+expect(waitArgs.token).toBeUndefined();
732+expect(waitArgs.password).toBe("session-password");
733+const healthArgs = requireMockArg<{
734+json?: boolean;
735+timeoutMs?: number;
736+token?: string;
737+password?: string;
738+config?: OpenClawConfig;
739+}>(healthCommand);
740+expect(healthArgs.json).toBe(false);
741+expect(healthArgs.timeoutMs).toBe(10_000);
742+expect(healthArgs.token).toBeUndefined();
743+expect(healthArgs.password).toBe("session-password");
744+expect(healthArgs.config?.gateway?.auth?.mode).toBe("password");
745+expect(requireMockArg<unknown>(healthCommand, 0, 1)).toBeTypeOf("object");
729746});
730747731748it("shows actionable gateway guidance instead of a hard error in no-daemon onboarding", async () => {
@@ -765,15 +782,12 @@ describe("finalizeSetupWizard", () => {
765782});
766783767784expect(runtime.error).not.toHaveBeenCalledWith("health failed");
768-expect(prompter.note).toHaveBeenCalledWith(
769-expect.stringContaining("Setup was run without Gateway service install"),
770-"Gateway",
771-);
772-expect(prompter.note).not.toHaveBeenCalledWith(expect.any(String), "Dashboard ready");
785+expectNoteContains(prompter, "Setup was run without Gateway service install", "Gateway");
786+expectNoteTitleNotCalled(prompter, "Dashboard ready");
773787});
774788775789it("does not show a Codex native search summary when web search is globally disabled", async () => {
776-const note = vi.fn(async () => {});
790+const note = vi.fn(async (_message: string, _title?: string) => {});
777791const prompter = buildWizardPrompter({
778792 note,
779793select: vi.fn(async () => "later") as never,
@@ -816,9 +830,6 @@ describe("finalizeSetupWizard", () => {
816830runtime: createRuntime(),
817831});
818832819-expect(note).not.toHaveBeenCalledWith(
820-expect.stringContaining("Codex native search:"),
821-"Codex native search",
822-);
833+expect(note.mock.calls.every((call) => call[1] !== "Codex native search")).toBe(true);
823834});
824835});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。