diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256 index 273b5e4ee9e..26ce037c324 100644 --- a/docs/.generated/plugin-sdk-api-baseline.sha256 +++ b/docs/.generated/plugin-sdk-api-baseline.sha256 @@ -1,2 +1,2 @@ -1fb6adb8edadd5ec27c0c4866478f6919bc33ce38816d28f3548fc7cac9dacb9 plugin-sdk-api-baseline.json -0840e1f2a59b8b660f58ab1810dc333b6b535e3235fdbb377da6f1e913fb1a87 plugin-sdk-api-baseline.jsonl +4e36981eb12b201f14b9d94ba44ab23793ed7555b2d736c1f477aeeb02e9ab9c plugin-sdk-api-baseline.json +8228f54b594b2462b1454c5c43c165ca8a57bec10da5b991fb4b3ba65427f61d plugin-sdk-api-baseline.jsonl diff --git a/docs/plugins/sdk-subpaths.md b/docs/plugins/sdk-subpaths.md index 4976e76fa3d..8abaf8be106 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, 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, 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 | diff --git a/docs/plugins/sdk-testing.md b/docs/plugins/sdk-testing.md index ad012088f75..bbc04863134 100644 --- a/docs/plugins/sdk-testing.md +++ b/docs/plugins/sdk-testing.md @@ -38,6 +38,17 @@ import { | `installCommonResolveTargetErrorCases` | Shared test cases for target resolution error handling | | `shouldAckReaction` | Check whether a channel should add an ack reaction | | `removeAckReactionAfterReply` | Remove ack reaction after reply delivery | +| `createTestRegistry` | Build a channel plugin registry fixture | +| `createEmptyPluginRegistry` | Build an empty plugin registry fixture | +| `setActivePluginRegistry` | Install a registry fixture for plugin runtime tests | +| `createRequestCaptureJsonFetch` | Capture JSON fetch requests in media helper tests | +| `withFetchPreconnect` | Run fetch tests with preconnect hooks installed | +| `withEnv` / `withEnvAsync` | Temporarily patch environment variables | +| `createTempHomeEnv` / `withTempDir` | Create isolated filesystem test fixtures | +| `createMockServerResponse` | Create a minimal HTTP server response mock | +| `registerSingleProviderPlugin` | Register one provider plugin in loader smoke tests | +| `createRuntimeTaskFlow` | Create isolated runtime task-flow state | +| `typedCases` | Preserve literal types for table-driven tests | ### Types diff --git a/scripts/check-no-extension-test-core-imports.ts b/scripts/check-no-extension-test-core-imports.ts index 2669a77c7ac..64fa17b9788 100644 --- a/scripts/check-no-extension-test-core-imports.ts +++ b/scripts/check-no-extension-test-core-imports.ts @@ -43,6 +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 = [ + "test/helpers/plugins/env.ts", + "test/helpers/plugins/fetch-mock.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/runtime-taskflow.ts", + "test/helpers/plugins/temp-dir.ts", + "test/helpers/plugins/temp-home.ts", + "test/helpers/plugins/typed-cases.ts", +]; + function isExtensionTestFile(filePath: string): boolean { return /\.test\.[cm]?[jt]sx?$/u.test(filePath) || /\.e2e\.test\.[cm]?[jt]sx?$/u.test(filePath); } @@ -109,7 +122,12 @@ function collectRelativeCoreImportOffenders( function main() { const extensionsDir = path.join(process.cwd(), "extensions"); - const files = collectExtensionTestFiles(extensionsDir); + const files = [ + ...collectExtensionTestFiles(extensionsDir), + ...EXTENSION_TEST_HELPER_BRIDGE_FILES.map((file) => path.join(process.cwd(), file)).filter( + (file) => fs.existsSync(file), + ), + ]; const offenders: Offender[] = []; for (const file of files) { @@ -130,7 +148,7 @@ function main() { if (offenders.length > 0) { console.error( - "Extension test files must stay on extension test bridges or public plugin-sdk surfaces.", + "Extension test files and helper bridges must stay on public plugin-sdk surfaces.", ); for (const offender of offenders.toSorted((a, b) => a.file.localeCompare(b.file))) { const location = offender.line @@ -143,7 +161,7 @@ function main() { } console.log( - `OK: extension test files and support helpers avoid direct core test/internal imports (${files.length} checked).`, + `OK: extension test files, support helpers, and helper bridges avoid direct core test/internal imports (${files.length} checked).`, ); } diff --git a/src/plugin-sdk/testing.ts b/src/plugin-sdk/testing.ts index cfc85fcbc6d..8cfbde3ab7e 100644 --- a/src/plugin-sdk/testing.ts +++ b/src/plugin-sdk/testing.ts @@ -114,10 +114,15 @@ export { countLines, hasBalancedFences } from "../test-utils/chunk-test-helpers. export { expectGeneratedTokenPersistedToGatewayAuth } from "../test-utils/auth-token-assertions.js"; 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 { 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 { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js"; export { buildPluginApi } from "../plugins/api-builder.js"; export { createCapturedPluginRegistration, type CapturedPluginRegistration, } from "../plugins/captured-registration.js"; +export { createRuntimeTaskFlow } from "../plugins/runtime/runtime-taskflow.js"; diff --git a/test/helpers/plugins/env.ts b/test/helpers/plugins/env.ts index fc63cd27c4a..8292d8f7418 100644 --- a/test/helpers/plugins/env.ts +++ b/test/helpers/plugins/env.ts @@ -1 +1 @@ -export { withEnv, withEnvAsync } from "../../../src/test-utils/env.js"; +export { withEnv, withEnvAsync } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/fetch-mock.ts b/test/helpers/plugins/fetch-mock.ts index e1774b46463..e7b86b14350 100644 --- a/test/helpers/plugins/fetch-mock.ts +++ b/test/helpers/plugins/fetch-mock.ts @@ -1 +1 @@ -export { withFetchPreconnect, type FetchMock } from "../../../src/test-utils/fetch-mock.js"; +export { withFetchPreconnect, type FetchMock } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/media-understanding.ts b/test/helpers/plugins/media-understanding.ts index e524e9f3199..c902d959443 100644 --- a/test/helpers/plugins/media-understanding.ts +++ b/test/helpers/plugins/media-understanding.ts @@ -1 +1 @@ -export { createRequestCaptureJsonFetch } from "../../../src/media-understanding/audio.test-helpers.js"; +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 index 3bbed0372a8..5579344ff0d 100644 --- a/test/helpers/plugins/mock-http-response.ts +++ b/test/helpers/plugins/mock-http-response.ts @@ -1 +1 @@ -export { createMockServerResponse } from "../../../src/test-utils/mock-http-response.js"; +export { createMockServerResponse } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/plugin-registration.ts b/test/helpers/plugins/plugin-registration.ts index bd20510800e..9c9f806e8fc 100644 --- a/test/helpers/plugins/plugin-registration.ts +++ b/test/helpers/plugins/plugin-registration.ts @@ -1 +1 @@ -export { registerSingleProviderPlugin } from "../../../src/test-utils/plugin-registration.js"; +export { registerSingleProviderPlugin } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/plugin-registry.ts b/test/helpers/plugins/plugin-registry.ts index c75fe4838bc..c0f1f84db9b 100644 --- a/test/helpers/plugins/plugin-registry.ts +++ b/test/helpers/plugins/plugin-registry.ts @@ -1,3 +1,5 @@ -export { createEmptyPluginRegistry } from "../../../src/plugins/registry.js"; -export { setActivePluginRegistry } from "../../../src/plugins/runtime.js"; -export { createTestRegistry } from "../../../src/test-utils/channel-plugins.js"; +export { + createEmptyPluginRegistry, + createTestRegistry, + setActivePluginRegistry, +} from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/runtime-taskflow.ts b/test/helpers/plugins/runtime-taskflow.ts index a1293bfa651..8a1e00fdf72 100644 --- a/test/helpers/plugins/runtime-taskflow.ts +++ b/test/helpers/plugins/runtime-taskflow.ts @@ -1 +1 @@ -export { createRuntimeTaskFlow } from "../../../src/plugins/runtime/runtime-taskflow.js"; +export { createRuntimeTaskFlow } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/temp-dir.ts b/test/helpers/plugins/temp-dir.ts index 08ec26218ec..f5ad08cd585 100644 --- a/test/helpers/plugins/temp-dir.ts +++ b/test/helpers/plugins/temp-dir.ts @@ -1 +1 @@ -export { withTempDir } from "../../../src/test-utils/temp-dir.js"; +export { withTempDir } from "openclaw/plugin-sdk/testing"; diff --git a/test/helpers/plugins/temp-home.ts b/test/helpers/plugins/temp-home.ts index 11db678ef77..cf200c4f7fe 100644 --- a/test/helpers/plugins/temp-home.ts +++ b/test/helpers/plugins/temp-home.ts @@ -1 +1 @@ -export { createTempHomeEnv, type TempHomeEnv } from "../../../src/test-utils/temp-home.js"; +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 index 45be30b08c3..cabfb116195 100644 --- a/test/helpers/plugins/typed-cases.ts +++ b/test/helpers/plugins/typed-cases.ts @@ -1 +1 @@ -export { typedCases } from "../../../src/test-utils/typed-cases.js"; +export { typedCases } from "openclaw/plugin-sdk/testing";