mirror of https://github.com/openclaw/openclaw.git
150 lines
4.5 KiB
TypeScript
150 lines
4.5 KiB
TypeScript
import "./monitor-inbox.test-harness.js";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { monitorWebInbox } from "./inbound.js";
|
|
import {
|
|
DEFAULT_ACCOUNT_ID,
|
|
getAuthDir,
|
|
getSock,
|
|
installWebMonitorInboxUnitTestHooks,
|
|
} from "./monitor-inbox.test-harness.js";
|
|
|
|
describe("append upsert handling (#20952)", () => {
|
|
installWebMonitorInboxUnitTestHooks();
|
|
type InboxOnMessage = NonNullable<Parameters<typeof monitorWebInbox>[0]["onMessage"]>;
|
|
|
|
async function tick() {
|
|
await new Promise((resolve) => setImmediate(resolve));
|
|
}
|
|
|
|
async function startInboxMonitor(onMessage: InboxOnMessage) {
|
|
const listener = await monitorWebInbox({
|
|
verbose: false,
|
|
onMessage,
|
|
accountId: DEFAULT_ACCOUNT_ID,
|
|
authDir: getAuthDir(),
|
|
});
|
|
return { listener, sock: getSock() };
|
|
}
|
|
|
|
it("processes recent append messages (within 60s of connect)", async () => {
|
|
const onMessage = vi.fn(async () => {});
|
|
const { listener, sock } = await startInboxMonitor(onMessage);
|
|
|
|
// Timestamp ~5 seconds ago — recent, should be processed.
|
|
const recentTs = Math.floor(Date.now() / 1000) - 5;
|
|
sock.ev.emit("messages.upsert", {
|
|
type: "append",
|
|
messages: [
|
|
{
|
|
key: { id: "recent-1", fromMe: false, remoteJid: "120363@g.us" },
|
|
message: { conversation: "hello from group" },
|
|
messageTimestamp: recentTs,
|
|
pushName: "Tester",
|
|
},
|
|
],
|
|
});
|
|
await tick();
|
|
|
|
expect(onMessage).toHaveBeenCalledTimes(1);
|
|
|
|
await listener.close();
|
|
});
|
|
|
|
it("skips stale append messages (older than 60s before connect)", async () => {
|
|
const onMessage = vi.fn(async () => {});
|
|
const { listener, sock } = await startInboxMonitor(onMessage);
|
|
|
|
// Timestamp 5 minutes ago — stale history sync, should be skipped.
|
|
const staleTs = Math.floor(Date.now() / 1000) - 300;
|
|
sock.ev.emit("messages.upsert", {
|
|
type: "append",
|
|
messages: [
|
|
{
|
|
key: { id: "stale-1", fromMe: false, remoteJid: "120363@g.us" },
|
|
message: { conversation: "old history sync" },
|
|
messageTimestamp: staleTs,
|
|
pushName: "OldTester",
|
|
},
|
|
],
|
|
});
|
|
await tick();
|
|
|
|
expect(onMessage).not.toHaveBeenCalled();
|
|
|
|
await listener.close();
|
|
});
|
|
|
|
it("skips append messages with NaN/non-finite timestamps", async () => {
|
|
const onMessage = vi.fn(async () => {});
|
|
const { listener, sock } = await startInboxMonitor(onMessage);
|
|
|
|
// NaN timestamp should be treated as 0 (stale) and skipped.
|
|
sock.ev.emit("messages.upsert", {
|
|
type: "append",
|
|
messages: [
|
|
{
|
|
key: { id: "nan-1", fromMe: false, remoteJid: "120363@g.us" },
|
|
message: { conversation: "bad timestamp" },
|
|
messageTimestamp: NaN,
|
|
pushName: "BadTs",
|
|
},
|
|
],
|
|
});
|
|
await tick();
|
|
|
|
expect(onMessage).not.toHaveBeenCalled();
|
|
|
|
await listener.close();
|
|
});
|
|
|
|
it("handles Long-like protobuf timestamps correctly", async () => {
|
|
const onMessage = vi.fn(async () => {});
|
|
const { listener, sock } = await startInboxMonitor(onMessage);
|
|
|
|
// Baileys can deliver messageTimestamp as a Long object (from protobufjs).
|
|
// Number(longObj) calls valueOf() and returns the numeric value.
|
|
const recentTs = Math.floor(Date.now() / 1000) - 5;
|
|
const longLike = { low: recentTs, high: 0, unsigned: true, valueOf: () => recentTs };
|
|
sock.ev.emit("messages.upsert", {
|
|
type: "append",
|
|
messages: [
|
|
{
|
|
key: { id: "long-1", fromMe: false, remoteJid: "120363@g.us" },
|
|
message: { conversation: "long timestamp" },
|
|
messageTimestamp: longLike,
|
|
pushName: "LongTs",
|
|
},
|
|
],
|
|
});
|
|
await tick();
|
|
|
|
expect(onMessage).toHaveBeenCalledTimes(1);
|
|
|
|
await listener.close();
|
|
});
|
|
|
|
it("always processes notify messages regardless of timestamp", async () => {
|
|
const onMessage = vi.fn(async () => {});
|
|
const { listener, sock } = await startInboxMonitor(onMessage);
|
|
|
|
// Very old timestamp but type=notify — should always be processed.
|
|
const oldTs = Math.floor(Date.now() / 1000) - 86400;
|
|
sock.ev.emit("messages.upsert", {
|
|
type: "notify",
|
|
messages: [
|
|
{
|
|
key: { id: "notify-1", fromMe: false, remoteJid: "999@s.whatsapp.net" },
|
|
message: { conversation: "normal message" },
|
|
messageTimestamp: oldTs,
|
|
pushName: "User",
|
|
},
|
|
],
|
|
});
|
|
await tick();
|
|
|
|
expect(onMessage).toHaveBeenCalledTimes(1);
|
|
|
|
await listener.close();
|
|
});
|
|
});
|