mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
chore: Fix types in tests 27/N.
This commit is contained in:
@@ -94,6 +94,8 @@ const baseParams = () => ({
|
||||
textLimit: 4000,
|
||||
ackReactionScope: "group-mentions",
|
||||
mediaMaxBytes: 1,
|
||||
threadHistoryScope: "thread" as const,
|
||||
threadInheritParent: false,
|
||||
removeAckAfterReply: false,
|
||||
});
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ describe("usage-format", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
} as unknown as OpenClawConfig;
|
||||
|
||||
const cost = resolveModelCostConfig({
|
||||
provider: "test",
|
||||
|
||||
@@ -158,6 +158,7 @@ describe("broadcast groups", () => {
|
||||
from: "+1000",
|
||||
conversationId: "+1000",
|
||||
to: "+2000",
|
||||
accountId: "default",
|
||||
body: "hello",
|
||||
timestamp: Date.now(),
|
||||
chatType: "direct",
|
||||
|
||||
@@ -11,6 +11,18 @@ import {
|
||||
|
||||
installWebAutoReplyTestHomeHooks();
|
||||
|
||||
function createMockListener() {
|
||||
return {
|
||||
close: vi.fn(async () => undefined),
|
||||
onClose: new Promise<import("./inbound.js").WebListenerCloseReason>(() => {}),
|
||||
signalClose: vi.fn(),
|
||||
sendMessage: vi.fn(async () => ({ messageId: "msg-1" })),
|
||||
sendPoll: vi.fn(async () => ({ messageId: "poll-1" })),
|
||||
sendReaction: vi.fn(async () => undefined),
|
||||
sendComposingTo: vi.fn(async () => undefined),
|
||||
};
|
||||
}
|
||||
|
||||
describe("typing controller idle", () => {
|
||||
installWebAutoReplyUnitTestHooks();
|
||||
|
||||
@@ -53,11 +65,12 @@ describe("typing controller idle", () => {
|
||||
timestamp: Date.now(),
|
||||
chatType: "direct",
|
||||
chatId: "direct:+1000",
|
||||
accountId: "default",
|
||||
sendComposing,
|
||||
reply,
|
||||
sendMedia,
|
||||
});
|
||||
return { close: vi.fn().mockResolvedValue(undefined) };
|
||||
return createMockListener();
|
||||
},
|
||||
false,
|
||||
replyResolver,
|
||||
|
||||
@@ -16,6 +16,18 @@ describe("web auto-reply", () => {
|
||||
installWebAutoReplyUnitTestHooks({ pinDns: true });
|
||||
type ListenerFactory = NonNullable<Parameters<typeof monitorWebChannel>[1]>;
|
||||
|
||||
function createMockListener() {
|
||||
return {
|
||||
close: vi.fn(async () => undefined),
|
||||
onClose: new Promise<import("./inbound.js").WebListenerCloseReason>(() => {}),
|
||||
signalClose: vi.fn(),
|
||||
sendMessage: vi.fn(async () => ({ messageId: "msg-1" })),
|
||||
sendPoll: vi.fn(async () => ({ messageId: "poll-1" })),
|
||||
sendReaction: vi.fn(async () => undefined),
|
||||
sendComposingTo: vi.fn(async () => undefined),
|
||||
};
|
||||
}
|
||||
|
||||
async function setupSingleInboundMessage(params: {
|
||||
resolverValue: { text: string; mediaUrl: string };
|
||||
sendMedia: ReturnType<typeof vi.fn>;
|
||||
@@ -28,7 +40,7 @@ describe("web auto-reply", () => {
|
||||
let capturedOnMessage: ((msg: WebInboundMessage) => Promise<void>) | undefined;
|
||||
const listenerFactory: ListenerFactory = async ({ onMessage }) => {
|
||||
capturedOnMessage = onMessage;
|
||||
return { close: vi.fn() };
|
||||
return createMockListener();
|
||||
};
|
||||
|
||||
await monitorWebChannel(false, listenerFactory, false, resolver);
|
||||
@@ -115,7 +127,7 @@ describe("web auto-reply", () => {
|
||||
let capturedOnMessage: ((msg: WebInboundMessage) => Promise<void>) | undefined;
|
||||
const listenerFactory: ListenerFactory = async ({ onMessage }) => {
|
||||
capturedOnMessage = onMessage;
|
||||
return { close: vi.fn() };
|
||||
return createMockListener();
|
||||
};
|
||||
|
||||
const big = await fmt.make(sharedRaw, { width, height });
|
||||
@@ -173,7 +185,7 @@ describe("web auto-reply", () => {
|
||||
let capturedOnMessage: ((msg: WebInboundMessage) => Promise<void>) | undefined;
|
||||
const listenerFactory: ListenerFactory = async ({ onMessage }) => {
|
||||
capturedOnMessage = onMessage;
|
||||
return { close: vi.fn() };
|
||||
return createMockListener();
|
||||
};
|
||||
|
||||
const bigPng = await sharp({
|
||||
|
||||
@@ -36,7 +36,9 @@ function createHandlerForTest(opts: { cfg: OpenClawConfig; replyResolver: unknow
|
||||
groupMemberNames: new Map(),
|
||||
echoTracker: createEchoTracker({ maxItems: 10 }),
|
||||
backgroundTasks,
|
||||
replyResolver: opts.replyResolver,
|
||||
replyResolver: opts.replyResolver as Parameters<
|
||||
typeof createWebOnMessageHandler
|
||||
>[0]["replyResolver"],
|
||||
replyLogger: makeReplyLogger(),
|
||||
baseMentionConfig: buildMentionConfig(opts.cfg),
|
||||
account: {},
|
||||
@@ -74,7 +76,7 @@ function buildInboundMessage(params: {
|
||||
timestamp: params.timestamp,
|
||||
chatType: params.chatType,
|
||||
chatId: params.chatId,
|
||||
accountId: params.accountId,
|
||||
accountId: params.accountId ?? "default",
|
||||
senderE164: params.senderE164,
|
||||
senderName: params.senderName,
|
||||
selfE164: params.selfE164,
|
||||
|
||||
@@ -77,7 +77,11 @@ describe("web auto-reply monitor logging", () => {
|
||||
await capturedOnMessage?.({
|
||||
body: "hello",
|
||||
from: "+1",
|
||||
conversationId: "+1",
|
||||
to: "+2",
|
||||
accountId: "default",
|
||||
chatType: "direct",
|
||||
chatId: "+1",
|
||||
id: "msg1",
|
||||
sendComposing: vi.fn(),
|
||||
reply: vi.fn(),
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
makeSessionStore,
|
||||
setLoadConfigMock,
|
||||
} from "./auto-reply.test-harness.js";
|
||||
import type { WebInboundMessage } from "./inbound.js";
|
||||
|
||||
installWebAutoReplyTestHomeHooks();
|
||||
|
||||
@@ -19,7 +20,7 @@ function createRuntime() {
|
||||
|
||||
function startMonitorWebChannel(params: {
|
||||
monitorWebChannelFn: (...args: unknown[]) => Promise<unknown>;
|
||||
listenerFactory: (...args: unknown[]) => Promise<unknown>;
|
||||
listenerFactory: unknown;
|
||||
sleep: ReturnType<typeof vi.fn>;
|
||||
signal?: AbortSignal;
|
||||
reconnect?: { initialMs: number; maxMs: number; maxAttempts: number; factor: number };
|
||||
@@ -43,6 +44,32 @@ function startMonitorWebChannel(params: {
|
||||
return { runtime, controller, run };
|
||||
}
|
||||
|
||||
function makeInboundMessage(params: {
|
||||
body: string;
|
||||
from: string;
|
||||
to: string;
|
||||
id?: string;
|
||||
timestamp?: number;
|
||||
sendComposing: ReturnType<typeof vi.fn>;
|
||||
reply: ReturnType<typeof vi.fn>;
|
||||
sendMedia: ReturnType<typeof vi.fn>;
|
||||
}): WebInboundMessage {
|
||||
return {
|
||||
body: params.body,
|
||||
from: params.from,
|
||||
to: params.to,
|
||||
id: params.id,
|
||||
timestamp: params.timestamp,
|
||||
conversationId: params.from,
|
||||
accountId: "default",
|
||||
chatType: "direct",
|
||||
chatId: params.from,
|
||||
sendComposing: params.sendComposing as unknown as WebInboundMessage["sendComposing"],
|
||||
reply: params.reply as unknown as WebInboundMessage["reply"],
|
||||
sendMedia: params.sendMedia as unknown as WebInboundMessage["sendMedia"],
|
||||
};
|
||||
}
|
||||
|
||||
describe("web auto-reply", () => {
|
||||
installWebAutoReplyUnitTestHooks();
|
||||
|
||||
@@ -133,15 +160,17 @@ describe("web auto-reply", () => {
|
||||
|
||||
// The watchdog only needs `lastMessageAt` to be set. Don't await full message
|
||||
// processing here since it can schedule timers and become flaky under load.
|
||||
void capturedOnMessage?.({
|
||||
body: "hi",
|
||||
from: "+1",
|
||||
to: "+2",
|
||||
id: "m1",
|
||||
sendComposing,
|
||||
reply,
|
||||
sendMedia,
|
||||
});
|
||||
void capturedOnMessage?.(
|
||||
makeInboundMessage({
|
||||
body: "hi",
|
||||
from: "+1",
|
||||
to: "+2",
|
||||
id: "m1",
|
||||
sendComposing,
|
||||
reply,
|
||||
sendMedia,
|
||||
}),
|
||||
);
|
||||
|
||||
await vi.advanceTimersByTimeAsync(31 * 60 * 1000);
|
||||
await Promise.resolve();
|
||||
@@ -174,7 +203,7 @@ describe("web auto-reply", () => {
|
||||
|
||||
const run = monitorWebChannel(
|
||||
false,
|
||||
listenerFactory,
|
||||
listenerFactory as never,
|
||||
true,
|
||||
async () => ({ text: "ok" }),
|
||||
runtime as never,
|
||||
@@ -236,30 +265,34 @@ describe("web auto-reply", () => {
|
||||
session: { store: store.storePath },
|
||||
}));
|
||||
|
||||
await monitorWebChannel(false, listenerFactory, false, resolver);
|
||||
await monitorWebChannel(false, listenerFactory as never, false, resolver);
|
||||
expect(capturedOnMessage).toBeDefined();
|
||||
|
||||
// Two messages from the same sender with fixed timestamps
|
||||
await capturedOnMessage?.({
|
||||
body: "first",
|
||||
from: "+1",
|
||||
to: "+2",
|
||||
id: "m1",
|
||||
timestamp: 1735689600000, // Jan 1 2025 00:00:00 UTC
|
||||
sendComposing,
|
||||
reply,
|
||||
sendMedia,
|
||||
});
|
||||
await capturedOnMessage?.({
|
||||
body: "second",
|
||||
from: "+1",
|
||||
to: "+2",
|
||||
id: "m2",
|
||||
timestamp: 1735693200000, // Jan 1 2025 01:00:00 UTC
|
||||
sendComposing,
|
||||
reply,
|
||||
sendMedia,
|
||||
});
|
||||
await capturedOnMessage?.(
|
||||
makeInboundMessage({
|
||||
body: "first",
|
||||
from: "+1",
|
||||
to: "+2",
|
||||
id: "m1",
|
||||
timestamp: 1735689600000, // Jan 1 2025 00:00:00 UTC
|
||||
sendComposing,
|
||||
reply,
|
||||
sendMedia,
|
||||
}),
|
||||
);
|
||||
await capturedOnMessage?.(
|
||||
makeInboundMessage({
|
||||
body: "second",
|
||||
from: "+1",
|
||||
to: "+2",
|
||||
id: "m2",
|
||||
timestamp: 1735693200000, // Jan 1 2025 01:00:00 UTC
|
||||
sendComposing,
|
||||
reply,
|
||||
sendMedia,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(resolver).toHaveBeenCalledTimes(2);
|
||||
const firstArgs = resolver.mock.calls[0][0];
|
||||
|
||||
@@ -4,7 +4,7 @@ import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { resolveAgentRoute } from "../../routing/resolve-route.js";
|
||||
import { buildMentionConfig } from "./mentions.js";
|
||||
import { applyGroupGating } from "./monitor/group-gating.js";
|
||||
import { applyGroupGating, type GroupHistoryEntry } from "./monitor/group-gating.js";
|
||||
import { buildInboundLine, formatReplyContext } from "./monitor/message-line.js";
|
||||
|
||||
let sessionDir: string | undefined;
|
||||
@@ -41,7 +41,7 @@ function runGroupGating(params: {
|
||||
conversationId?: string;
|
||||
agentId?: string;
|
||||
}) {
|
||||
const groupHistories = new Map<string, unknown[]>();
|
||||
const groupHistories = new Map<string, GroupHistoryEntry[]>();
|
||||
const conversationId = params.conversationId ?? "123@g.us";
|
||||
const agentId = params.agentId ?? "main";
|
||||
const sessionKey = `agent:${agentId}:whatsapp:group:${conversationId}`;
|
||||
|
||||
@@ -112,7 +112,12 @@ describe("web inbound media saves with extension", () => {
|
||||
|
||||
it("stores image extension, extracts caption mentions, and keeps document filename", async () => {
|
||||
const onMessage = vi.fn();
|
||||
const listener = await monitorWebInbox({ verbose: false, onMessage });
|
||||
const listener = await monitorWebInbox({
|
||||
verbose: false,
|
||||
onMessage,
|
||||
accountId: "default",
|
||||
authDir: path.join(HOME, "wa-auth"),
|
||||
});
|
||||
const { createWaSocket } = await import("./session.js");
|
||||
const realSock = await (
|
||||
createWaSocket as unknown as () => Promise<{
|
||||
@@ -194,6 +199,8 @@ describe("web inbound media saves with extension", () => {
|
||||
verbose: false,
|
||||
onMessage,
|
||||
mediaMaxMb: 1,
|
||||
accountId: "default",
|
||||
authDir: path.join(HOME, "wa-auth"),
|
||||
});
|
||||
const { createWaSocket } = await import("./session.js");
|
||||
const realSock = await (
|
||||
|
||||
@@ -108,7 +108,7 @@ describe("createWebSendApi", () => {
|
||||
});
|
||||
|
||||
it("falls back to unknown messageId if Baileys result does not expose key.id", async () => {
|
||||
sendMessage.mockResolvedValueOnce("ok");
|
||||
sendMessage.mockResolvedValueOnce({ key: {} });
|
||||
const res = await api.sendMessage("+1555", "hello");
|
||||
expect(res.messageId).toBe("unknown");
|
||||
});
|
||||
|
||||
@@ -37,7 +37,9 @@ describe("web login", () => {
|
||||
});
|
||||
|
||||
it("loginWeb waits for connection and closes", async () => {
|
||||
const sock = await createWaSocket();
|
||||
const sock = await (
|
||||
createWaSocket as unknown as () => Promise<{ ws: { close: () => void } }>
|
||||
)();
|
||||
const close = vi.spyOn(sock.ws, "close");
|
||||
const waiter: typeof waitForWaConnection = vi.fn().mockResolvedValue(undefined);
|
||||
await loginWeb(false, waiter);
|
||||
|
||||
@@ -187,7 +187,7 @@ describe("web media loading", () => {
|
||||
status: 404,
|
||||
statusText: "Not Found",
|
||||
url: "https://example.com/missing.jpg",
|
||||
} as Response);
|
||||
} as unknown as Response);
|
||||
|
||||
await expect(loadWebMedia("https://example.com/missing.jpg", 1024 * 1024)).rejects.toThrow(
|
||||
/Failed to fetch media from https:\/\/example\.com\/missing\.jpg.*HTTP 404/i,
|
||||
@@ -225,7 +225,7 @@ describe("web media loading", () => {
|
||||
arrayBuffer: async () => Buffer.alloc(2048).buffer,
|
||||
headers: { get: () => "image/png" },
|
||||
status: 200,
|
||||
} as Response);
|
||||
} as unknown as Response);
|
||||
|
||||
await expect(loadWebMediaRaw("https://example.com/too-big.png", 1024)).rejects.toThrow(
|
||||
/exceeds maxBytes 1024/i,
|
||||
@@ -251,7 +251,7 @@ describe("web media loading", () => {
|
||||
},
|
||||
},
|
||||
status: 200,
|
||||
} as Response);
|
||||
} as unknown as Response);
|
||||
|
||||
const result = await loadWebMedia("https://example.com/download?id=1", 1024 * 1024);
|
||||
|
||||
@@ -274,7 +274,7 @@ describe("web media loading", () => {
|
||||
gifBytes.buffer.slice(gifBytes.byteOffset, gifBytes.byteOffset + gifBytes.byteLength),
|
||||
headers: { get: () => "image/gif" },
|
||||
status: 200,
|
||||
} as Response);
|
||||
} as unknown as Response);
|
||||
|
||||
const result = await loadWebMedia("https://example.com/animation.gif", 1024 * 1024);
|
||||
|
||||
|
||||
@@ -281,7 +281,9 @@ describe("web monitor inbox", () => {
|
||||
|
||||
expect(onMessage).toHaveBeenCalledTimes(2);
|
||||
|
||||
resolveFirst?.();
|
||||
if (typeof resolveFirst === "function") {
|
||||
resolveFirst();
|
||||
}
|
||||
await listener.close();
|
||||
});
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ describe("web session", () => {
|
||||
inFlight -= 1;
|
||||
});
|
||||
useMultiFileAuthStateMock.mockResolvedValueOnce({
|
||||
state: { creds: {}, keys: {} },
|
||||
state: { creds: {} as never, keys: {} as never },
|
||||
saveCreds,
|
||||
});
|
||||
|
||||
@@ -185,7 +185,7 @@ describe("web session", () => {
|
||||
await new Promise<void>((resolve) => setImmediate(resolve));
|
||||
expect(inFlight).toBe(1);
|
||||
|
||||
if (release) {
|
||||
if (typeof release === "function") {
|
||||
release();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user