diff --git a/docs/plugins/sdk-testing.md b/docs/plugins/sdk-testing.md index 616c711fe52c..f7e6a3fc184d 100644 --- a/docs/plugins/sdk-testing.md +++ b/docs/plugins/sdk-testing.md @@ -246,6 +246,13 @@ describe("my-channel plugin", () => { ### Unit testing a provider plugin +For bundled catalog tests that resolve provider endpoint capabilities, call +`useProviderCatalogMetadata(new URL(".", import.meta.url))` from +`openclaw/plugin-sdk/plugin-test-runtime` at file or suite scope. It prepares +the plugin's manifest metadata once, installs and clears that snapshot around +each test, and rejects Jiti loading during assertions. This keeps cold runtime +discovery out of catalog test deadlines without changing provider behavior. + ```typescript import { describe, it, expect } from "vitest"; diff --git a/extensions/moonshot/provider-catalog.test.ts b/extensions/moonshot/provider-catalog.test.ts index 9b3255a1ec94..da2917dd2d2c 100644 --- a/extensions/moonshot/provider-catalog.test.ts +++ b/extensions/moonshot/provider-catalog.test.ts @@ -1,4 +1,5 @@ // Moonshot tests cover provider catalog plugin behavior. +import { useProviderCatalogMetadata } from "openclaw/plugin-sdk/plugin-test-runtime"; import { describe, expect, it } from "vitest"; import { applyMoonshotNativeStreamingUsageCompat, @@ -7,6 +8,8 @@ import { MOONSHOT_CN_BASE_URL, } from "./api.js"; +useProviderCatalogMetadata(new URL(".", import.meta.url)); + type MoonshotProvider = ReturnType; type MoonshotModel = MoonshotProvider["models"][number]; diff --git a/extensions/qwen/provider-catalog.test.ts b/extensions/qwen/provider-catalog.test.ts index 416eaeb77398..b71e9c7029b7 100644 --- a/extensions/qwen/provider-catalog.test.ts +++ b/extensions/qwen/provider-catalog.test.ts @@ -1,3 +1,4 @@ +import { useProviderCatalogMetadata } from "openclaw/plugin-sdk/plugin-test-runtime"; import { buildOpenAICompatibleLiveModelProviderConfig } from "openclaw/plugin-sdk/provider-catalog-live-runtime"; // Qwen tests cover provider catalog plugin behavior. import { describe, expect, it } from "vitest"; @@ -18,6 +19,8 @@ import { } from "./api.js"; import manifest from "./openclaw.plugin.json" with { type: "json" }; +useProviderCatalogMetadata(new URL(".", import.meta.url)); + type QwenProvider = ReturnType; function getQwenModelIds(provider: QwenProvider): string[] { diff --git a/src/plugin-sdk/plugin-test-runtime.ts b/src/plugin-sdk/plugin-test-runtime.ts index 4926ae0247cd..08dd06652b11 100644 --- a/src/plugin-sdk/plugin-test-runtime.ts +++ b/src/plugin-sdk/plugin-test-runtime.ts @@ -71,6 +71,7 @@ export { export { addTestHook } from "../plugins/hooks.test-helpers.js"; export { createPluginRecord } from "../plugins/status.test-helpers.js"; export { createPluginMetadataSnapshotFixture } from "../plugins/plugin-metadata.test-support.js"; +export { useProviderCatalogMetadata } from "./test-helpers/provider-catalog.js"; export { resolveBundledExplicitWebFetchProvidersFromPublicArtifacts, resolveBundledExplicitWebSearchProvidersFromPublicArtifacts, diff --git a/src/plugin-sdk/test-helpers/provider-catalog.ts b/src/plugin-sdk/test-helpers/provider-catalog.ts index 079cc05ed8c9..361435f6a08d 100644 --- a/src/plugin-sdk/test-helpers/provider-catalog.ts +++ b/src/plugin-sdk/test-helpers/provider-catalog.ts @@ -1,6 +1,13 @@ /** * Provider catalog contract assertions and expected Codex catalog fixtures. */ +import { fileURLToPath } from "node:url"; +import { afterEach, beforeEach, vi } from "vitest"; +import { setCurrentPluginMetadataSnapshot } from "../../plugins/current-plugin-metadata.test-support.js"; +import * as jitiFactory from "../../plugins/jiti-factory.js"; +import { loadPluginManifest } from "../../plugins/manifest.js"; +import { createPluginMetadataSnapshotFixture } from "../../plugins/plugin-metadata.test-support.js"; + export { expectAugmentedCodexCatalog, expectedAugmentedOpenaiCodexCatalogEntriesWithGpt55, @@ -9,6 +16,23 @@ export { } from "../../plugins/provider-runtime.test-support.js"; export type { ProviderPlugin } from "../provider-model-shared.js"; +/** Supplies manifest facts without cold runtime discovery in provider catalog tests. */ +export function useProviderCatalogMetadata(pluginRoot: URL): void { + const loaded = loadPluginManifest(fileURLToPath(pluginRoot)); + if (!loaded.ok) { + throw new Error(loaded.error); + } + const snapshot = createPluginMetadataSnapshotFixture({ plugins: [loaded.manifest] }); + beforeEach(() => { + setCurrentPluginMetadataSnapshot(snapshot); + const loader = vi.spyOn(jitiFactory, "createJiti").mockImplementation(() => { + throw new Error("Provider catalog tests must use prepared metadata without Jiti"); + }); + return () => loader.mockRestore(); + }); + afterEach(() => setCurrentPluginMetadataSnapshot(undefined)); +} + type ProviderRuntimeCatalogModule = Pick< typeof import("openclaw/plugin-sdk/provider-catalog-runtime"), "augmentModelCatalogWithProviderPlugins"