diff --git a/src/gateway/call.test.ts b/src/gateway/call.test.ts index f6c5afb607a..56fb4497df7 100644 --- a/src/gateway/call.test.ts +++ b/src/gateway/call.test.ts @@ -281,18 +281,18 @@ describe("callGateway error details", () => { pickPrimaryTailnetIPv4.mockReturnValue(undefined); vi.useFakeTimers(); - let err: Error | null = null; + let errMessage = ""; const promise = callGateway({ method: "health", timeoutMs: 5 }).catch((caught) => { - err = caught as Error; + errMessage = caught instanceof Error ? caught.message : String(caught); }); await vi.advanceTimersByTimeAsync(5); await promise; - expect(err?.message).toContain("gateway timeout after 5ms"); - expect(err?.message).toContain("Gateway target: ws://127.0.0.1:18789"); - expect(err?.message).toContain("Source: local loopback"); - expect(err?.message).toContain("Bind: loopback"); + expect(errMessage).toContain("gateway timeout after 5ms"); + expect(errMessage).toContain("Gateway target: ws://127.0.0.1:18789"); + expect(errMessage).toContain("Source: local loopback"); + expect(errMessage).toContain("Bind: loopback"); }); it("does not overflow very large timeout values", async () => { @@ -304,18 +304,18 @@ describe("callGateway error details", () => { pickPrimaryTailnetIPv4.mockReturnValue(undefined); vi.useFakeTimers(); - let err: Error | null = null; + let errMessage = ""; const promise = callGateway({ method: "health", timeoutMs: 2_592_010_000 }).catch((caught) => { - err = caught as Error; + errMessage = caught instanceof Error ? caught.message : String(caught); }); await vi.advanceTimersByTimeAsync(1); - expect(err).toBeNull(); + expect(errMessage).toBe(""); lastClientOptions?.onClose?.(1006, ""); await promise; - expect(err?.message).toContain("gateway closed (1006"); + expect(errMessage).toContain("gateway closed (1006"); }); it("fails fast when remote mode is missing remote url", async () => { diff --git a/src/gateway/chat-attachments.test.ts b/src/gateway/chat-attachments.test.ts index e13d0ee19dd..6b4c20310f2 100644 --- a/src/gateway/chat-attachments.test.ts +++ b/src/gateway/chat-attachments.test.ts @@ -55,7 +55,7 @@ describe("buildMessageWithAttachments", () => { expect(() => buildMessageWithAttachments("x", [att], { maxBytes: 16 })).toThrow( /exceeds size limit/i, ); - const base64Calls = fromSpy.mock.calls.filter((args) => args[1] === "base64"); + const base64Calls = fromSpy.mock.calls.filter((args) => (args as unknown[])[1] === "base64"); expect(base64Calls).toHaveLength(0); fromSpy.mockRestore(); }); @@ -114,7 +114,7 @@ describe("parseMessageWithAttachments", () => { { maxBytes: 16, log: { warn: () => {} } }, ), ).rejects.toThrow(/exceeds size limit/i); - const base64Calls = fromSpy.mock.calls.filter((args) => args[1] === "base64"); + const base64Calls = fromSpy.mock.calls.filter((args) => (args as unknown[])[1] === "base64"); expect(base64Calls).toHaveLength(0); fromSpy.mockRestore(); }); diff --git a/src/gateway/server.agent.gateway-server-agent-a.e2e.test.ts b/src/gateway/server.agent.gateway-server-agent-a.e2e.test.ts index 1e599be4f89..922dcb575c0 100644 --- a/src/gateway/server.agent.gateway-server-agent-a.e2e.test.ts +++ b/src/gateway/server.agent.gateway-server-agent-a.e2e.test.ts @@ -57,7 +57,8 @@ async function setTestSessionStore(params: { } function latestAgentCall(): AgentCommandCall { - return vi.mocked(agentCommand).mock.calls.at(-1)?.[0] as AgentCommandCall; + const calls = vi.mocked(agentCommand).mock.calls as unknown as Array<[unknown]>; + return calls.at(-1)?.[0] as AgentCommandCall; } async function runMainAgentDeliveryWithSession(params: { diff --git a/src/gateway/server.cron.e2e.test.ts b/src/gateway/server.cron.e2e.test.ts index cd05a3b96ad..61b73983982 100644 --- a/src/gateway/server.cron.e2e.test.ts +++ b/src/gateway/server.cron.e2e.test.ts @@ -503,7 +503,7 @@ describe("gateway server cron", () => { expect(notifyRunRes.ok).toBe(true); await waitForCondition(() => fetchMock.mock.calls.length === 1, 5000); - const [notifyUrl, notifyInit] = fetchMock.mock.calls[0] as [ + const [notifyUrl, notifyInit] = fetchMock.mock.calls[0] as unknown as [ string, { method?: string; @@ -527,7 +527,7 @@ describe("gateway server cron", () => { ); expect(legacyRunRes.ok).toBe(true); await waitForCondition(() => fetchMock.mock.calls.length === 2, 5000); - const [legacyUrl, legacyInit] = fetchMock.mock.calls[1] as [ + const [legacyUrl, legacyInit] = fetchMock.mock.calls[1] as unknown as [ string, { method?: string; diff --git a/src/gateway/server.models-voicewake-misc.e2e.test.ts b/src/gateway/server.models-voicewake-misc.e2e.test.ts index 896edca232c..33d1b142355 100644 --- a/src/gateway/server.models-voicewake-misc.e2e.test.ts +++ b/src/gateway/server.models-voicewake-misc.e2e.test.ts @@ -52,13 +52,16 @@ const whatsappOutbound: ChannelOutboundAdapter = { if (!deps?.sendWhatsApp) { throw new Error("Missing sendWhatsApp dep"); } - return { channel: "whatsapp", ...(await deps.sendWhatsApp(to, text, {})) }; + return { channel: "whatsapp", ...(await deps.sendWhatsApp(to, text, { verbose: false })) }; }, sendMedia: async ({ deps, to, text, mediaUrl }) => { if (!deps?.sendWhatsApp) { throw new Error("Missing sendWhatsApp dep"); } - return { channel: "whatsapp", ...(await deps.sendWhatsApp(to, text, { mediaUrl })) }; + return { + channel: "whatsapp", + ...(await deps.sendWhatsApp(to, text, { verbose: false, mediaUrl })), + }; }, }; @@ -134,11 +137,10 @@ describe("gateway server models + voicewake", () => { expect(initial.ok).toBe(true); expect(initial.payload?.triggers).toEqual(["openclaw", "claude", "computer"]); - const changedP = onceMessage<{ - type: "event"; - event: string; - payload?: unknown; - }>(ws, (o) => o.type === "event" && o.event === "voicewake.changed"); + const changedP = onceMessage( + ws, + (o) => o.type === "event" && o.event === "voicewake.changed", + ); const setRes = await rpcReq<{ triggers: string[] }>(ws, "voicewake.set", { triggers: [" hi ", "", "there"], @@ -146,7 +148,7 @@ describe("gateway server models + voicewake", () => { expect(setRes.ok).toBe(true); expect(setRes.payload?.triggers).toEqual(["hi", "there"]); - const changed = await changedP; + const changed = (await changedP) as { event?: string; payload?: unknown }; expect(changed.event).toBe("voicewake.changed"); expect((changed.payload as { triggers?: unknown } | undefined)?.triggers).toEqual([ "hi", @@ -173,7 +175,7 @@ describe("gateway server models + voicewake", () => { const nodeWs = new WebSocket(`ws://127.0.0.1:${port}`); await new Promise((resolve) => nodeWs.once("open", resolve)); - const firstEventP = onceMessage<{ type: "event"; event: string; payload?: unknown }>( + const firstEventP = onceMessage( nodeWs, (o) => o.type === "event" && o.event === "voicewake.changed", ); @@ -187,7 +189,7 @@ describe("gateway server models + voicewake", () => { }, }); - const first = await firstEventP; + const first = (await firstEventP) as { event?: string; payload?: unknown }; expect(first.event).toBe("voicewake.changed"); expect((first.payload as { triggers?: unknown } | undefined)?.triggers).toEqual([ "openclaw", @@ -195,7 +197,7 @@ describe("gateway server models + voicewake", () => { "computer", ]); - const broadcastP = onceMessage<{ type: "event"; event: string; payload?: unknown }>( + const broadcastP = onceMessage( nodeWs, (o) => o.type === "event" && o.event === "voicewake.changed", ); @@ -204,7 +206,7 @@ describe("gateway server models + voicewake", () => { }); expect(setRes.ok).toBe(true); - const broadcast = await broadcastP; + const broadcast = (await broadcastP) as { event?: string; payload?: unknown }; expect(broadcast.event).toBe("voicewake.changed"); expect((broadcast.payload as { triggers?: unknown } | undefined)?.triggers).toEqual([ "openclaw", diff --git a/src/gateway/server.roles-allowlist-update.e2e.test.ts b/src/gateway/server.roles-allowlist-update.e2e.test.ts index 99f40a8c0ed..665648bf1b6 100644 --- a/src/gateway/server.roles-allowlist-update.e2e.test.ts +++ b/src/gateway/server.roles-allowlist-update.e2e.test.ts @@ -131,10 +131,7 @@ describe("gateway update.run", () => { }, }), ); - const res = await onceMessage<{ ok: boolean; payload?: unknown }>( - ws, - (o) => o.type === "res" && o.id === id, - ); + const res = await onceMessage(ws, (o) => o.type === "res" && o.id === id); expect(res.ok).toBe(true); await waitForSignal(() => sigusr1.mock.calls.length > 0); @@ -173,10 +170,7 @@ describe("gateway update.run", () => { }, }), ); - const res = await onceMessage<{ ok: boolean; payload?: unknown }>( - ws, - (o) => o.type === "res" && o.id === id, - ); + const res = await onceMessage(ws, (o) => o.type === "res" && o.id === id); expect(res.ok).toBe(true); expect(updateMock).toHaveBeenCalledOnce(); } finally { diff --git a/src/gateway/server.sessions-send.e2e.test.ts b/src/gateway/server.sessions-send.e2e.test.ts index dd72f28995d..fc1d6e574e8 100644 --- a/src/gateway/server.sessions-send.e2e.test.ts +++ b/src/gateway/server.sessions-send.e2e.test.ts @@ -1,6 +1,6 @@ import fs from "node:fs/promises"; import path from "node:path"; -import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; +import { afterAll, beforeAll, describe, expect, it, type Mock } from "vitest"; import { resolveSessionTranscriptPath } from "../config/sessions.js"; import { emitAgentEvent } from "../infra/agent-events.js"; import { captureEnv } from "../test-utils/env.js"; @@ -37,8 +37,8 @@ afterAll(async () => { describe("sessions_send gateway loopback", () => { it("returns reply when lifecycle ends before agent.wait", async () => { - const spy = vi.mocked(agentCommand); - spy.mockImplementation(async (opts) => { + const spy = agentCommand as unknown as Mock<(opts: unknown) => Promise>; + spy.mockImplementation(async (opts: unknown) => { const params = opts as { sessionId?: string; runId?: string; @@ -124,8 +124,8 @@ describe("sessions_send label lookup", () => { "utf-8", ); - const spy = vi.mocked(agentCommand); - spy.mockImplementation(async (opts) => { + const spy = agentCommand as unknown as Mock<(opts: unknown) => Promise>; + spy.mockImplementation(async (opts: unknown) => { const params = opts as { sessionId?: string; runId?: string; diff --git a/src/gateway/server.sessions.gateway-server-sessions-a.e2e.test.ts b/src/gateway/server.sessions.gateway-server-sessions-a.e2e.test.ts index b8af9d89324..4e5a4c82166 100644 --- a/src/gateway/server.sessions.gateway-server-sessions-a.e2e.test.ts +++ b/src/gateway/server.sessions.gateway-server-sessions-a.e2e.test.ts @@ -103,7 +103,9 @@ function expectActiveRunCleanup( requesterSessionKey, }); expect(sessionCleanupMocks.clearSessionQueues).toHaveBeenCalledTimes(1); - const clearedKeys = sessionCleanupMocks.clearSessionQueues.mock.calls[0]?.[0] as string[]; + const clearedKeys = ( + sessionCleanupMocks.clearSessionQueues.mock.calls as unknown as Array<[string[]]> + )[0]?.[0]; expect(clearedKeys).toEqual(expect.arrayContaining(expectedQueueKeys)); expect(embeddedRunMock.abortCalls).toEqual([sessionId]); expect(embeddedRunMock.waitCalls).toEqual([sessionId]); @@ -656,7 +658,12 @@ describe("gateway server sessions", () => { }); expect(reset.ok).toBe(true); expect(sessionHookMocks.triggerInternalHook).toHaveBeenCalledTimes(1); - const [event] = sessionHookMocks.triggerInternalHook.mock.calls[0] ?? []; + const event = ( + sessionHookMocks.triggerInternalHook.mock.calls as unknown as Array<[unknown]> + )[0]?.[0] as { context?: { previousSessionEntry?: unknown } } | undefined; + if (!event) { + throw new Error("expected session hook event"); + } expect(event).toMatchObject({ type: "command", action: "new", @@ -665,7 +672,7 @@ describe("gateway server sessions", () => { commandSource: "gateway:sessions.reset", }, }); - expect(event.context.previousSessionEntry).toMatchObject({ sessionId: "sess-main" }); + expect(event.context?.previousSessionEntry).toMatchObject({ sessionId: "sess-main" }); ws.close(); }); diff --git a/src/infra/fetch.test.ts b/src/infra/fetch.test.ts index b1ce6f383eb..b46d75e427d 100644 --- a/src/infra/fetch.test.ts +++ b/src/infra/fetch.test.ts @@ -17,7 +17,7 @@ function createForeignSignalHarness() { } }, removeEventListener, - } as AbortSignal; + } as unknown as AbortSignal; return { fakeSignal, @@ -38,7 +38,7 @@ describe("wrapFetchWithAbortSignal", () => { await wrapped("https://example.com", { method: "POST", body: "hi" }); - expect(seenInit?.duplex).toBe("half"); + expect((seenInit as (RequestInit & { duplex?: string }) | undefined)?.duplex).toBe("half"); }); it("converts foreign abort signals to native controllers", async () => { @@ -119,7 +119,7 @@ describe("wrapFetchWithAbortSignal", () => { aborted: false, addEventListener: (_event: string, _handler: () => void) => {}, removeEventListener, - } as AbortSignal; + } as unknown as AbortSignal; await expect(wrapped("https://example.com", { signal: fakeSignal })).rejects.toBe(fetchError); expect(removeEventListener).toHaveBeenCalledOnce(); @@ -141,7 +141,7 @@ describe("wrapFetchWithAbortSignal", () => { aborted: false, addEventListener: (_event: string, _handler: () => void) => {}, removeEventListener, - } as AbortSignal; + } as unknown as AbortSignal; expect(() => wrapped("https://example.com", { signal: fakeSignal })).toThrow(syncError); expect(removeEventListener).toHaveBeenCalledOnce(); @@ -157,7 +157,7 @@ describe("wrapFetchWithAbortSignal", () => { aborted: true, addEventListener, removeEventListener, - } as AbortSignal; + } as unknown as AbortSignal; await wrapped("https://example.com", { signal: fakeSignal }); @@ -177,7 +177,7 @@ describe("wrapFetchWithAbortSignal", () => { const preconnectSpy = vi.fn(function (this: unknown) { return this; }); - const fetchImpl = vi.fn(async () => ({ ok: true }) as Response) as typeof fetch & { + const fetchImpl = vi.fn(async () => ({ ok: true }) as Response) as unknown as typeof fetch & { preconnect: (url: string, init?: { credentials?: RequestCredentials }) => unknown; }; fetchImpl.preconnect = preconnectSpy; diff --git a/src/infra/http-body.test.ts b/src/infra/http-body.test.ts index e3548b1eaba..d5599c623be 100644 --- a/src/infra/http-body.test.ts +++ b/src/infra/http-body.test.ts @@ -9,19 +9,21 @@ import { readRequestBodyWithLimit, } from "./http-body.js"; +type MockIncomingMessage = IncomingMessage & { + destroyed?: boolean; + destroy: (error?: Error) => MockIncomingMessage; + __unhandledDestroyError?: unknown; +}; + function createMockRequest(params: { chunks?: string[]; headers?: Record; emitEnd?: boolean; -}): IncomingMessage { - const req = new EventEmitter() as IncomingMessage & { - destroyed?: boolean; - destroy: (error?: Error) => void; - __unhandledDestroyError?: unknown; - }; +}): MockIncomingMessage { + const req = new EventEmitter() as MockIncomingMessage; req.destroyed = false; req.headers = params.headers ?? {}; - req.destroy = (error?: Error) => { + req.destroy = ((error?: Error) => { req.destroyed = true; if (error) { // Simulate Node's async 'error' emission on destroy(err). If no listener is @@ -34,7 +36,8 @@ function createMockRequest(params: { } }); } - }; + return req; + }) as MockIncomingMessage["destroy"]; if (params.chunks) { void Promise.resolve().then(() => { diff --git a/src/infra/net/ssrf.pinning.test.ts b/src/infra/net/ssrf.pinning.test.ts index 48bb51c3486..f04c55b8ab9 100644 --- a/src/infra/net/ssrf.pinning.test.ts +++ b/src/infra/net/ssrf.pinning.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it, vi } from "vitest"; import { createPinnedLookup, + type LookupFn, resolvePinnedHostname, resolvePinnedHostnameWithPolicy, } from "./ssrf.js"; @@ -10,7 +11,7 @@ describe("ssrf pinning", () => { const lookup = vi.fn(async () => [ { address: "93.184.216.34", family: 4 }, { address: "93.184.216.35", family: 4 }, - ]); + ]) as unknown as LookupFn; const pinned = await resolvePinnedHostname("Example.com.", lookup); expect(pinned.hostname).toBe("example.com"); @@ -44,7 +45,7 @@ describe("ssrf pinning", () => { }); it("rejects private DNS results", async () => { - const lookup = vi.fn(async () => [{ address: "10.0.0.8", family: 4 }]); + const lookup = vi.fn(async () => [{ address: "10.0.0.8", family: 4 }]) as unknown as LookupFn; await expect(resolvePinnedHostname("example.com", lookup)).rejects.toThrow(/private|internal/i); }); @@ -52,7 +53,7 @@ describe("ssrf pinning", () => { const fallback = vi.fn((host: string, options?: unknown, callback?: unknown) => { const cb = typeof options === "function" ? options : (callback as () => void); (cb as (err: null, address: string, family: number) => void)(null, "1.2.3.4", 4); - }); + }) as unknown as Parameters[0]["fallback"]; const lookup = createPinnedLookup({ hostname: "example.com", addresses: ["93.184.216.34"], @@ -74,7 +75,9 @@ describe("ssrf pinning", () => { }); it("enforces hostname allowlist when configured", async () => { - const lookup = vi.fn(async () => [{ address: "93.184.216.34", family: 4 }]); + const lookup = vi.fn(async () => [ + { address: "93.184.216.34", family: 4 }, + ]) as unknown as LookupFn; await expect( resolvePinnedHostnameWithPolicy("api.example.com", { @@ -86,7 +89,9 @@ describe("ssrf pinning", () => { }); it("supports wildcard hostname allowlist patterns", async () => { - const lookup = vi.fn(async () => [{ address: "93.184.216.34", family: 4 }]); + const lookup = vi.fn(async () => [ + { address: "93.184.216.34", family: 4 }, + ]) as unknown as LookupFn; await expect( resolvePinnedHostnameWithPolicy("assets.example.com", { diff --git a/src/infra/outbound/message-action-runner.test.ts b/src/infra/outbound/message-action-runner.test.ts index f7ce41c7567..710e347be80 100644 --- a/src/infra/outbound/message-action-runner.test.ts +++ b/src/infra/outbound/message-action-runner.test.ts @@ -864,10 +864,15 @@ describe("runMessageAction accountId defaults", () => { }); expect(handleAction).toHaveBeenCalled(); - const ctx = handleAction.mock.calls[0]?.[0] as { - accountId?: string | null; - params: Record; - }; + const ctx = (handleAction.mock.calls as unknown as Array<[unknown]>)[0]?.[0] as + | { + accountId?: string | null; + params: Record; + } + | undefined; + if (!ctx) { + throw new Error("expected action context"); + } expect(ctx.accountId).toBe("ops"); expect(ctx.params.accountId).toBe("ops"); }); diff --git a/src/infra/session-cost-usage.test.ts b/src/infra/session-cost-usage.test.ts index 671dcb583af..71c417bd818 100644 --- a/src/infra/session-cost-usage.test.ts +++ b/src/infra/session-cost-usage.test.ts @@ -96,7 +96,7 @@ describe("session cost usage", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const originalState = process.env.OPENCLAW_STATE_DIR; process.env.OPENCLAW_STATE_DIR = root; @@ -275,7 +275,11 @@ describe("session cost usage", () => { try { const summary = await loadSessionCostSummary({ sessionId: "sess-worker-1", - sessionEntry: { sessionFile: workerSessionFile } as { sessionFile: string }, + sessionEntry: { + sessionId: "sess-worker-1", + updatedAt: Date.now(), + sessionFile: workerSessionFile, + }, agentId: "worker1", }); expect(summary?.totalTokens).toBe(18); @@ -317,7 +321,11 @@ describe("session cost usage", () => { try { const timeseries = await loadSessionUsageTimeSeries({ sessionId: "sess-worker-2", - sessionEntry: { sessionFile: workerSessionFile } as { sessionFile: string }, + sessionEntry: { + sessionId: "sess-worker-2", + updatedAt: Date.now(), + sessionFile: workerSessionFile, + }, agentId: "worker2", }); expect(timeseries?.points.length).toBe(1); @@ -357,7 +365,11 @@ describe("session cost usage", () => { try { const logs = await loadSessionLogs({ sessionId: "sess-worker-3", - sessionEntry: { sessionFile: workerSessionFile } as { sessionFile: string }, + sessionEntry: { + sessionId: "sess-worker-3", + updatedAt: Date.now(), + sessionFile: workerSessionFile, + }, agentId: "worker3", }); expect(logs).toHaveLength(1); diff --git a/src/media/input-files.fetch-guard.test.ts b/src/media/input-files.fetch-guard.test.ts index d7a4fc8294b..f731b90c0c2 100644 --- a/src/media/input-files.fetch-guard.test.ts +++ b/src/media/input-files.fetch-guard.test.ts @@ -73,7 +73,7 @@ describe("base64 size guards", () => { ).rejects.toThrow("Image too large"); // Regression check: the oversize reject must happen before Buffer.from(..., "base64") allocates. - const base64Calls = fromSpy.mock.calls.filter((args) => args[1] === "base64"); + const base64Calls = fromSpy.mock.calls.filter((args) => (args as unknown[])[1] === "base64"); expect(base64Calls).toHaveLength(0); fromSpy.mockRestore(); }); @@ -97,7 +97,7 @@ describe("base64 size guards", () => { }), ).rejects.toThrow("File too large"); - const base64Calls = fromSpy.mock.calls.filter((args) => args[1] === "base64"); + const base64Calls = fromSpy.mock.calls.filter((args) => (args as unknown[])[1] === "base64"); expect(base64Calls).toHaveLength(0); fromSpy.mockRestore(); }); diff --git a/src/memory/manager.watcher-config.test.ts b/src/memory/manager.watcher-config.test.ts index 8f45f256d25..a51f577685f 100644 --- a/src/memory/manager.watcher-config.test.ts +++ b/src/memory/manager.watcher-config.test.ts @@ -82,7 +82,10 @@ describe("memory watcher config", () => { manager = result.manager; expect(watchMock).toHaveBeenCalledTimes(1); - const [watchedPaths, options] = watchMock.mock.calls[0] as [string[], Record]; + const [watchedPaths, options] = watchMock.mock.calls[0] as unknown as [ + string[], + Record, + ]; expect(watchedPaths).toEqual( expect.arrayContaining([ path.join(workspaceDir, "MEMORY.md"), diff --git a/src/plugins/wired-hooks-compaction.test.ts b/src/plugins/wired-hooks-compaction.test.ts index fc5b6b83f89..3c9a0deddef 100644 --- a/src/plugins/wired-hooks-compaction.test.ts +++ b/src/plugins/wired-hooks-compaction.test.ts @@ -47,8 +47,11 @@ describe("compaction hook wiring", () => { expect(hookMocks.runner.runBeforeCompaction).toHaveBeenCalledTimes(1); - const [event] = hookMocks.runner.runBeforeCompaction.mock.calls[0]; - expect(event.messageCount).toBe(3); + const beforeCalls = hookMocks.runner.runBeforeCompaction.mock.calls as unknown as Array< + [unknown] + >; + const event = beforeCalls[0]?.[0] as { messageCount?: number } | undefined; + expect(event?.messageCount).toBe(3); }); it("calls runAfterCompaction when willRetry is false", async () => { @@ -75,9 +78,14 @@ describe("compaction hook wiring", () => { expect(hookMocks.runner.runAfterCompaction).toHaveBeenCalledTimes(1); - const [event] = hookMocks.runner.runAfterCompaction.mock.calls[0]; - expect(event.messageCount).toBe(2); - expect(event.compactedCount).toBe(1); + const afterCalls = hookMocks.runner.runAfterCompaction.mock.calls as unknown as Array< + [unknown] + >; + const event = afterCalls[0]?.[0] as + | { messageCount?: number; compactedCount?: number } + | undefined; + expect(event?.messageCount).toBe(2); + expect(event?.compactedCount).toBe(1); }); it("does not call runAfterCompaction when willRetry is true", async () => {