refactor: expose SDK test helper subpaths

This commit is contained in:
Peter Steinberger
2026-04-28 03:27:56 +01:00
parent 21528222c3
commit e1acb61317
156 changed files with 791 additions and 242 deletions

View File

@@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai
- Gateway/runtime: reuse the current plugin metadata snapshot for provider discovery so repeated model-provider discovery avoids rebuilding plugin manifest metadata. Thanks @shakkernerd.
- Gateway/startup: pass the plugin metadata snapshot from config validation into plugin bootstrap so startup reuses one manifest product instead of rebuilding plugin metadata. Thanks @shakkernerd.
- Plugin SDK/testing: move core-only channel contract fixtures under the channel contract test tree and retire the old `test/helpers/channels` bridge directory so plugin tests stay on focused SDK surfaces. Thanks @vincentkoc.
- Plugin SDK/testing: expose generic module reload, bundled-path, Node builtin mock, channel pairing/envelope, HTTP server, temp-home, replay-policy, and live STT helpers through focused SDK test subpaths so extension tests no longer depend on repo-only helper bridges. Thanks @vincentkoc.
- Plugin SDK: move maintained bundled channels off the deprecated `channel-config-schema-legacy` subpath, add an explicit bundled-channel schema SDK surface, and track both remaining legacy test/config compatibility barrels with dated removal windows. Thanks @vincentkoc.
- Plugin SDK/testing: expose media provider capability assertions and provider HTTP mocks through focused SDK test subpaths, and retire the repo-only media-generation test helper bridge. Thanks @vincentkoc.
- Plugin SDK/testing: promote bundled plugin/provider/channel contract helpers to focused SDK test subpaths and retire the repo-only `test/helpers/plugins` TypeScript bridge. Thanks @vincentkoc.

View File

@@ -1,2 +1,2 @@
31fd2178f08a4fcb28d6319eaa464b572b1e36a0fab700056f643feaccf95aa8 plugin-sdk-api-baseline.json
65b239e91e4d5f4cac71527058aa53179a8dcf65f8c50f4eabab346def966e74 plugin-sdk-api-baseline.jsonl
6b4c0c05e24f13c08daebf36a9853e66056ab677e10dac9c35e8d514f87ca74e plugin-sdk-api-baseline.json
e6ea9f91aa5118bf2c61cb50f774d96740509723e862b9b618e2061b04504dc7 plugin-sdk-api-baseline.jsonl

View File

@@ -16,24 +16,25 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview)
## Plugin entry
| Subpath | Key exports |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `plugin-sdk/plugin-entry` | `definePluginEntry` |
| `plugin-sdk/core` | `defineChannelPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase`, `defineSetupPluginEntry`, `buildChannelConfigSchema` |
| `plugin-sdk/config-schema` | `OpenClawSchema` |
| `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` |
| `plugin-sdk/testing` | Broad compatibility barrel for legacy plugin tests; prefer focused test subpaths for new extension tests |
| `plugin-sdk/plugin-test-api` | Minimal `OpenClawPluginApi` mock builder for direct plugin registration unit tests |
| `plugin-sdk/channel-test-helpers` | Channel account lifecycle, directory, send-config, runtime mock, hook, and generic channel contract test helpers |
| `plugin-sdk/channel-target-testing` | Shared channel target-resolution error-case test suite |
| `plugin-sdk/plugin-test-contracts` | Plugin registration, package manifest, public artifact, runtime API, import side-effect, and direct import contract helpers |
| `plugin-sdk/plugin-test-runtime` | Plugin runtime, registry, provider-registration, setup-wizard, and runtime task-flow fixtures for tests |
| `plugin-sdk/provider-test-contracts` | Provider runtime, auth, discovery, onboard, catalog, media capability, web-search/fetch, and wizard contract helpers |
| `plugin-sdk/provider-http-test-mocks` | Opt-in Vitest HTTP/auth mocks for provider tests that exercise `plugin-sdk/provider-http` |
| `plugin-sdk/test-env` | Test environment, fetch/network, live-test, temporary filesystem, and time-control fixtures |
| `plugin-sdk/test-fixtures` | Generic CLI, sandbox, skill, agent-message, system-event, terminal, chunking, auth-token, and typed-case test fixtures |
| `plugin-sdk/migration` | Migration provider item helpers such as `createMigrationItem`, reason constants, item status markers, redaction helpers, and `summarizeMigrationItems` |
| `plugin-sdk/migration-runtime` | Runtime migration helpers such as `copyMigrationFileItem` and `writeMigrationReport` |
| Subpath | Key exports |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `plugin-sdk/plugin-entry` | `definePluginEntry` |
| `plugin-sdk/core` | `defineChannelPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase`, `defineSetupPluginEntry`, `buildChannelConfigSchema` |
| `plugin-sdk/config-schema` | `OpenClawSchema` |
| `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` |
| `plugin-sdk/testing` | Broad compatibility barrel for legacy plugin tests; prefer focused test subpaths for new extension tests |
| `plugin-sdk/plugin-test-api` | Minimal `OpenClawPluginApi` mock builder for direct plugin registration unit tests |
| `plugin-sdk/channel-test-helpers` | Channel account lifecycle, directory, send-config, runtime mock, hook, bundled channel entry, envelope timestamp, pairing reply, and generic channel contract test helpers |
| `plugin-sdk/channel-target-testing` | Shared channel target-resolution error-case test suite |
| `plugin-sdk/plugin-test-contracts` | Plugin registration, package manifest, public artifact, runtime API, import side-effect, and direct import contract helpers |
| `plugin-sdk/plugin-test-runtime` | Plugin runtime, registry, provider-registration, setup-wizard, and runtime task-flow fixtures for tests |
| `plugin-sdk/provider-test-contracts` | Provider runtime, auth, discovery, onboard, catalog, media capability, replay policy, realtime STT live-audio, web-search/fetch, and wizard contract helpers |
| `plugin-sdk/provider-http-test-mocks` | Opt-in Vitest HTTP/auth mocks for provider tests that exercise `plugin-sdk/provider-http` |
| `plugin-sdk/test-env` | Test environment, fetch/network, disposable HTTP server, incoming request, live-test, temporary filesystem, and time-control fixtures |
| `plugin-sdk/test-fixtures` | Generic CLI, sandbox, skill, agent-message, system-event, module reload, bundled plugin path, terminal, chunking, auth-token, and typed-case test fixtures |
| `plugin-sdk/test-node-mocks` | Focused Node builtin mock helpers for use inside Vitest `vi.mock("node:*")` factories |
| `plugin-sdk/migration` | Migration provider item helpers such as `createMigrationItem`, reason constants, item status markers, redaction helpers, and `summarizeMigrationItems` |
| `plugin-sdk/migration-runtime` | Runtime migration helpers such as `copyMigrationFileItem` and `writeMigrationReport` |
<AccordionGroup>
<Accordion title="Channel subpaths">
@@ -275,9 +276,10 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview)
| `plugin-sdk/channel-test-helpers` | Channel-oriented test helpers for generic actions/setup/status contracts, directory assertions, account startup lifecycle, send-config threading, runtime mocks, status issues, outbound delivery, and hook registration |
| `plugin-sdk/channel-target-testing` | Shared target-resolution error-case suite for channel tests |
| `plugin-sdk/plugin-test-contracts` | Plugin package, registration, public artifact, direct import, runtime API, and import side-effect contract helpers |
| `plugin-sdk/provider-test-contracts` | Provider runtime, auth, discovery, onboard, catalog, wizard, media capability, web-search/fetch, and stream contract helpers |
| `plugin-sdk/provider-test-contracts` | Provider runtime, auth, discovery, onboard, catalog, wizard, media capability, replay policy, realtime STT live-audio, web-search/fetch, and stream contract helpers |
| `plugin-sdk/provider-http-test-mocks` | Opt-in Vitest HTTP/auth mocks for provider tests that exercise `plugin-sdk/provider-http` |
| `plugin-sdk/test-fixtures` | Generic CLI runtime capture, sandbox context, skill writer, agent-message, system-event, terminal-text, chunking, auth-token, and typed-case fixtures |
| `plugin-sdk/test-fixtures` | Generic CLI runtime capture, sandbox context, skill writer, agent-message, system-event, module reload, bundled plugin path, terminal-text, chunking, auth-token, and typed-case fixtures |
| `plugin-sdk/test-node-mocks` | Focused Node builtin mock helpers for use inside Vitest `vi.mock("node:*")` factories |
</Accordion>
<Accordion title="Memory subpaths">

