

























@@ -1,7 +1,9 @@
11import { rmSync } from "node:fs";
22import fs from "node:fs/promises";
3+import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
34import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest";
45import { loginWeb } from "./login.js";
6+import { renderQrTerminal } from "./qr-terminal.js";
57import { createWaSocket, formatError, waitForWaConnection } from "./session.js";
6879const rmMock = vi.spyOn(fs, "rm");
@@ -63,9 +65,14 @@ vi.mock("./session.js", async () => {
6365};
6466});
656768+vi.mock("./qr-terminal.js", () => ({
69+renderQrTerminal: vi.fn(async (qr: string) => `terminal:${qr}\n`),
70+}));
71+6672const createWaSocketMock = vi.mocked(createWaSocket);
6773const waitForWaConnectionMock = vi.mocked(waitForWaConnection);
6874const formatErrorMock = vi.mocked(formatError);
75+const renderQrTerminalMock = vi.mocked(renderQrTerminal);
69767077async function flushTasks() {
7178await Promise.resolve();
@@ -94,7 +101,7 @@ describe("loginWeb coverage", () => {
94101.mockRejectedValueOnce({ error: { output: { statusCode: 515 } } })
95102.mockResolvedValueOnce(undefined);
9610397-const runtime = { log: vi.fn(), error: vi.fn() } as never;
104+const runtime: RuntimeEnv = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
98105const pendingLogin = loginWeb(false, waitForWaConnectionMock as never, runtime);
99106await flushTasks();
100107@@ -109,6 +116,35 @@ describe("loginWeb coverage", () => {
109116expect(secondSock.ws.close).toHaveBeenCalled();
110117});
111118119+it("routes QR output through runtime for initial and restart sockets", async () => {
120+waitForWaConnectionMock
121+.mockRejectedValueOnce({ error: { output: { statusCode: 515 } } })
122+.mockResolvedValueOnce(undefined);
123+124+const runtime: RuntimeEnv = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
125+await loginWeb(false, waitForWaConnectionMock as never, runtime);
126+127+expect(createWaSocketMock).toHaveBeenCalledTimes(2);
128+expect(createWaSocketMock.mock.calls[0]?.[0]).toBe(false);
129+const initialOpts = createWaSocketMock.mock.calls[0]?.[2] as
130+| { onQr?: (qr: string) => void }
131+| undefined;
132+const restartOpts = createWaSocketMock.mock.calls[1]?.[2] as
133+| { onQr?: (qr: string) => void }
134+| undefined;
135+expect(initialOpts?.onQr).toBe(restartOpts?.onQr);
136+137+initialOpts?.onQr?.("initial-qr");
138+restartOpts?.onQr?.("restart-qr");
139+await flushTasks();
140+141+expect(runtime.log).toHaveBeenCalledWith("Scan this QR in WhatsApp (Linked Devices):");
142+expect(runtime.log).toHaveBeenCalledWith("terminal:initial-qr");
143+expect(runtime.log).toHaveBeenCalledWith("terminal:restart-qr");
144+expect(renderQrTerminalMock).toHaveBeenCalledWith("initial-qr", { small: true });
145+expect(renderQrTerminalMock).toHaveBeenCalledWith("restart-qr", { small: true });
146+});
147+112148it("clears creds and throws when logged out", async () => {
113149waitForWaConnectionMock.mockRejectedValueOnce({
114150output: { statusCode: 401 },
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。