Skip to content

Commit 54f8e41

Browse files
committed
test: speed up provider and security tests
1 parent d1e5f4b commit 54f8e41

10 files changed

Lines changed: 149 additions & 274 deletions

src/image-generation/provider-registry.allowlist.test.ts

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/image-generation/provider-registry.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
2+
import type { OpenClawConfig } from "../config/types.js";
23
import type { ImageGenerationProviderPlugin } from "../plugins/types.js";
34

45
const { resolvePluginCapabilityProvidersMock } = vi.hoisted(() => ({
@@ -40,10 +41,12 @@ describe("image-generation provider registry", () => {
4041
});
4142

4243
it("delegates provider resolution to the capability provider boundary", () => {
43-
expect(listImageGenerationProviders()).toEqual([]);
44+
const cfg = {} as OpenClawConfig;
45+
46+
expect(listImageGenerationProviders(cfg)).toEqual([]);
4447
expect(resolvePluginCapabilityProvidersMock).toHaveBeenCalledWith({
4548
key: "imageGenerationProviders",
46-
cfg: undefined,
49+
cfg,
4750
});
4851
});
4952

src/media-understanding/provider-registry.allowlist.test.ts

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/media-understanding/provider-registry.test.ts

Lines changed: 41 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,53 @@
1-
import { afterEach, describe, expect, it, vi } from "vitest";
2-
import { createEmptyPluginRegistry } from "../plugins/registry.js";
3-
import { setActivePluginRegistry } from "../plugins/runtime.js";
1+
import { beforeEach, describe, expect, it, vi } from "vitest";
42
import {
53
buildMediaUnderstandingRegistry,
64
getMediaUnderstandingProvider,
75
} from "./provider-registry.js";
6+
import type { MediaUnderstandingProvider } from "./types.js";
87

9-
vi.mock("../plugins/capability-provider-runtime.js", async () => {
10-
const actual = await vi.importActual<typeof import("../plugins/capability-provider-runtime.js")>(
11-
"../plugins/capability-provider-runtime.js",
12-
);
13-
const runtime =
14-
await vi.importActual<typeof import("../plugins/runtime.js")>("../plugins/runtime.js");
15-
return {
16-
...actual,
17-
resolvePluginCapabilityProviders: ({ key }: { key: string }) =>
18-
key !== "mediaUnderstandingProviders"
19-
? []
20-
: (() => {
21-
const activeProviders =
22-
runtime
23-
.getActivePluginRegistry()
24-
?.mediaUnderstandingProviders.map((entry) => entry.provider) ?? [];
25-
return activeProviders.length > 0
26-
? activeProviders
27-
: [
28-
{ id: "groq", capabilities: ["image", "audio"] },
29-
{ id: "deepgram", capabilities: ["audio"] },
30-
];
31-
})(),
32-
};
33-
});
8+
const resolvePluginCapabilityProvidersMock = vi.hoisted(() => vi.fn());
9+
10+
vi.mock("../plugins/capability-provider-runtime.js", () => ({
11+
resolvePluginCapabilityProviders: resolvePluginCapabilityProvidersMock,
12+
}));
13+
14+
function createMediaProvider(
15+
params: Pick<MediaUnderstandingProvider, "id" | "capabilities"> &
16+
Partial<MediaUnderstandingProvider>,
17+
): MediaUnderstandingProvider {
18+
return params;
19+
}
3420

3521
describe("media-understanding provider registry", () => {
36-
afterEach(() => {
37-
setActivePluginRegistry(createEmptyPluginRegistry());
22+
beforeEach(() => {
23+
resolvePluginCapabilityProvidersMock.mockReset();
24+
resolvePluginCapabilityProvidersMock.mockReturnValue([]);
3825
});
3926

40-
it("loads bundled providers by default when no active registry is present", () => {
27+
it("loads media providers from the capability runtime", () => {
28+
resolvePluginCapabilityProvidersMock.mockReturnValue([
29+
createMediaProvider({ id: "groq", capabilities: ["image", "audio"] }),
30+
createMediaProvider({ id: "deepgram", capabilities: ["audio"] }),
31+
]);
32+
4133
const registry = buildMediaUnderstandingRegistry();
34+
4235
expect(getMediaUnderstandingProvider("groq", registry)?.id).toBe("groq");
4336
expect(getMediaUnderstandingProvider("deepgram", registry)?.id).toBe("deepgram");
44-
});
45-
46-
it("merges plugin-registered media providers into the active registry", async () => {
47-
const pluginRegistry = createEmptyPluginRegistry();
48-
pluginRegistry.mediaUnderstandingProviders.push({
49-
pluginId: "google",
50-
pluginName: "Google Plugin",
51-
source: "test",
52-
provider: {
53-
id: "google",
54-
capabilities: ["image", "audio", "video"],
55-
describeImage: async () => ({ text: "plugin image" }),
56-
transcribeAudio: async () => ({ text: "plugin audio" }),
57-
describeVideo: async () => ({ text: "plugin video" }),
58-
},
37+
expect(resolvePluginCapabilityProvidersMock).toHaveBeenCalledWith({
38+
key: "mediaUnderstandingProviders",
39+
cfg: undefined,
5940
});
60-
setActivePluginRegistry(pluginRegistry);
61-
62-
const registry = buildMediaUnderstandingRegistry();
63-
const provider = getMediaUnderstandingProvider("gemini", registry);
64-
65-
expect(provider?.id).toBe("google");
66-
expect(await provider?.describeVideo?.({} as never)).toEqual({ text: "plugin video" });
6741
});
6842

69-
it("keeps provider id normalization behavior for plugin-owned providers", () => {
70-
const pluginRegistry = createEmptyPluginRegistry();
71-
pluginRegistry.mediaUnderstandingProviders.push({
72-
pluginId: "google",
73-
pluginName: "Google Plugin",
74-
source: "test",
75-
provider: {
76-
id: "google",
77-
capabilities: ["image", "audio", "video"],
78-
},
79-
});
80-
setActivePluginRegistry(pluginRegistry);
43+
it("keeps provider id normalization behavior for capability providers", () => {
44+
resolvePluginCapabilityProvidersMock.mockReturnValue([
45+
createMediaProvider({ id: "google", capabilities: ["image", "audio", "video"] }),
46+
]);
8147

8248
const registry = buildMediaUnderstandingRegistry();
83-
const provider = getMediaUnderstandingProvider("gemini", registry);
8449

85-
expect(provider?.id).toBe("google");
50+
expect(getMediaUnderstandingProvider("gemini", registry)?.id).toBe("google");
8651
});
8752

8853
it("auto-registers media-understanding for config providers with image-capable models (#51392)", () => {
@@ -109,21 +74,15 @@ describe("media-understanding provider registry", () => {
10974
expect(textOnlyProvider).toBeUndefined();
11075
});
11176

112-
it("does not override plugin-registered providers when config also has image-capable models", async () => {
113-
const pluginRegistry = createEmptyPluginRegistry();
114-
pluginRegistry.mediaUnderstandingProviders.push({
115-
pluginId: "google",
116-
pluginName: "Google Plugin",
117-
source: "test",
118-
provider: {
77+
it("does not override capability providers when config also has image-capable models", async () => {
78+
resolvePluginCapabilityProvidersMock.mockReturnValue([
79+
createMediaProvider({
11980
id: "google",
12081
capabilities: ["image", "audio", "video"],
12182
describeImage: async () => ({ text: "plugin image" }),
12283
transcribeAudio: async () => ({ text: "plugin audio" }),
123-
},
124-
});
125-
setActivePluginRegistry(pluginRegistry);
126-
84+
}),
85+
]);
12786
const cfg = {
12887
models: {
12988
providers: {
@@ -140,6 +99,10 @@ describe("media-understanding provider registry", () => {
14099
expect(provider?.capabilities).toEqual(["image", "audio", "video"]);
141100
expect(await provider?.describeImage?.({} as never)).toEqual({ text: "plugin image" });
142101
expect(await provider?.transcribeAudio?.({} as never)).toEqual({ text: "plugin audio" });
102+
expect(resolvePluginCapabilityProvidersMock).toHaveBeenCalledWith({
103+
key: "mediaUnderstandingProviders",
104+
cfg,
105+
});
143106
});
144107

145108
it("does not auto-register providers with audio or video only inputs", () => {

src/plugin-activation-boundary.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ vi.mock("./plugins/manifest-registry.js", () => ({
6868
loadPluginManifestRegistry,
6969
}));
7070

71+
vi.mock("./secrets/channel-env-vars.js", () => ({
72+
getChannelEnvVars: (channelId: string) => {
73+
const varsByChannel: Record<string, string[]> = {
74+
discord: ["DISCORD_BOT_TOKEN"],
75+
irc: ["IRC_HOST", "IRC_NICK"],
76+
slack: ["SLACK_BOT_TOKEN"],
77+
telegram: ["TELEGRAM_BOT_TOKEN"],
78+
};
79+
return varsByChannel[channelId] ?? [];
80+
},
81+
}));
82+
7183
vi.mock("./plugin-sdk/facade-loader.js", () => ({
7284
...facadeMockHelpers,
7385
listImportedBundledPluginFacadeIds: () => [],
@@ -114,7 +126,6 @@ describe("plugin activation boundary", () => {
114126
});
115127
expect(loadBundledPluginPublicSurfaceModuleSync).not.toHaveBeenCalled();
116128

117-
expect(loadBundledPluginPublicSurfaceModuleSync).not.toHaveBeenCalled();
118129
expect(parseBrowserMajorVersion("Google Chrome 144.0.7534.0")).toBe(144);
119130
expect(
120131
loadBundledPluginPublicSurfaceModuleSync.mock.calls.map(

src/security/audit-plugins-trust.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,24 @@ vi.mock("../plugins/config-state.js", () => ({
8383
}),
8484
}));
8585

86+
vi.mock("../plugins/plugin-registry.js", () => ({
87+
createPluginRegistryIdNormalizer: () => (id: string) => id,
88+
loadPluginRegistrySnapshot: () => ({
89+
diagnostics: [],
90+
plugins: [{ pluginId: "discord" }],
91+
}),
92+
}));
93+
94+
vi.mock("../config/commands.js", () => ({
95+
resolveNativeSkillsEnabled: ({
96+
globalSetting,
97+
providerSetting,
98+
}: {
99+
globalSetting?: boolean | "auto";
100+
providerSetting?: boolean | "auto";
101+
}) => providerSetting === true || (providerSetting === undefined && globalSetting === true),
102+
}));
103+
86104
vi.mock("../channels/plugins/read-only.js", () => ({
87105
listReadOnlyChannelPluginsForConfig: () => mockChannelPlugins,
88106
}));

src/security/dangerous-config-flags.test.ts

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
22
import type { OpenClawConfig } from "../config/config.js";
33
import { collectEnabledInsecureOrDangerousFlags } from "./dangerous-config-flags.js";
44

5-
const { loadPluginManifestRegistryMock } = vi.hoisted(() => ({
6-
loadPluginManifestRegistryMock: vi.fn(),
5+
const { resolvePluginConfigContractsByIdMock } = vi.hoisted(() => ({
6+
resolvePluginConfigContractsByIdMock: vi.fn(),
77
}));
88

9-
vi.mock("../plugins/manifest-registry.js", () => ({
10-
loadPluginManifestRegistry: loadPluginManifestRegistryMock,
9+
vi.mock("../plugins/config-contracts.js", () => ({
10+
collectPluginConfigContractMatches: ({
11+
pathPattern,
12+
root,
13+
}: {
14+
pathPattern: string;
15+
root: Record<string, unknown>;
16+
}) => (Object.hasOwn(root, pathPattern) ? [{ path: pathPattern, value: root[pathPattern] }] : []),
17+
resolvePluginConfigContractsById: resolvePluginConfigContractsByIdMock,
1118
}));
1219

1320
function asConfig(value: unknown): OpenClawConfig {
@@ -16,21 +23,23 @@ function asConfig(value: unknown): OpenClawConfig {
1623

1724
describe("collectEnabledInsecureOrDangerousFlags", () => {
1825
beforeEach(() => {
19-
loadPluginManifestRegistryMock.mockReset();
26+
resolvePluginConfigContractsByIdMock.mockReset();
27+
resolvePluginConfigContractsByIdMock.mockReturnValue(new Map());
2028
});
2129

2230
it("collects manifest-declared dangerous plugin config values", () => {
23-
loadPluginManifestRegistryMock.mockReturnValue({
24-
plugins: [
25-
{
26-
id: "acpx",
27-
configContracts: {
28-
dangerousFlags: [{ path: "permissionMode", equals: "approve-all" }],
31+
resolvePluginConfigContractsByIdMock.mockReturnValue(
32+
new Map([
33+
[
34+
"acpx",
35+
{
36+
configContracts: {
37+
dangerousFlags: [{ path: "permissionMode", equals: "approve-all" }],
38+
},
2939
},
30-
},
31-
],
32-
diagnostics: [],
33-
});
40+
],
41+
]),
42+
);
3443

3544
expect(
3645
collectEnabledInsecureOrDangerousFlags(
@@ -50,17 +59,18 @@ describe("collectEnabledInsecureOrDangerousFlags", () => {
5059
});
5160

5261
it("ignores plugin config values that are not declared as dangerous", () => {
53-
loadPluginManifestRegistryMock.mockReturnValue({
54-
plugins: [
55-
{
56-
id: "other",
57-
configContracts: {
58-
dangerousFlags: [{ path: "mode", equals: "danger" }],
62+
resolvePluginConfigContractsByIdMock.mockReturnValue(
63+
new Map([
64+
[
65+
"other",
66+
{
67+
configContracts: {
68+
dangerousFlags: [{ path: "mode", equals: "danger" }],
69+
},
5970
},
60-
},
61-
],
62-
diagnostics: [],
63-
});
71+
],
72+
]),
73+
);
6474

6575
expect(
6676
collectEnabledInsecureOrDangerousFlags(

src/test-utils/provider-registry-allowlist.test-helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { beforeEach, vi } from "vitest";
2-
import { createEmptyPluginRegistry } from "../plugins/registry.js";
2+
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
33

44
const providerRegistryAllowlistMocks = vi.hoisted(() => ({
55
resolveRuntimePluginRegistry: vi.fn<

0 commit comments

Comments
 (0)