mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
test(release): repair plugin prerelease coverage
This commit is contained in:
@@ -240,6 +240,7 @@ describe("codex media understanding provider", () => {
|
||||
"You are OpenClaw's bounded image-understanding worker. Describe only the provided image content. Do not call tools, edit files, or ask follow-up questions.",
|
||||
config: {
|
||||
"features.apps": false,
|
||||
"features.goals": false,
|
||||
"features.code_mode": false,
|
||||
"features.code_mode_only": false,
|
||||
"features.image_generation": false,
|
||||
@@ -535,6 +536,7 @@ describe("codex media understanding provider", () => {
|
||||
"You are OpenClaw's bounded structured-extraction worker. Return only the requested extraction. Do not call tools, edit files, ask follow-up questions, or include secrets.",
|
||||
config: {
|
||||
"features.apps": false,
|
||||
"features.goals": false,
|
||||
"features.code_mode": false,
|
||||
"features.code_mode_only": false,
|
||||
"features.image_generation": false,
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import type { AuthProfileStore } from "openclaw/plugin-sdk/agent-runtime";
|
||||
import {
|
||||
clearRuntimeAuthProfileStoreSnapshots,
|
||||
replaceRuntimeAuthProfileStoreSnapshots,
|
||||
type AuthProfileStore,
|
||||
} from "openclaw/plugin-sdk/agent-runtime";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
fingerprintCodexAppServerAuthBinding,
|
||||
@@ -6,9 +10,12 @@ import {
|
||||
} from "./auth-binding.js";
|
||||
|
||||
describe("Codex app-server auth binding", () => {
|
||||
afterEach(() => vi.unstubAllEnvs());
|
||||
afterEach(() => {
|
||||
clearRuntimeAuthProfileStoreSnapshots();
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it("materializes a SecretRef once and fingerprints the executed store", async () => {
|
||||
it("uses the materialized runtime SecretRef snapshot and fingerprints the executed store", async () => {
|
||||
const profileId = "openai:work";
|
||||
const store: AuthProfileStore = {
|
||||
version: 1,
|
||||
@@ -28,7 +35,25 @@ describe("Codex app-server auth binding", () => {
|
||||
auth: { profiles: { [profileId]: { provider: "openai", mode: "api_key" as const } } },
|
||||
},
|
||||
};
|
||||
vi.stubEnv("OPENAI_WORK_KEY", "work-key-a");
|
||||
const publishRuntimeKey = (key: string) => {
|
||||
replaceRuntimeAuthProfileStoreSnapshots([
|
||||
{
|
||||
agentDir: params.agentDir,
|
||||
store: {
|
||||
version: 1,
|
||||
profiles: {
|
||||
[profileId]: {
|
||||
type: "api_key",
|
||||
provider: "openai",
|
||||
keyRef: { source: "env", provider: "default", id: "OPENAI_WORK_KEY" },
|
||||
key,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
};
|
||||
publishRuntimeKey("work-key-a");
|
||||
|
||||
const prepared = await prepareCodexAppServerAuthBinding(params);
|
||||
expect(prepared?.authProfileStore).not.toBe(store);
|
||||
@@ -44,7 +69,7 @@ describe("Codex app-server auth binding", () => {
|
||||
});
|
||||
expect(await fingerprintCodexAppServerAuthBinding(params)).toBe(prepared?.fingerprint);
|
||||
|
||||
vi.stubEnv("OPENAI_WORK_KEY", "work-key-b");
|
||||
publishRuntimeKey("work-key-b");
|
||||
expect(await fingerprintCodexAppServerAuthBinding(params)).not.toBe(prepared?.fingerprint);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -640,6 +640,7 @@ describe("runCodexAppServerSideQuestion", () => {
|
||||
expect(forkParams?.approvalsReviewer).toBe("user");
|
||||
expect(forkParams?.cwd).toBe("/tmp/workspace");
|
||||
expect(forkParams?.config).toEqual({
|
||||
"features.goals": false,
|
||||
"features.code_mode": true,
|
||||
"features.code_mode_only": false,
|
||||
"features.apply_patch_streaming_events": true,
|
||||
|
||||
@@ -92,6 +92,7 @@ function createParams(sessionFile: string, workspaceDir: string) {
|
||||
}
|
||||
|
||||
const DEFAULT_CODEX_RUNTIME_THREAD_CONFIG = {
|
||||
"features.goals": false,
|
||||
"features.code_mode": true,
|
||||
"features.code_mode_only": false,
|
||||
"features.apply_patch_streaming_events": true,
|
||||
|
||||
@@ -3,6 +3,7 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import type { GetReplyOptions, MsgContext } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
||||
import type { waitForTransportReady } from "openclaw/plugin-sdk/transport-ready-runtime";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { createIMessageRpcClient } from "./client.js";
|
||||
@@ -37,7 +38,6 @@ const waitForTransportReadyMock = vi.hoisted(() =>
|
||||
);
|
||||
const createIMessageRpcClientMock = vi.hoisted(() => vi.fn<typeof createIMessageRpcClient>());
|
||||
const readChannelAllowFromStoreMock = vi.hoisted(() => vi.fn(async () => [] as string[]));
|
||||
const recordInboundSessionMock = vi.hoisted(() => vi.fn(async (_params: unknown) => {}));
|
||||
const dispatchInboundMessageMock = vi.hoisted(() =>
|
||||
vi.fn(
|
||||
async (_params: DispatchInboundMessageParams) =>
|
||||
@@ -92,7 +92,6 @@ vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
return {
|
||||
...actual,
|
||||
readChannelAllowFromStore: readChannelAllowFromStoreMock,
|
||||
recordInboundSession: recordInboundSessionMock,
|
||||
upsertChannelPairingRequest: vi.fn(),
|
||||
};
|
||||
});
|
||||
@@ -130,7 +129,6 @@ describe("iMessage monitor last-route updates", () => {
|
||||
waitForTransportReadyMock.mockReset().mockResolvedValue(undefined);
|
||||
createIMessageRpcClientMock.mockReset();
|
||||
readChannelAllowFromStoreMock.mockReset().mockResolvedValue([]);
|
||||
recordInboundSessionMock.mockClear();
|
||||
dispatchInboundMessageMock.mockClear();
|
||||
createChannelInboundDebouncerMock.mockClear();
|
||||
debouncerControl.reset();
|
||||
@@ -933,6 +931,11 @@ describe("iMessage monitor last-route updates", () => {
|
||||
);
|
||||
|
||||
it("keeps per-channel-peer direct-message last-route writes on the isolated session", async () => {
|
||||
const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-imsg-last-route-"));
|
||||
tempDirs.push(stateDir);
|
||||
const configuredStore = path.join(stateDir, "sessions.json");
|
||||
const storePath = resolveStorePath(configuredStore, { agentId: "main" });
|
||||
const sessionKey = "agent:main:imessage:direct:+15550001111";
|
||||
const runtimeErrorMock = vi.fn();
|
||||
let onNotification: ((message: { method: string; params: unknown }) => void) | undefined;
|
||||
const client = {
|
||||
@@ -969,7 +972,7 @@ describe("iMessage monitor last-route updates", () => {
|
||||
config: {
|
||||
channels: { imessage: { dmPolicy: "allowlist", allowFrom: ["+15550001111"] } },
|
||||
messages: { inbound: { debounceMs: 0 } },
|
||||
session: { dmScope: "per-channel-peer", mainKey: "main" },
|
||||
session: { dmScope: "per-channel-peer", mainKey: "main", store: configuredStore },
|
||||
} as never,
|
||||
runtime: { error: runtimeErrorMock, exit: vi.fn(), log: vi.fn() },
|
||||
});
|
||||
@@ -979,25 +982,13 @@ describe("iMessage monitor last-route updates", () => {
|
||||
});
|
||||
expect(runtimeErrorMock).not.toHaveBeenCalled();
|
||||
await vi.waitFor(() => {
|
||||
expect(recordInboundSessionMock).toHaveBeenCalledTimes(1);
|
||||
expect(getSessionEntry({ storePath, sessionKey })).toMatchObject({
|
||||
lastChannel: "imessage",
|
||||
lastTo: "imessage:+15550001111",
|
||||
lastAccountId: "default",
|
||||
});
|
||||
});
|
||||
const recordParams = recordInboundSessionMock.mock.calls.at(0)?.[0] as
|
||||
| {
|
||||
sessionKey?: string;
|
||||
updateLastRoute?: {
|
||||
channel?: string;
|
||||
mainDmOwnerPin?: unknown;
|
||||
sessionKey?: string;
|
||||
to?: string;
|
||||
};
|
||||
}
|
||||
| undefined;
|
||||
expect(recordParams?.sessionKey).toBe("agent:main:imessage:direct:+15550001111");
|
||||
expect(recordParams?.updateLastRoute?.sessionKey).toBe(recordParams?.sessionKey);
|
||||
expect(recordParams?.updateLastRoute?.sessionKey).not.toBe("agent:main:main");
|
||||
expect(recordParams?.updateLastRoute?.channel).toBe("imessage");
|
||||
expect(recordParams?.updateLastRoute?.to).toBe("imessage:+15550001111");
|
||||
expect(recordParams?.updateLastRoute?.mainDmOwnerPin).toBeUndefined();
|
||||
expect(getSessionEntry({ storePath, sessionKey: "agent:main:main" })).toBeUndefined();
|
||||
});
|
||||
|
||||
it("suppresses stale backlog rows but dispatches fresh live rows", async () => {
|
||||
|
||||
@@ -18,8 +18,8 @@ describe("ConsoleLogger", () => {
|
||||
);
|
||||
|
||||
const message = spy.mock.calls[0]?.[0];
|
||||
expect(message).toBe(
|
||||
"[MatrixHttpClient] Authorization: Bearer ***:abcdefghijklmnopqrstuvwxyzABCDEFG",
|
||||
);
|
||||
expect(message).toContain("[MatrixHttpClient] Authorization: Bearer ");
|
||||
expect(message).not.toContain("123456:abcdefghijklmnopqrstuvwxyzABCDEFG");
|
||||
expect(message).not.toContain("abcdefghijklmnopqrstuvwxyzABCDEFG");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -976,12 +976,8 @@ describe("msteams monitor handler authz", () => {
|
||||
);
|
||||
|
||||
const ctx = recordFromMockCall(ctxPayload);
|
||||
expect(ctx.SupplementalContext).toMatchObject({
|
||||
quote: {
|
||||
body: "Quoted body",
|
||||
sender: "Alice",
|
||||
},
|
||||
});
|
||||
expect(ctx.ReplyToBody).toBe("Quoted body");
|
||||
expect(ctx.ReplyToSender).toBe("Alice");
|
||||
});
|
||||
|
||||
it("drops quote context when attachment metadata disagrees with a blocked parent sender", async () => {
|
||||
@@ -994,7 +990,8 @@ describe("msteams monitor handler authz", () => {
|
||||
);
|
||||
|
||||
const ctx = recordFromMockCall(ctxPayload);
|
||||
expect(ctx.SupplementalContext).toEqual({});
|
||||
expect(ctx.ReplyToBody).toBeUndefined();
|
||||
expect(ctx.ReplyToSender).toBeUndefined();
|
||||
expect(ctx.BodyForAgent).toBe("Current message");
|
||||
});
|
||||
|
||||
@@ -1027,7 +1024,7 @@ describe("msteams monitor handler authz", () => {
|
||||
// group chat: the fetched body would bypass the supplemental-quote visibility
|
||||
// allowlist. Only 1:1 DMs may fetch full text.
|
||||
const ctx = recordFromMockCall(firstSettledDispatch().ctxPayload);
|
||||
expect(ctx.SupplementalContext).toMatchObject({ quote: { body: "secret snippet…" } });
|
||||
expect(ctx.ReplyToBody).toBe("secret snippet…");
|
||||
expect(graphThreadMockState.fetchChatMessageText).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -1067,10 +1064,9 @@ describe("msteams monitor handler authz", () => {
|
||||
timeoutMs: 10_000,
|
||||
}),
|
||||
);
|
||||
expect(recordFromMockCall(firstSettledDispatch().ctxPayload).SupplementalContext).toMatchObject(
|
||||
{
|
||||
quote: { id: "message-1", body: "complete quoted message", sender: "Bot" },
|
||||
},
|
||||
);
|
||||
const ctx = recordFromMockCall(firstSettledDispatch().ctxPayload);
|
||||
expect(ctx.ReplyToId).toBe("message-1");
|
||||
expect(ctx.ReplyToBody).toBe("complete quoted message");
|
||||
expect(ctx.ReplyToSender).toBe("Bot");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -114,7 +114,9 @@ function makeInbound(overrides: Partial<InboundContext> = {}): InboundContext {
|
||||
};
|
||||
}
|
||||
|
||||
function makeInboundRuntime(): GatewayPluginRuntime["channel"]["inbound"] {
|
||||
function makeInboundRuntime(
|
||||
onResolvedContext?: (ctx: Record<string, unknown>) => void,
|
||||
): GatewayPluginRuntime["channel"]["inbound"] {
|
||||
return {
|
||||
run: vi.fn(async (rawParams: unknown) => {
|
||||
const params = rawParams as {
|
||||
@@ -132,7 +134,8 @@ function makeInboundRuntime(): GatewayPluginRuntime["channel"]["inbound"] {
|
||||
kind: "message",
|
||||
},
|
||||
{},
|
||||
)) as { runDispatch: () => Promise<unknown> };
|
||||
)) as { ctxPayload: Record<string, unknown>; runDispatch: () => Promise<unknown> };
|
||||
onResolvedContext?.(turn.ctxPayload);
|
||||
return { dispatchResult: await turn.runDispatch() };
|
||||
}),
|
||||
};
|
||||
@@ -208,10 +211,7 @@ function makeRuntime(params: {
|
||||
await dispatcherOptions.onFreshSettledDelivery?.();
|
||||
}
|
||||
}),
|
||||
finalizeInboundContext: vi.fn((rawCtx: Record<string, unknown>) => {
|
||||
params.onFinalize?.(rawCtx);
|
||||
return rawCtx;
|
||||
}),
|
||||
finalizeInboundContext: vi.fn((rawCtx: Record<string, unknown>) => rawCtx),
|
||||
formatInboundEnvelope: vi.fn(() => "voice"),
|
||||
resolveEffectiveMessagesConfig: vi.fn(() => ({})),
|
||||
resolveEnvelopeFormatOptions: vi.fn(() => ({})),
|
||||
@@ -220,7 +220,7 @@ function makeRuntime(params: {
|
||||
resolveStorePath: vi.fn(() => "/tmp/openclaw/qqbot-sessions.json"),
|
||||
recordInboundSession: vi.fn(async () => undefined),
|
||||
},
|
||||
inbound: makeInboundRuntime(),
|
||||
inbound: makeInboundRuntime(params.onFinalize),
|
||||
text: {
|
||||
chunkMarkdownText: (text: string) => [text],
|
||||
},
|
||||
@@ -575,9 +575,6 @@ describe("dispatchOutbound", () => {
|
||||
expect.anything(),
|
||||
"assistant",
|
||||
);
|
||||
expect(runtime.channel.session.resolveStorePath).toHaveBeenCalledWith(undefined, {
|
||||
agentId: "assistant",
|
||||
});
|
||||
expect(finalized?.AgentId).toBe("assistant");
|
||||
} finally {
|
||||
await fs.rm(tmpRoot, { recursive: true, force: true });
|
||||
|
||||
Reference in New Issue
Block a user