test(channels): align outbound delivery assertions
Some checks are pending
CI / runner-admission (push) Waiting to run
CI / preflight (push) Blocked by required conditions
CI / security-fast (push) Blocked by required conditions
CI / pnpm-store-warmup (push) Blocked by required conditions
CI / build-artifacts (push) Blocked by required conditions
CI / native-i18n (push) Blocked by required conditions
CI / (push) Blocked by required conditions
CI / -1 (push) Blocked by required conditions
CI / -2 (push) Blocked by required conditions
CI / checks-node-compat-node22 (push) Blocked by required conditions
CI / -3 (push) Blocked by required conditions
CI / check-bundled-channel-config-metadata (push) Blocked by required conditions
CI / check-dependencies (push) Blocked by required conditions
CI / check-guards (push) Blocked by required conditions
CI / check-lint (push) Blocked by required conditions
CI / check-prod-types (push) Blocked by required conditions
CI / check-shrinkwrap (push) Blocked by required conditions
CI / check-test-types (push) Blocked by required conditions
CI / check-additional-boundaries-a (push) Blocked by required conditions
CI / check-additional-boundaries-bcd (push) Blocked by required conditions
CI / check-additional-extension-bundled (push) Blocked by required conditions
CI / check-additional-extension-channels (push) Blocked by required conditions
CI / check-additional-extension-package-boundary (push) Blocked by required conditions
CI / check-additional-runtime-topology-architecture (push) Blocked by required conditions
CI / check-session-accessor-boundary (push) Blocked by required conditions
CI / check-session-transcript-reader-boundary (push) Blocked by required conditions
CI / check-docs (push) Blocked by required conditions
CI / skills-python (push) Blocked by required conditions
CI / -4 (push) Blocked by required conditions
CI / -5 (push) Blocked by required conditions
CI / macos-swift (push) Blocked by required conditions
CI / ios-build (push) Blocked by required conditions
CI / -6 (push) Blocked by required conditions
CI / ci-timings-summary (push) Blocked by required conditions
ClawSweeper Dispatch / dispatch (push) Waiting to run
CodeQL / Security High (actions) (push) Waiting to run
CodeQL / Security High (channel-runtime-boundary) (push) Waiting to run
CodeQL / Security High (core-auth-secrets) (push) Waiting to run
CodeQL / Security High (mcp-process-tool-boundary) (push) Waiting to run
CodeQL / Security High (network-ssrf-boundary) (push) Waiting to run
CodeQL / Security High (plugin-trust-boundary) (push) Waiting to run
CodeQL / Security High (process-exec-boundary) (push) Waiting to run
Control UI Locale Refresh / plan (push) Waiting to run
Control UI Locale Refresh / Refresh (push) Blocked by required conditions
Control UI Locale Refresh / Commit control UI locale refresh (push) Blocked by required conditions
Docs Sync Publish Repo / sync-publish-repo (push) Waiting to run
Docs / docs (push) Waiting to run
Native App Locale Refresh / Refresh native ar (push) Waiting to run
Native App Locale Refresh / Refresh native de (push) Waiting to run
Native App Locale Refresh / Refresh native es (push) Waiting to run
Native App Locale Refresh / Refresh native fa (push) Waiting to run
Native App Locale Refresh / Refresh native fr (push) Waiting to run
Native App Locale Refresh / Refresh native hi (push) Waiting to run
Native App Locale Refresh / Refresh native id (push) Waiting to run
Native App Locale Refresh / Refresh native it (push) Waiting to run
Native App Locale Refresh / Refresh native ja-JP (push) Waiting to run
Native App Locale Refresh / Refresh native ko (push) Waiting to run
Native App Locale Refresh / Refresh native nl (push) Waiting to run
Native App Locale Refresh / Refresh native pl (push) Waiting to run
Native App Locale Refresh / Refresh native pt-BR (push) Waiting to run
Native App Locale Refresh / Refresh native ru (push) Waiting to run
Native App Locale Refresh / Refresh native sv (push) Waiting to run
Native App Locale Refresh / Refresh native th (push) Waiting to run
Native App Locale Refresh / Refresh native tr (push) Waiting to run
Native App Locale Refresh / Refresh native uk (push) Waiting to run
Native App Locale Refresh / Refresh native vi (push) Waiting to run
Native App Locale Refresh / Refresh native zh-CN (push) Waiting to run
Native App Locale Refresh / Refresh native zh-TW (push) Waiting to run
Native App Locale Refresh / Commit native locale refresh (push) Blocked by required conditions
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Waiting to run
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Blocked by required conditions
Plugin Init Scaffold Validation / Validate provider scaffold (push) Waiting to run
Plugin NPM Release / preview_plugins_npm (push) Waiting to run
Plugin NPM Release / Validate release publish approval (push) Blocked by required conditions
Plugin NPM Release / preview_plugin_pack (push) Blocked by required conditions
Plugin NPM Release / publish_plugins_npm (push) Blocked by required conditions
Website Installer Sync / static (push) Waiting to run
Website Installer Sync / linux-docker (push) Waiting to run
Website Installer Sync / macos-installer (push) Waiting to run
Website Installer Sync / windows-installer (push) Waiting to run
Website Installer Sync / sync-website (push) Blocked by required conditions
Workflow Sanity / no-tabs (push) Waiting to run
Workflow Sanity / actionlint (push) Waiting to run
Workflow Sanity / generated-doc-baselines (push) Waiting to run

