mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 08:00:42 +00:00
280 lines
8.3 KiB
TypeScript
280 lines
8.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { MatrixQaObservedEvent } from "./events.js";
|
|
import {
|
|
createMatrixQaRoomObserver,
|
|
primeMatrixQaRoom,
|
|
waitForOptionalMatrixQaRoomEvent,
|
|
} from "./sync.js";
|
|
|
|
describe("matrix sync helpers", () => {
|
|
it("primes the Matrix sync cursor without recording observed events", async () => {
|
|
const fetchImpl: typeof fetch = async () =>
|
|
new Response(JSON.stringify({ next_batch: "primed-sync-cursor" }), {
|
|
status: 200,
|
|
headers: { "content-type": "application/json" },
|
|
});
|
|
|
|
await expect(
|
|
primeMatrixQaRoom({
|
|
accessToken: "token",
|
|
baseUrl: "http://127.0.0.1:28008/",
|
|
fetchImpl,
|
|
}),
|
|
).resolves.toBe("primed-sync-cursor");
|
|
});
|
|
|
|
it("returns a typed no-match result while preserving the latest sync token", async () => {
|
|
const fetchImpl: typeof fetch = async () =>
|
|
new Response(
|
|
JSON.stringify({
|
|
next_batch: "next-batch-2",
|
|
rooms: {
|
|
join: {
|
|
"!room:matrix-qa.test": {
|
|
timeline: {
|
|
events: [
|
|
{
|
|
event_id: "$driver",
|
|
sender: "@driver:matrix-qa.test",
|
|
type: "m.room.message",
|
|
content: { body: "hello", msgtype: "m.text" },
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
{ status: 200, headers: { "content-type": "application/json" } },
|
|
);
|
|
|
|
const observedEvents: MatrixQaObservedEvent[] = [];
|
|
|
|
const result = await waitForOptionalMatrixQaRoomEvent({
|
|
accessToken: "token",
|
|
baseUrl: "http://127.0.0.1:28008/",
|
|
fetchImpl,
|
|
observedEvents,
|
|
predicate: (event) => event.sender === "@sut:matrix-qa.test",
|
|
roomId: "!room:matrix-qa.test",
|
|
since: "start-batch",
|
|
timeoutMs: 1,
|
|
});
|
|
|
|
expect(result).toEqual({
|
|
matched: false,
|
|
since: "next-batch-2",
|
|
});
|
|
expect(observedEvents).toEqual(
|
|
expect.arrayContaining([
|
|
expect.objectContaining({
|
|
kind: "message",
|
|
body: "hello",
|
|
eventId: "$driver",
|
|
roomId: "!room:matrix-qa.test",
|
|
sender: "@driver:matrix-qa.test",
|
|
type: "m.room.message",
|
|
}),
|
|
]),
|
|
);
|
|
});
|
|
|
|
it("keeps recording later same-batch events after the first match", async () => {
|
|
const fetchImpl: typeof fetch = async () =>
|
|
new Response(
|
|
JSON.stringify({
|
|
next_batch: "next-batch-2",
|
|
rooms: {
|
|
join: {
|
|
"!room:matrix-qa.test": {
|
|
timeline: {
|
|
events: [
|
|
{
|
|
event_id: "$sut",
|
|
sender: "@sut:matrix-qa.test",
|
|
type: "m.room.message",
|
|
content: { body: "target", msgtype: "m.text" },
|
|
},
|
|
{
|
|
event_id: "$driver",
|
|
sender: "@driver:matrix-qa.test",
|
|
type: "m.room.message",
|
|
content: { body: "trailing event", msgtype: "m.text" },
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
{ status: 200, headers: { "content-type": "application/json" } },
|
|
);
|
|
|
|
const observedEvents: MatrixQaObservedEvent[] = [];
|
|
|
|
const result = await waitForOptionalMatrixQaRoomEvent({
|
|
accessToken: "token",
|
|
baseUrl: "http://127.0.0.1:28008/",
|
|
fetchImpl,
|
|
observedEvents,
|
|
predicate: (event) => event.eventId === "$sut",
|
|
roomId: "!room:matrix-qa.test",
|
|
since: "start-batch",
|
|
timeoutMs: 1,
|
|
});
|
|
|
|
expect(result).toEqual({
|
|
event: expect.objectContaining({
|
|
eventId: "$sut",
|
|
}),
|
|
matched: true,
|
|
since: "next-batch-2",
|
|
});
|
|
expect(observedEvents).toEqual(
|
|
expect.arrayContaining([
|
|
expect.objectContaining({
|
|
kind: "message",
|
|
body: "target",
|
|
eventId: "$sut",
|
|
}),
|
|
expect.objectContaining({
|
|
kind: "message",
|
|
body: "trailing event",
|
|
eventId: "$driver",
|
|
}),
|
|
]),
|
|
);
|
|
});
|
|
|
|
it("lets a second wait reuse later same-batch events without another /sync", async () => {
|
|
let calls = 0;
|
|
const fetchImpl: typeof fetch = async () => {
|
|
calls += 1;
|
|
return new Response(
|
|
JSON.stringify({
|
|
next_batch: "next-batch-2",
|
|
rooms: {
|
|
join: {
|
|
"!room:matrix-qa.test": {
|
|
timeline: {
|
|
events: [
|
|
{
|
|
event_id: "$preview",
|
|
sender: "@sut:matrix-qa.test",
|
|
type: "m.room.message",
|
|
content: { body: "preview", msgtype: "m.notice" },
|
|
},
|
|
{
|
|
event_id: "$final",
|
|
sender: "@sut:matrix-qa.test",
|
|
type: "m.room.message",
|
|
content: {
|
|
body: "final",
|
|
msgtype: "m.text",
|
|
"m.relates_to": {
|
|
rel_type: "m.replace",
|
|
event_id: "$preview",
|
|
"m.new_content": { body: "final", msgtype: "m.text" },
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
{ status: 200, headers: { "content-type": "application/json" } },
|
|
);
|
|
};
|
|
const observedEvents: MatrixQaObservedEvent[] = [];
|
|
const observer = createMatrixQaRoomObserver({
|
|
accessToken: "token",
|
|
baseUrl: "http://127.0.0.1:28008/",
|
|
fetchImpl,
|
|
observedEvents,
|
|
since: "start-batch",
|
|
});
|
|
|
|
const preview = await observer.waitForRoomEvent({
|
|
predicate: (event) => event.eventId === "$preview",
|
|
roomId: "!room:matrix-qa.test",
|
|
timeoutMs: 1_000,
|
|
});
|
|
const finalized = await observer.waitForRoomEvent({
|
|
predicate: (event) => event.eventId === "$final",
|
|
roomId: "!room:matrix-qa.test",
|
|
timeoutMs: 1_000,
|
|
});
|
|
|
|
expect(preview.event.eventId).toBe("$preview");
|
|
expect(finalized.event.eventId).toBe("$final");
|
|
expect(calls).toBe(1);
|
|
});
|
|
|
|
it("shares one in-flight /sync poll across concurrent waits", async () => {
|
|
let calls = 0;
|
|
const fetchImpl: typeof fetch = async () => {
|
|
calls += 1;
|
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
return new Response(
|
|
JSON.stringify({
|
|
next_batch: "next-batch-2",
|
|
rooms: {
|
|
join: {
|
|
"!room:matrix-qa.test": {
|
|
timeline: {
|
|
events: [
|
|
{
|
|
event_id: "$reply",
|
|
sender: "@sut:matrix-qa.test",
|
|
type: "m.room.message",
|
|
content: { body: "reply", msgtype: "m.text" },
|
|
},
|
|
{
|
|
event_id: "$notice",
|
|
sender: "@sut:matrix-qa.test",
|
|
type: "m.room.message",
|
|
content: { body: "notice", msgtype: "m.notice" },
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
{ status: 200, headers: { "content-type": "application/json" } },
|
|
);
|
|
};
|
|
const observer = createMatrixQaRoomObserver({
|
|
accessToken: "token",
|
|
baseUrl: "http://127.0.0.1:28008/",
|
|
fetchImpl,
|
|
observedEvents: [],
|
|
since: "start-batch",
|
|
});
|
|
|
|
const [reply, notice] = await Promise.all([
|
|
observer.waitForRoomEvent({
|
|
predicate: (event) => event.eventId === "$reply",
|
|
roomId: "!room:matrix-qa.test",
|
|
timeoutMs: 1_000,
|
|
}),
|
|
observer.waitForOptionalRoomEvent({
|
|
predicate: (event) => event.eventId === "$notice",
|
|
roomId: "!room:matrix-qa.test",
|
|
timeoutMs: 1_000,
|
|
}),
|
|
]);
|
|
|
|
expect(reply.event.eventId).toBe("$reply");
|
|
expect(notice).toMatchObject({
|
|
event: expect.objectContaining({
|
|
eventId: "$notice",
|
|
}),
|
|
matched: true,
|
|
});
|
|
expect(calls).toBe(1);
|
|
});
|
|
});
|