test(plugins): repair prerelease fixture contracts (#113877)

* test(plugins): repair prerelease fixtures

* test(onepassword): run resolver fixture from source

* test(moonshot): align catalog input fixtures
This commit is contained in:
Peter Steinberger
2026-07-25 14:54:39 -07:00
committed by GitHub
parent 81d9d1a1f4
commit 7be5c0a7c9
3 changed files with 82 additions and 32 deletions
-6
View File
@@ -108,8 +108,6 @@ describe("Cohere provider plugin", () => {
}),
expect.objectContaining({
id: "command-a-03-2025",
status: "deprecated",
replacedBy: COHERE_COMMAND_A_PLUS_MODEL_ID,
compat: {
supportsStore: false,
supportsUsageInStreaming: false,
@@ -118,8 +116,6 @@ describe("Cohere provider plugin", () => {
}),
expect.objectContaining({
id: COHERE_COMMAND_A_REASONING_MODEL_ID,
status: "deprecated",
replacedBy: COHERE_COMMAND_A_PLUS_MODEL_ID,
reasoning: true,
input: ["text"],
contextWindow: 256000,
@@ -127,8 +123,6 @@ describe("Cohere provider plugin", () => {
}),
expect.objectContaining({
id: COHERE_COMMAND_A_VISION_MODEL_ID,
status: "deprecated",
replacedBy: COHERE_COMMAND_A_PLUS_MODEL_ID,
reasoning: false,
input: ["text", "image"],
contextWindow: 128000,
+21 -12
View File
@@ -54,6 +54,10 @@ function createDynamicConfig() {
};
}
function createCanonicalAgentRoster() {
return { list: [{ id: "main", default: true }] };
}
async function pathExists(target: string): Promise<boolean> {
return fs.promises
.stat(target)
@@ -75,7 +79,7 @@ describe("maybeCreateDynamicAgent", () => {
dynamicAgentCreation: createDynamicConfig(),
},
},
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig;
const { runtime, mutateConfigFile } = createRuntime(cfg);
@@ -98,7 +102,7 @@ describe("maybeCreateDynamicAgent", () => {
it("persists a sender agent and direct binding when config writes are allowed", async () => {
const cfg = {
channels: { feishu: { dynamicAgentCreation: createDynamicConfig() } },
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig;
const { runtime, mutateConfigFile } = createRuntime(cfg);
@@ -121,6 +125,7 @@ describe("maybeCreateDynamicAgent", () => {
mutate: expect.any(Function),
});
expect(result.updatedCfg.agents?.list).toEqual([
{ id: "main", default: true },
{
id: "feishu-ou_sender",
workspace: path.join(tempRoot, "workspace-feishu-ou_sender"),
@@ -144,7 +149,7 @@ describe("maybeCreateDynamicAgent", () => {
it("does not create persistent state when current ingress denies the sender", async () => {
const cfg = {
channels: { feishu: { dynamicAgentCreation: createDynamicConfig() } },
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig;
const { runtime, mutateConfigFile } = createRuntime(cfg);
@@ -167,7 +172,7 @@ describe("maybeCreateDynamicAgent", () => {
it("rechecks current ingress inside the config mutation lock", async () => {
const cfg = {
channels: { feishu: { dynamicAgentCreation: createDynamicConfig() } },
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig;
const { runtime, commitConfig, mutateConfigFile } = createRuntime(cfg);
@@ -189,7 +194,7 @@ describe("maybeCreateDynamicAgent", () => {
expect(canCreateForConfig).toHaveBeenCalledTimes(2);
expect(mutateConfigFile).toHaveBeenCalledTimes(1);
expect(commitConfig).not.toHaveBeenCalled();
expect(result.updatedCfg.agents?.list).toEqual([]);
expect(result.updatedCfg.agents?.list).toEqual([{ id: "main", default: true }]);
expect(result.updatedCfg.bindings).toEqual([]);
expect(await pathExists(path.join(tempRoot, "workspace-feishu-ou_sender"))).toBe(false);
expect(await pathExists(path.join(tempRoot, "agent-feishu-ou_sender"))).toBe(false);
@@ -198,7 +203,7 @@ describe("maybeCreateDynamicAgent", () => {
it("preserves a non-peer route added before the config mutation lock", async () => {
const cfg = {
channels: { feishu: { dynamicAgentCreation: createDynamicConfig() } },
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig;
const mutationCfg = {
@@ -230,7 +235,7 @@ describe("maybeCreateDynamicAgent", () => {
it("scopes bindings to the normalized account id", async () => {
const cfg = {
channels: { feishu: { dynamicAgentCreation: createDynamicConfig() } },
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig;
const { runtime } = createRuntime(cfg);
@@ -262,7 +267,7 @@ describe("maybeCreateDynamicAgent", () => {
const accountId = "a".repeat(64);
const cfg = {
channels: { feishu: { dynamicAgentCreation: createDynamicConfig() } },
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig;
const { runtime } = createRuntime(cfg);
@@ -288,6 +293,7 @@ describe("maybeCreateDynamicAgent", () => {
expect(second.agentId).toHaveLength(52);
expect(first.agentId).not.toBe(second.agentId);
expect(second.updatedCfg.agents?.list?.map((agent) => agent.id)).toEqual([
"main",
first.agentId,
second.agentId,
]);
@@ -305,6 +311,7 @@ describe("maybeCreateDynamicAgent", () => {
},
agents: {
list: [
{ id: "main", default: true },
{
id: "feishu-ou_existing",
workspace: path.join(tempRoot, "existing-workspace"),
@@ -345,6 +352,7 @@ describe("maybeCreateDynamicAgent", () => {
channels: { feishu: { dynamicAgentCreation: createDynamicConfig() } },
agents: {
list: [
{ id: "main", default: true },
{
id: "feishu-ou_existing",
workspace: path.join(tempRoot, "existing-workspace"),
@@ -365,7 +373,7 @@ describe("maybeCreateDynamicAgent", () => {
const { runtime, mutateConfigFile } = createRuntime(currentCfg);
const result = await maybeCreateDynamicAgent({
cfg: { agents: { list: [] }, bindings: [] } as OpenClawConfig,
cfg: { agents: createCanonicalAgentRoster(), bindings: [] } as OpenClawConfig,
runtime,
accountId: "default",
senderOpenId: "ou_sender",
@@ -407,7 +415,7 @@ describe("maybeCreateDynamicAgent", () => {
dynamicAgentCreation: createDynamicConfig(),
},
},
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig;
const persistedCfg = {
@@ -417,7 +425,7 @@ describe("maybeCreateDynamicAgent", () => {
dynamicAgentCreation: createDynamicConfig(),
},
},
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig;
const { runtime } = createRuntime(currentCfg, persistedCfg);
@@ -440,6 +448,7 @@ describe("maybeCreateDynamicAgent", () => {
channels: { feishu: { configWrites: false } },
agents: {
list: [
{ id: "main", default: true },
{
id: "feishu-ou_sender",
workspace: path.join(tempRoot, "existing-workspace"),
@@ -461,7 +470,7 @@ describe("maybeCreateDynamicAgent", () => {
const result = await maybeCreateDynamicAgent({
cfg: {
agents: { list: [] },
agents: createCanonicalAgentRoster(),
bindings: [],
} as OpenClawConfig,
runtime,
@@ -2,18 +2,61 @@ import { spawn } from "node:child_process";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { fileURLToPath, pathToFileURL } from "node:url";
import { DEFAULT_SECRET_FILE_MAX_BYTES } from "openclaw/plugin-sdk/secret-file-runtime";
import { afterEach, describe, expect, it } from "vitest";
import { afterAll, afterEach, beforeAll, describe, expect, it } from "vitest";
import { encodeOnePasswordSecretId } from "../onepassword-secret-id.js";
import { createTrustedNodeFixture } from "./trusted-node.test-support.js";
const resolverPath = fileURLToPath(
const sourceResolverPath = fileURLToPath(
new URL("../onepassword-secret-ref-resolver.js", import.meta.url),
);
const sourceStaticAssetPaths = [
sourceResolverPath,
fileURLToPath(new URL("../onepassword-op-path.js", import.meta.url)),
fileURLToPath(new URL("../onepassword-secret-id.js", import.meta.url)),
];
const manifestPath = fileURLToPath(new URL("../openclaw.plugin.json", import.meta.url));
const packagePath = fileURLToPath(new URL("../package.json", import.meta.url));
const tsxCliPath = fileURLToPath(import.meta.resolve("tsx/cli"));
const rootTsconfigPath = path.resolve("tsconfig.json");
const secretRefRuntimeSourceUrl = pathToFileURL(
path.resolve("src/plugin-sdk/secret-ref-runtime.ts"),
).href;
const tempDirs: string[] = [];
let resolverPath = sourceResolverPath;
let stagedResolverRoot: string | undefined;
beforeAll(() => {
const tempRoot = path.join(process.cwd(), ".tmp");
fs.mkdirSync(tempRoot, { recursive: true });
stagedResolverRoot = fs.mkdtempSync(path.join(tempRoot, "onepassword-resolver-"));
for (const sourcePath of sourceStaticAssetPaths) {
const stagedPath = path.join(stagedResolverRoot, path.basename(sourcePath));
if (sourcePath.endsWith("onepassword-op-path.js")) {
fs.writeFileSync(
stagedPath,
fs
.readFileSync(sourcePath, "utf8")
.replace(
'"openclaw/plugin-sdk/secret-ref-runtime"',
JSON.stringify(secretRefRuntimeSourceUrl),
),
);
continue;
}
fs.copyFileSync(sourcePath, stagedPath);
}
// Keep the relative static assets together, but resolve the real SDK from source so this
// focused test does not depend on a parallel build producing dist/plugin-sdk first.
resolverPath = path.join(stagedResolverRoot, path.basename(sourceResolverPath));
});
afterAll(() => {
if (stagedResolverRoot) {
fs.rmSync(stagedResolverRoot, { recursive: true, force: true });
}
});
function makeTempDir(): string {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-1password-test-"));
@@ -50,17 +93,21 @@ function runResolver(params: {
);
}
return new Promise((resolve, reject) => {
const child = spawn(process.execPath, [resolverPath], {
...(params.cwd ? { cwd: params.cwd } : {}),
stdio: ["pipe", "pipe", "pipe"],
env: {
...process.env,
OP_SERVICE_ACCOUNT_TOKEN: "",
CLAW_1PASSWORD_OP: "",
OPENCLAW_STATE_DIR: stateDir,
...params.env,
const child = spawn(
process.execPath,
[tsxCliPath, "--tsconfig", rootTsconfigPath, resolverPath],
{
...(params.cwd ? { cwd: params.cwd } : {}),
stdio: ["pipe", "pipe", "pipe"],
env: {
...process.env,
OP_SERVICE_ACCOUNT_TOKEN: "",
CLAW_1PASSWORD_OP: "",
OPENCLAW_STATE_DIR: stateDir,
...params.env,
},
},
});
);
let stdout = "";
let stderr = "";
child.stdout.setEncoding("utf8");
@@ -87,7 +134,7 @@ afterEach(() => {
describe("plugin manifest", () => {
it("declares the 1Password resolver as a managed Node SecretRef preset", () => {
const resolverSource = fs.readFileSync(resolverPath, "utf8");
const resolverSource = fs.readFileSync(sourceResolverPath, "utf8");
const readIntegerConstant = (name: string): number => {
const match = new RegExp(`const ${name} = (\\d[\\d_]*)`, "u").exec(resolverSource);
return Number(match?.[1]?.replaceAll("_", ""));