diff --git a/src/agents/pi-embedded-runner/extra-params.google.test.ts b/src/agents/pi-embedded-runner/extra-params.google.test.ts index e37ed4a872a..1a026a2ed3a 100644 --- a/src/agents/pi-embedded-runner/extra-params.google.test.ts +++ b/src/agents/pi-embedded-runner/extra-params.google.test.ts @@ -1,6 +1,6 @@ import type { Model } from "@mariozechner/pi-ai"; import { describe, expect, it, vi } from "vitest"; -import { createPiAiStreamSimpleMock } from "./extra-params.pi-ai-mock.js"; +import { createPiAiStreamSimpleMock } from "../../../test/helpers/agents/pi-ai-stream-simple-mock.js"; import { runExtraParamsCase } from "./extra-params.test-support.js"; vi.mock("@mariozechner/pi-ai", async () => diff --git a/src/agents/pi-embedded-runner/extra-params.zai-tool-stream.test.ts b/src/agents/pi-embedded-runner/extra-params.zai-tool-stream.test.ts index b372a7ca1bd..cf827e4a032 100644 --- a/src/agents/pi-embedded-runner/extra-params.zai-tool-stream.test.ts +++ b/src/agents/pi-embedded-runner/extra-params.zai-tool-stream.test.ts @@ -1,7 +1,7 @@ import type { Model, SimpleStreamOptions } from "@mariozechner/pi-ai"; import { describe, expect, it, vi } from "vitest"; +import { createPiAiStreamSimpleMock } from "../../../test/helpers/agents/pi-ai-stream-simple-mock.js"; import type { OpenClawConfig } from "../../config/config.js"; -import { createPiAiStreamSimpleMock } from "./extra-params.pi-ai-mock.js"; import { runExtraParamsCase } from "./extra-params.test-support.js"; vi.mock("@mariozechner/pi-ai", async () => diff --git a/src/config/heartbeat-config-honor.inventory.test.ts b/src/config/heartbeat-config-honor.inventory.test.ts index 749d711a5d2..b6df00e5583 100644 --- a/src/config/heartbeat-config-honor.inventory.test.ts +++ b/src/config/heartbeat-config-honor.inventory.test.ts @@ -1,9 +1,12 @@ import { describe, expect, it } from "vitest"; -import { auditConfigHonorInventory, listSchemaLeafKeysForPrefixes } from "./config-honor-audit.js"; +import { + auditConfigHonorInventory, + listSchemaLeafKeysForPrefixes, +} from "../../test/helpers/config/config-honor-audit.js"; import { HEARTBEAT_CONFIG_HONOR_INVENTORY, HEARTBEAT_CONFIG_PREFIXES, -} from "./heartbeat-config-honor.inventory.js"; +} from "../../test/helpers/config/heartbeat-config-honor.inventory.js"; const EXPECTED_HEARTBEAT_KEYS = [ "every", diff --git a/src/config/redact-snapshot.restore.test.ts b/src/config/redact-snapshot.restore.test.ts index dddc5f558ac..4f0184deaf2 100644 --- a/src/config/redact-snapshot.restore.test.ts +++ b/src/config/redact-snapshot.restore.test.ts @@ -1,11 +1,11 @@ import { describe, expect, it } from "vitest"; +import { redactSnapshotTestHints as mainSchemaHints } from "../../test/helpers/config/redact-snapshot-test-hints.js"; import { REDACTED_SENTINEL, redactConfigSnapshot, restoreRedactedValues as restoreRedactedValues_orig, } from "./redact-snapshot.js"; import { makeSnapshot, restoreRedactedValues } from "./redact-snapshot.test-helpers.js"; -import { redactSnapshotTestHints as mainSchemaHints } from "./redact-snapshot.test-hints.js"; import type { ConfigUiHints } from "./schema.js"; describe("restoreRedactedValues", () => { diff --git a/src/config/redact-snapshot.schema.test.ts b/src/config/redact-snapshot.schema.test.ts index 5f4335abc11..411b4c1829d 100644 --- a/src/config/redact-snapshot.schema.test.ts +++ b/src/config/redact-snapshot.schema.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; +import { redactSnapshotTestHints as mainSchemaHints } from "../../test/helpers/config/redact-snapshot-test-hints.js"; import { REDACTED_SENTINEL, redactConfigSnapshot } from "./redact-snapshot.js"; import { makeSnapshot, restoreRedactedValues } from "./redact-snapshot.test-helpers.js"; -import { redactSnapshotTestHints as mainSchemaHints } from "./redact-snapshot.test-hints.js"; import { buildConfigSchema } from "./schema.js"; describe("realredactConfigSnapshot_real", () => { diff --git a/src/config/redact-snapshot.test.ts b/src/config/redact-snapshot.test.ts index 5753b333236..0205add7190 100644 --- a/src/config/redact-snapshot.test.ts +++ b/src/config/redact-snapshot.test.ts @@ -1,12 +1,12 @@ import JSON5 from "json5"; import { describe, expect, it } from "vitest"; +import { redactSnapshotTestHints as mainSchemaHints } from "../../test/helpers/config/redact-snapshot-test-hints.js"; import { REDACTED_SENTINEL, redactConfigSnapshot } from "./redact-snapshot.js"; import { makeSnapshot, restoreRedactedValues, type TestSnapshot, } from "./redact-snapshot.test-helpers.js"; -import { redactSnapshotTestHints as mainSchemaHints } from "./redact-snapshot.test-hints.js"; import { buildConfigSchema, type ConfigUiHints } from "./schema.js"; import type { ConfigFileSnapshot } from "./types.openclaw.js"; diff --git a/src/infra/heartbeat-runner.test-harness.ts b/src/infra/heartbeat-runner.test-harness.ts index 6137f9555ed..0528b2920c1 100644 --- a/src/infra/heartbeat-runner.test-harness.ts +++ b/src/infra/heartbeat-runner.test-harness.ts @@ -1,11 +1,11 @@ import { beforeEach } from "vitest"; -import { setActivePluginRegistry } from "../plugins/runtime.js"; -import { createTestRegistry } from "../test-utils/channel-plugins.js"; import { heartbeatRunnerSlackPlugin, heartbeatRunnerTelegramPlugin, heartbeatRunnerWhatsAppPlugin, -} from "./heartbeat-runner.test-channel-plugins.js"; +} from "../../test/helpers/infra/heartbeat-runner-channel-plugins.js"; +import { setActivePluginRegistry } from "../plugins/runtime.js"; +import { createTestRegistry } from "../test-utils/channel-plugins.js"; export function installHeartbeatRunnerTestRuntime(params?: { includeSlack?: boolean }): void { beforeEach(() => { diff --git a/src/infra/heartbeat-runner.test-utils.ts b/src/infra/heartbeat-runner.test-utils.ts index 2da1a22bf12..e5d7bcd01d5 100644 --- a/src/infra/heartbeat-runner.test-utils.ts +++ b/src/infra/heartbeat-runner.test-utils.ts @@ -2,12 +2,12 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { vi } from "vitest"; +import { heartbeatRunnerTelegramPlugin } from "../../test/helpers/infra/heartbeat-runner-channel-plugins.js"; import type { OpenClawConfig } from "../config/config.js"; import { resolveMainSessionKey } from "../config/sessions.js"; import { setActivePluginRegistry } from "../plugins/runtime.js"; import { createTestRegistry } from "../test-utils/channel-plugins.js"; import type { HeartbeatDeps } from "./heartbeat-runner.js"; -import { heartbeatRunnerTelegramPlugin } from "./heartbeat-runner.test-channel-plugins.js"; export type HeartbeatSessionSeed = { sessionId?: string; diff --git a/src/infra/outbound/deliver.test-helpers.ts b/src/infra/outbound/deliver.test-helpers.ts index b5c4329b65e..c99900362af 100644 --- a/src/infra/outbound/deliver.test-helpers.ts +++ b/src/infra/outbound/deliver.test-helpers.ts @@ -1,5 +1,10 @@ import { vi } from "vitest"; import { createIMessageTestPlugin } from "../../../test/helpers/channels/imessage-test-plugin.js"; +import { + imessageOutboundForTest, + signalOutbound, + whatsappOutbound, +} from "../../../test/helpers/infra/deliver-test-outbounds.js"; import type { OpenClawConfig } from "../../config/config.js"; import { releasePinnedPluginChannelRegistry, @@ -8,11 +13,6 @@ import { import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; import { createInternalHookEventPayload } from "../../test-utils/internal-hook-event-payload.js"; import type { DeliverOutboundPayloadsParams, OutboundDeliveryResult } from "./deliver.js"; -import { - imessageOutboundForTest, - signalOutbound, - whatsappOutbound, -} from "./deliver.test-outbounds.js"; type DeliverMockState = { sessions: { diff --git a/src/infra/outbound/deliver.test.ts b/src/infra/outbound/deliver.test.ts index 1e863746bab..495b5a917bf 100644 --- a/src/infra/outbound/deliver.test.ts +++ b/src/infra/outbound/deliver.test.ts @@ -1,6 +1,11 @@ import path from "node:path"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { createIMessageTestPlugin } from "../../../test/helpers/channels/imessage-test-plugin.js"; +import { + imessageOutboundForTest, + signalOutbound, + whatsappOutbound, +} from "../../../test/helpers/infra/deliver-test-outbounds.js"; import type { OpenClawConfig } from "../../config/config.js"; import { createHookRunner } from "../../plugins/hooks.js"; import { addTestHook } from "../../plugins/hooks.test-helpers.js"; @@ -13,11 +18,6 @@ import type { PluginHookRegistration } from "../../plugins/types.js"; import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; import { createInternalHookEventPayload } from "../../test-utils/internal-hook-event-payload.js"; import { resolvePreferredOpenClawTmpDir } from "../tmp-openclaw-dir.js"; -import { - imessageOutboundForTest, - signalOutbound, - whatsappOutbound, -} from "./deliver.test-outbounds.js"; const mocks = vi.hoisted(() => ({ appendAssistantMessageToSessionTranscript: vi.fn(async () => ({ ok: true, sessionFile: "x" })), diff --git a/src/agents/pi-embedded-runner/extra-params.pi-ai-mock.ts b/test/helpers/agents/pi-ai-stream-simple-mock.ts similarity index 100% rename from src/agents/pi-embedded-runner/extra-params.pi-ai-mock.ts rename to test/helpers/agents/pi-ai-stream-simple-mock.ts diff --git a/src/config/config-honor-audit.ts b/test/helpers/config/config-honor-audit.ts similarity index 96% rename from src/config/config-honor-audit.ts rename to test/helpers/config/config-honor-audit.ts index 3690469d397..c269223fb8e 100644 --- a/src/config/config-honor-audit.ts +++ b/test/helpers/config/config-honor-audit.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; -import { GENERATED_BASE_CONFIG_SCHEMA } from "./schema.base.generated.js"; +import { GENERATED_BASE_CONFIG_SCHEMA } from "../../../src/config/schema.base.generated.js"; export type ConfigHonorInventoryRow = { key: string; @@ -34,7 +34,7 @@ export type ConfigHonorAuditResult = { }>; }; -const REPO_ROOT = fileURLToPath(new URL("../../", import.meta.url)); +const REPO_ROOT = fileURLToPath(new URL("../../../", import.meta.url)); function hasSchemaPath(schemaPath: string): boolean { const segments = schemaPath.split("."); diff --git a/src/config/heartbeat-config-honor.inventory.ts b/test/helpers/config/heartbeat-config-honor.inventory.ts similarity index 100% rename from src/config/heartbeat-config-honor.inventory.ts rename to test/helpers/config/heartbeat-config-honor.inventory.ts diff --git a/src/config/redact-snapshot.test-hints.ts b/test/helpers/config/redact-snapshot-test-hints.ts similarity index 92% rename from src/config/redact-snapshot.test-hints.ts rename to test/helpers/config/redact-snapshot-test-hints.ts index 354f89f9026..9f09a614dbd 100644 --- a/src/config/redact-snapshot.test-hints.ts +++ b/test/helpers/config/redact-snapshot-test-hints.ts @@ -1,4 +1,4 @@ -import type { ConfigUiHints } from "./schema.js"; +import type { ConfigUiHints } from "../../../src/config/schema.js"; // Keep this fixture minimal so redaction tests exercise the hint-matching // behavior they care about without paying to build the full config schema graph. diff --git a/src/infra/outbound/deliver.test-outbounds.ts b/test/helpers/infra/deliver-test-outbounds.ts similarity index 79% rename from src/infra/outbound/deliver.test-outbounds.ts rename to test/helpers/infra/deliver-test-outbounds.ts index 549bb6242e1..9768e2feaa0 100644 --- a/src/infra/outbound/deliver.test-outbounds.ts +++ b/test/helpers/infra/deliver-test-outbounds.ts @@ -1,8 +1,11 @@ -import { chunkMarkdownTextWithMode, chunkText } from "../../auto-reply/chunk.js"; -import type { ChannelOutboundAdapter } from "../../channels/plugins/types.js"; -import type { OpenClawConfig } from "../../config/config.js"; -import { sanitizeForPlainText } from "../../plugin-sdk/outbound-runtime.js"; -import { resolveOutboundSendDep, type OutboundSendDeps } from "./send-deps.js"; +import { chunkMarkdownTextWithMode, chunkText } from "../../../src/auto-reply/chunk.js"; +import type { ChannelOutboundAdapter } from "../../../src/channels/plugins/types.js"; +import type { OpenClawConfig } from "../../../src/config/config.js"; +import { + resolveOutboundSendDep, + type OutboundSendDeps, +} from "../../../src/infra/outbound/send-deps.js"; +import { sanitizeForPlainText } from "../../../src/plugin-sdk/outbound-runtime.js"; type SignalSendFn = ( to: string, @@ -53,8 +56,6 @@ function withSignalChannel(result: Awaited>) { }; } -// Keep deliver-core tests on a light local Signal stub. The real adapter owns -// markdown/style correctness in extensions/signal tests. export const signalOutbound: ChannelOutboundAdapter = { deliveryMode: "direct", textChunkLimit: 4000, @@ -218,40 +219,36 @@ function resolveIMessageSender(deps: OutboundSendDeps | undefined) { ) => Promise<{ messageId: string; chatId?: string }> >(deps, "imessage"); if (!sender) { - throw new Error("missing imessage dep"); + throw new Error("missing sendIMessage dep"); } return sender; } -function resolveIMessageMaxBytes(cfg: OpenClawConfig): number | undefined { - const channelMb = (cfg.channels?.imessage as { mediaMaxMb?: number } | undefined)?.mediaMaxMb; - const agentMb = cfg.agents?.defaults?.mediaMaxMb; - const mediaMaxMb = channelMb ?? agentMb; - return typeof mediaMaxMb === "number" ? mediaMaxMb * MB : undefined; +function withIMessageChannel( + result: Awaited>>, +) { + return { + channel: "imessage" as const, + ...result, + }; } export const imessageOutboundForTest: ChannelOutboundAdapter = { deliveryMode: "direct", - sendText: async ({ cfg, to, text, accountId, replyToId, deps }) => - ({ - channel: "imessage", - ...(await resolveIMessageSender(deps)(to, text, { - config: cfg, - maxBytes: resolveIMessageMaxBytes(cfg), + sanitizeText: ({ text }) => text, + sendText: async ({ to, text, accountId, deps }) => + withIMessageChannel( + await resolveIMessageSender(deps)(to, text, { accountId: accountId ?? undefined, - replyToId: replyToId ?? undefined, - })), - }) as const, - sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, accountId, replyToId, deps }) => - ({ - channel: "imessage", - ...(await resolveIMessageSender(deps)(to, text, { - config: cfg, + }), + ), + sendMedia: async ({ to, text, mediaUrl, mediaLocalRoots, mediaReadFile, accountId, deps }) => + withIMessageChannel( + await resolveIMessageSender(deps)(to, text, { mediaUrl, mediaLocalRoots, - maxBytes: resolveIMessageMaxBytes(cfg), + mediaReadFile, accountId: accountId ?? undefined, - replyToId: replyToId ?? undefined, - })), - }) as const, + }), + ), }; diff --git a/src/infra/heartbeat-runner.test-channel-plugins.ts b/test/helpers/infra/heartbeat-runner-channel-plugins.ts similarity index 92% rename from src/infra/heartbeat-runner.test-channel-plugins.ts rename to test/helpers/infra/heartbeat-runner-channel-plugins.ts index fa7fbce2ddc..6304056c58e 100644 --- a/src/infra/heartbeat-runner.test-channel-plugins.ts +++ b/test/helpers/infra/heartbeat-runner-channel-plugins.ts @@ -2,9 +2,12 @@ import type { ChannelId, ChannelOutboundAdapter, ChannelPlugin, -} from "../channels/plugins/types.js"; -import { createOutboundTestPlugin } from "../test-utils/channel-plugins.js"; -import { resolveOutboundSendDep, type OutboundSendDeps } from "./outbound/send-deps.js"; +} from "../../../src/channels/plugins/types.js"; +import { + resolveOutboundSendDep, + type OutboundSendDeps, +} from "../../../src/infra/outbound/send-deps.js"; +import { createOutboundTestPlugin } from "../../../src/test-utils/channel-plugins.js"; type HeartbeatSendChannelId = "slack" | "telegram" | "whatsapp"; type HeartbeatSendFn = (