View File

@@ -39,6 +39,8 @@ plugins.
**Generic fixture import:** `openclaw/plugin-sdk/test-fixtures`
**Node builtin mock import:** `openclaw/plugin-sdk/test-node-mocks`
Prefer the focused subpaths below for new plugin tests. The broad
`openclaw/plugin-sdk/testing` barrel is legacy compatibility only.
@@ -55,63 +57,79 @@ import { describePluginRegistrationContract } from "openclaw/plugin-sdk/plugin-t
import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/plugin-test-runtime";
import { describeOpenAIProviderRuntimeContract } from "openclaw/plugin-sdk/provider-test-contracts";
import { getProviderHttpMocks } from "openclaw/plugin-sdk/provider-http-test-mocks";
import { withEnv, withFetchPreconnect } from "openclaw/plugin-sdk/test-env";
import { createCliRuntimeCapture, typedCases } from "openclaw/plugin-sdk/test-fixtures";
import { withEnv, withFetchPreconnect, withServer } from "openclaw/plugin-sdk/test-env";
import {
bundledPluginRoot,
createCliRuntimeCapture,
typedCases,
} from "openclaw/plugin-sdk/test-fixtures";
import { mockNodeBuiltinModule } from "openclaw/plugin-sdk/test-node-mocks";
```
### Available exports
| Export | Purpose |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `createTestPluginApi` | Build a minimal plugin API mock for direct registration unit tests. Import from `plugin-sdk/plugin-test-api` |
| `expectChannelInboundContextContract` | Assert channel inbound context shape. Import from `plugin-sdk/channel-contract-testing` |
| `installChannelOutboundPayloadContractSuite` | Install channel outbound payload contract cases. Import from `plugin-sdk/channel-contract-testing` |
| `createStartAccountContext` | Build channel account lifecycle contexts. Import from `plugin-sdk/channel-test-helpers` |
| `installChannelActionsContractSuite` | Install generic channel message-action contract cases. Import from `plugin-sdk/channel-test-helpers` |
| `installChannelSetupContractSuite` | Install generic channel setup contract cases. Import from `plugin-sdk/channel-test-helpers` |
| `installChannelStatusContractSuite` | Install generic channel status contract cases. Import from `plugin-sdk/channel-test-helpers` |
| `expectDirectoryIds` | Assert channel directory ids from a directory-list function. Import from `plugin-sdk/channel-test-helpers` |
| `describePluginRegistrationContract` | Install plugin registration contract checks. Import from `plugin-sdk/plugin-test-contracts` |
| `registerSingleProviderPlugin` | Register one provider plugin in loader smoke tests. Import from `plugin-sdk/plugin-test-runtime` |
| `registerProviderPlugin` | Capture all provider kinds from one plugin. Import from `plugin-sdk/plugin-test-runtime` |
| `registerProviderPlugins` | Capture provider registrations across multiple plugins. Import from `plugin-sdk/plugin-test-runtime` |
| `requireRegisteredProvider` | Assert that a provider collection contains an id. Import from `plugin-sdk/plugin-test-runtime` |
| `createRuntimeEnv` | Build a mocked CLI/plugin runtime environment. Import from `plugin-sdk/plugin-test-runtime` |
| `createPluginSetupWizardStatus` | Build setup status helpers for channel plugins. Import from `plugin-sdk/plugin-test-runtime` |
| `describeOpenAIProviderRuntimeContract` | Install provider-family runtime contract checks. Import from `plugin-sdk/provider-test-contracts` |
| `expectExplicitVideoGenerationCapabilities` | Assert video providers declare explicit generation mode capabilities. Import from `plugin-sdk/provider-test-contracts` |
| `expectExplicitMusicGenerationCapabilities` | Assert music providers declare explicit generation/edit capabilities. Import from `plugin-sdk/provider-test-contracts` |
| `mockSuccessfulDashscopeVideoTask` | Install a successful DashScope-compatible video task response. Import from `plugin-sdk/provider-test-contracts` |
| `getProviderHttpMocks` | Access opt-in provider HTTP/auth Vitest mocks. Import from `plugin-sdk/provider-http-test-mocks` |
| `installProviderHttpMockCleanup` | Reset provider HTTP/auth mocks after each test. Import from `plugin-sdk/provider-http-test-mocks` |
| `installCommonResolveTargetErrorCases` | Shared test cases for target resolution error handling. Import from `plugin-sdk/channel-target-testing` |
| `shouldAckReaction` | Check whether a channel should add an ack reaction. Import from `plugin-sdk/channel-feedback` |
| `removeAckReactionAfterReply` | Remove ack reaction after reply delivery. Import from `plugin-sdk/channel-feedback` |
| `createTestRegistry` | Build a channel plugin registry fixture. Import from `plugin-sdk/plugin-test-runtime` or `plugin-sdk/channel-test-helpers` |
| `createEmptyPluginRegistry` | Build an empty plugin registry fixture. Import from `plugin-sdk/plugin-test-runtime` or `plugin-sdk/channel-test-helpers` |
| `setActivePluginRegistry` | Install a registry fixture for plugin runtime tests. Import from `plugin-sdk/plugin-test-runtime` or `plugin-sdk/channel-test-helpers` |
| `createRequestCaptureJsonFetch` | Capture JSON fetch requests in media helper tests. Import from `plugin-sdk/test-env` |
| `withFetchPreconnect` | Run fetch tests with preconnect hooks installed. Import from `plugin-sdk/test-env` |
| `withEnv` / `withEnvAsync` | Temporarily patch environment variables. Import from `plugin-sdk/test-env` |
| `createTempHomeEnv` / `withTempDir` | Create isolated filesystem test fixtures. Import from `plugin-sdk/test-env` |
| `createMockServerResponse` | Create a minimal HTTP server response mock. Import from `plugin-sdk/test-env` |
| `createCliRuntimeCapture` | Capture CLI runtime output in tests. Import from `plugin-sdk/test-fixtures` |
| `createSandboxTestContext` | Build sandbox test contexts. Import from `plugin-sdk/test-fixtures` |
| `writeSkill` | Write skill fixtures. Import from `plugin-sdk/test-fixtures` |
| `makeAgentAssistantMessage` | Build agent transcript message fixtures. Import from `plugin-sdk/test-fixtures` |
| `peekSystemEvents` / `resetSystemEventsForTest` | Inspect and reset system event fixtures. Import from `plugin-sdk/test-fixtures` |
| `sanitizeTerminalText` | Sanitize terminal output for assertions. Import from `plugin-sdk/test-fixtures` |
| `countLines` / `hasBalancedFences` | Assert chunking output shape. Import from `plugin-sdk/test-fixtures` |
| `runProviderCatalog` | Execute a provider catalog hook with test dependencies |
| `resolveProviderWizardOptions` | Resolve provider setup wizard choices in contract tests |
| `resolveProviderModelPickerEntries` | Resolve provider model-picker entries in contract tests |
| `buildProviderPluginMethodChoice` | Build provider wizard choice ids for assertions |
| `setProviderWizardProvidersResolverForTest` | Inject provider wizard providers for isolated tests |
| `createProviderUsageFetch` | Build provider usage fetch fixtures |
| `useFrozenTime` / `useRealTime` | Freeze and restore timers for time-sensitive tests. Import from `plugin-sdk/test-env` |
| `createTestWizardPrompter` | Build a mocked setup wizard prompter |
| `createRuntimeTaskFlow` | Create isolated runtime task-flow state |
| `typedCases` | Preserve literal types for table-driven tests. Import from `plugin-sdk/test-fixtures` |
| Export | Purpose |
| ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `createTestPluginApi` | Build a minimal plugin API mock for direct registration unit tests. Import from `plugin-sdk/plugin-test-api` |
| `expectChannelInboundContextContract` | Assert channel inbound context shape. Import from `plugin-sdk/channel-contract-testing` |
| `installChannelOutboundPayloadContractSuite` | Install channel outbound payload contract cases. Import from `plugin-sdk/channel-contract-testing` |
| `createStartAccountContext` | Build channel account lifecycle contexts. Import from `plugin-sdk/channel-test-helpers` |
| `installChannelActionsContractSuite` | Install generic channel message-action contract cases. Import from `plugin-sdk/channel-test-helpers` |
| `installChannelSetupContractSuite` | Install generic channel setup contract cases. Import from `plugin-sdk/channel-test-helpers` |
| `installChannelStatusContractSuite` | Install generic channel status contract cases. Import from `plugin-sdk/channel-test-helpers` |
| `expectDirectoryIds` | Assert channel directory ids from a directory-list function. Import from `plugin-sdk/channel-test-helpers` |
| `assertBundledChannelEntries` | Assert bundled channel entrypoints expose the expected public contract. Import from `plugin-sdk/channel-test-helpers` |
| `formatEnvelopeTimestamp` | Format deterministic envelope timestamps. Import from `plugin-sdk/channel-test-helpers` |
| `expectPairingReplyText` | Assert channel pairing reply text and extract its code. Import from `plugin-sdk/channel-test-helpers` |
| `describePluginRegistrationContract` | Install plugin registration contract checks. Import from `plugin-sdk/plugin-test-contracts` |
| `registerSingleProviderPlugin` | Register one provider plugin in loader smoke tests. Import from `plugin-sdk/plugin-test-runtime` |
| `registerProviderPlugin` | Capture all provider kinds from one plugin. Import from `plugin-sdk/plugin-test-runtime` |
| `registerProviderPlugins` | Capture provider registrations across multiple plugins. Import from `plugin-sdk/plugin-test-runtime` |
| `requireRegisteredProvider` | Assert that a provider collection contains an id. Import from `plugin-sdk/plugin-test-runtime` |
| `createRuntimeEnv` | Build a mocked CLI/plugin runtime environment. Import from `plugin-sdk/plugin-test-runtime` |
| `createPluginSetupWizardStatus` | Build setup status helpers for channel plugins. Import from `plugin-sdk/plugin-test-runtime` |
| `describeOpenAIProviderRuntimeContract` | Install provider-family runtime contract checks. Import from `plugin-sdk/provider-test-contracts` |
| `expectPassthroughReplayPolicy` | Assert provider replay policies pass through provider-owned tools and metadata. Import from `plugin-sdk/provider-test-contracts` |
| `runRealtimeSttLiveTest` | Run a live realtime STT provider test with shared audio fixtures. Import from `plugin-sdk/provider-test-contracts` |
| `normalizeTranscriptForMatch` | Normalize live transcript output before fuzzy assertions. Import from `plugin-sdk/provider-test-contracts` |
| `expectExplicitVideoGenerationCapabilities` | Assert video providers declare explicit generation mode capabilities. Import from `plugin-sdk/provider-test-contracts` |
| `expectExplicitMusicGenerationCapabilities` | Assert music providers declare explicit generation/edit capabilities. Import from `plugin-sdk/provider-test-contracts` |
| `mockSuccessfulDashscopeVideoTask` | Install a successful DashScope-compatible video task response. Import from `plugin-sdk/provider-test-contracts` |
| `getProviderHttpMocks` | Access opt-in provider HTTP/auth Vitest mocks. Import from `plugin-sdk/provider-http-test-mocks` |
| `installProviderHttpMockCleanup` | Reset provider HTTP/auth mocks after each test. Import from `plugin-sdk/provider-http-test-mocks` |
| `installCommonResolveTargetErrorCases` | Shared test cases for target resolution error handling. Import from `plugin-sdk/channel-target-testing` |
| `shouldAckReaction` | Check whether a channel should add an ack reaction. Import from `plugin-sdk/channel-feedback` |
| `removeAckReactionAfterReply` | Remove ack reaction after reply delivery. Import from `plugin-sdk/channel-feedback` |
| `createTestRegistry` | Build a channel plugin registry fixture. Import from `plugin-sdk/plugin-test-runtime` or `plugin-sdk/channel-test-helpers` |
| `createEmptyPluginRegistry` | Build an empty plugin registry fixture. Import from `plugin-sdk/plugin-test-runtime` or `plugin-sdk/channel-test-helpers` |
| `setActivePluginRegistry` | Install a registry fixture for plugin runtime tests. Import from `plugin-sdk/plugin-test-runtime` or `plugin-sdk/channel-test-helpers` |
| `createRequestCaptureJsonFetch` | Capture JSON fetch requests in media helper tests. Import from `plugin-sdk/test-env` |
| `withServer` | Run tests against a disposable local HTTP server. Import from `plugin-sdk/test-env` |
| `createMockIncomingRequest` | Build a minimal incoming HTTP request object. Import from `plugin-sdk/test-env` |
| `withFetchPreconnect` | Run fetch tests with preconnect hooks installed. Import from `plugin-sdk/test-env` |
| `withEnv` / `withEnvAsync` | Temporarily patch environment variables. Import from `plugin-sdk/test-env` |
| `createTempHomeEnv` / `withTempHome` / `withTempDir` | Create isolated filesystem test fixtures. Import from `plugin-sdk/test-env` |
| `createMockServerResponse` | Create a minimal HTTP server response mock. Import from `plugin-sdk/test-env` |
| `createCliRuntimeCapture` | Capture CLI runtime output in tests. Import from `plugin-sdk/test-fixtures` |
| `importFreshModule` | Import an ESM module with a fresh query token to bypass module cache. Import from `plugin-sdk/test-fixtures` |
| `bundledPluginRoot` / `bundledPluginFile` | Resolve bundled plugin source or dist fixture paths. Import from `plugin-sdk/test-fixtures` |
| `mockNodeBuiltinModule` | Install narrow Node builtin Vitest mocks. Import from `plugin-sdk/test-node-mocks` |
| `createSandboxTestContext` | Build sandbox test contexts. Import from `plugin-sdk/test-fixtures` |
| `writeSkill` | Write skill fixtures. Import from `plugin-sdk/test-fixtures` |
| `makeAgentAssistantMessage` | Build agent transcript message fixtures. Import from `plugin-sdk/test-fixtures` |
| `peekSystemEvents` / `resetSystemEventsForTest` | Inspect and reset system event fixtures. Import from `plugin-sdk/test-fixtures` |
| `sanitizeTerminalText` | Sanitize terminal output for assertions. Import from `plugin-sdk/test-fixtures` |
| `countLines` / `hasBalancedFences` | Assert chunking output shape. Import from `plugin-sdk/test-fixtures` |
| `runProviderCatalog` | Execute a provider catalog hook with test dependencies |
| `resolveProviderWizardOptions` | Resolve provider setup wizard choices in contract tests |
| `resolveProviderModelPickerEntries` | Resolve provider model-picker entries in contract tests |
| `buildProviderPluginMethodChoice` | Build provider wizard choice ids for assertions |
| `setProviderWizardProvidersResolverForTest` | Inject provider wizard providers for isolated tests |
| `createProviderUsageFetch` | Build provider usage fetch fixtures |
| `useFrozenTime` / `useRealTime` | Freeze and restore timers for time-sensitive tests. Import from `plugin-sdk/test-env` |
| `createTestWizardPrompter` | Build a mocked setup wizard prompter |
| `createRuntimeTaskFlow` | Create isolated runtime task-flow state |
| `typedCases` | Preserve literal types for table-driven tests. Import from `plugin-sdk/test-fixtures` |
Bundled-plugin contract suites also use SDK testing subpaths for test-only
registry, manifest, public-artifact, and runtime fixture helpers. Core-only

View File

@@ -2,8 +2,8 @@ import { spawn } from "node:child_process";
import { chmod, mkdtemp, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { bundledPluginFile } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it } from "vitest";
import { bundledPluginFile } from "../../../../test/helpers/bundled-plugin-paths.js";
const tempDirs: string[] = [];
const proxyPath = path.resolve(bundledPluginFile("acpx", "src/runtime-internals/mcp-proxy.mjs"));

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { describe, expect, it, vi, beforeEach } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import { sendBlueBubblesAttachment } from "./attachments.js";
import { editBlueBubblesMessage, setGroupIconBlueBubbles } from "./chat.js";
import { resolveBlueBubblesMessageId } from "./monitor-reply-cache.js";

View File

@@ -1,7 +1,7 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("node:child_process", async () => {
const { mockNodeBuiltinModule } = await import("../../../../test/helpers/node-builtin-mocks.js");
const { mockNodeBuiltinModule } = await import("openclaw/plugin-sdk/test-node-mocks");
return mockNodeBuiltinModule(
() => vi.importActual<typeof import("node:child_process")>("node:child_process"),
{
@@ -10,7 +10,7 @@ vi.mock("node:child_process", async () => {
);
});
vi.mock("node:fs", async () => {
const { mockNodeBuiltinModule } = await import("../../../../test/helpers/node-builtin-mocks.js");
const { mockNodeBuiltinModule } = await import("openclaw/plugin-sdk/test-node-mocks");
const existsSync = vi.fn();
const readFileSync = vi.fn();
return mockNodeBuiltinModule(
@@ -20,7 +20,7 @@ vi.mock("node:fs", async () => {
);
});
vi.mock("node:os", async () => {
const { mockNodeBuiltinModule } = await import("../../../../test/helpers/node-builtin-mocks.js");
const { mockNodeBuiltinModule } = await import("openclaw/plugin-sdk/test-node-mocks");
const homedir = vi.fn();
return mockNodeBuiltinModule(
() => vi.importActual<typeof import("node:os")>("node:os"),

View File

@@ -1,9 +1,9 @@
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import {
runRealtimeSttLiveTest,
synthesizeElevenLabsLiveSpeech,
} from "../../test/helpers/stt-live-audio.js";
} from "openclaw/plugin-sdk/provider-test-contracts";
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import { transcribeDeepgramAudio } from "./audio.js";
import { buildDeepgramRealtimeTranscriptionProvider } from "./realtime-transcription-provider.js";

View File

@@ -1,5 +1,5 @@
import { assertBundledChannelEntries } from "openclaw/plugin-sdk/channel-test-helpers";
import { describe } from "vitest";
import { assertBundledChannelEntries } from "../../test/helpers/bundled-channel-entry.ts";
import entry from "./index.js";
import setupEntry from "./setup-entry.js";

View File

@@ -1,10 +1,10 @@
import type { ButtonInteraction, ComponentData, StringSelectMenuInteraction } from "@buape/carbon";
import { ChannelType } from "discord-api-types/v10";
import { expectPairingReplyText } from "openclaw/plugin-sdk/channel-test-helpers";
import type { DiscordAccountConfig, OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
import { peekSystemEvents, resetSystemEventsForTest } from "openclaw/plugin-sdk/test-fixtures";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { expectPairingReplyText } from "../../../../test/helpers/pairing-reply.js";
import {
enqueueSystemEventMock,
readAllowFromStoreMock,

View File

@@ -2,13 +2,13 @@ import {
registerProviderPlugin,
requireRegisteredProvider,
} from "openclaw/plugin-sdk/plugin-test-runtime";
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import {
normalizeTranscriptForMatch,
runRealtimeSttLiveTest,
synthesizeElevenLabsLiveSpeech,
} from "../../test/helpers/stt-live-audio.js";
} from "openclaw/plugin-sdk/provider-test-contracts";
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import plugin from "./index.js";
import { elevenLabsMediaUnderstandingProvider } from "./media-understanding-provider.js";
import { buildElevenLabsRealtimeTranscriptionProvider } from "./realtime-transcription-provider.js";

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import type { ClawdbotConfig } from "../runtime-api.js";
const createFeishuClientMock = vi.hoisted(() => vi.fn());

View File

@@ -2,9 +2,9 @@ import {
registerProviderPlugin,
requireRegisteredProvider,
} from "openclaw/plugin-sdk/plugin-test-runtime";
import { normalizeTranscriptForMatch } from "openclaw/plugin-sdk/provider-test-contracts";
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
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";

View File

@@ -1,5 +1,5 @@
import { assertBundledChannelEntries } from "openclaw/plugin-sdk/channel-test-helpers";
import { describe } from "vitest";
import { assertBundledChannelEntries } from "../../test/helpers/bundled-channel-entry.ts";
import entry from "./index.js";
import setupEntry from "./setup-entry.js";

View File

@@ -1,8 +1,8 @@
import type { StreamFn } from "@mariozechner/pi-agent-core";
import type { Context, Model } from "@mariozechner/pi-ai";
import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/plugin-test-runtime";
import { expectPassthroughReplayPolicy } from "openclaw/plugin-sdk/provider-test-contracts";
import { describe, expect, it } from "vitest";
import { expectPassthroughReplayPolicy } from "../../test/helpers/provider-replay-policy.ts";
import plugin from "./index.js";
describe("kilocode provider plugin", () => {

View File

@@ -7,9 +7,9 @@ import {
runSetupWizardConfigure,
} from "openclaw/plugin-sdk/plugin-test-runtime";
import type { WizardPrompter } from "openclaw/plugin-sdk/plugin-test-runtime";
import { bundledPluginRoot } from "openclaw/plugin-sdk/test-fixtures";
import ts from "typescript";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { bundledPluginRoot } from "../../../test/helpers/bundled-plugin-paths.js";
import type { OpenClawConfig, PluginRuntime, ResolvedLineAccount } from "../api.js";
import { linePlugin } from "./channel.js";
import { lineGatewayAdapter } from "./gateway.js";

View File

@@ -1,7 +1,7 @@
import crypto from "node:crypto";
import type { IncomingMessage, ServerResponse } from "node:http";
import { createMockIncomingRequest } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it, vi } from "vitest";
import { createMockIncomingRequest } from "../../../test/helpers/mock-incoming-request.js";
import { createLineNodeWebhookHandler, readLineWebhookRequestBody } from "./webhook-node.js";
import { createLineWebhookMiddleware } from "./webhook.js";

View File

@@ -7,7 +7,7 @@ const availabilityState = vi.hoisted(() => ({
}));
vi.mock("node:fs", async () => {
const { mockNodeBuiltinModule } = await import("../../../test/helpers/node-builtin-mocks.js");
const { mockNodeBuiltinModule } = await import("openclaw/plugin-sdk/test-node-mocks");
return mockNodeBuiltinModule(
() => vi.importActual<typeof import("node:fs")>("node:fs"),
{

View File

@@ -1,8 +1,8 @@
import fs from "node:fs";
import path from "node:path";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { afterEach, describe, expect, it, vi } from "vitest";
import { withTempHome } from "../../../test/helpers/temp-home.js";
const legacyCryptoInspectorAvailability = vi.hoisted(() => ({
available: true,

View File

@@ -1,8 +1,8 @@
import fs from "node:fs";
import path from "node:path";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import { withTempHome } from "../../../test/helpers/temp-home.js";
import { autoMigrateLegacyMatrixState, detectLegacyMatrixState } from "./legacy-state.js";
function writeFile(filePath: string, value: string) {

View File

@@ -1,7 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it, vi } from "vitest";
import { withTempHome } from "../../../../../test/helpers/temp-home.js";
import { resolveMatrixAccountStorageRoot } from "../../storage-paths.js";
import type { MatrixRoomKeyBackupRestoreResult } from "../sdk.js";
import { maybeRestoreLegacyMatrixBackup } from "./legacy-crypto-restore.js";

View File

@@ -1,7 +1,7 @@
import path from "node:path";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import { withTempHome } from "../../../test/helpers/temp-home.js";
import { resolveMatrixMigrationAccountTarget } from "./migration-config.js";
import {
MATRIX_OPS_ACCESS_TOKEN,

View File

@@ -1,7 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { withTempHome } from "../../../test/helpers/temp-home.js";
const legacyCryptoInspectorAvailability = vi.hoisted(() => ({
available: true,

View File

@@ -1,7 +1,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { withTempHome } from "../../../test/helpers/temp-home.js";
const legacyCryptoInspectorAvailability = vi.hoisted(() => ({
available: true,

View File

@@ -1,10 +1,10 @@
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import {
normalizeTranscriptForMatch,
runRealtimeSttLiveTest,
synthesizeElevenLabsLiveSpeech,
} from "../../test/helpers/stt-live-audio.js";
} from "openclaw/plugin-sdk/provider-test-contracts";
import { isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import { mistralMediaUnderstandingProvider } from "./media-understanding-provider.js";
import { buildMistralRealtimeTranscriptionProvider } from "./realtime-transcription-provider.js";

View File

@@ -1,5 +1,5 @@
import { createMockIncomingRequest } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it, vi } from "vitest";
import { createMockIncomingRequest } from "../../../test/helpers/mock-incoming-request.js";
import {
NextcloudTalkRetryableWebhookError,
processNextcloudTalkReplayGuardedMessage,

View File

@@ -11,9 +11,9 @@ import {
registerProviderPlugin,
requireRegisteredProvider,
} from "openclaw/plugin-sdk/plugin-test-runtime";
import { runRealtimeSttLiveTest } from "openclaw/plugin-sdk/provider-test-contracts";
import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
import { describe, expect, it } from "vitest";
import { runRealtimeSttLiveTest } from "../../test/helpers/stt-live-audio.js";
import plugin from "./index.js";
const OPENAI_API_KEY = process.env.OPENAI_API_KEY ?? "";

View File

@@ -3,8 +3,8 @@ import {
registerProviderPlugin,
registerSingleProviderPlugin,
} from "openclaw/plugin-sdk/plugin-test-runtime";
import { expectPassthroughReplayPolicy } from "openclaw/plugin-sdk/provider-test-contracts";
import { describe, expect, it } from "vitest";
import { expectPassthroughReplayPolicy } from "../../test/helpers/provider-replay-policy.ts";
import plugin from "./index.js";
describe("opencode-go provider plugin", () => {

View File

@@ -2,8 +2,8 @@ import {
registerProviderPlugin,
requireRegisteredProvider,
} from "openclaw/plugin-sdk/plugin-test-runtime";
import { expectPassthroughReplayPolicy } from "openclaw/plugin-sdk/provider-test-contracts";
import { describe, expect, it } from "vitest";
import { expectPassthroughReplayPolicy } from "../../test/helpers/provider-replay-policy.ts";
import plugin from "./index.js";
describe("opencode provider plugin", () => {

View File

@@ -2,8 +2,8 @@ import {
registerProviderPlugin,
registerSingleProviderPlugin,
} from "openclaw/plugin-sdk/plugin-test-runtime";
import { expectPassthroughReplayPolicy } from "openclaw/plugin-sdk/provider-test-contracts";
import { describe, expect, it, vi } from "vitest";
import { expectPassthroughReplayPolicy } from "../../test/helpers/provider-replay-policy.ts";
import openrouterPlugin from "./index.js";
import {
buildOpenrouterProvider,

View File

@@ -1,8 +1,8 @@
import { expectPairingReplyText } from "openclaw/plugin-sdk/channel-test-helpers";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import { normalizeE164 } from "openclaw/plugin-sdk/text-runtime";
import { describe, expect, it, vi } from "vitest";
import { expectPairingReplyText } from "../../../test/helpers/pairing-reply.js";
import {
createSignalToolResultConfig,
config,

View File

@@ -1,5 +1,5 @@
import { assertBundledChannelEntries } from "openclaw/plugin-sdk/channel-test-helpers";
import { describe } from "vitest";
import { assertBundledChannelEntries } from "../../test/helpers/bundled-channel-entry.ts";
import entry from "./index.js";
import setupEntry from "./setup-entry.js";

View File

@@ -1,8 +1,8 @@
import { CURRENT_MESSAGE_MARKER } from "openclaw/plugin-sdk/channel-mention-gating";
import { expectPairingReplyText } from "openclaw/plugin-sdk/channel-test-helpers";
import { resetInboundDedupe } from "openclaw/plugin-sdk/reply-dedupe";
import { HISTORY_CONTEXT_MARKER } from "openclaw/plugin-sdk/reply-history";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { expectPairingReplyText } from "../../../test/helpers/pairing-reply.js";
import {
defaultSlackTestConfig,
getSlackTestState,

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import {
clearSlackThreadParticipationCache,
hasSlackThreadParticipation,

View File

@@ -1,5 +1,5 @@
import { assertBundledChannelEntries } from "openclaw/plugin-sdk/channel-test-helpers";
import { beforeEach, describe, vi } from "vitest";
import { assertBundledChannelEntries } from "../../test/helpers/bundled-channel-entry.ts";
import entry from "./index.js";
import setupEntry from "./setup-entry.js";

View File

@@ -1,6 +1,6 @@
import { escapeRegExp, formatEnvelopeTimestamp } from "openclaw/plugin-sdk/channel-test-helpers";
import type { GetReplyOptions, MsgContext } from "openclaw/plugin-sdk/reply-runtime";
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { escapeRegExp, formatEnvelopeTimestamp } from "../../../test/helpers/envelope-timestamp.js";
import type { TelegramBotOptions } from "./bot.types.js";
const harness = await import("./bot.create-telegram-bot.test-harness.js");
const conversationRuntime = await import("openclaw/plugin-sdk/conversation-runtime");

View File

@@ -72,7 +72,7 @@ function waitForReplyCalls(count: number) {
}
async function loadEnvelopeTimestampHelpers() {
return await import("../../../test/helpers/envelope-timestamp.js");
return await import("openclaw/plugin-sdk/channel-test-helpers");
}
async function loadInboundContextContract() {

View File

@@ -1,6 +1,6 @@
import type { Bot } from "grammy";
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import { __testing, createTelegramDraftStream } from "./draft-stream.js";
type TelegramDraftStreamParams = Parameters<typeof createTelegramDraftStream>[0];

View File

@@ -1,7 +1,7 @@
import fs from "node:fs";
import type { Bot } from "grammy";
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import {
getTelegramSendTestMocks,
importTelegramSendModule,

View File

@@ -4,8 +4,8 @@ import path from "node:path";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-runtime";
import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
const writeJsonFileAtomicallyMock = vi.hoisted(() => vi.fn());
const readAcpSessionEntryMock = vi.hoisted(() => vi.fn());

View File

@@ -1,5 +1,5 @@
import { assertBundledChannelEntries } from "openclaw/plugin-sdk/channel-test-helpers";
import { describe } from "vitest";
import { assertBundledChannelEntries } from "../../test/helpers/bundled-channel-entry.ts";
import entry from "./index.js";
import setupEntry from "./setup-entry.js";

View File

@@ -6,7 +6,7 @@ const { spawnMock } = vi.hoisted(() => ({
}));
vi.mock("node:child_process", async () => {
const { mockNodeBuiltinModule } = await import("../../../../test/helpers/node-builtin-mocks.js");
const { mockNodeBuiltinModule } = await import("openclaw/plugin-sdk/test-node-mocks");
return mockNodeBuiltinModule(
() => vi.importActual<typeof import("node:child_process")>("node:child_process"),
{

View File

@@ -1,5 +1,5 @@
import { assertBundledChannelEntries } from "openclaw/plugin-sdk/channel-test-helpers";
import { describe } from "vitest";
import { assertBundledChannelEntries } from "../../test/helpers/bundled-channel-entry.ts";
import entry from "./index.js";
import setupEntry from "./setup-entry.js";

View File

@@ -1,11 +1,11 @@
import "./test-helpers.js";
import crypto from "node:crypto";
import fs from "node:fs/promises";
import { escapeRegExp, formatEnvelopeTimestamp } from "openclaw/plugin-sdk/channel-test-helpers";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import { setLoggerOverride } from "openclaw/plugin-sdk/runtime-env";
import { withEnvAsync } from "openclaw/plugin-sdk/test-env";
import { beforeAll, describe, expect, it, vi } from "vitest";
import { escapeRegExp, formatEnvelopeTimestamp } from "../../../test/helpers/envelope-timestamp.js";
import { WhatsAppAuthUnstableError } from "./auth-store.js";
import {
createWebInboundDeliverySpies,

View File

@@ -1,9 +1,9 @@
import fsSync from "node:fs";
import fs from "node:fs/promises";
import path from "node:path";
import { formatEnvelopeTimestamp } from "openclaw/plugin-sdk/channel-test-helpers";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
import { vi } from "vitest";
import { formatEnvelopeTimestamp } from "../../../test/helpers/envelope-timestamp.js";
import type { MockBaileysSocket } from "../../../test/mocks/baileys.js";
import { createMockBaileys } from "../../../test/mocks/baileys.js";

View File

@@ -1,8 +1,8 @@
import { createTestWizardPrompter } from "openclaw/plugin-sdk/plugin-test-runtime";
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/test-env";
import { describe, expect, it, vi } from "vitest";
import { createWizardPrompter } from "../../test/helpers/wizard-prompter.js";
import { resolveXaiCatalogEntry } from "./model-definitions.js";
import { isModernXaiModel, resolveXaiForwardCompatModel } from "./provider-models.js";
import { resolveFallbackXaiAuth } from "./src/tool-auth-shared.js";
@@ -115,7 +115,7 @@ describe("xai web search config resolution", () => {
it("offers plugin-owned xSearch setup after Grok is selected", async () => {
const provider = createXaiWebSearchProvider();
const select = vi.fn().mockResolvedValueOnce("yes").mockResolvedValueOnce("grok-4-1-fast");
const prompter = createWizardPrompter({
const prompter = createTestWizardPrompter({
select: select as never,
});
@@ -175,7 +175,7 @@ describe("xai web search config resolution", () => {
},
},
};
const prompter = createWizardPrompter({});
const prompter = createTestWizardPrompter();
const next = await provider.runSetup?.({
config,

View File

@@ -7,9 +7,9 @@ import {
registerProviderPlugin,
requireRegisteredProvider,
} from "openclaw/plugin-sdk/plugin-test-runtime";
import { runRealtimeSttLiveTest } from "openclaw/plugin-sdk/provider-test-contracts";
import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
import { describe, expect, it } from "vitest";
import { runRealtimeSttLiveTest } from "../../test/helpers/stt-live-audio.js";
import plugin from "./index.js";
import { XAI_DEFAULT_STT_MODEL } from "./stt.js";

View File

@@ -1,5 +1,5 @@
import { assertBundledChannelEntries } from "openclaw/plugin-sdk/channel-test-helpers";
import { describe } from "vitest";
import { assertBundledChannelEntries } from "../../test/helpers/bundled-channel-entry.ts";
import entry from "./index.js";
import setupEntry from "./setup-entry.js";

View File

@@ -1,5 +1,5 @@
import { withServer } from "openclaw/plugin-sdk/test-env";
import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
import { withServer } from "../../../test/helpers/http-test-server.js";
import {
createLifecycleMonitorSetup,
createTextUpdate,

View File

@@ -1,5 +1,5 @@
import { withServer } from "openclaw/plugin-sdk/test-env";
import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
import { withServer } from "../../../test/helpers/http-test-server.js";
import type { PluginRuntime } from "../runtime-api.js";
import {
createLifecycleMonitorSetup,

View File

@@ -3,8 +3,8 @@ import {
createEmptyPluginRegistry,
setActivePluginRegistry,
} from "openclaw/plugin-sdk/plugin-test-runtime";
import { withServer } from "openclaw/plugin-sdk/test-env";
import { afterEach, describe, expect, it, vi } from "vitest";
import { withServer } from "../../../test/helpers/http-test-server.js";
import type { OpenClawConfig, PluginRuntime } from "../runtime-api.js";
import {
createImageLifecycleCore,

View File

@@ -538,6 +538,10 @@
"types": "./dist/plugin-sdk/test-fixtures.d.ts",
"default": "./dist/plugin-sdk/test-fixtures.js"
},
"./plugin-sdk/test-node-mocks": {
"types": "./dist/plugin-sdk/test-node-mocks.d.ts",
"default": "./dist/plugin-sdk/test-node-mocks.js"
},
"./plugin-sdk/testing": {
"types": "./dist/plugin-sdk/testing.d.ts",
"default": "./dist/plugin-sdk/testing.js"

View File

@@ -37,6 +37,26 @@ const FORBIDDEN_PATTERNS: Array<{ pattern: RegExp; hint: string }> = [
pattern: /["'](?:\.\.\/)+(?:test\/helpers\/media-generation\/)[^"']+["']/,
hint: "Use openclaw/plugin-sdk/provider-test-contracts or openclaw/plugin-sdk/provider-http-test-mocks instead of repo-only media provider helper bridges.",
},
{
pattern:
/["'](?:\.\.\/)+(?:test\/helpers\/(?:bundled-channel-entry|envelope-timestamp|pairing-reply)\.(?:js|ts))["']/,
hint: "Use openclaw/plugin-sdk/channel-test-helpers instead of repo-only channel test helper bridges.",
},
{
pattern:
/["'](?:\.\.\/)+(?:test\/helpers\/(?:http-test-server|mock-incoming-request|temp-home)\.(?:js|ts))["']/,
hint: "Use openclaw/plugin-sdk/test-env instead of repo-only environment/network test helper bridges.",
},
{
pattern:
/["'](?:\.\.\/)+(?:test\/helpers\/(?:bundled-plugin-paths|import-fresh|node-builtin-mocks)\.(?:js|ts))["']/,
hint: "Use openclaw/plugin-sdk/test-fixtures instead of repo-only generic test helper bridges.",
},
{
pattern:
/["'](?:\.\.\/)+(?:test\/helpers\/(?:provider-replay-policy|stt-live-audio)\.(?:js|ts))["']/,
hint: "Use openclaw/plugin-sdk/provider-test-contracts instead of repo-only provider test helper bridges.",
},
{
pattern: /["'](?:\.\.\/)+(?:src\/channels\/plugins\/contracts\/test-helpers\/)[^"']+["']/,
hint: "Use openclaw/plugin-sdk/channel-test-helpers or another focused SDK test subpath instead of core-only channel contract helpers.",
@@ -114,6 +134,17 @@ const RETIRED_EXTENSION_TEST_HELPER_BRIDGE_FILES = [
"test/helpers/media-generation/dashscope-video-provider.ts",
"test/helpers/media-generation/provider-capability-assertions.ts",
"test/helpers/media-generation/provider-http-mocks.ts",
"test/helpers/bundled-channel-entry.ts",
"test/helpers/bundled-plugin-paths.ts",
"test/helpers/envelope-timestamp.ts",
"test/helpers/http-test-server.ts",
"test/helpers/import-fresh.ts",
"test/helpers/mock-incoming-request.ts",
"test/helpers/node-builtin-mocks.ts",
"test/helpers/pairing-reply.ts",
"test/helpers/provider-replay-policy.ts",
"test/helpers/stt-live-audio.ts",
"test/helpers/temp-home.ts",
];
function isExtensionTestFile(filePath: string): boolean {

View File

@@ -118,6 +118,7 @@
"provider-test-contracts",
"test-env",
"test-fixtures",
"test-node-mocks",
"testing",
"temp-path",
"logging-core",

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../test/helpers/import-fresh.js";
const loadConfigMock = vi.hoisted(() => vi.fn());

View File

@@ -1,9 +1,9 @@
import fs from "node:fs/promises";
import path from "node:path";
import { afterEach, beforeEach, vi } from "vitest";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import { clearConfigCache, clearRuntimeConfigSnapshot } from "../config/config.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { withTempHome as withTempHomeBase } from "../plugin-sdk/test-helpers/temp-home.js";
import { resolveBundledPluginsDir } from "../plugins/bundled-dir.js";
import { resetPluginLoaderTestStateForTest } from "../plugins/loader.test-fixtures.js";
import { resetProviderRuntimeHookCacheForTest } from "../plugins/provider-runtime.js";

View File

@@ -153,6 +153,8 @@ describe("models-config write serialization", () => {
const modelPath = path.join(resolveOpenClawAgentDir(), "models.json");
await fs.writeFile(modelPath, `${JSON.stringify({ external: true })}\n`, "utf8");
const externalMtime = new Date(Date.now() + 2000);
await fs.utimes(modelPath, externalMtime, externalMtime);
await ensureOpenClawModelsJson(CUSTOM_PROXY_MODELS_CONFIG);
expect(planOpenClawModelsJsonMock).toHaveBeenCalledTimes(2);

View File

@@ -1,8 +1,8 @@
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
async function withOpenRouterStateDir(run: (stateDir: string) => Promise<void>) {
const stateDir = mkdtempSync(join(tmpdir(), "openclaw-openrouter-capabilities-"));

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import {
__testing,
abortEmbeddedPiRun,

View File

@@ -1,6 +1,6 @@
import path from "node:path";
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
import { afterEach, beforeEach, expect, vi } from "vitest";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import { clearRuntimeAuthProfileStoreSnapshots } from "../agents/auth-profiles.js";
import { resetSkillsRefreshForTest } from "../agents/skills/refresh.js";
import { clearSessionStoreCacheForTest, loadSessionStore } from "../config/sessions.js";

View File

@@ -1,8 +1,8 @@
import fs from "node:fs";
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { normalizeTestText } from "../../../test/helpers/normalize-text.js";
import { withTempHome } from "../../../test/helpers/temp-home.js";
import { clearAgentHarnesses, registerAgentHarness } from "../../agents/harness/registry.js";
import type { AgentHarness } from "../../agents/harness/types.js";
import {

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.ts";
import {
clearActiveEmbeddedRun,
setActiveEmbeddedRun,

View File

@@ -1,4 +1,4 @@
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
type GetReplyModule = typeof import("./get-reply.js");
type ReplyModule = typeof import("../reply.js");

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import type { MsgContext } from "../templating.js";
import { buildInboundDedupeKey, resetInboundDedupe } from "./inbound-dedupe.js";

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { beforeEach, describe, expect, it } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import type { FollowupRun, QueueSettings } from "./queue.js";
import {
enqueueFollowupRun,

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
import type { FollowupRun, QueueSettings } from "./queue.js";
import { enqueueFollowupRun, scheduleFollowupDrain } from "./queue.js";
import {

View File

@@ -1,5 +1,5 @@
import { join } from "node:path";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { MsgContext, TemplateContext } from "./templating.js";

View File

@@ -1,8 +1,8 @@
import fs from "node:fs";
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { afterEach, describe, expect, it, vi } from "vitest";
import { normalizeTestText } from "../../test/helpers/normalize-text.js";
import { withTempHome } from "../../test/helpers/temp-home.js";
import { MODEL_CONTEXT_TOKEN_CACHE } from "../agents/context-cache.js";
import type { OpenClawConfig } from "../config/config.js";
import { applyModelOverrideToSessionEntry } from "../sessions/model-overrides.js";

View File

@@ -1,8 +1,8 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.ts";
const tempDirs: string[] = [];
const originalBundledPluginsDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;

View File

@@ -1,8 +1,8 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.ts";
import { loadPluginManifestRegistry } from "../../plugins/manifest-registry.js";
const bundledChannelEntrypointPaths = ["index.ts", "channel-entry.ts", "setup-entry.ts"] as const;

View File

@@ -1,8 +1,8 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.ts";
import { shouldExpectNativeJitiForJavaScriptTestRuntime } from "../../test-utils/jiti-runtime.js";
import {
isJavaScriptModulePath,

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.ts";
import { clearSetupPromotionRuntimeModuleCache } from "./setup-helpers.js";
afterEach(() => {

View File

@@ -1,5 +1,5 @@
import { bundledPluginFile } from "openclaw/plugin-sdk/test-fixtures";
import { describe, expect, it } from "vitest";
import { bundledPluginFile } from "../../test/helpers/bundled-plugin-paths.js";
import { readCommandSource } from "./command-source.test-helpers.js";
const SECRET_TARGET_CALLSITES = [

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../test/helpers/import-fresh.ts";
import type { ChannelPlugin } from "../channels/plugins/types.js";
const runtimeFactories = vi.hoisted(() => ({

View File

@@ -1,5 +1,5 @@
import { installedPluginRoot } from "openclaw/plugin-sdk/test-fixtures";
import { describe, expect, it } from "vitest";
import { installedPluginRoot } from "../../test/helpers/bundled-plugin-paths.js";
import {
buildNpmInstallRecordFields,
logPinnedNpmSpecMessages,

View File

@@ -1,5 +1,5 @@
import { installedPluginRoot } from "openclaw/plugin-sdk/test-fixtures";
import { describe, expect, it, vi } from "vitest";
import { installedPluginRoot } from "../../test/helpers/bundled-plugin-paths.js";
import { PLUGIN_INSTALL_ERROR_CODE } from "../plugins/install.js";
import {
resolveBundledInstallPlanForCatalogEntry,

View File

@@ -1,8 +1,8 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { installedPluginRoot } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { installedPluginRoot } from "../../test/helpers/bundled-plugin-paths.js";
import type { OpenClawConfig } from "../config/config.js";
import {
applyExclusiveSlotSelection,

View File

@@ -1,5 +1,5 @@
import { installedPluginRoot } from "openclaw/plugin-sdk/test-fixtures";
import { beforeEach, describe, expect, it } from "vitest";
import { installedPluginRoot } from "../../test/helpers/bundled-plugin-paths.js";
import type { OpenClawConfig } from "../config/config.js";
import {
applyPluginUninstallDirectoryRemoval,

View File

@@ -1,5 +1,5 @@
import { bundledPluginRootAt, repoInstallSpec } from "openclaw/plugin-sdk/test-fixtures";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { bundledPluginRootAt, repoInstallSpec } from "../../test/helpers/bundled-plugin-paths.js";
import type { OpenClawConfig } from "../config/config.js";
import type { ConfigFileSnapshot } from "../config/types.openclaw.js";
import {

View File

@@ -1,6 +1,6 @@
import { Command } from "commander";
import { repoInstallSpec } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { repoInstallSpec } from "../../../test/helpers/bundled-plugin-paths.js";
import { loggingState } from "../../logging/state.js";
import { setCommandJsonMode } from "./json-mode.js";

View File

@@ -6,7 +6,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { prepareRestartScript, runRestartScript } from "./restart-helper.js";
vi.mock("node:child_process", async () => {
const { mockNodeBuiltinModule } = await import("../../../test/helpers/node-builtin-mocks.js");
const { mockNodeBuiltinModule } = await import("openclaw/plugin-sdk/test-node-mocks");
return mockNodeBuiltinModule(
() => vi.importActual<typeof import("node:child_process")>("node:child_process"),
{

View File

@@ -1,5 +1,5 @@
import path from "node:path";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
import type { OpenClawConfig } from "../config/types.openclaw.js";
type AgentDefaultConfig = NonNullable<NonNullable<OpenClawConfig["agents"]>["defaults"]>;

View File

@@ -1,7 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import "./agent-command.test-mocks.js";
import * as acpManagerModule from "../acp/control-plane/manager.js";
import { AcpRuntimeError } from "../acp/runtime/errors.js";

View File

@@ -1,6 +1,6 @@
import path from "node:path";
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import { resolveAgentRuntimeConfig } from "../agents/agent-runtime-config.js";
import { resolveSession } from "../agents/command/session.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";

View File

@@ -1,7 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
import { beforeEach, describe, expect, it } from "vitest";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import { resolveAgentDir, resolveSessionAgentId } from "../agents/agent-scope.js";
import { resolveSession } from "../agents/command/session.js";
import { clearSessionStoreCacheForTest } from "../config/sessions/store.js";

View File

@@ -1,7 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
import { beforeEach, describe, expect, it, type MockInstance, vi } from "vitest";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import "./agent-command.test-mocks.js";
import { __testing as acpManagerTesting } from "../acp/control-plane/manager.js";
import * as authProfileStoreModule from "../agents/auth-profiles/store.js";

View File

@@ -1,9 +1,6 @@
import path from "node:path";
import { bundledPluginRoot, bundledPluginRootAt } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
bundledPluginRoot,
bundledPluginRootAt,
} from "../../../test/helpers/bundled-plugin-paths.js";
vi.mock("node:fs", async () => {
const actual = await vi.importActual<typeof import("node:fs")>("node:fs");

View File

@@ -1,7 +1,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { withTempHome } from "../../test/helpers/temp-home.js";
import { loadAndMaybeMigrateDoctorConfig } from "./doctor-config-flow.js";
import {
getDoctorConfigInputForTest,

View File

@@ -1,9 +1,6 @@
import path from "node:path";
import { bundledDistPluginRootAt, bundledPluginRootAt } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
bundledDistPluginRootAt,
bundledPluginRootAt,
} from "../../../../test/helpers/bundled-plugin-paths.js";
import type { BundledPluginSource } from "../../../plugins/bundled-sources.js";
import * as bundledSources from "../../../plugins/bundled-sources.js";
import {

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { beforeAll, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.js";
let probeModule: typeof import("./list.probe.js");

View File

@@ -1,7 +1,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it, vi } from "vitest";
import { withTempHome } from "../../test/helpers/temp-home.js";
import { setupCommand } from "./setup.js";
function createSetupDeps(home: string) {

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../test/helpers/import-fresh.ts";
vi.mock("../plugins/bundled-plugin-metadata.js", () => ({
listBundledPluginMetadata: () => [

View File

@@ -1,8 +1,8 @@
import fs from "node:fs";
import path from "node:path";
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { describe, expect, it, vi } from "vitest";
import { loadChannelConfigSurfaceModule } from "../../scripts/load-channel-config-surface.ts";
import { importFreshModule } from "../../test/helpers/import-fresh.ts";
import { withTempDir } from "../test-helpers/temp-dir.js";
async function importLoaderWithMissingBun() {

View File

@@ -1,7 +1,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it, vi } from "vitest";
import { withTempHome } from "../../test/helpers/temp-home.js";
import {
listConfiguredMcpServers,
setConfiguredMcpServer,

View File

@@ -1,6 +1,6 @@
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import { withTempHome } from "../../test/helpers/temp-home.js";
import { normalizeConfigPaths } from "./normalize-paths.js";
describe("normalizeConfigPaths", () => {

View File

@@ -1,8 +1,8 @@
import fsSync from "node:fs";
import fs from "node:fs/promises";
import path from "node:path";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { describe, expect, it } from "vitest";
import { withTempHome } from "../../../test/helpers/temp-home.js";
import type { OpenClawConfig } from "../config.js";
import { resolveStorePath } from "./paths.js";
import {

View File

@@ -1,6 +1,6 @@
import fs from "node:fs/promises";
import path from "node:path";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
import { resetPluginLoaderTestStateForTest } from "../plugins/loader.test-fixtures.js";
import { clearPluginSetupRegistryCache } from "../plugins/setup-registry.js";
import { resetConfigRuntimeState, type OpenClawConfig } from "./config.js";

View File

@@ -1,5 +1,5 @@
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../test/helpers/import-fresh.ts";
import type { BundledPluginMetadata } from "../plugins/bundled-plugin-metadata.js";
import type { PluginManifestChannelConfig } from "../plugins/manifest.js";

View File

@@ -1,6 +1,6 @@
import fs from "node:fs/promises";
import path from "node:path";
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { CronJob } from "./types.js";

View File

@@ -6,7 +6,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
const execFileMock = vi.hoisted(() => vi.fn());
vi.mock("node:child_process", async () => {
const { mockNodeChildProcessExecFile } = await import("../../test/helpers/node-builtin-mocks.js");
const { mockNodeChildProcessExecFile } = await import("openclaw/plugin-sdk/test-node-mocks");
return mockNodeChildProcessExecFile(
Object.assign(execFileMock, {
__promisify__: vi.fn(),

Some files were not shown because too many files have changed in this diff Show More