From 43c97d18aa51e07787300d0868795c1c97be10ea Mon Sep 17 00:00:00 2001 From: cpojer Date: Tue, 17 Feb 2026 11:59:41 +0900 Subject: [PATCH] chore: Fix types in tests 17/N. --- src/memory/index.test.ts | 23 ++++++----- src/memory/search-manager.test.ts | 20 +++++----- src/telegram/bot.create-telegram-bot.test.ts | 40 +++++++++++++------- src/telegram/bot/delivery.test.ts | 16 ++++++-- src/telegram/monitor.test.ts | 2 +- src/telegram/webhook.test.ts | 4 +- 6 files changed, 66 insertions(+), 39 deletions(-) diff --git a/src/memory/index.test.ts b/src/memory/index.test.ts index 93408ae6f2..421fd7d4dd 100644 --- a/src/memory/index.test.ts +++ b/src/memory/index.test.ts @@ -198,16 +198,19 @@ describe("memory index", () => { it("reindexes when the embedding model changes", async () => { const indexModelPath = path.join(workspaceDir, `index-model-change-${Date.now()}.sqlite`); const base = createCfg({ storePath: indexModelPath }); + const baseAgents = base.agents!; + const baseDefaults = baseAgents.defaults!; + const baseMemorySearch = baseDefaults.memorySearch!; const first = await getMemorySearchManager({ cfg: { ...base, agents: { - ...base.agents, + ...baseAgents, defaults: { - ...base.agents.defaults, + ...baseDefaults, memorySearch: { - ...base.agents.defaults.memorySearch, + ...baseMemorySearch, model: "mock-embed-v1", }, }, @@ -219,19 +222,19 @@ describe("memory index", () => { if (!first.manager) { throw new Error("manager missing"); } - await first.manager.sync({ reason: "test" }); + await first.manager.sync?.({ reason: "test" }); const callsAfterFirstSync = embedBatchCalls; - await first.manager.close(); + await first.manager.close?.(); const second = await getMemorySearchManager({ cfg: { ...base, agents: { - ...base.agents, + ...baseAgents, defaults: { - ...base.agents.defaults, + ...baseDefaults, memorySearch: { - ...base.agents.defaults.memorySearch, + ...baseMemorySearch, model: "mock-embed-v2", }, }, @@ -243,11 +246,11 @@ describe("memory index", () => { if (!second.manager) { throw new Error("manager missing"); } - await second.manager.sync({ reason: "test" }); + await second.manager.sync?.({ reason: "test" }); expect(embedBatchCalls).toBeGreaterThan(callsAfterFirstSync); const status = second.manager.status(); expect(status.files).toBeGreaterThan(0); - await second.manager.close(); + await second.manager.close?.(); }); it("reuses cached embeddings on forced reindex", async () => { diff --git a/src/memory/search-manager.test.ts b/src/memory/search-manager.test.ts index e313cc98a6..9e47e20162 100644 --- a/src/memory/search-manager.test.ts +++ b/src/memory/search-manager.test.ts @@ -1,4 +1,5 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; +import type { OpenClawConfig } from "../config/config.js"; const mockPrimary = { search: vi.fn(async () => []), @@ -69,15 +70,16 @@ vi.mock("./manager.js", () => ({ import { QmdMemoryManager } from "./qmd-manager.js"; import { getMemorySearchManager } from "./search-manager.js"; +const createQmdManagerMock = vi.mocked(QmdMemoryManager.create.bind(QmdMemoryManager)); type SearchManagerResult = Awaited>; type SearchManager = NonNullable; -function createQmdCfg(agentId: string) { +function createQmdCfg(agentId: string): OpenClawConfig { return { memory: { backend: "qmd", qmd: {} }, agents: { list: [{ id: agentId, default: true, workspace: "/tmp/workspace" }] }, - } as const; + }; } function requireManager(result: SearchManagerResult): SearchManager { @@ -112,7 +114,7 @@ beforeEach(() => { fallbackManager.close.mockClear(); mockMemoryIndexGet.mockReset(); mockMemoryIndexGet.mockResolvedValue(fallbackManager); - QmdMemoryManager.create.mockClear(); + createQmdManagerMock.mockClear(); }); describe("getMemorySearchManager caching", () => { @@ -124,7 +126,7 @@ describe("getMemorySearchManager caching", () => { expect(first.manager).toBe(second.manager); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(QmdMemoryManager.create).toHaveBeenCalledTimes(1); + expect(createQmdManagerMock).toHaveBeenCalledTimes(1); }); it("evicts failed qmd wrapper so next call retries qmd", async () => { @@ -146,7 +148,7 @@ describe("getMemorySearchManager caching", () => { requireManager(second); expect(second.manager).not.toBe(first.manager); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(QmdMemoryManager.create).toHaveBeenCalledTimes(2); + expect(createQmdManagerMock).toHaveBeenCalledTimes(2); }); it("does not cache status-only qmd managers", async () => { @@ -159,14 +161,14 @@ describe("getMemorySearchManager caching", () => { requireManager(first); requireManager(second); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(QmdMemoryManager.create).toHaveBeenCalledTimes(2); + expect(createQmdManagerMock).toHaveBeenCalledTimes(2); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(QmdMemoryManager.create).toHaveBeenNthCalledWith( + expect(createQmdManagerMock).toHaveBeenNthCalledWith( 1, expect.objectContaining({ agentId, mode: "status" }), ); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(QmdMemoryManager.create).toHaveBeenNthCalledWith( + expect(createQmdManagerMock).toHaveBeenNthCalledWith( 2, expect.objectContaining({ agentId, mode: "status" }), ); @@ -193,7 +195,7 @@ describe("getMemorySearchManager caching", () => { const third = await getMemorySearchManager({ cfg, agentId: retryAgentId }); expect(third.manager).toBe(secondManager); // eslint-disable-next-line @typescript-eslint/unbound-method - expect(QmdMemoryManager.create).toHaveBeenCalledTimes(2); + expect(createQmdManagerMock).toHaveBeenCalledTimes(2); }); it("falls back to builtin search when qmd fails with sqlite busy", async () => { diff --git a/src/telegram/bot.create-telegram-bot.test.ts b/src/telegram/bot.create-telegram-bot.test.ts index c0e0f3387a..54dd77a591 100644 --- a/src/telegram/bot.create-telegram-bot.test.ts +++ b/src/telegram/bot.create-telegram-bot.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; -import type { Chat } from "@grammyjs/types"; +import type { Chat, Message } from "@grammyjs/types"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { escapeRegExp, formatEnvelopeTimestamp } from "../../test/helpers/envelope-timestamp.js"; import { @@ -39,6 +39,12 @@ const upsertChannelPairingRequest = getUpsertChannelPairingRequestMock(); const ORIGINAL_TZ = process.env.TZ; const mockChat = (chat: Pick & Partial>): Chat => chat as Chat; +const mockMessage = (message: Pick & Partial): Message => + ({ + message_id: 1, + date: 0, + ...message, + }) as Message; describe("createTelegramBot", () => { beforeEach(() => { @@ -112,57 +118,63 @@ describe("createTelegramBot", () => { expect(sequentializeSpy).toHaveBeenCalledTimes(1); expect(middlewareUseSpy).toHaveBeenCalledWith(sequentializeSpy.mock.results[0]?.value); expect(sequentializeKey).toBe(getTelegramSequentialKey); - expect(getTelegramSequentialKey({ message: { chat: mockChat({ id: 123 }) } })).toBe( - "telegram:123", - ); + expect( + getTelegramSequentialKey({ message: mockMessage({ chat: mockChat({ id: 123 }) }) }), + ).toBe("telegram:123"); expect( getTelegramSequentialKey({ - message: { chat: mockChat({ id: 123, type: "private" }), message_thread_id: 9 }, + message: mockMessage({ + chat: mockChat({ id: 123, type: "private" }), + message_thread_id: 9, + }), }), ).toBe("telegram:123:topic:9"); expect( getTelegramSequentialKey({ - message: { chat: mockChat({ id: 123, type: "supergroup" }), message_thread_id: 9 }, + message: mockMessage({ + chat: mockChat({ id: 123, type: "supergroup" }), + message_thread_id: 9, + }), }), ).toBe("telegram:123"); expect( getTelegramSequentialKey({ - message: { chat: mockChat({ id: 123, type: "supergroup", is_forum: true }) }, + message: mockMessage({ chat: mockChat({ id: 123, type: "supergroup", is_forum: true }) }), }), ).toBe("telegram:123:topic:1"); expect( getTelegramSequentialKey({ - update: { message: { chat: mockChat({ id: 555 }) } }, + update: { message: mockMessage({ chat: mockChat({ id: 555 }) }) }, }), ).toBe("telegram:555"); expect( getTelegramSequentialKey({ - message: { chat: mockChat({ id: 123 }), text: "/stop" }, + message: mockMessage({ chat: mockChat({ id: 123 }), text: "/stop" }), }), ).toBe("telegram:123:control"); expect( getTelegramSequentialKey({ - message: { chat: mockChat({ id: 123 }), text: "/status" }, + message: mockMessage({ chat: mockChat({ id: 123 }), text: "/status" }), }), ).toBe("telegram:123"); expect( getTelegramSequentialKey({ - message: { chat: mockChat({ id: 123 }), text: "stop" }, + message: mockMessage({ chat: mockChat({ id: 123 }), text: "stop" }), }), ).toBe("telegram:123:control"); expect( getTelegramSequentialKey({ - message: { chat: mockChat({ id: 123 }), text: "stop please" }, + message: mockMessage({ chat: mockChat({ id: 123 }), text: "stop please" }), }), ).toBe("telegram:123"); expect( getTelegramSequentialKey({ - message: { chat: mockChat({ id: 123 }), text: "/abort" }, + message: mockMessage({ chat: mockChat({ id: 123 }), text: "/abort" }), }), ).toBe("telegram:123"); expect( getTelegramSequentialKey({ - message: { chat: mockChat({ id: 123 }), text: "/abort now" }, + message: mockMessage({ chat: mockChat({ id: 123 }), text: "/abort now" }), }), ).toBe("telegram:123"); }); diff --git a/src/telegram/bot/delivery.test.ts b/src/telegram/bot/delivery.test.ts index 8c58bf9d81..c6d5b944f0 100644 --- a/src/telegram/bot/delivery.test.ts +++ b/src/telegram/bot/delivery.test.ts @@ -1,5 +1,6 @@ import type { Bot } from "grammy"; import { beforeEach, describe, expect, it, vi } from "vitest"; +import type { RuntimeEnv } from "../../runtime.js"; import { deliverReplies } from "./delivery.js"; const loadWebMedia = vi.fn(); @@ -10,7 +11,12 @@ const baseDeliveryParams = { textLimit: 4000, } as const; type DeliverRepliesParams = Parameters[0]; -type RuntimeStub = { error: ReturnType; log?: ReturnType }; +type DeliverWithParams = Omit< + DeliverRepliesParams, + "chatId" | "token" | "replyToMode" | "textLimit" +> & + Partial>; +type RuntimeStub = Pick; vi.mock("../../web/media.js", () => ({ loadWebMedia: (...args: unknown[]) => loadWebMedia(...args), @@ -29,14 +35,18 @@ vi.mock("grammy", () => ({ })); function createRuntime(withLog = true): RuntimeStub { - return withLog ? { error: vi.fn(), log: vi.fn() } : { error: vi.fn() }; + return { + error: vi.fn(), + log: withLog ? vi.fn() : vi.fn(), + exit: vi.fn(), + }; } function createBot(api: Record = {}): Bot { return { api } as unknown as Bot; } -async function deliverWith(params: Omit) { +async function deliverWith(params: DeliverWithParams) { await deliverReplies({ ...baseDeliveryParams, ...params, diff --git a/src/telegram/monitor.test.ts b/src/telegram/monitor.test.ts index 59fe773109..8b6b6b7433 100644 --- a/src/telegram/monitor.test.ts +++ b/src/telegram/monitor.test.ts @@ -87,7 +87,7 @@ vi.mock("../infra/backoff.js", () => ({ })); vi.mock("./webhook.js", () => ({ - startTelegramWebhook: (...args: unknown[]) => startTelegramWebhookSpy(...args), + startTelegramWebhook: startTelegramWebhookSpy, })); vi.mock("../auto-reply/reply.js", () => ({ diff --git a/src/telegram/webhook.test.ts b/src/telegram/webhook.test.ts index 9681a8b246..538c065356 100644 --- a/src/telegram/webhook.test.ts +++ b/src/telegram/webhook.test.ts @@ -20,12 +20,12 @@ vi.mock("grammy", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, - webhookCallback: (...args: unknown[]) => webhookCallbackSpy(...args), + webhookCallback: webhookCallbackSpy, }; }); vi.mock("./bot.js", () => ({ - createTelegramBot: (...args: unknown[]) => createTelegramBotSpy(...args), + createTelegramBot: createTelegramBotSpy, })); describe("startTelegramWebhook", () => {