From 0df6e5a473488e8cc3f5109f6cb1fd6a6bd4e774 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Apr 2026 23:45:08 +0100 Subject: [PATCH] refactor: expose plugin test helpers via sdk --- .../.generated/plugin-sdk-api-baseline.sha256 | 4 +- docs/plugins/sdk-subpaths.md | 2 +- docs/plugins/sdk-testing.md | 7 + .../amazon-bedrock-mantle/index.test.ts | 2 +- extensions/amazon-bedrock/index.test.ts | 3 +- extensions/amazon-bedrock/lazy-import.test.ts | 2 +- extensions/anthropic-vertex/index.test.ts | 2 +- extensions/anthropic/cli-migration.test.ts | 5 +- extensions/anthropic/index.test.ts | 6 +- extensions/arcee/index.test.ts | 6 +- .../azure-speech/azure-speech.live.test.ts | 6 +- .../bluebubbles/src/setup-surface.test.ts | 4 +- extensions/byteplus/index.test.ts | 2 +- extensions/chutes/implicit-provider.test.ts | 2 +- extensions/comfy/index.test.ts | 6 +- extensions/deepseek/index.test.ts | 6 +- extensions/diffs/src/browser.test.ts | 2 +- extensions/diffs/src/store.test.ts | 2 +- extensions/discord/src/monitor.test.ts | 2 +- .../native-command.plugin-dispatch.test.ts | 5 +- .../src/monitor/provider.allowlist.test.ts | 2 +- extensions/elevenlabs/elevenlabs.live.test.ts | 6 +- extensions/feishu/src/bot.card-action.test.ts | 2 +- extensions/feishu/src/bot.test.ts | 2 +- .../feishu/src/card-ux-launcher.test.ts | 2 +- ...acp-init-failure.lifecycle.test-support.ts | 6 +- ...monitor.bot-menu.lifecycle.test-support.ts | 6 +- ...dcast.reply-once.lifecycle.test-support.ts | 2 +- ...itor.card-action.lifecycle.test-support.ts | 6 +- extensions/feishu/src/monitor.comment.test.ts | 6 +- .../feishu/src/monitor.reaction.test.ts | 2 +- ...nitor.reply-once.lifecycle.test-support.ts | 6 +- extensions/feishu/src/monitor.startup.test.ts | 2 +- extensions/feishu/src/setup-surface.test.ts | 6 +- extensions/fireworks/index.test.ts | 6 +- extensions/github-copilot/models.test.ts | 5 +- extensions/google/google.live.test.ts | 6 +- extensions/google/index.test.ts | 5 +- .../src/monitor.webhook-routing.test.ts | 7 +- extensions/googlechat/src/setup.test.ts | 4 +- extensions/gradium/gradium.live.test.ts | 6 +- extensions/imessage/src/status.test.ts | 2 +- extensions/inworld/inworld.live.test.ts | 6 +- extensions/irc/src/setup.test.ts | 13 +- extensions/kilocode/index.test.ts | 2 +- .../kimi-coding/implicit-provider.test.ts | 2 +- extensions/kimi-coding/index.test.ts | 2 +- .../line/src/bot-message-context.test.ts | 5 +- extensions/line/src/channel.logout.test.ts | 2 +- extensions/line/src/setup-surface.test.ts | 8 +- .../matrix/src/channel.directory.test.ts | 2 +- extensions/matrix/src/channel.resolve.test.ts | 2 +- extensions/minimax/index.test.ts | 5 +- extensions/minimax/minimax.live.test.ts | 6 +- extensions/moonshot/index.test.ts | 2 +- .../music-generation-providers.live.test.ts | 6 +- extensions/nostr/src/channel.test.ts | 4 +- extensions/nvidia/index.test.ts | 6 +- extensions/openai/index.test.ts | 5 +- extensions/openai/openai.live.test.ts | 5 +- .../provider-catalog.contract-test-support.ts | 5 +- extensions/opencode-go/index.test.ts | 3 +- extensions/opencode/index.test.ts | 5 +- extensions/openrouter/index.test.ts | 3 +- extensions/openrouter/openrouter.live.test.ts | 5 +- extensions/qa-channel/src/channel.test.ts | 2 +- extensions/qianfan/index.test.ts | 6 +- extensions/qwen/index.test.ts | 3 +- extensions/signal/src/core.test.ts | 2 +- extensions/slack/src/channel.test.ts | 2 +- .../src/inbound-context.contract.test.ts | 2 +- extensions/slack/src/setup-surface.test.ts | 4 +- extensions/synology-chat/src/channel.test.ts | 2 +- extensions/synology-chat/src/core.test.ts | 4 +- ...te-telegram-bot.channel-post-media.test.ts | 2 +- extensions/tlon/src/core.test.ts | 4 +- extensions/venice/index.test.ts | 2 +- .../video-generation-providers.live.test.ts | 6 +- extensions/volcengine/index.test.ts | 2 +- extensions/vydra/vydra.live.test.ts | 6 +- extensions/webhooks/src/http.test.ts | 3 +- .../auto-reply/web-auto-reply-utils.test.ts | 2 +- extensions/whatsapp/src/channel.setup.test.ts | 2 +- extensions/whatsapp/src/setup-surface.test.ts | 4 +- extensions/xai/code-execution.test.ts | 2 +- extensions/xai/index.test.ts | 3 +- extensions/xai/web-search.test.ts | 2 +- extensions/xai/x-search.test.ts | 2 +- extensions/xai/xai.live.test.ts | 5 +- extensions/xiaomi/xiaomi.live.test.ts | 6 +- extensions/zai/index.test.ts | 2 +- .../zalo/src/monitor.image.polling.test.ts | 2 +- extensions/zalo/src/monitor.lifecycle.test.ts | 7 +- .../src/monitor.polling.media-reply.test.ts | 7 +- extensions/zalo/src/setup-status.test.ts | 2 +- extensions/zalo/src/setup-surface.test.ts | 4 +- .../monitor-mocks-test-support.ts | 6 +- extensions/zalouser/src/channel.setup.test.ts | 3 +- extensions/zalouser/src/channel.test.ts | 2 +- extensions/zalouser/src/setup-surface.test.ts | 4 +- .../check-no-extension-test-core-imports.ts | 31 +- .../plugins/setup-wizard-helpers.test.ts | 4 +- .../plugins/setup-wizard-proxy.test.ts | 4 +- src/plugin-sdk/channel-setup.test.ts | 2 +- src/plugin-sdk/testing.ts | 31 +- src/plugins/captured-registration.ts | 18 +- src/test-utils/plugin-registration.ts | 51 ++- src/test-utils/plugin-setup-wizard.ts | 344 ++++++++++++++++++ test/helpers/plugins/env.ts | 1 - test/helpers/plugins/fetch-mock.ts | 1 - test/helpers/plugins/frozen-time.ts | 1 - test/helpers/plugins/media-understanding.ts | 1 - test/helpers/plugins/mock-http-response.ts | 1 - test/helpers/plugins/plugin-registration.ts | 1 - test/helpers/plugins/plugin-registry.ts | 5 - .../plugins/provider-discovery-contract.ts | 2 +- test/helpers/plugins/provider-registration.ts | 91 ----- .../plugins/provider-runtime-contract.ts | 9 +- test/helpers/plugins/provider-usage-fetch.ts | 4 - test/helpers/plugins/runtime-taskflow.ts | 1 - test/helpers/plugins/start-account-context.ts | 2 +- test/helpers/plugins/temp-dir.ts | 1 - test/helpers/plugins/temp-home.ts | 1 - test/helpers/plugins/typed-cases.ts | 1 - test/helpers/provider-replay-policy.ts | 2 +- test/scripts/test-projects.test.ts | 2 +- 126 files changed, 659 insertions(+), 349 deletions(-) create mode 100644 src/test-utils/plugin-setup-wizard.ts delete mode 100644 test/helpers/plugins/env.ts delete mode 100644 test/helpers/plugins/fetch-mock.ts delete mode 100644 test/helpers/plugins/frozen-time.ts delete mode 100644 test/helpers/plugins/media-understanding.ts delete mode 100644 test/helpers/plugins/mock-http-response.ts delete mode 100644 test/helpers/plugins/plugin-registration.ts delete mode 100644 test/helpers/plugins/plugin-registry.ts delete mode 100644 test/helpers/plugins/provider-registration.ts delete mode 100644 test/helpers/plugins/provider-usage-fetch.ts delete mode 100644 test/helpers/plugins/runtime-taskflow.ts delete mode 100644 test/helpers/plugins/temp-dir.ts delete mode 100644 test/helpers/plugins/temp-home.ts delete mode 100644 test/helpers/plugins/typed-cases.ts diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256 index 26ce037c324..4a41cbe41d8 100644 --- a/docs/.generated/plugin-sdk-api-baseline.sha256 +++ b/docs/.generated/plugin-sdk-api-baseline.sha256 @@ -1,2 +1,2 @@ -4e36981eb12b201f14b9d94ba44ab23793ed7555b2d736c1f477aeeb02e9ab9c plugin-sdk-api-baseline.json -8228f54b594b2462b1454c5c43c165ca8a57bec10da5b991fb4b3ba65427f61d plugin-sdk-api-baseline.jsonl +af72813b59c6f35912bb5eacb01365d7686e3b2ca4c8813f7582de10c5da3c81 plugin-sdk-api-baseline.json +71603527acce8f5e1112a035dad6def83c0b02afd831b288fb655f83f8cb3bd1 plugin-sdk-api-baseline.jsonl diff --git a/docs/plugins/sdk-subpaths.md b/docs/plugins/sdk-subpaths.md index 8abaf8be106..fa5949ba721 100644 --- a/docs/plugins/sdk-subpaths.md +++ b/docs/plugins/sdk-subpaths.md @@ -258,7 +258,7 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview) | `plugin-sdk/webhook-path` | Webhook path normalization helpers | | `plugin-sdk/web-media` | Shared remote/local media loading helpers | | `plugin-sdk/zod` | Re-exported `zod` for plugin SDK consumers | - | `plugin-sdk/testing` | Public extension test helpers including plugin registry/runtime mocks, fetch/env/temp fixtures, schema/media/live-test helpers, `installCommonResolveTargetErrorCases`, `writeSkill`, `createTestRegistry`, and live generation env loading. Extension `*.test-support.ts` helpers stay on this or focused SDK subpaths, not core internals | + | `plugin-sdk/testing` | Public extension test helpers including plugin registry/runtime mocks, provider registration capture, setup-wizard helpers, fetch/env/temp/time fixtures, schema/media/live-test helpers, `installCommonResolveTargetErrorCases`, `writeSkill`, `createTestRegistry`, and live generation env loading. Extension `*.test-support.ts` helpers stay on this or focused SDK subpaths, not core internals | diff --git a/docs/plugins/sdk-testing.md b/docs/plugins/sdk-testing.md index bbc04863134..6058aa97275 100644 --- a/docs/plugins/sdk-testing.md +++ b/docs/plugins/sdk-testing.md @@ -47,6 +47,13 @@ import { | `createTempHomeEnv` / `withTempDir` | Create isolated filesystem test fixtures | | `createMockServerResponse` | Create a minimal HTTP server response mock | | `registerSingleProviderPlugin` | Register one provider plugin in loader smoke tests | +| `registerProviderPlugin` | Capture all provider kinds from one plugin | +| `requireRegisteredProvider` | Assert that a provider collection contains an id | +| `createProviderUsageFetch` | Build provider usage fetch fixtures | +| `useFrozenTime` / `useRealTime` | Freeze and restore timers for time-sensitive tests | +| `createRuntimeEnv` | Build a mocked CLI/plugin runtime environment | +| `createTestWizardPrompter` | Build a mocked setup wizard prompter | +| `createPluginSetupWizardStatus` | Build setup status helpers for channel plugins | | `createRuntimeTaskFlow` | Create isolated runtime task-flow state | | `typedCases` | Preserve literal types for table-driven tests | diff --git a/extensions/amazon-bedrock-mantle/index.test.ts b/extensions/amazon-bedrock-mantle/index.test.ts index b3aa7ef5559..de3936812b9 100644 --- a/extensions/amazon-bedrock-mantle/index.test.ts +++ b/extensions/amazon-bedrock-mantle/index.test.ts @@ -1,5 +1,5 @@ +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import bedrockMantlePlugin from "./index.js"; describe("amazon-bedrock-mantle provider plugin", () => { diff --git a/extensions/amazon-bedrock/index.test.ts b/extensions/amazon-bedrock/index.test.ts index 56e29039488..33e9a7486f7 100644 --- a/extensions/amazon-bedrock/index.test.ts +++ b/extensions/amazon-bedrock/index.test.ts @@ -2,9 +2,8 @@ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import type { PluginRuntime } from "openclaw/plugin-sdk/core"; -import { buildPluginApi } from "openclaw/plugin-sdk/testing"; +import { buildPluginApi, registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import { resetBedrockDiscoveryCacheForTest } from "./discovery.js"; import amazonBedrockPlugin from "./index.js"; import { diff --git a/extensions/amazon-bedrock/lazy-import.test.ts b/extensions/amazon-bedrock/lazy-import.test.ts index 312144b8d48..a47d1579465 100644 --- a/extensions/amazon-bedrock/lazy-import.test.ts +++ b/extensions/amazon-bedrock/lazy-import.test.ts @@ -1,5 +1,5 @@ +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; function mockBedrockSdkImportTripwire(): () => number { let importCount = 0; diff --git a/extensions/anthropic-vertex/index.test.ts b/extensions/anthropic-vertex/index.test.ts index d5cc97cc362..5f5a200475b 100644 --- a/extensions/anthropic-vertex/index.test.ts +++ b/extensions/anthropic-vertex/index.test.ts @@ -1,5 +1,5 @@ +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it, vi, beforeEach, afterEach } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; const { hasAnthropicVertexAvailableAuthMock } = vi.hoisted(() => ({ hasAnthropicVertexAvailableAuthMock: vi.fn(), diff --git a/extensions/anthropic/cli-migration.test.ts b/extensions/anthropic/cli-migration.test.ts index 6751daa357a..cc4b6ea0fe7 100644 --- a/extensions/anthropic/cli-migration.test.ts +++ b/extensions/anthropic/cli-migration.test.ts @@ -20,9 +20,8 @@ vi.mock("./cli-auth-seam.js", async (importActual) => { }); const { buildAnthropicCliMigrationResult, hasClaudeCliAuth } = await import("./cli-migration.js"); -const { registerSingleProviderPlugin } = - await import("../../test/helpers/plugins/plugin-registration.js"); -const { createTestWizardPrompter } = await import("../../test/helpers/plugins/setup-wizard.js"); +const { createTestWizardPrompter, registerSingleProviderPlugin } = + await import("openclaw/plugin-sdk/testing"); const { default: anthropicPlugin } = await import("./index.js"); async function resolveAnthropicCliAuthMethod() { diff --git a/extensions/anthropic/index.test.ts b/extensions/anthropic/index.test.ts index 622693fac96..f9212671b1c 100644 --- a/extensions/anthropic/index.test.ts +++ b/extensions/anthropic/index.test.ts @@ -2,9 +2,11 @@ import type { ProviderResolveDynamicModelContext, ProviderRuntimeModel, } from "openclaw/plugin-sdk/plugin-entry"; -import { capturePluginRegistration } from "openclaw/plugin-sdk/testing"; +import { + capturePluginRegistration, + registerSingleProviderPlugin, +} from "openclaw/plugin-sdk/testing"; import { describe, expect, it, vi } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; const { readClaudeCliCredentialsForSetupMock, readClaudeCliCredentialsForRuntimeMock } = vi.hoisted( () => ({ diff --git a/extensions/arcee/index.test.ts b/extensions/arcee/index.test.ts index 19e63741bd8..ce624b7d827 100644 --- a/extensions/arcee/index.test.ts +++ b/extensions/arcee/index.test.ts @@ -1,7 +1,9 @@ import { resolveProviderAuthEnvVarCandidates } from "openclaw/plugin-sdk/provider-env-vars"; -import { resolveProviderPluginChoice } from "openclaw/plugin-sdk/testing"; +import { + registerSingleProviderPlugin, + resolveProviderPluginChoice, +} from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import { runSingleProviderCatalog } from "../test-support/provider-model-test-helpers.js"; import arceePlugin from "./index.js"; diff --git a/extensions/azure-speech/azure-speech.live.test.ts b/extensions/azure-speech/azure-speech.live.test.ts index 44a45ae243f..2215084cd07 100644 --- a/extensions/azure-speech/azure-speech.live.test.ts +++ b/extensions/azure-speech/azure-speech.live.test.ts @@ -1,9 +1,9 @@ -import { isLiveTestEnabled } from "openclaw/plugin-sdk/testing"; -import { describe, expect, it } from "vitest"; import { + isLiveTestEnabled, registerProviderPlugin, requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it } from "vitest"; import plugin from "./index.js"; const AZURE_SPEECH_KEY = diff --git a/extensions/bluebubbles/src/setup-surface.test.ts b/extensions/bluebubbles/src/setup-surface.test.ts index 9a49ea3a622..fb98de88a97 100644 --- a/extensions/bluebubbles/src/setup-surface.test.ts +++ b/extensions/bluebubbles/src/setup-surface.test.ts @@ -2,13 +2,13 @@ import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-h import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing"; import { isPrivateNetworkOptInEnabled } from "openclaw/plugin-sdk/ssrf-runtime"; -import { describe, expect, it, vi } from "vitest"; import { createSetupWizardAdapter, createTestWizardPrompter, runSetupWizardConfigure, type WizardPrompter, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it, vi } from "vitest"; import { resolveBlueBubblesAccount } from "./accounts.js"; import { BlueBubblesConfigSchema } from "./config-schema.js"; import { diff --git a/extensions/byteplus/index.test.ts b/extensions/byteplus/index.test.ts index 253ecd5f791..2fdb636bfe7 100644 --- a/extensions/byteplus/index.test.ts +++ b/extensions/byteplus/index.test.ts @@ -1,7 +1,7 @@ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; import { BYTEPLUS_CODING_MODEL_CATALOG, BYTEPLUS_MODEL_CATALOG } from "./models.js"; diff --git a/extensions/chutes/implicit-provider.test.ts b/extensions/chutes/implicit-provider.test.ts index 4104fb0f8a8..046cce62776 100644 --- a/extensions/chutes/implicit-provider.test.ts +++ b/extensions/chutes/implicit-provider.test.ts @@ -1,6 +1,6 @@ import { resolveOAuthApiKeyMarker } from "openclaw/plugin-sdk/provider-auth"; +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; import { CHUTES_BASE_URL } from "./models.js"; diff --git a/extensions/comfy/index.test.ts b/extensions/comfy/index.test.ts index fae7ea616e2..fc69b24fbcb 100644 --- a/extensions/comfy/index.test.ts +++ b/extensions/comfy/index.test.ts @@ -1,7 +1,9 @@ import fs from "node:fs"; -import { resolveProviderPluginChoice } from "openclaw/plugin-sdk/testing"; +import { + registerSingleProviderPlugin, + resolveProviderPluginChoice, +} from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; type ComfyManifest = { diff --git a/extensions/deepseek/index.test.ts b/extensions/deepseek/index.test.ts index 2e0520c521d..c92bc28a68a 100644 --- a/extensions/deepseek/index.test.ts +++ b/extensions/deepseek/index.test.ts @@ -1,9 +1,11 @@ import type { Context, Model } from "@mariozechner/pi-ai"; import { createAssistantMessageEventStream } from "@mariozechner/pi-ai"; import { buildOpenAICompletionsParams } from "openclaw/plugin-sdk/provider-transport-runtime"; -import { resolveProviderPluginChoice } from "openclaw/plugin-sdk/testing"; +import { + registerSingleProviderPlugin, + resolveProviderPluginChoice, +} from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import { runSingleProviderCatalog } from "../test-support/provider-model-test-helpers.js"; import deepseekPlugin from "./index.js"; import { createDeepSeekV4ThinkingWrapper } from "./stream.js"; diff --git a/extensions/diffs/src/browser.test.ts b/extensions/diffs/src/browser.test.ts index 8c6d5c20104..538265aae6c 100644 --- a/extensions/diffs/src/browser.test.ts +++ b/extensions/diffs/src/browser.test.ts @@ -1,8 +1,8 @@ import fs from "node:fs/promises"; import type { IncomingMessage, ServerResponse } from "node:http"; import path from "node:path"; +import { createMockServerResponse } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { createMockServerResponse } from "../../../test/helpers/plugins/mock-http-response.js"; import { createTestPluginApi } from "../../../test/helpers/plugins/plugin-api.js"; import type { OpenClawConfig } from "../api.js"; import type { OpenClawPluginApi, OpenClawPluginToolContext } from "../api.js"; diff --git a/extensions/diffs/src/store.test.ts b/extensions/diffs/src/store.test.ts index 0c4d61ee1c5..0f32b275a3d 100644 --- a/extensions/diffs/src/store.test.ts +++ b/extensions/diffs/src/store.test.ts @@ -1,8 +1,8 @@ import fs from "node:fs/promises"; import type { IncomingMessage } from "node:http"; import path from "node:path"; +import { createMockServerResponse } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { createMockServerResponse } from "../../../test/helpers/plugins/mock-http-response.js"; import { createDiffsHttpHandler } from "./http.js"; import { DiffArtifactStore } from "./store.js"; import { createDiffStoreHarness } from "./test-helpers.js"; diff --git a/extensions/discord/src/monitor.test.ts b/extensions/discord/src/monitor.test.ts index f0e7eecb5e9..0456d2f26dd 100644 --- a/extensions/discord/src/monitor.test.ts +++ b/extensions/discord/src/monitor.test.ts @@ -1,6 +1,6 @@ import { ChannelType, type Guild } from "@buape/carbon"; +import { typedCases } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { typedCases } from "../../../test/helpers/plugins/typed-cases.js"; import { allowListMatches, type DiscordGuildEntryResolved, diff --git a/extensions/discord/src/monitor/native-command.plugin-dispatch.test.ts b/extensions/discord/src/monitor/native-command.plugin-dispatch.test.ts index 6336d6a1aa4..5e6c07d1568 100644 --- a/extensions/discord/src/monitor/native-command.plugin-dispatch.test.ts +++ b/extensions/discord/src/monitor/native-command.plugin-dispatch.test.ts @@ -9,11 +9,8 @@ import { registerPluginCommand, } from "openclaw/plugin-sdk/plugin-runtime"; import { dispatchReplyWithDispatcher } from "openclaw/plugin-sdk/reply-dispatch-runtime"; +import { createTestRegistry, setActivePluginRegistry } from "openclaw/plugin-sdk/testing"; import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { - createTestRegistry, - setActivePluginRegistry, -} from "../../../../test/helpers/plugins/plugin-registry.js"; import { defineThrowingDiscordChannelGetter } from "../test-support/partial-channel.js"; import { resolveDiscordNativeInteractionRouteState } from "./native-command-route.js"; import { diff --git a/extensions/discord/src/monitor/provider.allowlist.test.ts b/extensions/discord/src/monitor/provider.allowlist.test.ts index 80a95bc20bf..b31b067f1c1 100644 --- a/extensions/discord/src/monitor/provider.allowlist.test.ts +++ b/extensions/discord/src/monitor/provider.allowlist.test.ts @@ -1,6 +1,6 @@ import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env"; +import { createNonExitingTypedRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { createNonExitingTypedRuntimeEnv } from "../../../../test/helpers/plugins/runtime-env.js"; import * as resolveChannelsModule from "../resolve-channels.js"; import * as resolveUsersModule from "../resolve-users.js"; import { resolveDiscordAllowlistConfig } from "./provider.allowlist.js"; diff --git a/extensions/elevenlabs/elevenlabs.live.test.ts b/extensions/elevenlabs/elevenlabs.live.test.ts index e3e09b9a1c3..57bc37e17d4 100644 --- a/extensions/elevenlabs/elevenlabs.live.test.ts +++ b/extensions/elevenlabs/elevenlabs.live.test.ts @@ -1,9 +1,9 @@ -import { isLiveTestEnabled } from "openclaw/plugin-sdk/testing"; -import { describe, expect, it } from "vitest"; import { + isLiveTestEnabled, registerProviderPlugin, requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it } from "vitest"; import { normalizeTranscriptForMatch, runRealtimeSttLiveTest, diff --git a/extensions/feishu/src/bot.card-action.test.ts b/extensions/feishu/src/bot.card-action.test.ts index 9c9ba50e0ed..4ca24492088 100644 --- a/extensions/feishu/src/bot.card-action.test.ts +++ b/extensions/feishu/src/bot.card-action.test.ts @@ -1,5 +1,5 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { describe, it, expect, vi, beforeEach } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js"; import { FeishuRetryableCardActionError, diff --git a/extensions/feishu/src/bot.test.ts b/extensions/feishu/src/bot.test.ts index 755d523902d..7b3db8914a1 100644 --- a/extensions/feishu/src/bot.test.ts +++ b/extensions/feishu/src/bot.test.ts @@ -1,7 +1,7 @@ import type * as ConversationRuntime from "openclaw/plugin-sdk/conversation-runtime"; import type { ResolvedAgentRoute } from "openclaw/plugin-sdk/routing"; +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { ClawdbotConfig, PluginRuntime } from "../runtime-api.js"; import type { FeishuMessageEvent } from "./bot.js"; import { handleFeishuMessage } from "./bot.js"; diff --git a/extensions/feishu/src/card-ux-launcher.test.ts b/extensions/feishu/src/card-ux-launcher.test.ts index 1cbacaffb78..5ca6c794c1d 100644 --- a/extensions/feishu/src/card-ux-launcher.test.ts +++ b/extensions/feishu/src/card-ux-launcher.test.ts @@ -1,5 +1,5 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { describe, expect, it, vi, beforeEach } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js"; import { expectFirstSentCardUsesFillWidthOnly, diff --git a/extensions/feishu/src/monitor.acp-init-failure.lifecycle.test-support.ts b/extensions/feishu/src/monitor.acp-init-failure.lifecycle.test-support.ts index 7a9bd1f7d61..9e9130b8000 100644 --- a/extensions/feishu/src/monitor.acp-init-failure.lifecycle.test-support.ts +++ b/extensions/feishu/src/monitor.acp-init-failure.lifecycle.test-support.ts @@ -1,6 +1,6 @@ import "./lifecycle.test-support.js"; +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { ClawdbotConfig } from "../runtime-api.js"; import { getFeishuLifecycleTestMocks, @@ -30,7 +30,7 @@ const { } = getFeishuLifecycleTestMocks(); let _handlers: Record Promise> = {}; -let lastRuntime: ReturnType | null = null; +let lastRuntime = createRuntimeEnv(); const originalStateDir = process.env.OPENCLAW_STATE_DIR; const { cfg: lifecycleConfig, account: lifecycleAccount } = createFeishuLifecycleFixture({ accountId: "acct-acp", @@ -78,7 +78,7 @@ describe("Feishu ACP-init failure lifecycle", () => { vi.useRealTimers(); resetFeishuLifecycleTestMocks(); _handlers = {}; - lastRuntime = null; + lastRuntime = createRuntimeEnv(); setFeishuLifecycleStateDir("openclaw-feishu-acp-failure"); resolveBoundConversationMock.mockReturnValue(null); diff --git a/extensions/feishu/src/monitor.bot-menu.lifecycle.test-support.ts b/extensions/feishu/src/monitor.bot-menu.lifecycle.test-support.ts index c1f7aadb585..f026fa2e29e 100644 --- a/extensions/feishu/src/monitor.bot-menu.lifecycle.test-support.ts +++ b/extensions/feishu/src/monitor.bot-menu.lifecycle.test-support.ts @@ -1,5 +1,5 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import "./lifecycle.test-support.js"; import { getFeishuLifecycleTestMocks, @@ -33,7 +33,7 @@ const { } = getFeishuLifecycleTestMocks(); let _handlers: Record Promise> = {}; -let lastRuntime: ReturnType | null = null; +let lastRuntime = createRuntimeEnv(); const originalStateDir = process.env.OPENCLAW_STATE_DIR; const lifecycleConfig = createFeishuLifecycleConfig({ accountId: "acct-menu", @@ -90,7 +90,7 @@ describe("Feishu bot-menu lifecycle", () => { vi.useRealTimers(); resetFeishuLifecycleTestMocks(); _handlers = {}; - lastRuntime = null; + lastRuntime = createRuntimeEnv(); setFeishuLifecycleStateDir("openclaw-feishu-bot-menu"); createFeishuReplyDispatcherMock.mockReturnValue(createFeishuLifecycleReplyDispatcher()); diff --git a/extensions/feishu/src/monitor.broadcast.reply-once.lifecycle.test-support.ts b/extensions/feishu/src/monitor.broadcast.reply-once.lifecycle.test-support.ts index bd3afc357c2..7ce3344db24 100644 --- a/extensions/feishu/src/monitor.broadcast.reply-once.lifecycle.test-support.ts +++ b/extensions/feishu/src/monitor.broadcast.reply-once.lifecycle.test-support.ts @@ -1,6 +1,6 @@ import "./lifecycle.test-support.js"; +import { createNonExitingRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { createNonExitingRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js"; import { FeishuConfigSchema } from "./config-schema.js"; import { diff --git a/extensions/feishu/src/monitor.card-action.lifecycle.test-support.ts b/extensions/feishu/src/monitor.card-action.lifecycle.test-support.ts index f3b34d4378d..90f6e077ca4 100644 --- a/extensions/feishu/src/monitor.card-action.lifecycle.test-support.ts +++ b/extensions/feishu/src/monitor.card-action.lifecycle.test-support.ts @@ -1,5 +1,5 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import "./lifecycle.test-support.js"; import { resetProcessedFeishuCardActionTokensForTests } from "./card-action.js"; import { createFeishuCardInteractionEnvelope } from "./card-interaction.js"; @@ -35,7 +35,7 @@ const { } = getFeishuLifecycleTestMocks(); let _handlers: Record Promise> = {}; -let lastRuntime: ReturnType | null = null; +let lastRuntime = createRuntimeEnv(); const originalStateDir = process.env.OPENCLAW_STATE_DIR; const lifecycleConfig = createFeishuLifecycleConfig({ accountId: "acct-card", @@ -117,7 +117,7 @@ describe("Feishu card-action lifecycle", () => { vi.useRealTimers(); resetFeishuLifecycleTestMocks(); _handlers = {}; - lastRuntime = null; + lastRuntime = createRuntimeEnv(); resetProcessedFeishuCardActionTokensForTests(); setFeishuLifecycleStateDir("openclaw-feishu-card-action"); diff --git a/extensions/feishu/src/monitor.comment.test.ts b/extensions/feishu/src/monitor.comment.test.ts index f3237c99c18..4e906e0b9c1 100644 --- a/extensions/feishu/src/monitor.comment.test.ts +++ b/extensions/feishu/src/monitor.comment.test.ts @@ -1,5 +1,5 @@ +import { createNonExitingRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { createNonExitingRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { ClawdbotConfig } from "../runtime-api.js"; import * as dedup from "./dedup.js"; import { createFeishuDriveCommentNoticeHandler } from "./monitor.comment-notice-handler.js"; @@ -11,7 +11,7 @@ import { const handleFeishuCommentEventMock = vi.hoisted(() => vi.fn(async () => {})); const createFeishuClientMock = vi.hoisted(() => vi.fn()); -let lastRuntime: ReturnType | null = null; +let lastRuntime = createNonExitingRuntimeEnv(); const TEST_DOC_TOKEN = "ZsJfdxrBFo0RwuxteOLc1Ekvneb"; const TEST_WIKI_TOKEN = "OtYpd5pKOoMeQzxrzkocv9KIn4H"; @@ -804,7 +804,7 @@ describe("resolveDriveCommentEventTurn", () => { describe("drive.notice.comment_add_v1 monitor handler", () => { beforeEach(() => { - lastRuntime = null; + lastRuntime = createNonExitingRuntimeEnv(); handleFeishuCommentEventMock.mockClear(); createFeishuClientMock.mockReset().mockReturnValue(makeOpenApiClient({}) as never); vi.spyOn(dedup, "claimUnprocessedFeishuMessage").mockResolvedValue("claimed"); diff --git a/extensions/feishu/src/monitor.reaction.test.ts b/extensions/feishu/src/monitor.reaction.test.ts index b07d8543d9c..1933745bf63 100644 --- a/extensions/feishu/src/monitor.reaction.test.ts +++ b/extensions/feishu/src/monitor.reaction.test.ts @@ -3,8 +3,8 @@ import { resolveInboundDebounceMs, } from "openclaw/plugin-sdk/channel-inbound-debounce"; import { hasControlCommand } from "openclaw/plugin-sdk/command-detection"; +import { createNonExitingTypedRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { createNonExitingTypedRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { ClawdbotConfig, PluginRuntime, RuntimeEnv } from "../runtime-api.js"; import { parseFeishuMessageEvent, type FeishuMessageEvent } from "./bot.js"; import * as dedup from "./dedup.js"; diff --git a/extensions/feishu/src/monitor.reply-once.lifecycle.test-support.ts b/extensions/feishu/src/monitor.reply-once.lifecycle.test-support.ts index a4c326b4173..66faa3f8cd1 100644 --- a/extensions/feishu/src/monitor.reply-once.lifecycle.test-support.ts +++ b/extensions/feishu/src/monitor.reply-once.lifecycle.test-support.ts @@ -1,5 +1,5 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import "./lifecycle.test-support.js"; import { getFeishuLifecycleTestMocks, @@ -27,7 +27,7 @@ const { withReplyDispatcherMock, } = getFeishuLifecycleTestMocks(); -let lastRuntime: ReturnType | null = null; +let lastRuntime = createRuntimeEnv(); let lifecycleCore: ReturnType; const handleMessageMock = vi.fn(); const originalStateDir = process.env.OPENCLAW_STATE_DIR; @@ -67,7 +67,7 @@ describe("Feishu reply-once lifecycle", () => { vi.useRealTimers(); resetFeishuLifecycleTestMocks(); handleMessageMock.mockReset(); - lastRuntime = null; + lastRuntime = createRuntimeEnv(); setFeishuLifecycleStateDir("openclaw-feishu-lifecycle"); createFeishuReplyDispatcherMock.mockReturnValue(createFeishuLifecycleReplyDispatcher()); diff --git a/extensions/feishu/src/monitor.startup.test.ts b/extensions/feishu/src/monitor.startup.test.ts index 2abf3b15b74..f9c44c64c62 100644 --- a/extensions/feishu/src/monitor.startup.test.ts +++ b/extensions/feishu/src/monitor.startup.test.ts @@ -1,5 +1,5 @@ +import { createNonExitingRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { createNonExitingRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { ClawdbotConfig } from "../runtime-api.js"; import { monitorFeishuProvider, stopFeishuMonitor } from "./monitor.js"; diff --git a/extensions/feishu/src/setup-surface.test.ts b/extensions/feishu/src/setup-surface.test.ts index 98fc669f360..d734fc6584c 100644 --- a/extensions/feishu/src/setup-surface.test.ts +++ b/extensions/feishu/src/setup-surface.test.ts @@ -1,11 +1,11 @@ -import { describe, expect, it, vi } from "vitest"; -import { createNonExitingTypedRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import { + createNonExitingTypedRuntimeEnv, createPluginSetupWizardConfigure, createPluginSetupWizardStatus, createTestWizardPrompter, runSetupWizardConfigure, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it, vi } from "vitest"; vi.mock("./probe.js", () => ({ probeFeishu: vi.fn(async () => ({ ok: false, error: "mocked" })), diff --git a/extensions/fireworks/index.test.ts b/extensions/fireworks/index.test.ts index b866ea4c0a4..350c85baca2 100644 --- a/extensions/fireworks/index.test.ts +++ b/extensions/fireworks/index.test.ts @@ -1,7 +1,9 @@ import type { ProviderRuntimeModel } from "openclaw/plugin-sdk/plugin-entry"; -import { resolveProviderPluginChoice } from "openclaw/plugin-sdk/testing"; +import { + registerSingleProviderPlugin, + resolveProviderPluginChoice, +} from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import { createProviderDynamicModelContext, runSingleProviderCatalog, diff --git a/extensions/github-copilot/models.test.ts b/extensions/github-copilot/models.test.ts index 9ff231062e1..3edc43dfcae 100644 --- a/extensions/github-copilot/models.test.ts +++ b/extensions/github-copilot/models.test.ts @@ -1,8 +1,5 @@ +import { createProviderUsageFetch, makeResponse } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { - createProviderUsageFetch, - makeResponse, -} from "../../test/helpers/plugins/provider-usage-fetch.js"; import { buildCopilotModelDefinition, getDefaultCopilotModelIds } from "./models-defaults.js"; import { fetchCopilotUsage } from "./usage.js"; diff --git a/extensions/google/google.live.test.ts b/extensions/google/google.live.test.ts index 601a213e301..4849455488e 100644 --- a/extensions/google/google.live.test.ts +++ b/extensions/google/google.live.test.ts @@ -1,9 +1,9 @@ -import { isLiveTestEnabled } from "openclaw/plugin-sdk/testing"; -import { describe, expect, it } from "vitest"; import { + isLiveTestEnabled, registerProviderPlugin, requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it } from "vitest"; import { normalizeTranscriptForMatch } from "../../test/helpers/stt-live-audio.js"; import plugin from "./index.js"; import { createGeminiWebSearchProvider } from "./src/gemini-web-search-provider.js"; diff --git a/extensions/google/index.test.ts b/extensions/google/index.test.ts index 400ef9cdf89..bfecc7f0c8d 100644 --- a/extensions/google/index.test.ts +++ b/extensions/google/index.test.ts @@ -3,11 +3,8 @@ import type { ProviderReplaySessionEntry, ProviderSanitizeReplayHistoryContext, } from "openclaw/plugin-sdk/plugin-entry"; +import { registerProviderPlugin, requireRegisteredProvider } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; import { createCapturedThinkingConfigStream } from "../../test/helpers/plugins/stream-hooks.js"; import { registerGoogleGeminiCliProvider } from "./gemini-cli-provider.js"; import { registerGoogleProvider } from "./provider-registration.js"; diff --git a/extensions/googlechat/src/monitor.webhook-routing.test.ts b/extensions/googlechat/src/monitor.webhook-routing.test.ts index be07f360c33..6f3fe9b592b 100644 --- a/extensions/googlechat/src/monitor.webhook-routing.test.ts +++ b/extensions/googlechat/src/monitor.webhook-routing.test.ts @@ -1,8 +1,11 @@ import { EventEmitter } from "node:events"; import type { IncomingMessage } from "node:http"; -import { createEmptyPluginRegistry, setActivePluginRegistry } from "openclaw/plugin-sdk/testing"; +import { + createEmptyPluginRegistry, + createMockServerResponse, + setActivePluginRegistry, +} from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { createMockServerResponse } from "../../../test/helpers/plugins/mock-http-response.js"; import type { OpenClawConfig, PluginRuntime } from "../runtime-api.js"; import type { ResolvedGoogleChatAccount } from "./accounts.js"; import { verifyGoogleChatRequest } from "./auth.js"; diff --git a/extensions/googlechat/src/setup.test.ts b/extensions/googlechat/src/setup.test.ts index 1a978394d31..c7a07d2da8c 100644 --- a/extensions/googlechat/src/setup.test.ts +++ b/extensions/googlechat/src/setup.test.ts @@ -1,12 +1,12 @@ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/setup"; -import { afterEach, describe, expect, it, vi } from "vitest"; import { createPluginSetupWizardConfigure, createPluginSetupWizardStatus, createTestWizardPrompter, runSetupWizardConfigure, type WizardPrompter, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { expectLifecyclePatch, expectPendingUntilAbort, diff --git a/extensions/gradium/gradium.live.test.ts b/extensions/gradium/gradium.live.test.ts index fd1fc80dcfe..c3ae7c77fe0 100644 --- a/extensions/gradium/gradium.live.test.ts +++ b/extensions/gradium/gradium.live.test.ts @@ -1,12 +1,12 @@ import { writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { isLiveTestEnabled } from "openclaw/plugin-sdk/testing"; -import { describe, expect, it } from "vitest"; import { + isLiveTestEnabled, registerProviderPlugin, requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it } from "vitest"; import plugin from "./index.js"; const LIVE = isLiveTestEnabled(); diff --git a/extensions/imessage/src/status.test.ts b/extensions/imessage/src/status.test.ts index 63f6ba8c1c7..6acd1fde808 100644 --- a/extensions/imessage/src/status.test.ts +++ b/extensions/imessage/src/status.test.ts @@ -1,7 +1,7 @@ import * as processRuntime from "openclaw/plugin-sdk/process-runtime"; import * as setupRuntime from "openclaw/plugin-sdk/setup"; +import { createPluginSetupWizardStatus } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { createPluginSetupWizardStatus } from "../../../test/helpers/plugins/setup-wizard.js"; import { resolveIMessageAccount } from "./accounts.js"; import * as channelRuntimeModule from "./channel.runtime.js"; import * as clientModule from "./client.js"; diff --git a/extensions/inworld/inworld.live.test.ts b/extensions/inworld/inworld.live.test.ts index 7bc37cf5fbe..6f1144cf6df 100644 --- a/extensions/inworld/inworld.live.test.ts +++ b/extensions/inworld/inworld.live.test.ts @@ -1,9 +1,9 @@ -import { isLiveTestEnabled } from "openclaw/plugin-sdk/testing"; -import { describe, expect, it } from "vitest"; import { + isLiveTestEnabled, registerProviderPlugin, requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it } from "vitest"; import plugin from "./index.js"; const INWORLD_API_KEY = process.env.INWORLD_API_KEY?.trim() ?? ""; diff --git a/extensions/irc/src/setup.test.ts b/extensions/irc/src/setup.test.ts index 9a15b47a060..278bde319fa 100644 --- a/extensions/irc/src/setup.test.ts +++ b/extensions/irc/src/setup.test.ts @@ -1,4 +1,3 @@ -import { afterEach, describe, expect, it, vi } from "vitest"; import { createPluginSetupWizardAdapter, createPluginSetupWizardStatus, @@ -6,7 +5,8 @@ import { promptSetupWizardAllowFrom, runSetupWizardConfigure, type WizardPrompter, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { expectStopPendingUntilAbort, startAccountAndTrackLifecycle, @@ -409,15 +409,16 @@ describe("irc setup", () => { }, }; - const updated = (await promptSetupWizardAllowFrom({ + const updated = await promptSetupWizardAllowFrom({ promptAllowFrom, cfg, prompter, accountId: "work", - })) as CoreConfig; + }); + expect(updated).toBeDefined(); - expect(updated.channels?.irc?.allowFrom).toEqual(["alice", "bob!ident@example.org"]); - expect(updated.channels?.irc?.accounts?.work?.allowFrom).toBeUndefined(); + expect(updated?.channels?.irc?.allowFrom).toEqual(["alice", "bob!ident@example.org"]); + expect(updated?.channels?.irc?.accounts?.work?.allowFrom).toBeUndefined(); }); it("keeps startAccount pending until abort, then stops the monitor", async () => { diff --git a/extensions/kilocode/index.test.ts b/extensions/kilocode/index.test.ts index 632c1067470..d17ed9d0ac6 100644 --- a/extensions/kilocode/index.test.ts +++ b/extensions/kilocode/index.test.ts @@ -1,7 +1,7 @@ import type { StreamFn } from "@mariozechner/pi-agent-core"; import type { Context, Model } from "@mariozechner/pi-ai"; +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import { expectPassthroughReplayPolicy } from "../../test/helpers/provider-replay-policy.ts"; import plugin from "./index.js"; diff --git a/extensions/kimi-coding/implicit-provider.test.ts b/extensions/kimi-coding/implicit-provider.test.ts index ff2d0141494..6f2544c0ea4 100644 --- a/extensions/kimi-coding/implicit-provider.test.ts +++ b/extensions/kimi-coding/implicit-provider.test.ts @@ -1,5 +1,5 @@ +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; async function runKimiCatalog(params: { diff --git a/extensions/kimi-coding/index.test.ts b/extensions/kimi-coding/index.test.ts index 92631bf2e89..fe9921c8861 100644 --- a/extensions/kimi-coding/index.test.ts +++ b/extensions/kimi-coding/index.test.ts @@ -1,5 +1,5 @@ +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; describe("kimi provider plugin", () => { diff --git a/extensions/line/src/bot-message-context.test.ts b/extensions/line/src/bot-message-context.test.ts index 3487378ee60..052b23bd76a 100644 --- a/extensions/line/src/bot-message-context.test.ts +++ b/extensions/line/src/bot-message-context.test.ts @@ -5,11 +5,8 @@ import type { webhook } from "@line/bot-sdk"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-runtime"; import { __testing as sessionBindingTesting } from "openclaw/plugin-sdk/conversation-runtime"; +import { createTestRegistry, setActivePluginRegistry } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { - createTestRegistry, - setActivePluginRegistry, -} from "../../../test/helpers/plugins/plugin-registry.js"; import { lineBindingsAdapter } from "./bindings.js"; import { buildLineMessageContext, buildLinePostbackContext } from "./bot-message-context.js"; import type { ResolvedLineAccount } from "./types.js"; diff --git a/extensions/line/src/channel.logout.test.ts b/extensions/line/src/channel.logout.test.ts index ac78351206c..e6a830aae9e 100644 --- a/extensions/line/src/channel.logout.test.ts +++ b/extensions/line/src/channel.logout.test.ts @@ -1,5 +1,5 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { OpenClawConfig, PluginRuntime, ResolvedLineAccount } from "../api.js"; import { lineGatewayAdapter } from "./gateway.js"; import { setLineRuntime } from "./runtime.js"; diff --git a/extensions/line/src/setup-surface.test.ts b/extensions/line/src/setup-surface.test.ts index 442365778df..d7cb4d2c902 100644 --- a/extensions/line/src/setup-surface.test.ts +++ b/extensions/line/src/setup-surface.test.ts @@ -1,14 +1,14 @@ import { readFileSync } from "node:fs"; import path from "node:path"; -import ts from "typescript"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { bundledPluginRoot } from "../../../test/helpers/bundled-plugin-paths.js"; import { createPluginSetupWizardConfigure, createTestWizardPrompter, runSetupWizardConfigure, type WizardPrompter, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import ts from "typescript"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { bundledPluginRoot } from "../../../test/helpers/bundled-plugin-paths.js"; import { createStartAccountContext } from "../../../test/helpers/plugins/start-account-context.js"; import type { OpenClawConfig, PluginRuntime, ResolvedLineAccount } from "../api.js"; import { linePlugin } from "./channel.js"; diff --git a/extensions/matrix/src/channel.directory.test.ts b/extensions/matrix/src/channel.directory.test.ts index 32e9a48bd22..fbabb024c72 100644 --- a/extensions/matrix/src/channel.directory.test.ts +++ b/extensions/matrix/src/channel.directory.test.ts @@ -1,5 +1,5 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { RuntimeEnv } from "../runtime-api.js"; import { matrixPlugin } from "./channel.js"; import { resolveMatrixAccount } from "./matrix/accounts.js"; diff --git a/extensions/matrix/src/channel.resolve.test.ts b/extensions/matrix/src/channel.resolve.test.ts index c69f3436cdd..be17b57d93c 100644 --- a/extensions/matrix/src/channel.resolve.test.ts +++ b/extensions/matrix/src/channel.resolve.test.ts @@ -1,5 +1,5 @@ +import { createNonExitingRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { createNonExitingRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; const resolveMatrixTargetsMock = vi.hoisted(() => vi.fn(async () => [])); diff --git a/extensions/minimax/index.test.ts b/extensions/minimax/index.test.ts index 46c25956d2e..7b95f614b31 100644 --- a/extensions/minimax/index.test.ts +++ b/extensions/minimax/index.test.ts @@ -1,10 +1,7 @@ import type { StreamFn } from "@mariozechner/pi-agent-core"; import type { Context, Model } from "@mariozechner/pi-ai"; +import { registerProviderPlugin, requireRegisteredProvider } from "openclaw/plugin-sdk/testing"; import { describe, expect, it, vi } from "vitest"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; import { registerMinimaxProviders } from "./provider-registration.js"; import { createMiniMaxWebSearchProvider } from "./src/minimax-web-search-provider.js"; diff --git a/extensions/minimax/minimax.live.test.ts b/extensions/minimax/minimax.live.test.ts index 57ddece57d3..37d0a64c96c 100644 --- a/extensions/minimax/minimax.live.test.ts +++ b/extensions/minimax/minimax.live.test.ts @@ -1,9 +1,9 @@ -import { isLiveTestEnabled } from "openclaw/plugin-sdk/testing"; -import { describe, expect, it } from "vitest"; import { + isLiveTestEnabled, registerProviderPlugin, requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it } from "vitest"; import plugin from "./index.js"; import { buildMinimaxSpeechProvider } from "./speech-provider.js"; import { createMiniMaxWebSearchProvider } from "./src/minimax-web-search-provider.js"; diff --git a/extensions/moonshot/index.test.ts b/extensions/moonshot/index.test.ts index a5527a47938..d6806425c92 100644 --- a/extensions/moonshot/index.test.ts +++ b/extensions/moonshot/index.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import type { Context, Model } from "@mariozechner/pi-ai"; +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import { createCapturedThinkingConfigStream } from "../../test/helpers/plugins/stream-hooks.js"; import plugin from "./index.js"; import { createKimiWebSearchProvider } from "./src/kimi-web-search-provider.js"; diff --git a/extensions/music-generation-providers.live.test.ts b/extensions/music-generation-providers.live.test.ts index 46efd503405..bffdefe9482 100644 --- a/extensions/music-generation-providers.live.test.ts +++ b/extensions/music-generation-providers.live.test.ts @@ -16,14 +16,12 @@ import { parseCsvFilter, parseProviderModelMap, redactLiveApiKey, + registerProviderPlugin, + requireRegisteredProvider, resolveConfiguredLiveMusicModels, resolveLiveMusicAuthStore, } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../test/helpers/plugins/provider-registration.js"; import googlePlugin from "./google/index.js"; import minimaxPlugin from "./minimax/index.js"; import { maybeLoadShellEnvForGenerationProviders } from "./test-support/generation-live-test-helpers.js"; diff --git a/extensions/nostr/src/channel.test.ts b/extensions/nostr/src/channel.test.ts index 9bc18fb72ce..e9ee740a73e 100644 --- a/extensions/nostr/src/channel.test.ts +++ b/extensions/nostr/src/channel.test.ts @@ -1,10 +1,10 @@ -import { describe, expect, it, vi } from "vitest"; import { createPluginSetupWizardConfigure, createTestWizardPrompter, runSetupWizardConfigure, type WizardPrompter, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../runtime-api.js"; import { nostrSetupWizard } from "./setup-surface.js"; import { diff --git a/extensions/nvidia/index.test.ts b/extensions/nvidia/index.test.ts index 2f91e953554..32bb070eb30 100644 --- a/extensions/nvidia/index.test.ts +++ b/extensions/nvidia/index.test.ts @@ -1,7 +1,9 @@ import fs from "node:fs"; -import { resolveProviderPluginChoice } from "openclaw/plugin-sdk/testing"; +import { + registerSingleProviderPlugin, + resolveProviderPluginChoice, +} from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; type NvidiaManifest = { diff --git a/extensions/openai/index.test.ts b/extensions/openai/index.test.ts index e8addcbde11..58a51676c05 100644 --- a/extensions/openai/index.test.ts +++ b/extensions/openai/index.test.ts @@ -2,12 +2,9 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import * as providerAuth from "openclaw/plugin-sdk/provider-auth-runtime"; import * as providerHttp from "openclaw/plugin-sdk/provider-http"; import type { ProviderPlugin } from "openclaw/plugin-sdk/provider-model-shared"; +import { registerProviderPlugin, requireRegisteredProvider } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { createTestPluginApi } from "../../test/helpers/plugins/plugin-api.js"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; import { buildOpenAIImageGenerationProvider } from "./image-generation-provider.js"; import plugin from "./index.js"; import { diff --git a/extensions/openai/openai.live.test.ts b/extensions/openai/openai.live.test.ts index 27af5b04fea..6009388df6f 100644 --- a/extensions/openai/openai.live.test.ts +++ b/extensions/openai/openai.live.test.ts @@ -8,11 +8,8 @@ import type { ResolvedTtsConfig } from "openclaw/plugin-sdk/agent-runtime"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import { encodePngRgba, fillPixel } from "openclaw/plugin-sdk/media-runtime"; import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot"; +import { registerProviderPlugin, requireRegisteredProvider } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; import { runRealtimeSttLiveTest } from "../../test/helpers/stt-live-audio.js"; import plugin from "./index.js"; diff --git a/extensions/openai/test-support/provider-catalog.contract-test-support.ts b/extensions/openai/test-support/provider-catalog.contract-test-support.ts index a854ce3a6f6..f18bd495df5 100644 --- a/extensions/openai/test-support/provider-catalog.contract-test-support.ts +++ b/extensions/openai/test-support/provider-catalog.contract-test-support.ts @@ -1,3 +1,4 @@ +import { registerProviderPlugin, requireRegisteredProvider } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, it, vi } from "vitest"; import { expectAugmentedCodexCatalog, @@ -8,10 +9,6 @@ import { loadBundledPluginPublicSurface, } from "../../../test/helpers/plugins/provider-catalog.js"; import type { ProviderPlugin } from "../../../test/helpers/plugins/provider-catalog.js"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../../../test/helpers/plugins/provider-registration.js"; const PROVIDER_CATALOG_CONTRACT_TIMEOUT_MS = 300_000; diff --git a/extensions/opencode-go/index.test.ts b/extensions/opencode-go/index.test.ts index 31d541e6bf6..c0b5d6c47d2 100644 --- a/extensions/opencode-go/index.test.ts +++ b/extensions/opencode-go/index.test.ts @@ -1,7 +1,6 @@ import { getModels } from "@mariozechner/pi-ai"; +import { registerProviderPlugin, registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; -import { registerProviderPlugin } from "../../test/helpers/plugins/provider-registration.js"; import { expectPassthroughReplayPolicy } from "../../test/helpers/provider-replay-policy.ts"; import plugin from "./index.js"; diff --git a/extensions/opencode/index.test.ts b/extensions/opencode/index.test.ts index 1e4e8c3d88b..768b79330d6 100644 --- a/extensions/opencode/index.test.ts +++ b/extensions/opencode/index.test.ts @@ -1,8 +1,5 @@ +import { registerProviderPlugin, requireRegisteredProvider } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; import { expectPassthroughReplayPolicy } from "../../test/helpers/provider-replay-policy.ts"; import plugin from "./index.js"; diff --git a/extensions/openrouter/index.test.ts b/extensions/openrouter/index.test.ts index d13412a4840..97bb1efabb3 100644 --- a/extensions/openrouter/index.test.ts +++ b/extensions/openrouter/index.test.ts @@ -1,6 +1,5 @@ +import { registerProviderPlugin, registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it, vi } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; -import { registerProviderPlugin } from "../../test/helpers/plugins/provider-registration.js"; import { expectPassthroughReplayPolicy } from "../../test/helpers/provider-replay-policy.ts"; import openrouterPlugin from "./index.js"; import { diff --git a/extensions/openrouter/openrouter.live.test.ts b/extensions/openrouter/openrouter.live.test.ts index 1bafd08c37b..8f2e24c4c73 100644 --- a/extensions/openrouter/openrouter.live.test.ts +++ b/extensions/openrouter/openrouter.live.test.ts @@ -1,10 +1,7 @@ import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent"; import OpenAI from "openai"; +import { registerProviderPlugin, requireRegisteredProvider } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; import plugin from "./index.js"; const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY ?? ""; diff --git a/extensions/qa-channel/src/channel.test.ts b/extensions/qa-channel/src/channel.test.ts index a776097b78b..8eec6a51f37 100644 --- a/extensions/qa-channel/src/channel.test.ts +++ b/extensions/qa-channel/src/channel.test.ts @@ -1,11 +1,11 @@ import type { PluginRuntime } from "openclaw/plugin-sdk/core"; import { + createTestRegistry, resetPluginRuntimeStateForTest, setActivePluginRegistry, } from "openclaw/plugin-sdk/testing"; import { extractToolPayload } from "openclaw/plugin-sdk/tool-payload"; import { afterEach, describe, expect, it } from "vitest"; -import { createTestRegistry } from "../../../test/helpers/plugins/plugin-registry.js"; import { createStartAccountContext } from "../../../test/helpers/plugins/start-account-context.js"; import { createQaBusState, startQaBusServer } from "../../qa-lab/bus-api.js"; import { qaChannelPlugin, setQaChannelRuntime } from "../api.js"; diff --git a/extensions/qianfan/index.test.ts b/extensions/qianfan/index.test.ts index 91f606de58b..b898f83161b 100644 --- a/extensions/qianfan/index.test.ts +++ b/extensions/qianfan/index.test.ts @@ -1,7 +1,9 @@ import { resolveAgentModelPrimaryValue } from "openclaw/plugin-sdk/provider-onboard"; -import { resolveProviderPluginChoice } from "openclaw/plugin-sdk/testing"; +import { + registerSingleProviderPlugin, + resolveProviderPluginChoice, +} from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import { runSingleProviderCatalog } from "../test-support/provider-model-test-helpers.js"; import qianfanPlugin from "./index.js"; import { diff --git a/extensions/qwen/index.test.ts b/extensions/qwen/index.test.ts index 852603d2138..5949bf61135 100644 --- a/extensions/qwen/index.test.ts +++ b/extensions/qwen/index.test.ts @@ -1,6 +1,5 @@ -import type { OpenClawConfig } from "openclaw/plugin-sdk/testing"; +import { type OpenClawConfig, registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import qwenPlugin from "./index.js"; async function registerQwenProvider() { diff --git a/extensions/signal/src/core.test.ts b/extensions/signal/src/core.test.ts index c8f8c862b43..71c26035969 100644 --- a/extensions/signal/src/core.test.ts +++ b/extensions/signal/src/core.test.ts @@ -1,6 +1,6 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; +import { createPluginSetupWizardStatus } from "openclaw/plugin-sdk/testing"; import { describe, expect, it, vi } from "vitest"; -import { createPluginSetupWizardStatus } from "../../../test/helpers/plugins/setup-wizard.js"; import { signalPlugin } from "./channel.js"; import * as clientModule from "./client.js"; import { classifySignalCliLogLine } from "./daemon.js"; diff --git a/extensions/slack/src/channel.test.ts b/extensions/slack/src/channel.test.ts index 0853796a705..a4430c54b44 100644 --- a/extensions/slack/src/channel.test.ts +++ b/extensions/slack/src/channel.test.ts @@ -1,5 +1,5 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import { slackPlugin } from "./channel.js"; import { slackOutbound } from "./outbound-adapter.js"; import * as probeModule from "./probe.js"; diff --git a/extensions/slack/src/inbound-context.contract.test.ts b/extensions/slack/src/inbound-context.contract.test.ts index 16dd5f5fa9a..5b6ec58821d 100644 --- a/extensions/slack/src/inbound-context.contract.test.ts +++ b/extensions/slack/src/inbound-context.contract.test.ts @@ -1,7 +1,7 @@ import { expectChannelInboundContextContract } from "openclaw/plugin-sdk/channel-contract-testing"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; +import { createTempHomeEnv } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { createTempHomeEnv } from "../../../test/helpers/plugins/temp-home.js"; import { createInboundSlackTestContext, prepareSlackMessage, diff --git a/extensions/slack/src/setup-surface.test.ts b/extensions/slack/src/setup-surface.test.ts index 240c572568b..6225c5a5ec9 100644 --- a/extensions/slack/src/setup-surface.test.ts +++ b/extensions/slack/src/setup-surface.test.ts @@ -1,10 +1,10 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; -import { describe, expect, it, vi } from "vitest"; import { createTestWizardPrompter, runSetupWizardFinalize, type WizardPrompter, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it, vi } from "vitest"; import { createSlackSetupWizardBase } from "./setup-core.js"; const slackSetupWizard = createSlackSetupWizardBase({ diff --git a/extensions/synology-chat/src/channel.test.ts b/extensions/synology-chat/src/channel.test.ts index 862b953e370..6eb2b1adff4 100644 --- a/extensions/synology-chat/src/channel.test.ts +++ b/extensions/synology-chat/src/channel.test.ts @@ -1,5 +1,5 @@ +import { createPluginSetupWizardStatus } from "openclaw/plugin-sdk/testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { createPluginSetupWizardStatus } from "../../../test/helpers/plugins/setup-wizard.js"; import type { ResolvedSynologyChatAccount } from "./types.js"; const securityAccountDefaults: ResolvedSynologyChatAccount = { diff --git a/extensions/synology-chat/src/core.test.ts b/extensions/synology-chat/src/core.test.ts index fad44348168..b82d0e166e0 100644 --- a/extensions/synology-chat/src/core.test.ts +++ b/extensions/synology-chat/src/core.test.ts @@ -1,11 +1,11 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; -import { beforeEach, describe, expect, it, vi } from "vitest"; import { createPluginSetupWizardConfigure, createTestWizardPrompter, runSetupWizardConfigure, type WizardPrompter, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import { listAccountIds, resolveAccount } from "./accounts.js"; import { SynologyChatChannelConfigSchema } from "./config-schema.js"; import { diff --git a/extensions/telegram/src/bot.create-telegram-bot.channel-post-media.test.ts b/extensions/telegram/src/bot.create-telegram-bot.channel-post-media.test.ts index 118fea2657b..34675e7ebc7 100644 --- a/extensions/telegram/src/bot.create-telegram-bot.channel-post-media.test.ts +++ b/extensions/telegram/src/bot.create-telegram-bot.channel-post-media.test.ts @@ -1,5 +1,5 @@ +import { useFrozenTime, useRealTime } from "openclaw/plugin-sdk/testing"; import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { useFrozenTime, useRealTime } from "../../../test/helpers/plugins/frozen-time.js"; const harness = await import("./bot.create-telegram-bot.test-harness.js"); const { diff --git a/extensions/tlon/src/core.test.ts b/extensions/tlon/src/core.test.ts index 420661549ec..1235c6a343b 100644 --- a/extensions/tlon/src/core.test.ts +++ b/extensions/tlon/src/core.test.ts @@ -1,11 +1,11 @@ -import { describe, expect, it, vi } from "vitest"; import { createPluginSetupWizardConfigure, createPluginSetupWizardStatus, createTestWizardPrompter, runSetupWizardConfigure, type WizardPrompter, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../api.js"; import { TlonAuthorizationSchema, TlonConfigSchema } from "./config-schema.js"; import { tlonSetupWizard } from "./setup-surface.js"; diff --git a/extensions/venice/index.test.ts b/extensions/venice/index.test.ts index a0e61446475..62992657175 100644 --- a/extensions/venice/index.test.ts +++ b/extensions/venice/index.test.ts @@ -1,5 +1,5 @@ +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; describe("venice provider plugin", () => { diff --git a/extensions/video-generation-providers.live.test.ts b/extensions/video-generation-providers.live.test.ts index f1893e3d7f7..ed5e3017114 100644 --- a/extensions/video-generation-providers.live.test.ts +++ b/extensions/video-generation-providers.live.test.ts @@ -26,6 +26,8 @@ import { parseProviderModelMap, parseVideoGenerationModelRef, redactLiveApiKey, + registerProviderPlugin, + requireRegisteredProvider, resolveConfiguredLiveVideoModels, resolveLiveVideoAuthStore, resolveLiveVideoResolution, @@ -36,10 +38,6 @@ import { type VideoGenerationRequest, } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../test/helpers/plugins/provider-registration.js"; import alibabaPlugin from "./alibaba/index.js"; import byteplusPlugin from "./byteplus/index.js"; import falPlugin from "./fal/index.js"; diff --git a/extensions/volcengine/index.test.ts b/extensions/volcengine/index.test.ts index 38eba54ca90..588d1bc3c7c 100644 --- a/extensions/volcengine/index.test.ts +++ b/extensions/volcengine/index.test.ts @@ -1,7 +1,7 @@ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; import { DOUBAO_CODING_MODEL_CATALOG, DOUBAO_MODEL_CATALOG } from "./models.js"; diff --git a/extensions/vydra/vydra.live.test.ts b/extensions/vydra/vydra.live.test.ts index 99f8f694525..2109b4875cc 100644 --- a/extensions/vydra/vydra.live.test.ts +++ b/extensions/vydra/vydra.live.test.ts @@ -1,9 +1,9 @@ -import { isLiveTestEnabled } from "openclaw/plugin-sdk/testing"; -import { describe, expect, it } from "vitest"; import { + isLiveTestEnabled, registerProviderPlugin, requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it } from "vitest"; import plugin from "./index.js"; const LIVE = isLiveTestEnabled(); diff --git a/extensions/webhooks/src/http.test.ts b/extensions/webhooks/src/http.test.ts index 4800a2d5f33..2af536874ba 100644 --- a/extensions/webhooks/src/http.test.ts +++ b/extensions/webhooks/src/http.test.ts @@ -1,8 +1,7 @@ import { EventEmitter } from "node:events"; import type { IncomingMessage } from "node:http"; +import { createMockServerResponse, createRuntimeTaskFlow } from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { createMockServerResponse } from "../../../test/helpers/plugins/mock-http-response.js"; -import { createRuntimeTaskFlow } from "../../../test/helpers/plugins/runtime-taskflow.js"; import type { OpenClawConfig } from "../runtime-api.js"; import { createTaskFlowWebhookRequestHandler, type TaskFlowWebhookTarget } from "./http.js"; diff --git a/extensions/whatsapp/src/auto-reply/web-auto-reply-utils.test.ts b/extensions/whatsapp/src/auto-reply/web-auto-reply-utils.test.ts index 1ea38cdd838..644cb14d013 100644 --- a/extensions/whatsapp/src/auto-reply/web-auto-reply-utils.test.ts +++ b/extensions/whatsapp/src/auto-reply/web-auto-reply-utils.test.ts @@ -1,8 +1,8 @@ import fs from "node:fs/promises"; import path from "node:path"; import { saveSessionStore } from "openclaw/plugin-sdk/session-store-runtime"; +import { withTempDir } from "openclaw/plugin-sdk/testing"; import { describe, expect, it, vi } from "vitest"; -import { withTempDir } from "../../../../test/helpers/plugins/temp-dir.js"; import { debugMention, isBotMentionedFromTargets, diff --git a/extensions/whatsapp/src/channel.setup.test.ts b/extensions/whatsapp/src/channel.setup.test.ts index b9533af4535..c083aea3623 100644 --- a/extensions/whatsapp/src/channel.setup.test.ts +++ b/extensions/whatsapp/src/channel.setup.test.ts @@ -1,7 +1,7 @@ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing"; import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env"; +import { createQueuedWizardPrompter } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { createQueuedWizardPrompter } from "../../../test/helpers/plugins/setup-wizard.js"; import { WHATSAPP_AUTH_UNSTABLE_CODE } from "./auth-store.js"; import { whatsappSetupPlugin } from "./channel.setup.js"; import { checkWhatsAppHeartbeatReady } from "./heartbeat.js"; diff --git a/extensions/whatsapp/src/setup-surface.test.ts b/extensions/whatsapp/src/setup-surface.test.ts index e037bd80768..188aa698b36 100644 --- a/extensions/whatsapp/src/setup-surface.test.ts +++ b/extensions/whatsapp/src/setup-surface.test.ts @@ -1,11 +1,11 @@ import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env"; import { DEFAULT_ACCOUNT_ID, type OpenClawConfig } from "openclaw/plugin-sdk/setup"; -import { beforeEach, describe, expect, it, vi } from "vitest"; import { createPluginSetupWizardStatus, createQueuedWizardPrompter, runSetupWizardFinalize, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import { whatsappSetupWizard } from "./setup-surface.js"; import { createWhatsAppAllowlistModeInput, diff --git a/extensions/xai/code-execution.test.ts b/extensions/xai/code-execution.test.ts index e621e551377..4810bebcc8a 100644 --- a/extensions/xai/code-execution.test.ts +++ b/extensions/xai/code-execution.test.ts @@ -1,5 +1,5 @@ +import { withFetchPreconnect } from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { withFetchPreconnect } from "../../test/helpers/plugins/fetch-mock.js"; import { createCodeExecutionTool } from "./code-execution.js"; function installCodeExecutionFetch(payload?: Record) { diff --git a/extensions/xai/index.test.ts b/extensions/xai/index.test.ts index b5205e9bace..f9b40f549fb 100644 --- a/extensions/xai/index.test.ts +++ b/extensions/xai/index.test.ts @@ -1,8 +1,7 @@ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"; +import { registerProviderPlugin, registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; import { createTestPluginApi } from "../../test/helpers/plugins/plugin-api.js"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; -import { registerProviderPlugin } from "../../test/helpers/plugins/provider-registration.js"; import plugin from "./index.js"; import setupPlugin from "./setup-api.js"; import { diff --git a/extensions/xai/web-search.test.ts b/extensions/xai/web-search.test.ts index 330542f163f..18176d6d235 100644 --- a/extensions/xai/web-search.test.ts +++ b/extensions/xai/web-search.test.ts @@ -1,7 +1,7 @@ import { NON_ENV_SECRETREF_MARKER } from "openclaw/plugin-sdk/provider-auth-runtime"; import { createNonExitingRuntime } from "openclaw/plugin-sdk/runtime-env"; +import { withEnv, withEnvAsync } from "openclaw/plugin-sdk/testing"; import { describe, expect, it, vi } from "vitest"; -import { withEnv, withEnvAsync } from "../../test/helpers/plugins/env.js"; import { createWizardPrompter } from "../../test/helpers/wizard-prompter.js"; import { resolveXaiCatalogEntry } from "./model-definitions.js"; import { isModernXaiModel, resolveXaiForwardCompatModel } from "./provider-models.js"; diff --git a/extensions/xai/x-search.test.ts b/extensions/xai/x-search.test.ts index 74f4634cc20..f6e57052abe 100644 --- a/extensions/xai/x-search.test.ts +++ b/extensions/xai/x-search.test.ts @@ -1,5 +1,5 @@ +import { withFetchPreconnect } from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { withFetchPreconnect } from "../../test/helpers/plugins/fetch-mock.js"; import { createXSearchTool } from "./x-search.js"; function installXSearchFetch(payload?: Record) { diff --git a/extensions/xai/xai.live.test.ts b/extensions/xai/xai.live.test.ts index fee8424db45..22099794498 100644 --- a/extensions/xai/xai.live.test.ts +++ b/extensions/xai/xai.live.test.ts @@ -4,11 +4,8 @@ import path from "node:path"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import { encodePngRgba, fillPixel } from "openclaw/plugin-sdk/media-runtime"; import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot"; +import { registerProviderPlugin, requireRegisteredProvider } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { - registerProviderPlugin, - requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; import { runRealtimeSttLiveTest } from "../../test/helpers/stt-live-audio.js"; import plugin from "./index.js"; import { XAI_DEFAULT_STT_MODEL } from "./stt.js"; diff --git a/extensions/xiaomi/xiaomi.live.test.ts b/extensions/xiaomi/xiaomi.live.test.ts index eade68a935d..f0a5c42784b 100644 --- a/extensions/xiaomi/xiaomi.live.test.ts +++ b/extensions/xiaomi/xiaomi.live.test.ts @@ -1,9 +1,9 @@ -import { isLiveTestEnabled } from "openclaw/plugin-sdk/testing"; -import { describe, expect, it } from "vitest"; import { + isLiveTestEnabled, registerProviderPlugin, requireRegisteredProvider, -} from "../../test/helpers/plugins/provider-registration.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it } from "vitest"; import plugin from "./index.js"; const XIAOMI_API_KEY = process.env.XIAOMI_API_KEY?.trim() ?? ""; diff --git a/extensions/zai/index.test.ts b/extensions/zai/index.test.ts index a8d6deca02b..c37d7afd93e 100644 --- a/extensions/zai/index.test.ts +++ b/extensions/zai/index.test.ts @@ -1,8 +1,8 @@ import type { StreamFn } from "@mariozechner/pi-agent-core"; import type { Context, Model } from "@mariozechner/pi-ai"; import { buildOpenAICompletionsParams } from "openclaw/plugin-sdk/provider-transport-runtime"; +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js"; import plugin from "./index.js"; function createGlm47Template() { diff --git a/extensions/zalo/src/monitor.image.polling.test.ts b/extensions/zalo/src/monitor.image.polling.test.ts index a9fa7f4ec8d..12b9df5f94f 100644 --- a/extensions/zalo/src/monitor.image.polling.test.ts +++ b/extensions/zalo/src/monitor.image.polling.test.ts @@ -1,5 +1,5 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { afterAll, beforeEach, describe, expect, it } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import { createImageLifecycleCore, createImageUpdate, diff --git a/extensions/zalo/src/monitor.lifecycle.test.ts b/extensions/zalo/src/monitor.lifecycle.test.ts index 19d0a99596c..eded1b29ad5 100644 --- a/extensions/zalo/src/monitor.lifecycle.test.ts +++ b/extensions/zalo/src/monitor.lifecycle.test.ts @@ -1,6 +1,9 @@ -import { createEmptyPluginRegistry, setActivePluginRegistry } from "openclaw/plugin-sdk/testing"; +import { + createEmptyPluginRegistry, + createRuntimeEnv, + setActivePluginRegistry, +} from "openclaw/plugin-sdk/testing"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { OpenClawConfig } from "../runtime-api.js"; import type { ResolvedZaloAccount } from "./accounts.js"; diff --git a/extensions/zalo/src/monitor.polling.media-reply.test.ts b/extensions/zalo/src/monitor.polling.media-reply.test.ts index da9bf221bcc..cbf01b45c26 100644 --- a/extensions/zalo/src/monitor.polling.media-reply.test.ts +++ b/extensions/zalo/src/monitor.polling.media-reply.test.ts @@ -1,6 +1,9 @@ -import { createEmptyPluginRegistry, setActivePluginRegistry } from "openclaw/plugin-sdk/testing"; +import { + createEmptyPluginRegistry, + createRuntimeEnv, + setActivePluginRegistry, +} from "openclaw/plugin-sdk/testing"; import { afterAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { PluginRuntime } from "../runtime-api.js"; import { createLifecycleMonitorSetup, diff --git a/extensions/zalo/src/setup-status.test.ts b/extensions/zalo/src/setup-status.test.ts index 241a6b278db..e2a2393806d 100644 --- a/extensions/zalo/src/setup-status.test.ts +++ b/extensions/zalo/src/setup-status.test.ts @@ -1,5 +1,5 @@ +import { createPluginSetupWizardStatus } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { createPluginSetupWizardStatus } from "../../../test/helpers/plugins/setup-wizard.js"; import type { OpenClawConfig } from "../runtime-api.js"; import { zaloSetupWizard } from "./setup-surface.js"; diff --git a/extensions/zalo/src/setup-surface.test.ts b/extensions/zalo/src/setup-surface.test.ts index 269baeb40d1..3f4706d91c1 100644 --- a/extensions/zalo/src/setup-surface.test.ts +++ b/extensions/zalo/src/setup-surface.test.ts @@ -1,11 +1,11 @@ import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers"; -import { describe, expect, it, vi } from "vitest"; import { createPluginSetupWizardConfigure, createTestWizardPrompter, runSetupWizardConfigure, type WizardPrompter, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../runtime-api.js"; import { listZaloAccountIds, resolveDefaultZaloAccountId, resolveZaloAccount } from "./accounts.js"; import { zaloDmPolicy } from "./setup-core.js"; diff --git a/extensions/zalo/test-support/monitor-mocks-test-support.ts b/extensions/zalo/test-support/monitor-mocks-test-support.ts index 167888c04f6..4c91d5c3546 100644 --- a/extensions/zalo/test-support/monitor-mocks-test-support.ts +++ b/extensions/zalo/test-support/monitor-mocks-test-support.ts @@ -1,10 +1,10 @@ -import { vi, type Mock } from "vitest"; import { createEmptyPluginRegistry, + createRuntimeEnv, setActivePluginRegistry, -} from "../../../test/helpers/plugins/plugin-registry.js"; +} from "openclaw/plugin-sdk/testing"; +import { vi, type Mock } from "vitest"; import { createPluginRuntimeMock } from "../../../test/helpers/plugins/plugin-runtime-mock.js"; -import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import type { OpenClawConfig } from "../runtime-api.js"; import type { ResolvedZaloAccount } from "../src/types.js"; diff --git a/extensions/zalouser/src/channel.setup.test.ts b/extensions/zalouser/src/channel.setup.test.ts index c30cf501274..a0e846afc9d 100644 --- a/extensions/zalouser/src/channel.setup.test.ts +++ b/extensions/zalouser/src/channel.setup.test.ts @@ -1,9 +1,8 @@ import { mkdtemp, rm } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { withEnvAsync } from "openclaw/plugin-sdk/testing"; +import { createPluginSetupWizardStatus, withEnvAsync } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { createPluginSetupWizardStatus } from "../../../test/helpers/plugins/setup-wizard.js"; import "./zalo-js.test-mocks.js"; import { zalouserSetupPlugin } from "./setup-test-helpers.js"; diff --git a/extensions/zalouser/src/channel.test.ts b/extensions/zalouser/src/channel.test.ts index 0bc0f9be3b5..ab8df1c8cd8 100644 --- a/extensions/zalouser/src/channel.test.ts +++ b/extensions/zalouser/src/channel.test.ts @@ -1,5 +1,5 @@ +import { createNonExitingRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import { createNonExitingRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js"; import "./zalo-js.test-mocks.js"; import { zalouserAuthAdapter, diff --git a/extensions/zalouser/src/setup-surface.test.ts b/extensions/zalouser/src/setup-surface.test.ts index 57c717a36e7..ad43d41fe21 100644 --- a/extensions/zalouser/src/setup-surface.test.ts +++ b/extensions/zalouser/src/setup-surface.test.ts @@ -1,9 +1,9 @@ -import { describe, expect, it, vi } from "vitest"; import { createPluginSetupWizardConfigure, createTestWizardPrompter, runSetupWizardConfigure, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../runtime-api.js"; import "./zalo-js.test-mocks.js"; import { zalouserSetupWizard } from "./setup-surface.js"; diff --git a/scripts/check-no-extension-test-core-imports.ts b/scripts/check-no-extension-test-core-imports.ts index 64fa17b9788..397cd25dd1d 100644 --- a/scripts/check-no-extension-test-core-imports.ts +++ b/scripts/check-no-extension-test-core-imports.ts @@ -43,14 +43,19 @@ const MOCK_RELATIVE_MODULE_PATTERN = const RELATIVE_CORE_HINT = "Use openclaw/plugin-sdk/testing or a focused plugin-sdk test/runtime subpath instead of core internals."; -const EXTENSION_TEST_HELPER_BRIDGE_FILES = [ +const RETIRED_EXTENSION_TEST_HELPER_BRIDGE_FILES = [ "test/helpers/plugins/env.ts", "test/helpers/plugins/fetch-mock.ts", + "test/helpers/plugins/frozen-time.ts", "test/helpers/plugins/media-understanding.ts", "test/helpers/plugins/mock-http-response.ts", "test/helpers/plugins/plugin-registration.ts", "test/helpers/plugins/plugin-registry.ts", + "test/helpers/plugins/provider-registration.ts", + "test/helpers/plugins/provider-usage-fetch.ts", "test/helpers/plugins/runtime-taskflow.ts", + "test/helpers/plugins/runtime-env.ts", + "test/helpers/plugins/setup-wizard.ts", "test/helpers/plugins/temp-dir.ts", "test/helpers/plugins/temp-home.ts", "test/helpers/plugins/typed-cases.ts", @@ -122,14 +127,20 @@ function collectRelativeCoreImportOffenders( function main() { const extensionsDir = path.join(process.cwd(), "extensions"); - const files = [ - ...collectExtensionTestFiles(extensionsDir), - ...EXTENSION_TEST_HELPER_BRIDGE_FILES.map((file) => path.join(process.cwd(), file)).filter( - (file) => fs.existsSync(file), - ), - ]; + const files = collectExtensionTestFiles(extensionsDir); const offenders: Offender[] = []; + for (const file of RETIRED_EXTENSION_TEST_HELPER_BRIDGE_FILES) { + const filePath = path.join(process.cwd(), file); + if (!fs.existsSync(filePath)) { + continue; + } + offenders.push({ + file: filePath, + hint: "Import the helper directly from openclaw/plugin-sdk/testing instead of recreating this bridge.", + }); + } + for (const file of files) { const content = fs.readFileSync(file, "utf8"); for (const rule of FORBIDDEN_PATTERNS) { @@ -147,9 +158,7 @@ function main() { } if (offenders.length > 0) { - console.error( - "Extension test files and helper bridges must stay on public plugin-sdk surfaces.", - ); + console.error("Extension test files must stay on public plugin-sdk surfaces."); for (const offender of offenders.toSorted((a, b) => a.file.localeCompare(b.file))) { const location = offender.line ? `${relativeToCwd(offender.file)}:${offender.line}` @@ -161,7 +170,7 @@ function main() { } console.log( - `OK: extension test files, support helpers, and helper bridges avoid direct core test/internal imports (${files.length} checked).`, + `OK: extension test files and support helpers avoid direct core test/internal imports (${files.length} checked).`, ); } diff --git a/src/channels/plugins/setup-wizard-helpers.test.ts b/src/channels/plugins/setup-wizard-helpers.test.ts index 54b3bcaf038..ad2c33200f1 100644 --- a/src/channels/plugins/setup-wizard-helpers.test.ts +++ b/src/channels/plugins/setup-wizard-helpers.test.ts @@ -1,8 +1,8 @@ -import { afterAll, beforeEach, describe, expect, it, vi } from "vitest"; import { resolveSetupWizardAllowFromEntries, resolveSetupWizardGroupAllowlist, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { afterAll, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../../config/config.js"; import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../../plugins/runtime.js"; import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js"; diff --git a/src/channels/plugins/setup-wizard-proxy.test.ts b/src/channels/plugins/setup-wizard-proxy.test.ts index c11eee84533..4362bf5ef74 100644 --- a/src/channels/plugins/setup-wizard-proxy.test.ts +++ b/src/channels/plugins/setup-wizard-proxy.test.ts @@ -1,11 +1,11 @@ -import { describe, expect, it, vi } from "vitest"; import { promptSetupWizardAllowFrom, resolveSetupWizardAllowFromEntries, resolveSetupWizardGroupAllowlist, runSetupWizardFinalize, runSetupWizardPrepare, -} from "../../../test/helpers/plugins/setup-wizard.js"; +} from "openclaw/plugin-sdk/testing"; +import { describe, expect, it, vi } from "vitest"; import { createAllowlistSetupWizardProxy, createDelegatedFinalize, diff --git a/src/plugin-sdk/channel-setup.test.ts b/src/plugin-sdk/channel-setup.test.ts index 4b4e58809a1..23ab9e69c8d 100644 --- a/src/plugin-sdk/channel-setup.test.ts +++ b/src/plugin-sdk/channel-setup.test.ts @@ -1,5 +1,5 @@ +import { runSetupWizardFinalize } from "openclaw/plugin-sdk/testing"; import { describe, expect, it } from "vitest"; -import { runSetupWizardFinalize } from "../../test/helpers/plugins/setup-wizard.js"; import { createOptionalChannelSetupSurface } from "./channel-setup.js"; describe("createOptionalChannelSetupSurface", () => { diff --git a/src/plugin-sdk/testing.ts b/src/plugin-sdk/testing.ts index 8cfbde3ab7e..87a27cd2513 100644 --- a/src/plugin-sdk/testing.ts +++ b/src/plugin-sdk/testing.ts @@ -115,10 +115,39 @@ export { expectGeneratedTokenPersistedToGatewayAuth } from "../test-utils/auth-t export { captureEnv, withEnv, withEnvAsync } from "../test-utils/env.js"; export { withFetchPreconnect, type FetchMock } from "../test-utils/fetch-mock.js"; export { createMockServerResponse } from "../test-utils/mock-http-response.js"; -export { registerSingleProviderPlugin } from "../test-utils/plugin-registration.js"; +export { + registerProviderPlugin, + registerSingleProviderPlugin, + requireRegisteredProvider, + type RegisteredProviderCollections, +} from "../test-utils/plugin-registration.js"; export { createTempHomeEnv, type TempHomeEnv } from "../test-utils/temp-home.js"; export { withTempDir } from "../test-utils/temp-dir.js"; export { typedCases } from "../test-utils/typed-cases.js"; +export { createProviderUsageFetch, makeResponse } from "../test-utils/provider-usage-fetch.js"; +export { useFrozenTime, useRealTime } from "../test-utils/frozen-time.js"; +export { + createNonExitingRuntimeEnv, + createNonExitingTypedRuntimeEnv, + createRuntimeEnv, + createTypedRuntimeEnv, +} from "../test-utils/plugin-runtime-env.js"; +export { + createPluginSetupWizardAdapter, + createPluginSetupWizardConfigure, + createPluginSetupWizardStatus, + createQueuedWizardPrompter, + createSetupWizardAdapter, + createTestWizardPrompter, + promptSetupWizardAllowFrom, + resolveSetupWizardAllowFromEntries, + resolveSetupWizardGroupAllowlist, + runSetupWizardConfigure, + runSetupWizardFinalize, + runSetupWizardPrepare, + selectFirstWizardOption, + type WizardPrompter, +} from "../test-utils/plugin-setup-wizard.js"; export { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js"; export { buildPluginApi } from "../plugins/api-builder.js"; export { diff --git a/src/plugins/captured-registration.ts b/src/plugins/captured-registration.ts index 4fb6a13d40c..31a2ad4f626 100644 --- a/src/plugins/captured-registration.ts +++ b/src/plugins/captured-registration.ts @@ -61,7 +61,10 @@ export type CapturedPluginRegistration = { export function createCapturedPluginRegistration(params?: { config?: OpenClawConfig; + id?: string; + name?: string; registrationMode?: OpenClawPluginApi["registrationMode"]; + source?: string; }): CapturedPluginRegistration { const providers: ProviderPlugin[] = []; const agentHarnesses: AgentHarness[] = []; @@ -82,6 +85,9 @@ export function createCapturedPluginRegistration(params?: { const migrationProviders: MigrationProviderPlugin[] = []; const memoryEmbeddingProviders: MemoryEmbeddingProviderAdapter[] = []; const tools: AnyAgentTool[] = []; + const pluginId = params?.id ?? "captured-plugin-registration"; + const pluginName = params?.name ?? "Captured Plugin Registration"; + const pluginSource = params?.source ?? "captured-plugin-registration"; const noopLogger = { info() {}, warn() {}, @@ -110,9 +116,9 @@ export function createCapturedPluginRegistration(params?: { memoryEmbeddingProviders, tools, api: buildPluginApi({ - id: "captured-plugin-registration", - name: "Captured Plugin Registration", - source: "captured-plugin-registration", + id: pluginId, + name: pluginName, + source: pluginSource, registrationMode: params?.registrationMode ?? "full", config: params?.config ?? ({} as OpenClawConfig), runtime: {} as PluginRuntime, @@ -157,12 +163,12 @@ export function createCapturedPluginRegistration(params?: { ) { const runtimes = normalizeAgentToolResultMiddlewareRuntimes(options); agentToolResultMiddlewares.push({ - pluginId: "captured-plugin-registration", - pluginName: "Captured Plugin Registration", + pluginId, + pluginName, rawHandler: handler, handler, runtimes, - source: "captured-plugin-registration", + source: pluginSource, }); }, registerCliBackend(backend: CliBackendPlugin) { diff --git a/src/test-utils/plugin-registration.ts b/src/test-utils/plugin-registration.ts index 7f9f62ebbe8..ea9531b43cb 100644 --- a/src/test-utils/plugin-registration.ts +++ b/src/test-utils/plugin-registration.ts @@ -1,5 +1,14 @@ import { createCapturedPluginRegistration } from "../plugins/captured-registration.js"; -import type { OpenClawPluginApi, ProviderPlugin } from "../plugins/types.js"; +import type { + ImageGenerationProviderPlugin, + MediaUnderstandingProviderPlugin, + MusicGenerationProviderPlugin, + OpenClawPluginApi, + ProviderPlugin, + RealtimeTranscriptionProviderPlugin, + SpeechProviderPlugin, + VideoGenerationProviderPlugin, +} from "../plugins/types.js"; export { createCapturedPluginRegistration }; @@ -7,6 +16,16 @@ type RegistrablePlugin = { register(api: OpenClawPluginApi): void; }; +export type RegisteredProviderCollections = { + providers: ProviderPlugin[]; + realtimeTranscriptionProviders: RealtimeTranscriptionProviderPlugin[]; + speechProviders: SpeechProviderPlugin[]; + mediaProviders: MediaUnderstandingProviderPlugin[]; + imageProviders: ImageGenerationProviderPlugin[]; + musicProviders: MusicGenerationProviderPlugin[]; + videoProviders: VideoGenerationProviderPlugin[]; +}; + export async function registerSingleProviderPlugin(params: { register(api: OpenClawPluginApi): void; }): Promise { @@ -19,6 +38,28 @@ export async function registerSingleProviderPlugin(params: { return provider; } +export async function registerProviderPlugin(params: { + plugin: RegistrablePlugin; + id: string; + name: string; +}): Promise { + const captured = createCapturedPluginRegistration({ + id: params.id, + name: params.name, + source: "test", + }); + params.plugin.register(captured.api); + return { + providers: captured.providers, + realtimeTranscriptionProviders: captured.realtimeTranscriptionProviders, + speechProviders: captured.speechProviders, + mediaProviders: captured.mediaUnderstandingProviders, + imageProviders: captured.imageGenerationProviders, + musicProviders: captured.musicGenerationProviders, + videoProviders: captured.videoGenerationProviders, + }; +} + export async function registerProviderPlugins( ...plugins: RegistrablePlugin[] ): Promise { @@ -29,10 +70,14 @@ export async function registerProviderPlugins( return captured.providers; } -export function requireRegisteredProvider(providers: ProviderPlugin[], providerId: string) { +export function requireRegisteredProvider( + providers: T[], + providerId: string, + label = "provider", +): T { const provider = providers.find((entry) => entry.id === providerId); if (!provider) { - throw new Error(`provider ${providerId} missing`); + throw new Error(`${label} ${providerId} missing`); } return provider; } diff --git a/src/test-utils/plugin-setup-wizard.ts b/src/test-utils/plugin-setup-wizard.ts new file mode 100644 index 00000000000..044593b6cd6 --- /dev/null +++ b/src/test-utils/plugin-setup-wizard.ts @@ -0,0 +1,344 @@ +import { vi, type Mock } from "vitest"; +import { buildChannelSetupWizardAdapterFromSetupWizard } from "../channels/plugins/setup-wizard.js"; +import type { ChannelPlugin } from "../channels/plugins/types.js"; +import type { WizardPrompter } from "../wizard/prompts.js"; +import { createRuntimeEnv } from "./plugin-runtime-env.js"; + +export type { WizardPrompter } from "../wizard/prompts.js"; +type UnknownMock = Mock<(...args: unknown[]) => unknown>; +type AsyncUnknownMock = Mock<(...args: unknown[]) => Promise>; +type QueuedWizardPrompter = { + intro: AsyncUnknownMock; + outro: AsyncUnknownMock; + note: AsyncUnknownMock; + select: AsyncUnknownMock; + multiselect: AsyncUnknownMock; + text: AsyncUnknownMock; + confirm: AsyncUnknownMock; + progress: Mock<() => { update: UnknownMock; stop: UnknownMock }>; + prompter: WizardPrompter; +}; + +export async function selectFirstWizardOption(params: { + options: Array<{ value: T }>; +}): Promise { + const first = params.options[0]; + if (!first) { + throw new Error("no options"); + } + return first.value; +} + +export function createTestWizardPrompter(overrides: Partial = {}): WizardPrompter { + return { + intro: vi.fn(async () => {}), + outro: vi.fn(async () => {}), + note: vi.fn(async () => {}), + select: selectFirstWizardOption as WizardPrompter["select"], + multiselect: vi.fn(async () => []), + text: vi.fn(async () => "") as WizardPrompter["text"], + confirm: vi.fn(async () => false), + progress: vi.fn(() => ({ update: vi.fn(), stop: vi.fn() })), + ...overrides, + }; +} + +export function createQueuedWizardPrompter(params?: { + selectValues?: string[]; + textValues?: string[]; + confirmValues?: boolean[]; +}): QueuedWizardPrompter { + const selectValues = [...(params?.selectValues ?? [])]; + const textValues = [...(params?.textValues ?? [])]; + const confirmValues = [...(params?.confirmValues ?? [])]; + + const intro = vi.fn(async () => undefined); + const outro = vi.fn(async () => undefined); + const note = vi.fn(async () => undefined); + const select = vi.fn(async () => selectValues.shift() ?? ""); + const multiselect = vi.fn(async () => [] as string[]); + const text = vi.fn(async () => textValues.shift() ?? ""); + const confirm = vi.fn(async () => confirmValues.shift() ?? false); + const progress = vi.fn(() => ({ + update: vi.fn(), + stop: vi.fn(), + })); + + return { + intro, + outro, + note, + select, + multiselect, + text, + confirm, + progress, + prompter: createTestWizardPrompter({ + intro, + outro, + note, + select: select as WizardPrompter["select"], + multiselect: multiselect as WizardPrompter["multiselect"], + text: text as WizardPrompter["text"], + confirm, + progress, + }), + }; +} + +type SetupWizardAdapterParams = Parameters[0]; +type SetupWizardPlugin = SetupWizardAdapterParams["plugin"]; +type SetupWizard = NonNullable; +type SetupWizardCredentialValues = Record; +type SetupWizardTestPlugin = { + id: string; + setupWizard?: ChannelPlugin["setupWizard"]; + config: Record; +} & Record; + +function isDeclarativeSetupWizard( + setupWizard: ChannelPlugin["setupWizard"], +): setupWizard is SetupWizard { + return Boolean( + setupWizard && + typeof setupWizard === "object" && + "status" in setupWizard && + "credentials" in setupWizard, + ); +} + +function requireDeclarativeSetupWizard(plugin: SetupWizardTestPlugin): SetupWizard { + const { setupWizard } = plugin; + if (!setupWizard) { + throw new Error(`${plugin.id} is missing setupWizard`); + } + if (!isDeclarativeSetupWizard(setupWizard)) { + throw new Error(`${plugin.id} setupWizard is adapter-shaped; test helper expects a wizard`); + } + return setupWizard; +} + +function resolveSetupWizardAccountContext(params: { + cfg?: TCfg; + accountId?: string; + credentialValues?: SetupWizardCredentialValues; +}) { + return { + cfg: (params.cfg ?? {}) as TCfg, + accountId: params.accountId ?? "default", + credentialValues: params.credentialValues ?? {}, + }; +} + +function resolveSetupWizardRuntime(runtime?: TRuntime): TRuntime { + return (runtime ?? createRuntimeEnv({ throwOnExit: false })) as TRuntime; +} + +function resolveSetupWizardPrompter(prompter?: WizardPrompter): WizardPrompter { + return prompter ?? createTestWizardPrompter(); +} + +function resolveSetupWizardNotePrompter(prompter?: Pick) { + return ( + prompter ?? + ({ + note: vi.fn(async () => undefined), + } satisfies Pick) + ); +} + +export function createSetupWizardAdapter(params: SetupWizardAdapterParams) { + return buildChannelSetupWizardAdapterFromSetupWizard(params); +} + +export function createPluginSetupWizardAdapter(plugin: SetupWizardTestPlugin) { + const wizard = requireDeclarativeSetupWizard(plugin); + return createSetupWizardAdapter({ + plugin: plugin as unknown as SetupWizardPlugin, + wizard, + }); +} + +export function createPluginSetupWizardConfigure(plugin: SetupWizardTestPlugin) { + return createPluginSetupWizardAdapter(plugin).configure; +} + +export function createPluginSetupWizardStatus(plugin: SetupWizardTestPlugin) { + return createPluginSetupWizardAdapter(plugin).getStatus; +} + +export async function runSetupWizardConfigure< + TCfg, + TOptions extends Record, + TAccountOverrides extends Record, + TRuntime, + TResult, +>(params: { + configure: (args: { + cfg: TCfg; + runtime: TRuntime; + prompter: WizardPrompter; + options: TOptions; + accountOverrides: TAccountOverrides; + shouldPromptAccountIds: boolean; + forceAllowFrom: boolean; + }) => Promise; + cfg?: TCfg; + runtime?: TRuntime; + prompter: WizardPrompter; + options?: TOptions; + accountOverrides?: TAccountOverrides; + shouldPromptAccountIds?: boolean; + forceAllowFrom?: boolean; +}): Promise { + return await params.configure({ + cfg: (params.cfg ?? {}) as TCfg, + runtime: (params.runtime ?? createRuntimeEnv()) as TRuntime, + prompter: params.prompter, + options: (params.options ?? {}) as TOptions, + accountOverrides: (params.accountOverrides ?? {}) as TAccountOverrides, + shouldPromptAccountIds: params.shouldPromptAccountIds ?? false, + forceAllowFrom: params.forceAllowFrom ?? false, + }); +} + +export async function runSetupWizardPrepare< + TCfg, + TOptions extends Record, + TRuntime, + TResult, +>(params: { + prepare?: (args: { + cfg: TCfg; + accountId: string; + credentialValues: Record; + runtime: TRuntime; + prompter: WizardPrompter; + options?: TOptions; + }) => Promise | TResult; + cfg?: TCfg; + accountId?: string; + credentialValues?: Record; + runtime?: TRuntime; + prompter?: WizardPrompter; + options?: TOptions; +}): Promise { + const context = resolveSetupWizardAccountContext({ + cfg: params.cfg, + accountId: params.accountId, + credentialValues: params.credentialValues, + }); + return await params.prepare?.({ + ...context, + runtime: resolveSetupWizardRuntime(params.runtime), + prompter: resolveSetupWizardPrompter(params.prompter), + options: params.options, + }); +} + +export async function runSetupWizardFinalize< + TCfg, + TOptions extends Record, + TRuntime, + TResult, +>(params: { + finalize?: (args: { + cfg: TCfg; + accountId: string; + credentialValues: Record; + runtime: TRuntime; + prompter: WizardPrompter; + options?: TOptions; + forceAllowFrom: boolean; + }) => Promise | TResult; + cfg?: TCfg; + accountId?: string; + credentialValues?: Record; + runtime?: TRuntime; + prompter?: WizardPrompter; + options?: TOptions; + forceAllowFrom?: boolean; +}): Promise { + const context = resolveSetupWizardAccountContext({ + cfg: params.cfg, + accountId: params.accountId, + credentialValues: params.credentialValues, + }); + return await params.finalize?.({ + ...context, + runtime: resolveSetupWizardRuntime(params.runtime), + prompter: resolveSetupWizardPrompter(params.prompter), + options: params.options, + forceAllowFrom: params.forceAllowFrom ?? false, + }); +} + +export async function promptSetupWizardAllowFrom(params: { + promptAllowFrom?: (args: { + cfg: TCfg; + prompter: WizardPrompter; + accountId: string; + }) => Promise | TResult; + cfg?: TCfg; + prompter?: WizardPrompter; + accountId?: string; +}): Promise { + const context = resolveSetupWizardAccountContext({ + cfg: params.cfg, + accountId: params.accountId, + }); + return await params.promptAllowFrom?.({ + cfg: context.cfg, + accountId: context.accountId, + prompter: resolveSetupWizardPrompter(params.prompter), + }); +} + +export async function resolveSetupWizardAllowFromEntries(params: { + resolveEntries?: (args: { + cfg: TCfg; + accountId: string; + credentialValues: Record; + entries: string[]; + }) => Promise | TResult; + entries: string[]; + cfg?: TCfg; + accountId?: string; + credentialValues?: SetupWizardCredentialValues; +}): Promise { + const context = resolveSetupWizardAccountContext({ + cfg: params.cfg, + accountId: params.accountId, + credentialValues: params.credentialValues, + }); + return await params.resolveEntries?.({ + ...context, + entries: params.entries, + }); +} + +export async function resolveSetupWizardGroupAllowlist(params: { + resolveAllowlist?: (args: { + cfg: TCfg; + accountId: string; + credentialValues: Record; + entries: string[]; + prompter: Pick; + }) => Promise | TResult; + entries: string[]; + cfg?: TCfg; + accountId?: string; + credentialValues?: SetupWizardCredentialValues; + prompter?: Pick; +}): Promise { + const context = resolveSetupWizardAccountContext({ + cfg: params.cfg, + accountId: params.accountId, + credentialValues: params.credentialValues, + }); + return await params.resolveAllowlist?.({ + ...context, + entries: params.entries, + prompter: resolveSetupWizardNotePrompter(params.prompter), + }); +} diff --git a/test/helpers/plugins/env.ts b/test/helpers/plugins/env.ts deleted file mode 100644 index 8292d8f7418..00000000000 --- a/test/helpers/plugins/env.ts +++ /dev/null @@ -1 +0,0 @@ -export { withEnv, withEnvAsync } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/fetch-mock.ts b/test/helpers/plugins/fetch-mock.ts deleted file mode 100644 index e7b86b14350..00000000000 --- a/test/helpers/plugins/fetch-mock.ts +++ /dev/null @@ -1 +0,0 @@ -export { withFetchPreconnect, type FetchMock } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/frozen-time.ts b/test/helpers/plugins/frozen-time.ts deleted file mode 100644 index 69f188f09ca..00000000000 --- a/test/helpers/plugins/frozen-time.ts +++ /dev/null @@ -1 +0,0 @@ -export { useFrozenTime, useRealTime } from "../../../src/test-utils/frozen-time.js"; diff --git a/test/helpers/plugins/media-understanding.ts b/test/helpers/plugins/media-understanding.ts deleted file mode 100644 index c902d959443..00000000000 --- a/test/helpers/plugins/media-understanding.ts +++ /dev/null @@ -1 +0,0 @@ -export { createRequestCaptureJsonFetch } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/mock-http-response.ts b/test/helpers/plugins/mock-http-response.ts deleted file mode 100644 index 5579344ff0d..00000000000 --- a/test/helpers/plugins/mock-http-response.ts +++ /dev/null @@ -1 +0,0 @@ -export { createMockServerResponse } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/plugin-registration.ts b/test/helpers/plugins/plugin-registration.ts deleted file mode 100644 index 9c9f806e8fc..00000000000 --- a/test/helpers/plugins/plugin-registration.ts +++ /dev/null @@ -1 +0,0 @@ -export { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/plugin-registry.ts b/test/helpers/plugins/plugin-registry.ts deleted file mode 100644 index c0f1f84db9b..00000000000 --- a/test/helpers/plugins/plugin-registry.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { - createEmptyPluginRegistry, - createTestRegistry, - setActivePluginRegistry, -} from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/provider-discovery-contract.ts b/test/helpers/plugins/provider-discovery-contract.ts index 8169283698a..32275065ea7 100644 --- a/test/helpers/plugins/provider-discovery-contract.ts +++ b/test/helpers/plugins/provider-discovery-contract.ts @@ -16,7 +16,7 @@ export type ProviderDiscoveryContractPluginLoader = () => Promise<{ default: Parameters[0]; }>; -type ProviderHandle = Awaited>; +type ProviderHandle = Awaited>[number]; type DiscoveryState = { runProviderCatalog: typeof import("../../../src/plugins/provider-discovery.js").runProviderCatalog; diff --git a/test/helpers/plugins/provider-registration.ts b/test/helpers/plugins/provider-registration.ts deleted file mode 100644 index 39bb9e39a06..00000000000 --- a/test/helpers/plugins/provider-registration.ts +++ /dev/null @@ -1,91 +0,0 @@ -import type { - ImageGenerationProviderPlugin, - MediaUnderstandingProviderPlugin, - MusicGenerationProviderPlugin, - ProviderPlugin, - RealtimeTranscriptionProviderPlugin, - SpeechProviderPlugin, - VideoGenerationProviderPlugin, -} from "../../../src/plugins/types.js"; -import { createTestPluginApi } from "./plugin-api.js"; - -type RegisteredProviderCollections = { - providers: ProviderPlugin[]; - realtimeTranscriptionProviders: RealtimeTranscriptionProviderPlugin[]; - speechProviders: SpeechProviderPlugin[]; - mediaProviders: MediaUnderstandingProviderPlugin[]; - imageProviders: ImageGenerationProviderPlugin[]; - musicProviders: MusicGenerationProviderPlugin[]; - videoProviders: VideoGenerationProviderPlugin[]; -}; - -type ProviderPluginModule = { - register(api: ReturnType): void; -}; - -export async function registerProviderPlugin(params: { - plugin: ProviderPluginModule; - id: string; - name: string; -}): Promise { - const providers: ProviderPlugin[] = []; - const realtimeTranscriptionProviders: RealtimeTranscriptionProviderPlugin[] = []; - const speechProviders: SpeechProviderPlugin[] = []; - const mediaProviders: MediaUnderstandingProviderPlugin[] = []; - const imageProviders: ImageGenerationProviderPlugin[] = []; - const musicProviders: MusicGenerationProviderPlugin[] = []; - const videoProviders: VideoGenerationProviderPlugin[] = []; - - params.plugin.register( - createTestPluginApi({ - id: params.id, - name: params.name, - source: "test", - config: {}, - runtime: {} as never, - registerProvider: (provider) => { - providers.push(provider); - }, - registerRealtimeTranscriptionProvider: (provider) => { - realtimeTranscriptionProviders.push(provider); - }, - registerSpeechProvider: (provider) => { - speechProviders.push(provider); - }, - registerMediaUnderstandingProvider: (provider) => { - mediaProviders.push(provider); - }, - registerImageGenerationProvider: (provider) => { - imageProviders.push(provider); - }, - registerMusicGenerationProvider: (provider) => { - musicProviders.push(provider); - }, - registerVideoGenerationProvider: (provider) => { - videoProviders.push(provider); - }, - }), - ); - - return { - providers, - realtimeTranscriptionProviders, - speechProviders, - mediaProviders, - imageProviders, - musicProviders, - videoProviders, - }; -} - -export function requireRegisteredProvider( - entries: T[], - id: string, - label = "provider", -): T { - const entry = entries.find((candidate) => candidate.id === id); - if (!entry) { - throw new Error(`${label} ${id} was not registered`); - } - return entry; -} diff --git a/test/helpers/plugins/provider-runtime-contract.ts b/test/helpers/plugins/provider-runtime-contract.ts index 32b9f1a9f3a..d3951b77cf4 100644 --- a/test/helpers/plugins/provider-runtime-contract.ts +++ b/test/helpers/plugins/provider-runtime-contract.ts @@ -1,13 +1,14 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import type { ProviderPlugin, ProviderRuntimeModel } from "../../../src/plugins/types.js"; import { createProviderUsageFetch, makeResponse, -} from "../../../src/test-utils/provider-usage-fetch.js"; -import { registerProviderPlugin, requireRegisteredProvider } from "./provider-registration.js"; + registerProviderPlugin, + requireRegisteredProvider, +} from "openclaw/plugin-sdk/testing"; +import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import type { ProviderPlugin, ProviderRuntimeModel } from "../../../src/plugins/types.js"; const CONTRACT_SETUP_TIMEOUT_MS = 300_000; diff --git a/test/helpers/plugins/provider-usage-fetch.ts b/test/helpers/plugins/provider-usage-fetch.ts deleted file mode 100644 index fe54174732e..00000000000 --- a/test/helpers/plugins/provider-usage-fetch.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - createProviderUsageFetch, - makeResponse, -} from "../../../src/test-utils/provider-usage-fetch.js"; diff --git a/test/helpers/plugins/runtime-taskflow.ts b/test/helpers/plugins/runtime-taskflow.ts deleted file mode 100644 index 8a1e00fdf72..00000000000 --- a/test/helpers/plugins/runtime-taskflow.ts +++ /dev/null @@ -1 +0,0 @@ -export { createRuntimeTaskFlow } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/start-account-context.ts b/test/helpers/plugins/start-account-context.ts index 3b07bae8092..eccfc01e7d4 100644 --- a/test/helpers/plugins/start-account-context.ts +++ b/test/helpers/plugins/start-account-context.ts @@ -1,3 +1,4 @@ +import { createRuntimeEnv } from "openclaw/plugin-sdk/testing"; import { vi } from "vitest"; import type { ChannelAccountSnapshot, @@ -5,7 +6,6 @@ import type { } from "../../../src/channels/plugins/types.js"; import type { OpenClawConfig } from "../../../src/config/config.js"; import type { RuntimeEnv } from "../../../src/runtime.js"; -import { createRuntimeEnv } from "./runtime-env.js"; export function createStartAccountContext(params: { account: TAccount; diff --git a/test/helpers/plugins/temp-dir.ts b/test/helpers/plugins/temp-dir.ts deleted file mode 100644 index f5ad08cd585..00000000000 --- a/test/helpers/plugins/temp-dir.ts +++ /dev/null @@ -1 +0,0 @@ -export { withTempDir } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/temp-home.ts b/test/helpers/plugins/temp-home.ts deleted file mode 100644 index cf200c4f7fe..00000000000 --- a/test/helpers/plugins/temp-home.ts +++ /dev/null @@ -1 +0,0 @@ -export { createTempHomeEnv, type TempHomeEnv } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/typed-cases.ts b/test/helpers/plugins/typed-cases.ts deleted file mode 100644 index cabfb116195..00000000000 --- a/test/helpers/plugins/typed-cases.ts +++ /dev/null @@ -1 +0,0 @@ -export { typedCases } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/provider-replay-policy.ts b/test/helpers/provider-replay-policy.ts index 33da777c9a1..d8d8a115d43 100644 --- a/test/helpers/provider-replay-policy.ts +++ b/test/helpers/provider-replay-policy.ts @@ -1,5 +1,5 @@ +import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; import { expect } from "vitest"; -import { registerSingleProviderPlugin } from "./plugins/plugin-registration.js"; export async function expectPassthroughReplayPolicy(params: { modelId: string; diff --git a/test/scripts/test-projects.test.ts b/test/scripts/test-projects.test.ts index b028386ce03..55303db0492 100644 --- a/test/scripts/test-projects.test.ts +++ b/test/scripts/test-projects.test.ts @@ -692,7 +692,7 @@ describe("scripts/test-projects changed-target routing", () => { it("uses import-graph targets in default changed mode", () => { expect( - resolveChangedTestTargetPlan(["test/helpers/plugins/plugin-registration.ts"]).targets, + resolveChangedTestTargetPlan(["test/helpers/provider-replay-policy.ts"]).targets, ).toContain("extensions/openrouter/index.test.ts"); });