From 8af475d9be9c8fd8313a762ed7c0adcbf7680309 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 8 May 2026 06:17:10 +0100 Subject: [PATCH] test: tighten function-shape assertions --- extensions/feishu/src/docx.test.ts | 1 - .../msteams/src/monitor.lifecycle.test.ts | 20 +++++++++---------- .../xai/image-generation-provider.test.ts | 18 +++++++++++++++-- src/channels/message/outbound-bridge.test.ts | 15 ++++++++++++-- src/gateway/server-methods/config.test.ts | 6 ++++-- .../host/backend-config.test.ts | 3 ++- 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/extensions/feishu/src/docx.test.ts b/extensions/feishu/src/docx.test.ts index c8f9438262c..e2de98cdcfb 100644 --- a/extensions/feishu/src/docx.test.ts +++ b/extensions/feishu/src/docx.test.ts @@ -166,7 +166,6 @@ describe("feishu_doc image fetch hardening", () => { if (!tool) { throw new Error("expected Feishu doc tool"); } - expect(tool.execute).toEqual(expect.any(Function)); return tool; } diff --git a/extensions/msteams/src/monitor.lifecycle.test.ts b/extensions/msteams/src/monitor.lifecycle.test.ts index 7df9d4f940b..11d4f6ef412 100644 --- a/extensions/msteams/src/monitor.lifecycle.test.ts +++ b/extensions/msteams/src/monitor.lifecycle.test.ts @@ -3,6 +3,7 @@ import type { Request, Response } from "express"; import { afterEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig, RuntimeEnv } from "../runtime-api.js"; import type { MSTeamsConversationStore } from "./conversation-store.js"; +import type { MSTeamsActivityHandler, MSTeamsMessageHandlerDeps } from "./monitor-handler.js"; import type { MSTeamsPollStore } from "./polls.js"; type FakeServer = EventEmitter & { @@ -36,11 +37,9 @@ type ResolveMSTeamsUserAllowlistMock = (params: { }) => Promise; type RegisterMSTeamsHandlersMock = ( - handler: unknown, - deps: unknown, -) => { - run: () => Promise; -}; + handler: MSTeamsActivityHandler, + deps: MSTeamsMessageHandlerDeps, +) => MSTeamsActivityHandler; const expressControl = vi.hoisted(() => ({ mode: { value: "listening" as "listening" | "error" }, @@ -124,9 +123,7 @@ vi.mock("express", () => { }); const registerMSTeamsHandlers = vi.hoisted(() => - vi.fn(() => ({ - run: vi.fn(async () => {}), - })), + vi.fn((handler) => handler), ); const createMSTeamsAdapter = vi.hoisted(() => vi.fn(() => ({ @@ -148,8 +145,7 @@ const loadMSTeamsSdkWithAuth = vi.hoisted(() => ); vi.mock("./monitor-handler.js", () => ({ - registerMSTeamsHandlers: (handler: unknown, deps: unknown) => - registerMSTeamsHandlers(handler, deps), + registerMSTeamsHandlers, })); const resolveAllowlistMocks = vi.hoisted(() => ({ @@ -302,7 +298,9 @@ describe("monitorMSTeamsProvider lifecycle", () => { expect(app.use).toHaveBeenCalledTimes(4); const jsonMiddleware = vi.mocked((await import("express")).json).mock.results[0]?.value; - expect(jsonMiddleware).toEqual(expect.any(Function)); + if (typeof jsonMiddleware !== "function") { + throw new Error("expected Express JSON middleware"); + } expect(app.use.mock.calls[1]?.[0]).not.toBe(jsonMiddleware); expect(app.use.mock.calls[2]?.[0]).toBe(jsonMiddleware); diff --git a/extensions/xai/image-generation-provider.test.ts b/extensions/xai/image-generation-provider.test.ts index d3c8731c57e..18e4eda8668 100644 --- a/extensions/xai/image-generation-provider.test.ts +++ b/extensions/xai/image-generation-provider.test.ts @@ -3,6 +3,7 @@ import { buildXaiImageGenerationProvider } from "./image-generation-provider.js" const { resolveApiKeyForProviderMock, + isProviderApiKeyConfiguredMock, postJsonRequestMock, postMultipartRequestMock, assertOkOrThrowHttpErrorMock, @@ -12,6 +13,7 @@ const { sanitizeConfiguredModelProviderRequestMock, } = vi.hoisted(() => ({ resolveApiKeyForProviderMock: vi.fn(async () => ({ apiKey: "xai-key" })), + isProviderApiKeyConfiguredMock: vi.fn(() => true), postJsonRequestMock: vi.fn(), postMultipartRequestMock: vi.fn(), assertOkOrThrowHttpErrorMock: vi.fn(async () => {}), @@ -35,6 +37,10 @@ vi.mock("openclaw/plugin-sdk/provider-auth-runtime", () => ({ resolveApiKeyForProvider: resolveApiKeyForProviderMock, })); +vi.mock("openclaw/plugin-sdk/provider-auth", () => ({ + isProviderApiKeyConfigured: isProviderApiKeyConfiguredMock, +})); + vi.mock("openclaw/plugin-sdk/provider-http", () => ({ assertOkOrThrowHttpError: assertOkOrThrowHttpErrorMock, createProviderOperationDeadline: createProviderOperationDeadlineMock, @@ -55,6 +61,7 @@ vi.mock("openclaw/plugin-sdk/text-runtime", () => ({ describe("xai image generation provider", () => { afterEach(() => { resolveApiKeyForProviderMock.mockClear(); + isProviderApiKeyConfiguredMock.mockClear(); postJsonRequestMock.mockReset(); assertOkOrThrowHttpErrorMock.mockClear(); resolveProviderHttpRequestConfigMock.mockClear(); @@ -82,8 +89,15 @@ describe("xai image generation provider", () => { ]); expect(provider.capabilities.edit.enabled).toBe(true); expect(provider.capabilities.edit.maxInputImages).toBe(5); - expect(provider.isConfigured).toEqual(expect.any(Function)); - expect(provider.generateImage).toEqual(expect.any(Function)); + const isConfigured = provider.isConfigured; + if (!isConfigured) { + throw new Error("expected XAI image provider config predicate"); + } + expect(isConfigured({ agentDir: "/tmp/openclaw-xai-test" })).toBe(true); + expect(isProviderApiKeyConfiguredMock).toHaveBeenCalledWith({ + provider: "xai", + agentDir: "/tmp/openclaw-xai-test", + }); }); it("uses main provider URL and resolves auth for generation", async () => { diff --git a/src/channels/message/outbound-bridge.test.ts b/src/channels/message/outbound-bridge.test.ts index 41fab3324e8..8e8f44ce558 100644 --- a/src/channels/message/outbound-bridge.test.ts +++ b/src/channels/message/outbound-bridge.test.ts @@ -113,14 +113,25 @@ describe("createChannelMessageAdapterFromOutbound", () => { ); }); - it("exposes only send methods backed by outbound handlers", () => { + it("exposes only send methods backed by outbound handlers", async () => { const adapter = createChannelMessageAdapterFromOutbound({ outbound: { sendText: vi.fn(async () => ({ messageId: "msg-1" })), }, }); - expect(adapter.send?.text).toEqual(expect.any(Function)); + const sendText = adapter.send?.text; + if (!sendText) { + throw new Error("expected text send adapter"); + } + + await expect(sendText({ cfg, to: "room-1", text: "hello" })).resolves.toEqual({ + messageId: "msg-1", + receipt: expect.objectContaining({ + primaryPlatformMessageId: "msg-1", + platformMessageIds: ["msg-1"], + }), + }); expect(adapter.send?.media).toBeUndefined(); expect(adapter.send?.payload).toBeUndefined(); }); diff --git a/src/gateway/server-methods/config.test.ts b/src/gateway/server-methods/config.test.ts index a73e0fdd057..2a0d0e3517f 100644 --- a/src/gateway/server-methods/config.test.ts +++ b/src/gateway/server-methods/config.test.ts @@ -18,8 +18,10 @@ vi.mock("node:child_process", async () => { function invokeExecFileCallback(args: unknown[], error: Error | null) { const callback = args.at(-1); - expect(callback).toEqual(expect.any(Function)); - (callback as (error: Error | null) => void)(error); + if (typeof callback !== "function") { + throw new Error("expected execFile callback"); + } + callback(error); } describe("resolveConfigOpenCommand", () => { diff --git a/src/memory-host-sdk/host/backend-config.test.ts b/src/memory-host-sdk/host/backend-config.test.ts index 2fdf3156caf..fe6bdcf46fc 100644 --- a/src/memory-host-sdk/host/backend-config.test.ts +++ b/src/memory-host-sdk/host/backend-config.test.ts @@ -1,8 +1,9 @@ import { describe, expect, it } from "vitest"; +import { resolveMemoryBackendConfig as packageResolveMemoryBackendConfig } from "../../../packages/memory-host-sdk/src/host/backend-config.js"; import { resolveMemoryBackendConfig } from "./backend-config.js"; describe("memory-host-sdk backend-config bridge", () => { it("exports the package-owned backend resolver", () => { - expect(resolveMemoryBackendConfig).toEqual(expect.any(Function)); + expect(resolveMemoryBackendConfig).toBe(packageResolveMemoryBackendConfig); }); });