From 427372b3f93e7afaec69da5d07435139a378a05f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 11 May 2026 21:10:11 +0100 Subject: [PATCH] test: guard auto reply null helpers --- .../reply/agent-runner-execution.test.ts | 2 -- .../reply/agent-runner-payloads.test.ts | 5 ++-- .../agent-runner.runreplyagent.e2e.test.ts | 2 -- src/auto-reply/reply/commands-approve.test.ts | 2 -- src/auto-reply/reply/commands-btw.test.ts | 25 +++++++++++-------- .../reply/commands-plugins.install.test.ts | 10 +++++--- src/auto-reply/reply/commands-plugins.test.ts | 5 ++-- .../reply/commands-reset-hooks.test.ts | 10 +++++--- src/auto-reply/reply/dispatch-acp.test.ts | 5 ++-- ...et-reply-directives.target-session.test.ts | 5 ++-- ...ine-actions.skip-when-config-empty.test.ts | 2 -- src/auto-reply/reply/route-reply.test.ts | 10 +++++--- .../reply/session-hooks-context.test.ts | 5 ++-- .../reply/session-transcript-replay.test.ts | 5 ++-- 14 files changed, 51 insertions(+), 42 deletions(-) diff --git a/src/auto-reply/reply/agent-runner-execution.test.ts b/src/auto-reply/reply/agent-runner-execution.test.ts index 8105ceb1117..7dff08438cd 100644 --- a/src/auto-reply/reply/agent-runner-execution.test.ts +++ b/src/auto-reply/reply/agent-runner-execution.test.ts @@ -283,8 +283,6 @@ function createMockReplyOperation(): { } function requireRecord(value: unknown, label: string): Record { - expect(typeof value).toBe("object"); - expect(value).not.toBeNull(); if (typeof value !== "object" || value === null) { throw new Error(`${label} was not an object`); } diff --git a/src/auto-reply/reply/agent-runner-payloads.test.ts b/src/auto-reply/reply/agent-runner-payloads.test.ts index d026f1f4def..ac7d2a53f6a 100644 --- a/src/auto-reply/reply/agent-runner-payloads.test.ts +++ b/src/auto-reply/reply/agent-runner-payloads.test.ts @@ -16,8 +16,9 @@ const baseParams = { }; function expectFields(value: unknown, expected: Record): void { - expect(value).toBeTypeOf("object"); - expect(value).not.toBeNull(); + if (!value || typeof value !== "object") { + throw new Error("expected fields object"); + } const record = value as Record; for (const [key, expectedValue] of Object.entries(expected)) { expect(record[key], key).toEqual(expectedValue); diff --git a/src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts b/src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts index a060abcb42d..9d5a4ae7bdc 100644 --- a/src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts +++ b/src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts @@ -41,8 +41,6 @@ function countMatching(items: readonly T[], predicate: (item: T) => boolean): } function requireRecord(value: unknown, label: string): Record { - expect(value).toBeTypeOf("object"); - expect(value).not.toBeNull(); if (!value || typeof value !== "object" || Array.isArray(value)) { throw new Error(`expected ${label} to be an object`); } diff --git a/src/auto-reply/reply/commands-approve.test.ts b/src/auto-reply/reply/commands-approve.test.ts index 8184c011804..74f355afc72 100644 --- a/src/auto-reply/reply/commands-approve.test.ts +++ b/src/auto-reply/reply/commands-approve.test.ts @@ -26,8 +26,6 @@ vi.mock("../../globals.js", () => ({ })); function requireRecord(value: unknown, label: string): Record { - expect(value).toBeTypeOf("object"); - expect(value).not.toBeNull(); if (!value || typeof value !== "object" || Array.isArray(value)) { throw new Error(`expected ${label} to be an object`); } diff --git a/src/auto-reply/reply/commands-btw.test.ts b/src/auto-reply/reply/commands-btw.test.ts index c839e8b9a42..f9c807deb31 100644 --- a/src/auto-reply/reply/commands-btw.test.ts +++ b/src/auto-reply/reply/commands-btw.test.ts @@ -34,14 +34,16 @@ function mockCall(mock: unknown, index = 0): Array { function mockFirstObjectArg(mock: unknown): Record { const [arg] = mockCall(mock); - expect(arg).toBeTypeOf("object"); - expect(arg).not.toBeNull(); + if (!arg || typeof arg !== "object") { + throw new Error("expected first mock argument object"); + } return arg as Record; } function expectObjectFields(value: unknown, expected: Record): void { - expect(value).toBeTypeOf("object"); - expect(value).not.toBeNull(); + if (!value || typeof value !== "object") { + throw new Error("expected object fields"); + } const record = value as Record; for (const [key, expectedValue] of Object.entries(expected)) { expect(record[key], key).toEqual(expectedValue); @@ -217,8 +219,9 @@ describe("handleBtwCommand", () => { const sessionAgentArgs = mockFirstObjectArg(resolveSessionAgentIdMock); expect(sessionAgentArgs.sessionKey).toBe("agent:worker-1:whatsapp:direct:12345"); - expect(sessionAgentArgs.config).toBeTypeOf("object"); - expect(sessionAgentArgs.config).not.toBeNull(); + if (!sessionAgentArgs.config || typeof sessionAgentArgs.config !== "object") { + throw new Error("expected session agent config"); + } expect(String(mockFirstObjectArg(runBtwSideQuestionMock).agentDir)).toContain( "/agents/worker-1/agent", ); @@ -245,11 +248,13 @@ describe("handleBtwCommand", () => { const canonicalAgentArgs = mockFirstObjectArg(resolveSessionAgentIdMock); expect(canonicalAgentArgs.sessionKey).toBe("agent:worker-1:whatsapp:direct:12345"); - expect(canonicalAgentArgs.config).toBeTypeOf("object"); - expect(canonicalAgentArgs.config).not.toBeNull(); + if (!canonicalAgentArgs.config || typeof canonicalAgentArgs.config !== "object") { + throw new Error("expected canonical agent config"); + } const resolveDirCall = mockCall(resolveAgentDirMock); - expect(resolveDirCall[0]).toBeTypeOf("object"); - expect(resolveDirCall[0]).not.toBeNull(); + if (!resolveDirCall[0] || typeof resolveDirCall[0] !== "object") { + throw new Error("expected resolveAgentDir config"); + } expect(resolveDirCall[1]).toBe("worker-1"); expect(mockFirstObjectArg(runBtwSideQuestionMock).agentDir).toBe("/tmp/worker-1-agent"); expect(result).toEqual({ diff --git a/src/auto-reply/reply/commands-plugins.install.test.ts b/src/auto-reply/reply/commands-plugins.install.test.ts index 52ff1b4c2a1..5b0d8729c6c 100644 --- a/src/auto-reply/reply/commands-plugins.install.test.ts +++ b/src/auto-reply/reply/commands-plugins.install.test.ts @@ -76,14 +76,16 @@ function mockCall(mock: unknown, index = 0): Array { function mockFirstObjectArg(mock: unknown): Record { const [arg] = mockCall(mock); - expect(arg).toBeTypeOf("object"); - expect(arg).not.toBeNull(); + if (!arg || typeof arg !== "object") { + throw new Error("expected first mock argument object"); + } return arg as Record; } function expectObjectFields(value: unknown, expected: Record): void { - expect(value).toBeTypeOf("object"); - expect(value).not.toBeNull(); + if (!value || typeof value !== "object") { + throw new Error("expected object fields"); + } const record = value as Record; for (const [key, expectedValue] of Object.entries(expected)) { expect(record[key], key).toEqual(expectedValue); diff --git a/src/auto-reply/reply/commands-plugins.test.ts b/src/auto-reply/reply/commands-plugins.test.ts index cb0fe95e9cd..e4b135f1adb 100644 --- a/src/auto-reply/reply/commands-plugins.test.ts +++ b/src/auto-reply/reply/commands-plugins.test.ts @@ -107,8 +107,9 @@ type MockCalls = { }; function requireRecord(value: unknown, label: string): Record { - expect(typeof value, label).toBe("object"); - expect(value, label).not.toBeNull(); + if (!value || typeof value !== "object") { + throw new Error(`expected ${label}`); + } return value as Record; } diff --git a/src/auto-reply/reply/commands-reset-hooks.test.ts b/src/auto-reply/reply/commands-reset-hooks.test.ts index e3c51cd52e8..24e321d7126 100644 --- a/src/auto-reply/reply/commands-reset-hooks.test.ts +++ b/src/auto-reply/reply/commands-reset-hooks.test.ts @@ -115,8 +115,9 @@ function mockCall(mock: unknown, index = 0): Array { } function requireRecord(value: unknown, label: string): Record { - expect(value, label).toBeTypeOf("object"); - expect(value, label).not.toBeNull(); + if (!value || typeof value !== "object") { + throw new Error(`expected ${label}`); + } return value as Record; } @@ -229,8 +230,9 @@ describe("handleCommands reset hooks", () => { mockCall(resetMocks.resetConfiguredBindingTargetInPlace)[0], "reset args", ); - expect(resetArgs.cfg).toBeTypeOf("object"); - expect(resetArgs.cfg).not.toBeNull(); + if (!resetArgs.cfg || typeof resetArgs.cfg !== "object") { + throw new Error("expected reset config"); + } expectObjectFields(resetArgs, { sessionKey: "agent:claude:acp:binding:discord:default:9373ab192b2317f4", reason: "reset", diff --git a/src/auto-reply/reply/dispatch-acp.test.ts b/src/auto-reply/reply/dispatch-acp.test.ts index 3e232dc5377..1c6561f48a9 100644 --- a/src/auto-reply/reply/dispatch-acp.test.ts +++ b/src/auto-reply/reply/dispatch-acp.test.ts @@ -187,8 +187,9 @@ type MockTtsReply = Awaited>; type MockCallSource = { mock: { calls: Array> } }; function requireRecord(value: unknown, label: string): Record { - expect(value, label).toBeTypeOf("object"); - expect(value, label).not.toBeNull(); + if (!value || typeof value !== "object") { + throw new Error(`expected ${label}`); + } return value as Record; } diff --git a/src/auto-reply/reply/get-reply-directives.target-session.test.ts b/src/auto-reply/reply/get-reply-directives.target-session.test.ts index 14c3a784ffa..c2f565f8379 100644 --- a/src/auto-reply/reply/get-reply-directives.target-session.test.ts +++ b/src/auto-reply/reply/get-reply-directives.target-session.test.ts @@ -119,8 +119,9 @@ function mockCallInput(mock: { mock: { calls: unknown[][] } }, index = 0): Recor throw new Error(`Expected mock call ${index}`); } const input = call[0]; - expect(typeof input).toBe("object"); - expect(input).not.toBeNull(); + if (!input || typeof input !== "object") { + throw new Error(`expected mock input ${index}`); + } return input as Record; } diff --git a/src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts b/src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts index 1120e9b944b..33e73585181 100644 --- a/src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts +++ b/src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts @@ -144,8 +144,6 @@ async function runInlineStatusAction(storePath?: string) { } function requireRecord(value: unknown, label: string): Record { - expect(value).toBeTypeOf("object"); - expect(value).not.toBeNull(); if (!value || typeof value !== "object" || Array.isArray(value)) { throw new Error(`expected ${label} to be an object`); } diff --git a/src/auto-reply/reply/route-reply.test.ts b/src/auto-reply/reply/route-reply.test.ts index 1ebc86e0c06..bc26b754a4c 100644 --- a/src/auto-reply/reply/route-reply.test.ts +++ b/src/auto-reply/reply/route-reply.test.ts @@ -112,8 +112,9 @@ function lastDelivery() { throw new Error("Expected outbound delivery call"); } const delivery = call[0]; - expect(typeof delivery).toBe("object"); - expect(delivery).not.toBeNull(); + if (!delivery || typeof delivery !== "object") { + throw new Error("expected outbound delivery"); + } return delivery as Record; } @@ -128,8 +129,9 @@ function lastDeliveryPayload(index = 0): Record { const payloads = lastDelivery().payloads; expect(Array.isArray(payloads)).toBe(true); const payload = (payloads as unknown[])[index]; - expect(typeof payload).toBe("object"); - expect(payload).not.toBeNull(); + if (!payload || typeof payload !== "object") { + throw new Error(`expected delivery payload ${index}`); + } return payload as Record; } diff --git a/src/auto-reply/reply/session-hooks-context.test.ts b/src/auto-reply/reply/session-hooks-context.test.ts index 9fc2f7a025a..31405da56bf 100644 --- a/src/auto-reply/reply/session-hooks-context.test.ts +++ b/src/auto-reply/reply/session-hooks-context.test.ts @@ -136,8 +136,9 @@ async function initStoredSessionState(params: { } function expectFields(value: unknown, expected: Record): void { - expect(value).toBeTypeOf("object"); - expect(value).not.toBeNull(); + if (!value || typeof value !== "object") { + throw new Error("expected fields object"); + } const record = value as Record; for (const [key, expectedValue] of Object.entries(expected)) { expect(record[key], key).toEqual(expectedValue); diff --git a/src/auto-reply/reply/session-transcript-replay.test.ts b/src/auto-reply/reply/session-transcript-replay.test.ts index a82e34b4ca7..eca85120d02 100644 --- a/src/auto-reply/reply/session-transcript-replay.test.ts +++ b/src/auto-reply/reply/session-transcript-replay.test.ts @@ -40,8 +40,9 @@ async function expectPathMissing(targetPath: string): Promise { if (statError === undefined) { throw new Error(`Expected ${targetPath} to be missing`); } - expect(typeof statError).toBe("object"); - expect(statError).not.toBeNull(); + if (!statError || typeof statError !== "object") { + throw new Error("expected stat error object"); + } expect((statError as NodeJS.ErrnoException).code).toBe("ENOENT"); }