diff --git a/src/config/sessions.test.ts b/src/config/sessions.test.ts index 33c9a5d10..dcab9cb14 100644 --- a/src/config/sessions.test.ts +++ b/src/config/sessions.test.ts @@ -1,6 +1,6 @@ +import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import fs from "node:fs/promises"; import { describe, expect, it } from "vitest"; import { diff --git a/src/gateway/server.test.ts b/src/gateway/server.test.ts index 0aa2bd101..847aa3cdf 100644 --- a/src/gateway/server.test.ts +++ b/src/gateway/server.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; +import { type AddressInfo, createServer } from "node:net"; import os from "node:os"; import path from "node:path"; -import { type AddressInfo, createServer } from "node:net"; import { describe, expect, test, vi } from "vitest"; import { WebSocket } from "ws"; import { agentCommand } from "../commands/agent.js"; diff --git a/src/infra/gateway-lock.ts b/src/infra/gateway-lock.ts index a959c17d2..f77c7fcf0 100644 --- a/src/infra/gateway-lock.ts +++ b/src/infra/gateway-lock.ts @@ -1,5 +1,8 @@ export class GatewayLockError extends Error { - constructor(message: string, public readonly cause?: unknown) { + constructor( + message: string, + public readonly cause?: unknown, + ) { super(message); this.name = "GatewayLockError"; } diff --git a/src/web/auto-reply.test.ts b/src/web/auto-reply.test.ts index 1e7cd5386..fc48794bb 100644 --- a/src/web/auto-reply.test.ts +++ b/src/web/auto-reply.test.ts @@ -5,7 +5,7 @@ import os from "node:os"; import path from "node:path"; import sharp from "sharp"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; - +import { getReplyFromConfig } from "../auto-reply/reply.js"; import type { ClawdisConfig } from "../config/config.js"; import { resetLogger, setLoggerOverride } from "../logging.js"; import * as commandQueue from "../process/command-queue.js"; @@ -18,7 +18,6 @@ import { runWebHeartbeatOnce, stripHeartbeatToken, } from "./auto-reply.js"; -import { getReplyFromConfig } from "../auto-reply/reply.js"; import type { sendMessageWhatsApp } from "./outbound.js"; import { resetBaileysMocks, @@ -565,48 +564,52 @@ describe("web auto-reply", () => { await run; }); - it("stops after hitting max reconnect attempts", { timeout: 20000 }, async () => { - const closeResolvers: Array<() => void> = []; - const sleep = vi.fn(async () => {}); - const listenerFactory = vi.fn(async () => { - const onClose = new Promise((res) => closeResolvers.push(res)); - return { close: vi.fn(), onClose }; - }); - const runtime = { - log: vi.fn(), - error: vi.fn(), - exit: vi.fn(), - }; + it( + "stops after hitting max reconnect attempts", + { timeout: 20000 }, + async () => { + const closeResolvers: Array<() => void> = []; + const sleep = vi.fn(async () => {}); + const listenerFactory = vi.fn(async () => { + const onClose = new Promise((res) => closeResolvers.push(res)); + return { close: vi.fn(), onClose }; + }); + const runtime = { + log: vi.fn(), + error: vi.fn(), + exit: vi.fn(), + }; - const run = monitorWebProvider( - false, - listenerFactory, - true, - async () => ({ text: "ok" }), - runtime as never, - undefined, - { - heartbeatSeconds: 1, - reconnect: { initialMs: 5, maxMs: 5, maxAttempts: 2, factor: 1.1 }, - sleep, - }, - ); + const run = monitorWebProvider( + false, + listenerFactory, + true, + async () => ({ text: "ok" }), + runtime as never, + undefined, + { + heartbeatSeconds: 1, + reconnect: { initialMs: 5, maxMs: 5, maxAttempts: 2, factor: 1.1 }, + sleep, + }, + ); - await Promise.resolve(); - expect(listenerFactory).toHaveBeenCalledTimes(1); + await Promise.resolve(); + expect(listenerFactory).toHaveBeenCalledTimes(1); - closeResolvers.shift()?.(); - await new Promise((resolve) => setTimeout(resolve, 15)); - expect(listenerFactory).toHaveBeenCalledTimes(2); + closeResolvers.shift()?.(); + await new Promise((resolve) => setTimeout(resolve, 15)); + expect(listenerFactory).toHaveBeenCalledTimes(2); - closeResolvers.shift()?.(); - await new Promise((resolve) => setTimeout(resolve, 15)); - await run; + closeResolvers.shift()?.(); + await new Promise((resolve) => setTimeout(resolve, 15)); + await run; - expect(runtime.error).toHaveBeenCalledWith( - expect.stringContaining("max attempts reached"), - ); - }); + expect(runtime.error).toHaveBeenCalledWith( + expect.stringContaining("max attempts reached"), + ); + }, + ); it("skips reply heartbeat when requests are running", async () => { const tmpDir = await fs.mkdtemp( diff --git a/src/web/monitor-inbox.test.ts b/src/web/monitor-inbox.test.ts index 467615211..fa26d6850 100644 --- a/src/web/monitor-inbox.test.ts +++ b/src/web/monitor-inbox.test.ts @@ -553,59 +553,67 @@ describe("web monitor inbox", () => { await listener.close(); }); }); - it("defaults to self-only when no config is present", async () => { - // No config file => allowFrom should be derived from selfE164 - mockLoadConfig.mockReturnValue({}); +it("defaults to self-only when no config is present", async () => { + // No config file => allowFrom should be derived from selfE164 + mockLoadConfig.mockReturnValue({}); - const onMessage = vi.fn(); - const listener = await monitorWebInbox({ verbose: false, onMessage }); - const sock = await createWaSocket(); + const onMessage = vi.fn(); + const listener = await monitorWebInbox({ verbose: false, onMessage }); + const sock = await createWaSocket(); - // Message from someone else should be blocked - const upsertBlocked = { - type: "notify", - messages: [ - { - key: { id: "no-config-1", fromMe: false, remoteJid: "999@s.whatsapp.net" }, - message: { conversation: "ping" }, - messageTimestamp: 1_700_000_000, + // Message from someone else should be blocked + const upsertBlocked = { + type: "notify", + messages: [ + { + key: { + id: "no-config-1", + fromMe: false, + remoteJid: "999@s.whatsapp.net", }, - ], - }; - - sock.ev.emit("messages.upsert", upsertBlocked); - await new Promise((resolve) => setImmediate(resolve)); - expect(onMessage).not.toHaveBeenCalled(); - - // Message from self should be allowed - const upsertSelf = { - type: "notify", - messages: [ - { - key: { id: "no-config-2", fromMe: false, remoteJid: "123@s.whatsapp.net" }, - message: { conversation: "self ping" }, - messageTimestamp: 1_700_000_001, - }, - ], - }; - - sock.ev.emit("messages.upsert", upsertSelf); - await new Promise((resolve) => setImmediate(resolve)); - - expect(onMessage).toHaveBeenCalledTimes(1); - expect(onMessage).toHaveBeenCalledWith( - expect.objectContaining({ body: "self ping", from: "+123", to: "+123" }), - ); - - // Reset mock for other tests - mockLoadConfig.mockReturnValue({ - inbound: { - allowFrom: ["*"], - messagePrefix: undefined, - responsePrefix: undefined, - timestampPrefix: false, + message: { conversation: "ping" }, + messageTimestamp: 1_700_000_000, }, - }); + ], + }; - await listener.close(); + sock.ev.emit("messages.upsert", upsertBlocked); + await new Promise((resolve) => setImmediate(resolve)); + expect(onMessage).not.toHaveBeenCalled(); + + // Message from self should be allowed + const upsertSelf = { + type: "notify", + messages: [ + { + key: { + id: "no-config-2", + fromMe: false, + remoteJid: "123@s.whatsapp.net", + }, + message: { conversation: "self ping" }, + messageTimestamp: 1_700_000_001, + }, + ], + }; + + sock.ev.emit("messages.upsert", upsertSelf); + await new Promise((resolve) => setImmediate(resolve)); + + expect(onMessage).toHaveBeenCalledTimes(1); + expect(onMessage).toHaveBeenCalledWith( + expect.objectContaining({ body: "self ping", from: "+123", to: "+123" }), + ); + + // Reset mock for other tests + mockLoadConfig.mockReturnValue({ + inbound: { + allowFrom: ["*"], + messagePrefix: undefined, + responsePrefix: undefined, + timestampPrefix: false, + }, }); + + await listener.close(); +});