This commit is contained in:
Vincent Koc 2026-07-04 14:57:35 +02:00
parent 5ea80c8d80
commit 787f3a2ce5
No known key found for this signature in database
11 changed files with 208 additions and 130 deletions

View file

@ -142,17 +142,22 @@ describe("discord channel message adapter", () => {
payload: { text: "payload" },
accountId: "default",
});
expect(hoisted.sendMessageDiscordMock).toHaveBeenLastCalledWith("channel:123456", "payload", {
verbose: false,
replyTo: undefined,
accountId: "default",
silent: undefined,
cfg: {},
textLimit: undefined,
maxLinesPerMessage: undefined,
tableMode: undefined,
chunkMode: undefined,
});
expect(hoisted.sendMessageDiscordMock).toHaveBeenLastCalledWith(
"channel:123456",
"payload",
expect.objectContaining({
verbose: false,
replyTo: undefined,
accountId: "default",
silent: undefined,
cfg: {},
textLimit: undefined,
maxLinesPerMessage: undefined,
tableMode: undefined,
chunkMode: undefined,
onDeliveryResult: expect.any(Function),
}),
);
expect(result.receipt.platformMessageIds).toEqual(["msg-1"]);
};

View file

@ -52,7 +52,7 @@ describe("discordOutbound shared interactive ordering", () => {
expect(hoisted.sendDiscordComponentMessageMock).toHaveBeenCalledWith(
"channel:123456",
{
expect.objectContaining({
blocks: [
{ type: "text", text: "First" },
{
@ -61,8 +61,8 @@ describe("discordOutbound shared interactive ordering", () => {
},
{ type: "text", text: "Last" },
],
},
{
}),
expect.objectContaining({
accountId: undefined,
chunkMode: undefined,
cfg: {},
@ -71,7 +71,7 @@ describe("discordOutbound shared interactive ordering", () => {
silent: undefined,
tableMode: undefined,
textLimit: undefined,
},
}),
);
expect(hoisted.sendMessageDiscordMock).not.toHaveBeenCalled();
expect(result).toEqual({

View file

@ -576,7 +576,14 @@ describe("matrix transport streaming OOM guard — real HTTP server without Cont
// Deliberately omit Content-Length so enforceDeclaredResponseSize is a no-op.
res.writeHead(200, { "content-type": "application/octet-stream" });
let sent = 0;
let closed = false;
res.on("close", () => {
closed = true;
});
const sendChunk = () => {
if (closed) {
return;
}
if (sent >= TOTAL_CHUNKS) {
res.end();
return;
@ -584,8 +591,14 @@ describe("matrix transport streaming OOM guard — real HTTP server without Cont
sent++;
chunksWritten++;
const ok = res.write(CHUNK);
if (ok) { setImmediate(sendChunk); }
else { res.once("drain", sendChunk); }
const scheduleNextChunk = () => {
setTimeout(sendChunk, 5);
};
if (ok) {
scheduleNextChunk();
} else {
res.once("drain", scheduleNextChunk);
}
};
sendChunk();
});
@ -637,20 +650,21 @@ describe("matrix transport streaming OOM guard — real HTTP server without Cont
const { port } = server.address() as { port: number };
try {
const result = (await performMatrixRequest({
homeserver: `http://127.0.0.1:${port}`,
accessToken: "token",
method: "GET",
endpoint: "/_matrix/media/v3/download/example/id",
timeoutMs: 10_000,
raw: true,
maxBytes: 16 * 1024 * 1024,
ssrfPolicy: { allowPrivateNetwork: true },
})).buffer;
const result = (
await performMatrixRequest({
homeserver: `http://127.0.0.1:${port}`,
accessToken: "token",
method: "GET",
endpoint: "/_matrix/media/v3/download/example/id",
timeoutMs: 10_000,
raw: true,
maxBytes: 16 * 1024 * 1024,
ssrfPolicy: { allowPrivateNetwork: true },
})
).buffer;
expect(result).toEqual(payload);
console.log(
"[matrix-bound-proof] under-cap: raw buffer returned correctly, size=" +
result.length,
"[matrix-bound-proof] under-cap: raw buffer returned correctly, size=" + result.length,
);
} finally {
await new Promise<void>((resolve) => {

View file

@ -1105,7 +1105,7 @@ describe("mattermostPlugin", () => {
}),
);
const options = expectSingleMattermostSend("channel:CHAN1", "Pick\n\n- Plugins");
const options = expectSingleMattermostSend("channel:CHAN1", "Pick\n\n- Plugins: `/codex`");
expect(options.buttons).toBeUndefined();
});

View file

@ -216,11 +216,11 @@ describe("deliverMattermostReplyPayload", () => {
expect(sendMessage).toHaveBeenCalledWith(
"channel:town-square",
"Intro line\nReasoning: appears in content but is not a prefix",
{
expect.objectContaining({
cfg,
accountId: "default",
replyToId: "root-post",
},
}),
);
});
@ -251,19 +251,23 @@ describe("deliverMattermostReplyPayload", () => {
});
expect(sendMessage).toHaveBeenCalledTimes(1);
expect(sendMessage).toHaveBeenCalledWith("channel:town-square", "caption", {
cfg,
accountId: "default",
mediaUrl,
replyToId: "root-post",
mediaLocalRoots: expect.arrayContaining([
path.join(stateDir, "media"),
path.join(stateDir, "canvas"),
path.join(stateDir, "workspace"),
path.join(stateDir, "sandboxes"),
path.join(stateDir, `workspace-${agentId}`),
]),
});
expect(sendMessage).toHaveBeenCalledWith(
"channel:town-square",
"caption",
expect.objectContaining({
cfg,
accountId: "default",
mediaUrl,
replyToId: "root-post",
mediaLocalRoots: expect.arrayContaining([
path.join(stateDir, "media"),
path.join(stateDir, "canvas"),
path.join(stateDir, "workspace"),
path.join(stateDir, "sandboxes"),
path.join(stateDir, `workspace-${agentId}`),
]),
}),
);
} finally {
if (previousStateDir === undefined) {
delete process.env.OPENCLAW_STATE_DIR;
@ -294,11 +298,15 @@ describe("deliverMattermostReplyPayload", () => {
});
expect(sendMessage).toHaveBeenCalledTimes(1);
expect(sendMessage).toHaveBeenCalledWith("channel:town-square", "hello", {
cfg,
accountId: "default",
replyToId: "root-post",
});
expect(sendMessage).toHaveBeenCalledWith(
"channel:town-square",
"hello",
expect.objectContaining({
cfg,
accountId: "default",
replyToId: "root-post",
}),
);
expect(outcome).toBe("text");
});
});

View file

@ -260,10 +260,10 @@ describe("slash-http cfg threading", () => {
expect(mockState.sendMessageMattermost).toHaveBeenCalledWith(
"channel:chan-1",
"No models available.",
{
expect.objectContaining({
cfg,
accountId: "default",
},
}),
);
});

View file

@ -108,11 +108,16 @@ describe("slack outbound shared hook wiring", () => {
replyToId: "1712000000.000001",
});
expect(sendMessageSlackMock).toHaveBeenCalledWith("C123", "hello", {
cfg,
threadTs: "1712000000.000001",
accountId: "default",
});
expect(sendMessageSlackMock).toHaveBeenCalledWith(
"C123",
"hello",
expect.objectContaining({
cfg,
threadTs: "1712000000.000001",
accountId: "default",
onDeliveryResult: expect.any(Function),
}),
);
});
it("respects cancel from the shared hook without a second adapter pass", async () => {

View file

@ -811,14 +811,19 @@ describe("deliverWebReply", () => {
});
expect(sendWhatsApp).toHaveBeenCalledTimes(1);
expect(sendWhatsApp).toHaveBeenCalledWith("5511999999999@c.us", "caption", {
verbose: false,
cfg: {},
mediaUrl: "/tmp/voice.ogg",
mediaLocalRoots: undefined,
accountId: undefined,
gifPlayback: undefined,
});
expect(sendWhatsApp).toHaveBeenCalledWith(
"5511999999999@c.us",
"caption",
expect.objectContaining({
verbose: false,
cfg: {},
mediaUrl: "/tmp/voice.ogg",
mediaLocalRoots: undefined,
accountId: undefined,
gifPlayback: undefined,
onDeliveryResult: expect.any(Function),
}),
);
expect(loadWebMedia).toHaveBeenCalledWith("/tmp/voice.ogg", {
maxBytes: 1024 * 1024,
localRoots: undefined,

View file

@ -86,20 +86,32 @@ describe("whatsappOutbound sendPayload", () => {
deps: { sendWhatsApp },
});
expect(sendWhatsApp).toHaveBeenNthCalledWith(1, "5511999999999@c.us", "hello", {
verbose: false,
cfg: {},
accountId: undefined,
gifPlayback: undefined,
});
expect(sendWhatsApp).toHaveBeenNthCalledWith(2, "5511999999999@c.us", "caption", {
verbose: false,
cfg: {},
mediaUrl: "/tmp/test.png",
mediaLocalRoots: undefined,
accountId: undefined,
gifPlayback: undefined,
});
expect(sendWhatsApp).toHaveBeenNthCalledWith(
1,
"5511999999999@c.us",
"hello",
expect.objectContaining({
verbose: false,
cfg: {},
accountId: undefined,
gifPlayback: undefined,
onDeliveryResult: expect.any(Function),
}),
);
expect(sendWhatsApp).toHaveBeenNthCalledWith(
2,
"5511999999999@c.us",
"caption",
expect.objectContaining({
verbose: false,
cfg: {},
mediaUrl: "/tmp/test.png",
mediaLocalRoots: undefined,
accountId: undefined,
gifPlayback: undefined,
onDeliveryResult: expect.any(Function),
}),
);
});
it("preserves audioAsVoice from payload media sends", async () => {
@ -113,15 +125,20 @@ describe("whatsappOutbound sendPayload", () => {
deps: { sendWhatsApp },
});
expect(sendWhatsApp).toHaveBeenCalledWith("5511999999999@c.us", "voice", {
verbose: false,
cfg: {},
mediaUrl: "/tmp/voice.ogg",
mediaLocalRoots: undefined,
audioAsVoice: true,
accountId: undefined,
gifPlayback: undefined,
});
expect(sendWhatsApp).toHaveBeenCalledWith(
"5511999999999@c.us",
"voice",
expect.objectContaining({
verbose: false,
cfg: {},
mediaUrl: "/tmp/voice.ogg",
mediaLocalRoots: undefined,
audioAsVoice: true,
accountId: undefined,
gifPlayback: undefined,
onDeliveryResult: expect.any(Function),
}),
);
});
it("drops blank mediaUrls before sending payload media", async () => {
@ -139,14 +156,19 @@ describe("whatsappOutbound sendPayload", () => {
});
expect(sendWhatsApp).toHaveBeenCalledTimes(1);
expect(sendWhatsApp).toHaveBeenCalledWith("5511999999999@c.us", "caption", {
verbose: false,
cfg: {},
mediaUrl: "/tmp/voice.ogg",
mediaLocalRoots: undefined,
accountId: undefined,
gifPlayback: undefined,
});
expect(sendWhatsApp).toHaveBeenCalledWith(
"5511999999999@c.us",
"caption",
expect.objectContaining({
verbose: false,
cfg: {},
mediaUrl: "/tmp/voice.ogg",
mediaLocalRoots: undefined,
accountId: undefined,
gifPlayback: undefined,
onDeliveryResult: expect.any(Function),
}),
);
});
it("skips whitespace-only text payloads", async () => {

View file

@ -70,17 +70,21 @@ describe("WhatsApp outbound payload contract", () => {
});
expect(sendWhatsApp).toHaveBeenCalledTimes(1);
expect(sendWhatsApp).toHaveBeenCalledWith("5511999999999@c.us", "caption", {
verbose: false,
cfg: {},
mediaUrl: "/tmp/voice.ogg",
mediaAccess: undefined,
mediaLocalRoots: undefined,
mediaReadFile: undefined,
accountId: undefined,
gifPlayback: undefined,
quotedMessageKey: undefined,
});
expect(sendWhatsApp).toHaveBeenCalledWith(
"5511999999999@c.us",
"caption",
expect.objectContaining({
verbose: false,
cfg: {},
mediaUrl: "/tmp/voice.ogg",
mediaAccess: undefined,
mediaLocalRoots: undefined,
mediaReadFile: undefined,
accountId: undefined,
gifPlayback: undefined,
onDeliveryResult: expect.any(Function),
}),
);
});
it("backs declared durable final capabilities with delivery proofs", async () => {

View file

@ -108,17 +108,22 @@ describe("zalouser outbound", () => {
accountId: "default",
} as never);
expect(mockSendMessage).toHaveBeenCalledWith("123456", "hello world\nthis is a test", {
profile: "default",
isGroup: true,
textMode: "markdown",
textChunkMode: "newline",
textChunkLimit: 10,
});
expect(mockSendMessage).toHaveBeenCalledWith(
"123456",
"hello world\nthis is a test",
expect.objectContaining({
profile: "default",
isGroup: true,
textMode: "markdown",
textChunkMode: "newline",
textChunkLimit: 10,
onDeliveryResult: expect.any(Function),
}),
);
expect(result).toEqual({
channel: "zalouser",
messageId: "mid-1",
ok: true,
receipt: undefined,
});
});
@ -142,17 +147,22 @@ describe("zalouser outbound", () => {
accountId: "work",
} as never);
expect(mockSendMessage).toHaveBeenCalledWith("987654", "hello user", {
profile: "work-profile",
isGroup: false,
textMode: "markdown",
textChunkMode: "newline",
textChunkLimit: 10,
});
expect(mockSendMessage).toHaveBeenCalledWith(
"987654",
"hello user",
expect.objectContaining({
profile: "work-profile",
isGroup: false,
textMode: "markdown",
textChunkMode: "newline",
textChunkLimit: 10,
onDeliveryResult: expect.any(Function),
}),
);
expect(result).toEqual({
channel: "zalouser",
messageId: "mid-1",
ok: true,
receipt: undefined,
});
});
@ -165,13 +175,18 @@ describe("zalouser outbound", () => {
text: "hello default",
} as never);
expect(mockSendMessage).toHaveBeenCalledWith("111222", "hello default", {
profile: "default",
isGroup: false,
textMode: "markdown",
textChunkMode: "newline",
textChunkLimit: 10,
});
expect(mockSendMessage).toHaveBeenCalledWith(
"111222",
"hello default",
expect.objectContaining({
profile: "default",
isGroup: false,
textMode: "markdown",
textChunkMode: "newline",
textChunkLimit: 10,
onDeliveryResult: expect.any(Function),
}),
);
});
});