mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
test(matrix): add coverage for deduped action helpers
This commit is contained in:
15
extensions/matrix/src/matrix/actions/limits.test.ts
Normal file
15
extensions/matrix/src/matrix/actions/limits.test.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveMatrixActionLimit } from "./limits.js";
|
||||
|
||||
describe("resolveMatrixActionLimit", () => {
|
||||
it("uses fallback for non-finite values", () => {
|
||||
expect(resolveMatrixActionLimit(undefined, 20)).toBe(20);
|
||||
expect(resolveMatrixActionLimit(Number.NaN, 20)).toBe(20);
|
||||
});
|
||||
|
||||
it("normalizes finite numbers to positive integers", () => {
|
||||
expect(resolveMatrixActionLimit(7.9, 20)).toBe(7);
|
||||
expect(resolveMatrixActionLimit(0, 20)).toBe(1);
|
||||
expect(resolveMatrixActionLimit(-3, 20)).toBe(1);
|
||||
});
|
||||
});
|
||||
74
extensions/matrix/src/matrix/actions/pins.test.ts
Normal file
74
extensions/matrix/src/matrix/actions/pins.test.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { listMatrixPins, pinMatrixMessage, unpinMatrixMessage } from "./pins.js";
|
||||
|
||||
function createPinsClient(seedPinned: string[], knownBodies: Record<string, string> = {}) {
|
||||
let pinned = [...seedPinned];
|
||||
const getRoomStateEvent = vi.fn(async () => ({ pinned: [...pinned] }));
|
||||
const sendStateEvent = vi.fn(
|
||||
async (_roomId: string, _type: string, _key: string, payload: any) => {
|
||||
pinned = [...payload.pinned];
|
||||
},
|
||||
);
|
||||
const getEvent = vi.fn(async (_roomId: string, eventId: string) => {
|
||||
const body = knownBodies[eventId];
|
||||
if (!body) {
|
||||
throw new Error("missing");
|
||||
}
|
||||
return {
|
||||
event_id: eventId,
|
||||
sender: "@alice:example.org",
|
||||
type: "m.room.message",
|
||||
origin_server_ts: 123,
|
||||
content: { msgtype: "m.text", body },
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
client: {
|
||||
getRoomStateEvent,
|
||||
sendStateEvent,
|
||||
getEvent,
|
||||
stop: vi.fn(),
|
||||
} as unknown as MatrixClient,
|
||||
getPinned: () => pinned,
|
||||
sendStateEvent,
|
||||
};
|
||||
}
|
||||
|
||||
describe("matrix pins actions", () => {
|
||||
it("pins a message once even when asked twice", async () => {
|
||||
const { client, getPinned, sendStateEvent } = createPinsClient(["$a"]);
|
||||
|
||||
const first = await pinMatrixMessage("!room:example.org", "$b", { client });
|
||||
const second = await pinMatrixMessage("!room:example.org", "$b", { client });
|
||||
|
||||
expect(first.pinned).toEqual(["$a", "$b"]);
|
||||
expect(second.pinned).toEqual(["$a", "$b"]);
|
||||
expect(getPinned()).toEqual(["$a", "$b"]);
|
||||
expect(sendStateEvent).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("unpinds only the selected message id", async () => {
|
||||
const { client, getPinned } = createPinsClient(["$a", "$b", "$c"]);
|
||||
|
||||
const result = await unpinMatrixMessage("!room:example.org", "$b", { client });
|
||||
|
||||
expect(result.pinned).toEqual(["$a", "$c"]);
|
||||
expect(getPinned()).toEqual(["$a", "$c"]);
|
||||
});
|
||||
|
||||
it("lists pinned ids and summarizes only resolvable events", async () => {
|
||||
const { client } = createPinsClient(["$a", "$missing"], { $a: "hello" });
|
||||
|
||||
const result = await listMatrixPins("!room:example.org", { client });
|
||||
|
||||
expect(result.pinned).toEqual(["$a", "$missing"]);
|
||||
expect(result.events).toEqual([
|
||||
expect.objectContaining({
|
||||
eventId: "$a",
|
||||
body: "hello",
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
109
extensions/matrix/src/matrix/actions/reactions.test.ts
Normal file
109
extensions/matrix/src/matrix/actions/reactions.test.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { listMatrixReactions, removeMatrixReactions } from "./reactions.js";
|
||||
|
||||
function createReactionsClient(params: {
|
||||
chunk: Array<{
|
||||
event_id?: string;
|
||||
sender?: string;
|
||||
key?: string;
|
||||
}>;
|
||||
userId?: string | null;
|
||||
}) {
|
||||
const doRequest = vi.fn(async (_method: string, _path: string, _query: any) => ({
|
||||
chunk: params.chunk.map((item) => ({
|
||||
event_id: item.event_id ?? "",
|
||||
sender: item.sender ?? "",
|
||||
content: item.key
|
||||
? {
|
||||
"m.relates_to": {
|
||||
rel_type: "m.annotation",
|
||||
event_id: "$target",
|
||||
key: item.key,
|
||||
},
|
||||
}
|
||||
: {},
|
||||
})),
|
||||
}));
|
||||
const getUserId = vi.fn(async () => params.userId ?? null);
|
||||
const redactEvent = vi.fn(async () => undefined);
|
||||
|
||||
return {
|
||||
client: {
|
||||
doRequest,
|
||||
getUserId,
|
||||
redactEvent,
|
||||
stop: vi.fn(),
|
||||
} as unknown as MatrixClient,
|
||||
doRequest,
|
||||
redactEvent,
|
||||
};
|
||||
}
|
||||
|
||||
describe("matrix reaction actions", () => {
|
||||
it("aggregates reactions by key and unique sender", async () => {
|
||||
const { client, doRequest } = createReactionsClient({
|
||||
chunk: [
|
||||
{ event_id: "$1", sender: "@alice:example.org", key: "👍" },
|
||||
{ event_id: "$2", sender: "@bob:example.org", key: "👍" },
|
||||
{ event_id: "$3", sender: "@alice:example.org", key: "👎" },
|
||||
{ event_id: "$4", sender: "@bot:example.org" },
|
||||
],
|
||||
userId: "@bot:example.org",
|
||||
});
|
||||
|
||||
const result = await listMatrixReactions("!room:example.org", "$msg", { client, limit: 2.9 });
|
||||
|
||||
expect(doRequest).toHaveBeenCalledWith(
|
||||
"GET",
|
||||
expect.stringContaining("/rooms/!room%3Aexample.org/relations/%24msg/"),
|
||||
expect.objectContaining({ limit: 2 }),
|
||||
);
|
||||
expect(result).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
key: "👍",
|
||||
count: 2,
|
||||
users: expect.arrayContaining(["@alice:example.org", "@bob:example.org"]),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
key: "👎",
|
||||
count: 1,
|
||||
users: ["@alice:example.org"],
|
||||
}),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("removes only current-user reactions matching emoji filter", async () => {
|
||||
const { client, redactEvent } = createReactionsClient({
|
||||
chunk: [
|
||||
{ event_id: "$1", sender: "@me:example.org", key: "👍" },
|
||||
{ event_id: "$2", sender: "@me:example.org", key: "👎" },
|
||||
{ event_id: "$3", sender: "@other:example.org", key: "👍" },
|
||||
],
|
||||
userId: "@me:example.org",
|
||||
});
|
||||
|
||||
const result = await removeMatrixReactions("!room:example.org", "$msg", {
|
||||
client,
|
||||
emoji: "👍",
|
||||
});
|
||||
|
||||
expect(result).toEqual({ removed: 1 });
|
||||
expect(redactEvent).toHaveBeenCalledTimes(1);
|
||||
expect(redactEvent).toHaveBeenCalledWith("!room:example.org", "$1");
|
||||
});
|
||||
|
||||
it("returns removed=0 when current user id is unavailable", async () => {
|
||||
const { client, redactEvent } = createReactionsClient({
|
||||
chunk: [{ event_id: "$1", sender: "@me:example.org", key: "👍" }],
|
||||
userId: null,
|
||||
});
|
||||
|
||||
const result = await removeMatrixReactions("!room:example.org", "$msg", { client });
|
||||
|
||||
expect(result).toEqual({ removed: 0 });
|
||||
expect(redactEvent).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user