mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:20:43 +00:00
test: slim channel contract hotspots
This commit is contained in:
2
extensions/slack/inbound-contract-test-api.ts
Normal file
2
extensions/slack/inbound-contract-test-api.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { prepareSlackMessage } from "./src/monitor/message-handler/prepare.js";
|
||||
export { createInboundSlackTestContext } from "./src/monitor/message-handler/prepare.test-helpers.js";
|
||||
1
extensions/slack/outbound-payload-test-api.ts
Normal file
1
extensions/slack/outbound-payload-test-api.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { createSlackOutboundPayloadHarness } from "./src/outbound-payload.test-harness.js";
|
||||
1
extensions/whatsapp/outbound-payload-test-api.ts
Normal file
1
extensions/whatsapp/outbound-payload-test-api.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { whatsappOutbound } from "./src/outbound-adapter.js";
|
||||
@@ -11,8 +11,7 @@ import {
|
||||
import { chunkText } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { WHATSAPP_LEGACY_OUTBOUND_SEND_DEP_KEYS } from "./outbound-send-deps.js";
|
||||
import { resolveWhatsAppOutboundTarget } from "./runtime-api.js";
|
||||
import { sendPollWhatsApp } from "./send.js";
|
||||
import { resolveWhatsAppOutboundTarget } from "./resolve-outbound-target.js";
|
||||
|
||||
function trimLeadingWhitespace(text: string | undefined): string {
|
||||
return text?.trimStart() ?? "";
|
||||
@@ -90,7 +89,9 @@ export const whatsappOutbound: ChannelOutboundAdapter = {
|
||||
});
|
||||
},
|
||||
sendPoll: async ({ cfg, to, poll, accountId }) =>
|
||||
await sendPollWhatsApp(to, poll, {
|
||||
await (
|
||||
await import("./send.js")
|
||||
).sendPollWhatsApp(to, poll, {
|
||||
verbose: shouldLogVerbose(),
|
||||
accountId: accountId ?? undefined,
|
||||
cfg,
|
||||
|
||||
@@ -248,6 +248,14 @@ const sourceAnalysisCache = new Map<string, SourceAnalysis>();
|
||||
let extensionSourceFilesCache: string[] | null = null;
|
||||
let coreSourceFilesCache: string[] | null = null;
|
||||
const extensionFilesCache = new Map<string, string[]>();
|
||||
const STATIC_FROM_IMPORT_RE =
|
||||
/^\s*import(?:\s+type)?\s+(?!["'])(?:[\s\S]*?)\s+from\s*["']([^"']+)["']/gmu;
|
||||
const STATIC_SIDE_EFFECT_IMPORT_RE = /^\s*import\s*["']([^"']+)["']/gmu;
|
||||
const RE_EXPORT_STAR_RE =
|
||||
/^\s*export\s+(?:type\s+)?\*\s*(?:as\s+\w+\s+)?from\s*["']([^"']+)["']/gmu;
|
||||
const RE_EXPORT_NAMED_RE = /^\s*export\s+(?:type\s+)?\{[^}]*\}\s+from\s*["']([^"']+)["']/gmu;
|
||||
const DYNAMIC_IMPORT_RE = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/gmu;
|
||||
const REQUIRE_RE = /\brequire\s*\(\s*["']([^"']+)["']\s*\)/gmu;
|
||||
|
||||
type SourceFileCollectorOptions = {
|
||||
rootDir: string;
|
||||
@@ -388,16 +396,18 @@ function collectExtensionFiles(extensionId: string): string[] {
|
||||
|
||||
function collectModuleSpecifiers(text: string): string[] {
|
||||
const patterns = [
|
||||
/\bimport\s*\(\s*["']([^"']+\.(?:[cm]?[jt]sx?))["']\s*\)/g,
|
||||
/\brequire\s*\(\s*["']([^"']+\.(?:[cm]?[jt]sx?))["']\s*\)/g,
|
||||
/\b(?:import|export)\b[\s\S]*?\bfrom\s*["']([^"']+\.(?:[cm]?[jt]sx?))["']/g,
|
||||
/\bimport\s*["']([^"']+\.(?:[cm]?[jt]sx?))["']/g,
|
||||
DYNAMIC_IMPORT_RE,
|
||||
REQUIRE_RE,
|
||||
STATIC_FROM_IMPORT_RE,
|
||||
STATIC_SIDE_EFFECT_IMPORT_RE,
|
||||
RE_EXPORT_STAR_RE,
|
||||
RE_EXPORT_NAMED_RE,
|
||||
] as const;
|
||||
const specifiers = new Set<string>();
|
||||
for (const pattern of patterns) {
|
||||
for (const match of text.matchAll(pattern)) {
|
||||
const specifier = match[1]?.trim();
|
||||
if (specifier) {
|
||||
if (specifier && /\.(?:[cm]?[jt]sx?)$/u.test(specifier)) {
|
||||
specifiers.add(specifier);
|
||||
}
|
||||
}
|
||||
|
||||
28
src/channels/plugins/contracts/inbound.contract.test.ts
Normal file
28
src/channels/plugins/contracts/inbound.contract.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe } from "vitest";
|
||||
import { installDiscordInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.discord.js";
|
||||
import { installSignalInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.signal.js";
|
||||
import { installSlackInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.slack.js";
|
||||
import { installTelegramInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.telegram.js";
|
||||
import { installWhatsAppInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.whatsapp.js";
|
||||
|
||||
describe("inbound channel contracts", () => {
|
||||
describe("discord", () => {
|
||||
installDiscordInboundContractSuite();
|
||||
});
|
||||
|
||||
describe("signal", () => {
|
||||
installSignalInboundContractSuite();
|
||||
});
|
||||
|
||||
describe("slack", () => {
|
||||
installSlackInboundContractSuite();
|
||||
});
|
||||
|
||||
describe("telegram", () => {
|
||||
installTelegramInboundContractSuite();
|
||||
});
|
||||
|
||||
describe("whatsapp", () => {
|
||||
installWhatsAppInboundContractSuite();
|
||||
});
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installDiscordInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.discord.js";
|
||||
|
||||
describe("discord inbound contract", () => {
|
||||
installDiscordInboundContractSuite();
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installSignalInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.signal.js";
|
||||
|
||||
describe("signal inbound contract", () => {
|
||||
installSignalInboundContractSuite();
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installSlackInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.slack.js";
|
||||
|
||||
describe("slack inbound contract", () => {
|
||||
installSlackInboundContractSuite();
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installTelegramInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.telegram.js";
|
||||
|
||||
describe("telegram inbound contract", () => {
|
||||
installTelegramInboundContractSuite();
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installWhatsAppInboundContractSuite } from "../../../../test/helpers/channels/inbound-contract.whatsapp.js";
|
||||
|
||||
describe("whatsapp inbound contract", () => {
|
||||
installWhatsAppInboundContractSuite();
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { describe } from "vitest";
|
||||
import {
|
||||
installDirectTextMediaOutboundPayloadContractSuite,
|
||||
installDiscordOutboundPayloadContractSuite,
|
||||
installSlackOutboundPayloadContractSuite,
|
||||
installWhatsAppOutboundPayloadContractSuite,
|
||||
installZaloOutboundPayloadContractSuite,
|
||||
installZalouserOutboundPayloadContractSuite,
|
||||
} from "../../../../test/helpers/channels/outbound-payload-contract.js";
|
||||
|
||||
describe("outbound payload contracts", () => {
|
||||
describe("discord", () => {
|
||||
installDiscordOutboundPayloadContractSuite();
|
||||
});
|
||||
|
||||
describe("imessage", () => {
|
||||
installDirectTextMediaOutboundPayloadContractSuite();
|
||||
});
|
||||
|
||||
describe("slack", () => {
|
||||
installSlackOutboundPayloadContractSuite();
|
||||
});
|
||||
|
||||
describe("whatsapp", () => {
|
||||
installWhatsAppOutboundPayloadContractSuite();
|
||||
});
|
||||
|
||||
describe("zalo", () => {
|
||||
installZaloOutboundPayloadContractSuite();
|
||||
});
|
||||
|
||||
describe("zalouser", () => {
|
||||
installZalouserOutboundPayloadContractSuite();
|
||||
});
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installDiscordOutboundPayloadContractSuite } from "../../../../test/helpers/channels/outbound-payload-contract.js";
|
||||
|
||||
describe("discord outbound payload contract", () => {
|
||||
installDiscordOutboundPayloadContractSuite();
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installDirectTextMediaOutboundPayloadContractSuite } from "../../../../test/helpers/channels/outbound-payload-contract.js";
|
||||
|
||||
describe("imessage outbound payload contract", () => {
|
||||
installDirectTextMediaOutboundPayloadContractSuite();
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installSlackOutboundPayloadContractSuite } from "../../../../test/helpers/channels/outbound-payload-contract.js";
|
||||
|
||||
describe("slack outbound payload contract", () => {
|
||||
installSlackOutboundPayloadContractSuite();
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installWhatsAppOutboundPayloadContractSuite } from "../../../../test/helpers/channels/outbound-payload-contract.js";
|
||||
|
||||
describe("whatsapp outbound payload contract", () => {
|
||||
installWhatsAppOutboundPayloadContractSuite();
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installZaloOutboundPayloadContractSuite } from "../../../../test/helpers/channels/outbound-payload-contract.js";
|
||||
|
||||
describe("zalo outbound payload contract", () => {
|
||||
installZaloOutboundPayloadContractSuite();
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { describe } from "vitest";
|
||||
import { installZalouserOutboundPayloadContractSuite } from "../../../../test/helpers/channels/outbound-payload-contract.js";
|
||||
|
||||
describe("zalouser outbound payload contract", () => {
|
||||
installZalouserOutboundPayloadContractSuite();
|
||||
});
|
||||
@@ -1,12 +1,9 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { existsSync, mkdirSync, readdirSync, readFileSync } from "node:fs";
|
||||
import { readdirSync, readFileSync } from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import { dirname, join, relative, resolve } from "node:path";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import * as tar from "tar";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { pluginSdkEntrypoints } from "../../plugin-sdk/entrypoints.js";
|
||||
import { cleanupTrackedTempDirs, makeTrackedTempDir } from "../test-helpers/fs-fixtures.js";
|
||||
|
||||
const ROOT_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const REPO_ROOT = resolve(ROOT_DIR, "..");
|
||||
@@ -15,9 +12,6 @@ const PUBLIC_CONTRACT_REFERENCE_FILES = [
|
||||
"src/plugins/contracts/plugin-sdk-subpaths.test.ts",
|
||||
] as const;
|
||||
const PLUGIN_SDK_SUBPATH_PATTERN = /openclaw\/plugin-sdk\/([a-z0-9][a-z0-9-]*)\b/g;
|
||||
const NPM_PACK_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
|
||||
const WINDOWS_UNSAFE_CMD_CHARS_RE = /[&|<>^%\r\n]/;
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
function collectPluginSdkPackageExports(): string[] {
|
||||
const packageJson = JSON.parse(readFileSync(resolve(REPO_ROOT, "package.json"), "utf8")) as {
|
||||
@@ -87,124 +81,6 @@ function createRootPackageRequire() {
|
||||
return createRequire(pathToFileURL(resolve(REPO_ROOT, "package.json")).href);
|
||||
}
|
||||
|
||||
function isNpmExecPath(value: string): boolean {
|
||||
return /^npm(?:-cli)?(?:\.(?:c?js|cmd|exe))?$/.test(
|
||||
value.split(/[\\/]/).at(-1)?.toLowerCase() ?? "",
|
||||
);
|
||||
}
|
||||
|
||||
function escapeForCmdExe(arg: string): string {
|
||||
if (WINDOWS_UNSAFE_CMD_CHARS_RE.test(arg)) {
|
||||
throw new Error(`unsafe Windows cmd.exe argument detected: ${JSON.stringify(arg)}`);
|
||||
}
|
||||
if (!arg.includes(" ") && !arg.includes('"')) {
|
||||
return arg;
|
||||
}
|
||||
return `"${arg.replace(/"/g, '""')}"`;
|
||||
}
|
||||
|
||||
function buildCmdExeCommandLine(command: string, args: string[]): string {
|
||||
return [escapeForCmdExe(command), ...args.map(escapeForCmdExe)].join(" ");
|
||||
}
|
||||
|
||||
type NpmCommandInvocation = {
|
||||
command: string;
|
||||
args: string[];
|
||||
env?: NodeJS.ProcessEnv;
|
||||
windowsVerbatimArguments?: boolean;
|
||||
};
|
||||
|
||||
function resolveNpmCommandInvocation(npmArgs: string[]): NpmCommandInvocation {
|
||||
const npmExecPath = process.env.npm_execpath;
|
||||
if (typeof npmExecPath === "string" && npmExecPath.length > 0 && isNpmExecPath(npmExecPath)) {
|
||||
return { command: process.execPath, args: [npmExecPath, ...npmArgs] };
|
||||
}
|
||||
|
||||
if (process.platform !== "win32") {
|
||||
return { command: "npm", args: npmArgs };
|
||||
}
|
||||
|
||||
const nodeDir = dirname(process.execPath);
|
||||
const npmCliCandidates = [
|
||||
resolve(nodeDir, "../lib/node_modules/npm/bin/npm-cli.js"),
|
||||
resolve(nodeDir, "node_modules/npm/bin/npm-cli.js"),
|
||||
];
|
||||
const npmCliPath = npmCliCandidates.find((candidate) => existsSync(candidate));
|
||||
if (npmCliPath) {
|
||||
return { command: process.execPath, args: [npmCliPath, ...npmArgs] };
|
||||
}
|
||||
|
||||
const npmExePath = resolve(nodeDir, "npm.exe");
|
||||
if (existsSync(npmExePath)) {
|
||||
return { command: npmExePath, args: npmArgs };
|
||||
}
|
||||
|
||||
const npmCmdPath = resolve(nodeDir, "npm.cmd");
|
||||
if (existsSync(npmCmdPath)) {
|
||||
return {
|
||||
command: process.env.ComSpec ?? "cmd.exe",
|
||||
args: ["/d", "/s", "/c", buildCmdExeCommandLine(npmCmdPath, npmArgs)],
|
||||
windowsVerbatimArguments: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
command: process.env.ComSpec ?? "cmd.exe",
|
||||
args: ["/d", "/s", "/c", buildCmdExeCommandLine("npm.cmd", npmArgs)],
|
||||
windowsVerbatimArguments: true,
|
||||
};
|
||||
}
|
||||
|
||||
function packOpenClawToTempDir(packDir: string): string {
|
||||
const invocation = resolveNpmCommandInvocation([
|
||||
"pack",
|
||||
"--ignore-scripts",
|
||||
"--json",
|
||||
"--pack-destination",
|
||||
packDir,
|
||||
]);
|
||||
const result = spawnSync(invocation.command, invocation.args, {
|
||||
cwd: REPO_ROOT,
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...process.env,
|
||||
...invocation.env,
|
||||
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0",
|
||||
},
|
||||
maxBuffer: NPM_PACK_MAX_BUFFER_BYTES,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
||||
});
|
||||
if (result.error) {
|
||||
throw result.error;
|
||||
}
|
||||
if (result.status !== 0) {
|
||||
throw new Error((result.stderr || result.stdout || "npm pack failed").trim());
|
||||
}
|
||||
const raw = result.stdout;
|
||||
const parsed = JSON.parse(raw) as Array<{ filename?: string }>;
|
||||
const filename = parsed[0]?.filename?.trim();
|
||||
if (!filename) {
|
||||
throw new Error(`npm pack did not return a filename: ${raw}`);
|
||||
}
|
||||
return join(packDir, filename);
|
||||
}
|
||||
|
||||
async function readPackedRootPackageJson(archivePath: string): Promise<{
|
||||
dependencies?: Record<string, string>;
|
||||
}> {
|
||||
const extractDir = makeTrackedTempDir("openclaw-packed-root-package-json", tempDirs);
|
||||
await tar.x({
|
||||
file: archivePath,
|
||||
cwd: extractDir,
|
||||
filter: (entryPath) => entryPath === "package/package.json",
|
||||
strict: true,
|
||||
});
|
||||
return JSON.parse(readFileSync(join(extractDir, "package", "package.json"), "utf8")) as {
|
||||
dependencies?: Record<string, string>;
|
||||
};
|
||||
}
|
||||
|
||||
function collectExtensionFiles(dir: string): string[] {
|
||||
const entries = readdirSync(dir, { withFileTypes: true });
|
||||
const files: string[] = [];
|
||||
@@ -259,10 +135,6 @@ function collectExtensionCoreImportLeaks(): Array<{ file: string; specifier: str
|
||||
}
|
||||
|
||||
describe("plugin-sdk package contract guardrails", () => {
|
||||
afterEach(() => {
|
||||
cleanupTrackedTempDirs(tempDirs);
|
||||
});
|
||||
|
||||
it("keeps package.json exports aligned with built plugin-sdk entrypoints", () => {
|
||||
expect(collectPluginSdkPackageExports()).toEqual([...pluginSdkEntrypoints].toSorted());
|
||||
});
|
||||
@@ -291,7 +163,7 @@ describe("plugin-sdk package contract guardrails", () => {
|
||||
expect(failures).toEqual([]);
|
||||
});
|
||||
|
||||
it("mirrors matrix runtime deps needed by the bundled host graph", () => {
|
||||
it("mirrors package runtime deps needed by bundled host graphs", () => {
|
||||
const rootRuntimeDeps = collectRuntimeDependencySpecs(readRootPackageJson());
|
||||
const matrixPackageJson = readMatrixPackageJson();
|
||||
const matrixRuntimeDeps = collectRuntimeDependencySpecs(matrixPackageJson);
|
||||
@@ -304,6 +176,7 @@ describe("plugin-sdk package contract guardrails", () => {
|
||||
]) {
|
||||
expect(rootRuntimeDeps.get(dep)).toBe(matrixRuntimeDeps.get(dep));
|
||||
}
|
||||
expect(rootRuntimeDeps.has("@openclaw/plugin-package-contract")).toBe(false);
|
||||
});
|
||||
|
||||
it("resolves matrix crypto WASM from the root runtime surface", () => {
|
||||
@@ -316,20 +189,6 @@ describe("plugin-sdk package contract guardrails", () => {
|
||||
expect(resolvedPath).toContain("@matrix-org/matrix-sdk-crypto-wasm");
|
||||
});
|
||||
|
||||
it("keeps matrix crypto WASM in the packed artifact manifest", async () => {
|
||||
const tempRoot = makeTrackedTempDir("openclaw-matrix-wasm-pack", tempDirs);
|
||||
const packDir = join(tempRoot, "pack");
|
||||
mkdirSync(packDir, { recursive: true });
|
||||
|
||||
const archivePath = packOpenClawToTempDir(packDir);
|
||||
const packedPackageJson = await readPackedRootPackageJson(archivePath);
|
||||
const matrixPackageJson = readMatrixPackageJson();
|
||||
expect(packedPackageJson.dependencies?.["@matrix-org/matrix-sdk-crypto-wasm"]).toBe(
|
||||
matrixPackageJson.dependencies?.["@matrix-org/matrix-sdk-crypto-wasm"],
|
||||
);
|
||||
expect(packedPackageJson.dependencies?.["@openclaw/plugin-package-contract"]).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps extension sources on public sdk or local package seams", () => {
|
||||
expect(collectExtensionCoreImportLeaks()).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -34,7 +34,7 @@ type SlackTestApi = {
|
||||
const slackPrepareTestApiModuleId = resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "slack",
|
||||
artifactBasename: "test-api.js",
|
||||
artifactBasename: "inbound-contract-test-api.js",
|
||||
});
|
||||
|
||||
let slackTestApiPromise: Promise<SlackTestApi> | undefined;
|
||||
|
||||
@@ -21,12 +21,12 @@ const discordOutboundAdapterModuleId = resolveRelativeBundledPluginPublicModuleI
|
||||
const slackTestApiModuleId = resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "slack",
|
||||
artifactBasename: "test-api.js",
|
||||
artifactBasename: "outbound-payload-test-api.js",
|
||||
});
|
||||
const whatsappTestApiModuleId = resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "whatsapp",
|
||||
artifactBasename: "test-api.js",
|
||||
artifactBasename: "outbound-payload-test-api.js",
|
||||
});
|
||||
|
||||
let discordOutboundCache: Promise<ChannelOutboundAdapter> | undefined;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { AuthProfileStore } from "../../../src/agents/auth-profiles/types.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import type { ModelDefinitionConfig } from "../../../src/config/types.models.js";
|
||||
@@ -179,6 +179,7 @@ function installDiscoveryHooks(
|
||||
providerIds: readonly BundledProviderUnderTest[],
|
||||
) {
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
vi.doMock("openclaw/plugin-sdk/agent-runtime", () => {
|
||||
return {
|
||||
ensureAuthProfileStore: ensureAuthProfileStoreMock,
|
||||
@@ -311,10 +312,13 @@ function installDiscoveryHooks(
|
||||
"cloudflare-ai-gateway",
|
||||
);
|
||||
}
|
||||
setRuntimeAuthStore();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setRuntimeAuthStore();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
resolveCopilotApiTokenMock.mockReset();
|
||||
buildOllamaProviderMock.mockReset();
|
||||
|
||||
Reference in New Issue
Block a user