mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-14 19:40:40 +00:00
90 lines
2.6 KiB
TypeScript
90 lines
2.6 KiB
TypeScript
import crypto from "node:crypto";
|
|
import fs from "node:fs/promises";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { setLoggerOverride } from "../logging.js";
|
|
import {
|
|
createWebListenerFactoryCapture,
|
|
installWebAutoReplyTestHomeHooks,
|
|
installWebAutoReplyUnitTestHooks,
|
|
} from "./auto-reply.test-harness.js";
|
|
import { monitorWebChannel } from "./auto-reply/monitor.js";
|
|
|
|
installWebAutoReplyTestHomeHooks();
|
|
|
|
describe("web auto-reply monitor logging", () => {
|
|
installWebAutoReplyUnitTestHooks();
|
|
|
|
it("emits heartbeat logs with connection metadata", async () => {
|
|
vi.useFakeTimers();
|
|
const logPath = `/tmp/openclaw-heartbeat-${crypto.randomUUID()}.log`;
|
|
setLoggerOverride({ level: "trace", file: logPath });
|
|
|
|
const runtime = {
|
|
log: vi.fn(),
|
|
error: vi.fn(),
|
|
exit: vi.fn(),
|
|
};
|
|
|
|
const controller = new AbortController();
|
|
const listenerFactory = vi.fn(async () => {
|
|
const onClose = new Promise<void>(() => {
|
|
// never resolves; abort will short-circuit
|
|
});
|
|
return { close: vi.fn(), onClose };
|
|
});
|
|
|
|
const run = monitorWebChannel(
|
|
false,
|
|
listenerFactory as never,
|
|
true,
|
|
async () => ({ text: "ok" }),
|
|
runtime as never,
|
|
controller.signal,
|
|
{
|
|
heartbeatSeconds: 1,
|
|
reconnect: { initialMs: 5, maxMs: 5, maxAttempts: 1, factor: 1.1 },
|
|
},
|
|
);
|
|
|
|
await vi.advanceTimersByTimeAsync(1_000);
|
|
controller.abort();
|
|
await vi.runAllTimersAsync();
|
|
await run.catch(() => {});
|
|
|
|
const content = await fs.readFile(logPath, "utf-8");
|
|
expect(content).toMatch(/web-heartbeat/);
|
|
expect(content).toMatch(/connectionId/);
|
|
expect(content).toMatch(/messagesHandled/);
|
|
});
|
|
|
|
it("logs outbound replies to file", async () => {
|
|
const logPath = `/tmp/openclaw-log-test-${crypto.randomUUID()}.log`;
|
|
setLoggerOverride({ level: "trace", file: logPath });
|
|
|
|
const capture = createWebListenerFactoryCapture();
|
|
|
|
const resolver = vi.fn().mockResolvedValue({ text: "auto" });
|
|
await monitorWebChannel(false, capture.listenerFactory as never, false, resolver as never);
|
|
const capturedOnMessage = capture.getOnMessage();
|
|
expect(capturedOnMessage).toBeDefined();
|
|
|
|
await capturedOnMessage?.({
|
|
body: "hello",
|
|
from: "+1",
|
|
conversationId: "+1",
|
|
to: "+2",
|
|
accountId: "default",
|
|
chatType: "direct",
|
|
chatId: "+1",
|
|
id: "msg1",
|
|
sendComposing: vi.fn(),
|
|
reply: vi.fn(),
|
|
sendMedia: vi.fn(),
|
|
});
|
|
|
|
const content = await fs.readFile(logPath, "utf-8");
|
|
expect(content).toMatch(/web-auto-reply/);
|
|
expect(content).toMatch(/auto/);
|
|
});
|
|
});
|