fix(whatsapp): capture login outcome output

This commit is contained in:
Vincent Koc
2026-05-04 01:18:39 -07:00
parent a1304c92c6
commit 071db2ca69
3 changed files with 15 additions and 5 deletions

View File

@@ -64,6 +64,7 @@ Docs: https://docs.openclaw.ai
- Control UI/Talk: stop and clear failed realtime Talk sessions when dismissing runtime error banners, so the next Talk click starts a fresh session instead of only stopping the stale one. Thanks @vincentkoc.
- Control UI/Talk: retry from a failed realtime Talk session on the next Talk click instead of requiring a separate stale-session stop click first. Thanks @vincentkoc.
- Canvas host: preserve the Gateway TLS scheme in browser canvas host URLs and startup mount logs, so direct HTTPS gateways do not advertise insecure canvas links. Thanks @vincentkoc.
- WhatsApp/login: route login success and failure messages through the injected runtime, so setup/onboarding surfaces capture all login output instead of only the QR. Thanks @vincentkoc.
- Google Chat: create an isolated Google auth transport per auth client, so google-auth-library interceptor mutations do not accumulate across webhook verification and access-token clients. Thanks @vincentkoc.
- Doctor/plugins: remove orphaned managed npm copies of bundled `@openclaw/*` plugins during `doctor --fix`, so stale package manifests cannot shadow the current bundled plugin config schema.
- Control UI/performance: cap long-task and long-animation-frame diagnostics in the shared event log, so slow-render telemetry does not evict gateway/plugin events from the Debug and Overview views. Thanks @vincentkoc.

View File

@@ -111,6 +111,9 @@ describe("loginWeb coverage", () => {
expect(createWaSocketMock).toHaveBeenCalledTimes(2);
const firstSock = await createWaSocketMock.mock.results[0]?.value;
expect(firstSock.ws.close).toHaveBeenCalled();
expect(runtime.log).toHaveBeenCalledWith(
expect.stringContaining("Linked after restart; web session ready."),
);
vi.runAllTimers();
const secondSock = await createWaSocketMock.mock.results[1]?.value;
expect(secondSock.ws.close).toHaveBeenCalled();
@@ -150,9 +153,11 @@ describe("loginWeb coverage", () => {
output: { statusCode: 401 },
});
await expect(loginWeb(false, waitForWaConnectionMock as never)).rejects.toThrow(
const runtime: RuntimeEnv = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
await expect(loginWeb(false, waitForWaConnectionMock as never, runtime)).rejects.toThrow(
/cache cleared/i,
);
expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("session is logged out"));
expect(rmMock).toHaveBeenCalledWith(testState.authDir, {
recursive: true,
force: true,
@@ -161,9 +166,13 @@ describe("loginWeb coverage", () => {
it("formats and rethrows generic errors", async () => {
waitForWaConnectionMock.mockRejectedValueOnce(new Error("boom"));
await expect(loginWeb(false, waitForWaConnectionMock as never)).rejects.toThrow(
const runtime: RuntimeEnv = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
await expect(loginWeb(false, waitForWaConnectionMock as never, runtime)).rejects.toThrow(
"formatted:Error: boom",
);
expect(runtime.error).toHaveBeenCalledWith(
expect.stringContaining("WhatsApp Web connection ended before fully opening."),
);
expect(formatErrorMock).toHaveBeenCalled();
});
});

View File

@@ -51,7 +51,7 @@ export async function loginWeb(
},
});
if (result.outcome === "connected") {
console.log(
runtime.log(
success(
result.restarted
? "✅ Linked after restart; web session ready."
@@ -64,7 +64,7 @@ export async function loginWeb(
}
if (result.outcome === "logged-out") {
console.error(
runtime.error(
danger(
`WhatsApp reported the session is logged out. Cleared cached web session; please rerun ${formatCliCommand("openclaw channels login")} and scan the QR again.`,
),
@@ -74,7 +74,7 @@ export async function loginWeb(
});
}
console.error(danger(`WhatsApp Web connection ended before fully opening. ${result.message}`));
runtime.error(danger(`WhatsApp Web connection ended before fully opening. ${result.message}`));
throw new Error(result.message, { cause: result.error });
} finally {
// Let Baileys flush any final events before closing the socket.