import { beforeEach, describe, expect, it, vi } from "vitest" ;
import type { OpenClawConfig } from "../runtime-api.js" ;
const mocks = vi.hoisted(() => ({
sendMessageMatrix: vi.fn(),
sendPollMatrix: vi.fn(),
}));
vi.mock("./matrix/send.js" , () => ({
sendMessageMatrix: mocks.sendMessageMatrix,
sendPollMatrix: mocks.sendPollMatrix,
}));
vi.mock("./runtime.js" , () => ({
getMatrixRuntime: () => ({
channel: {
text: {
chunkMarkdownText: (text: string) => [text],
},
},
}),
}));
import { matrixOutbound } from "./outbound.js" ;
describe("matrixOutbound cfg threading" , () => {
beforeEach(() => {
mocks.sendMessageMatrix.mockReset();
mocks.sendPollMatrix.mockReset();
mocks.sendMessageMatrix.mockResolvedValue({ messageId: "evt-1" , roomId: "!room:example" });
mocks.sendPollMatrix.mockResolvedValue({ eventId: "$poll" , roomId: "!room:example" });
});
it("chunks outbound text without requiring Matrix runtime initialization" , () => {
const chunker = matrixOutbound.chunker;
if (!chunker) {
throw new Error("matrixOutbound.chunker missing" );
}
expect(() => chunker("hello world" , 5 )).not.toThrow();
expect(chunker("hello world" , 5 )).toEqual(["hello" , "world" ]);
});
it("passes resolved cfg to sendMessageMatrix for text sends" , async () => {
const cfg = {
channels: {
matrix: {
accessToken: "resolved-token" ,
},
},
} as OpenClawConfig;
await matrixOutbound.sendText!({
cfg,
to: "room:!room:example" ,
text: "hello" ,
accountId: "default" ,
threadId: "$thread" ,
replyToId: "$reply" ,
});
expect(mocks.sendMessageMatrix).toHaveBeenCalledWith(
"room:!room:example" ,
"hello" ,
expect.objectContaining({
cfg,
accountId: "default" ,
threadId: "$thread" ,
replyToId: "$reply" ,
}),
);
});
it("passes resolved cfg to sendMessageMatrix for media sends" , async () => {
const cfg = {
channels: {
matrix: {
accessToken: "resolved-token" ,
},
},
} as OpenClawConfig;
await matrixOutbound.sendMedia!({
cfg,
to: "room:!room:example" ,
text: "caption" ,
mediaUrl: "file:///tmp/cat.png",
mediaLocalRoots: ["/tmp/openclaw" ],
accountId: "default" ,
audioAsVoice: true ,
});
expect(mocks.sendMessageMatrix).toHaveBeenCalledWith(
"room:!room:example" ,
"caption" ,
expect.objectContaining({
cfg,
mediaUrl: "file:///tmp/cat.png",
mediaLocalRoots: ["/tmp/openclaw" ],
audioAsVoice: true ,
}),
);
});
it("passes resolved cfg through injected deps.matrix" , async () => {
const cfg = {
channels: {
matrix: {
accessToken: "resolved-token" ,
},
},
} as OpenClawConfig;
const matrix = vi.fn(async () => ({
messageId: "evt-injected" ,
roomId: "!room:example" ,
}));
await matrixOutbound.sendText!({
cfg,
to: "room:!room:example" ,
text: "hello via deps" ,
deps: { matrix },
accountId: "default" ,
threadId: "$thread" ,
replyToId: "$reply" ,
});
expect(matrix).toHaveBeenCalledWith(
"room:!room:example" ,
"hello via deps" ,
expect.objectContaining({
cfg,
accountId: "default" ,
threadId: "$thread" ,
replyToId: "$reply" ,
}),
);
});
it("passes resolved cfg to sendPollMatrix" , async () => {
const cfg = {
channels: {
matrix: {
accessToken: "resolved-token" ,
},
},
} as OpenClawConfig;
await matrixOutbound.sendPoll!({
cfg,
to: "room:!room:example" ,
poll: {
question: "Snack?" ,
options: ["Pizza" , "Sushi" ],
},
accountId: "default" ,
threadId: "$thread" ,
});
expect(mocks.sendPollMatrix).toHaveBeenCalledWith(
"room:!room:example" ,
expect.objectContaining({
question: "Snack?" ,
options: ["Pizza" , "Sushi" ],
}),
expect.objectContaining({
cfg,
accountId: "default" ,
threadId: "$thread" ,
}),
);
});
});
Messung V0.5 in Prozent C=99 H=100 G=99
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland