mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-19 17:11:42 -06:00
dd2083c7ec
* fix: add timeout to waitForWaConnection to prevent indefinite hangs If Baileys fails to emit a 'connection.update' event with either 'open' or 'close' status (e.g. due to network issues or internal errors), the waitForWaConnection promise hangs forever, blocking the entire monitor loop. Add a configurable timeout (default 60s) that rejects the promise and cleans up the event listener if no connection state is received in time. The timeout is backward-compatible as an optional parameter with a sensible default. * test: add coverage for waitForWaConnection timeout path - Test that promise rejects with descriptive error after timeout - Test that event listener is cleaned up after timeout - Test that timer is cleared when connection opens before timeout * fix: default timeoutMs to 0 to preserve QR login behavior The 60s default broke the QR login flow in login-qr.ts, which calls waitForWaConnection without a timeout and expects to wait up to 3 minutes while the user scans. Change the default to 0 (wait forever, matching original behavior) and pass the 60s timeout explicitly at the monitor callsite where it's actually needed. * fix: bound whatsapp connection startup waits * fix: align web channel wait contract * fix: retry whatsapp setup timeouts * fix: satisfy whatsapp status lint * fix: preserve whatsapp wait compatibility --------- Co-authored-by: MMMMSSSS8899 <praelovk@gmail.com>
85 lines
3.2 KiB
TypeScript
85 lines
3.2 KiB
TypeScript
// Runtime web-channel plugin tests cover web channel plugin activation and runtime behavior.
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
afterEach(() => {
|
|
vi.doUnmock("./runtime-plugin-boundary.js");
|
|
vi.resetModules();
|
|
});
|
|
|
|
describe("runtime web channel plugin", () => {
|
|
it("resolves the default auth dir through the light runtime on each call", async () => {
|
|
let authDir = "/tmp/openclaw-default-auth";
|
|
const resolveDefaultWebAuthDir = vi.fn(() => authDir);
|
|
|
|
vi.doMock("./runtime-plugin-boundary.js", () => ({
|
|
loadPluginBoundaryModule: () => ({ resolveDefaultWebAuthDir }),
|
|
resolvePluginRuntimeModulePath: () => "/tmp/light-runtime-api.js",
|
|
resolvePluginRuntimeRecordByEntryBaseNames: () => ({
|
|
origin: "bundled",
|
|
source: "test",
|
|
}),
|
|
}));
|
|
|
|
const { resolveWebChannelAuthDir } = await import("./runtime-web-channel-plugin.js");
|
|
|
|
expect(resolveWebChannelAuthDir()).toBe("/tmp/openclaw-default-auth");
|
|
authDir = "/tmp/openclaw-profile-auth";
|
|
expect(resolveWebChannelAuthDir()).toBe("/tmp/openclaw-profile-auth");
|
|
expect(resolveDefaultWebAuthDir).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it("falls back to the older WhatsApp light runtime auth dir export", async () => {
|
|
vi.doMock("./runtime-plugin-boundary.js", () => ({
|
|
loadPluginBoundaryModule: () => ({ WA_WEB_AUTH_DIR: "/tmp/openclaw-legacy-auth" }),
|
|
resolvePluginRuntimeModulePath: () => "/tmp/light-runtime-api.js",
|
|
resolvePluginRuntimeRecordByEntryBaseNames: () => ({
|
|
origin: "external",
|
|
source: "test",
|
|
}),
|
|
}));
|
|
|
|
const { resolveWebChannelAuthDir } = await import("./runtime-web-channel-plugin.js");
|
|
|
|
expect(resolveWebChannelAuthDir()).toBe("/tmp/openclaw-legacy-auth");
|
|
});
|
|
|
|
it("rejects non-string legacy auth dir exports", async () => {
|
|
vi.doMock("./runtime-plugin-boundary.js", () => ({
|
|
loadPluginBoundaryModule: () => ({
|
|
WA_WEB_AUTH_DIR: Object("/tmp/openclaw-string-object-auth"),
|
|
}),
|
|
resolvePluginRuntimeModulePath: () => "/tmp/light-runtime-api.js",
|
|
resolvePluginRuntimeRecordByEntryBaseNames: () => ({
|
|
origin: "external",
|
|
source: "test",
|
|
}),
|
|
}));
|
|
|
|
const { resolveWebChannelAuthDir } = await import("./runtime-web-channel-plugin.js");
|
|
|
|
expect(() => resolveWebChannelAuthDir()).toThrow(
|
|
"web channel plugin runtime is missing export 'resolveDefaultWebAuthDir'",
|
|
);
|
|
});
|
|
|
|
it("forwards the explicit connection wait policy to the heavy runtime", async () => {
|
|
const waitForWaConnection = vi.fn().mockResolvedValue(undefined);
|
|
const sock = { id: "socket" };
|
|
|
|
vi.doMock("./runtime-plugin-boundary.js", () => ({
|
|
loadPluginBoundaryModule: () => ({ waitForWaConnection }),
|
|
resolvePluginRuntimeModulePath: () => "/tmp/runtime-api.js",
|
|
resolvePluginRuntimeRecordByEntryBaseNames: () => ({
|
|
origin: "bundled",
|
|
source: "test",
|
|
}),
|
|
}));
|
|
|
|
const { waitForWebChannelConnection } = await import("./runtime-web-channel-plugin.js");
|
|
|
|
await waitForWebChannelConnection(sock, { timeoutMs: 12_345 });
|
|
|
|
expect(waitForWaConnection).toHaveBeenCalledWith(sock, { timeoutMs: 12_345 });
|
|
});
|
|
});
|