mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:10:44 +00:00
test: share matrix event fixtures
This commit is contained in:
@@ -2,6 +2,25 @@ import type { MatrixEvent } from "matrix-js-sdk/lib/matrix.js";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildHttpError, matrixEventToRaw, parseMxc } from "./event-helpers.js";
|
||||
|
||||
const makeEditedMessageEvent = (): MatrixEvent =>
|
||||
({
|
||||
getId: () => "$root",
|
||||
getSender: () => "@alice:example.org",
|
||||
getType: () => "m.room.message",
|
||||
getTs: () => 1000,
|
||||
getOriginalContent: () => ({ body: "original", msgtype: "m.text" }),
|
||||
getContent: () => ({
|
||||
body: "@bot edited",
|
||||
"m.mentions": { user_ids: ["@bot:example.org"] },
|
||||
msgtype: "m.text",
|
||||
}),
|
||||
getUnsigned: () => ({
|
||||
"m.relations": {
|
||||
"m.replace": { event_id: "$edit" },
|
||||
},
|
||||
}),
|
||||
}) as unknown as MatrixEvent;
|
||||
|
||||
describe("event-helpers", () => {
|
||||
it("parses mxc URIs", () => {
|
||||
expect(parseMxc("mxc://server.example/media-id")).toEqual({
|
||||
@@ -59,25 +78,7 @@ describe("event-helpers", () => {
|
||||
});
|
||||
|
||||
it("serializes current content by default for read APIs", () => {
|
||||
const event = {
|
||||
getId: () => "$root",
|
||||
getSender: () => "@alice:example.org",
|
||||
getType: () => "m.room.message",
|
||||
getTs: () => 1000,
|
||||
getOriginalContent: () => ({ body: "original", msgtype: "m.text" }),
|
||||
getContent: () => ({
|
||||
body: "@bot edited",
|
||||
"m.mentions": { user_ids: ["@bot:example.org"] },
|
||||
msgtype: "m.text",
|
||||
}),
|
||||
getUnsigned: () => ({
|
||||
"m.relations": {
|
||||
"m.replace": { event_id: "$edit" },
|
||||
},
|
||||
}),
|
||||
} as unknown as MatrixEvent;
|
||||
|
||||
expect(matrixEventToRaw(event)).toMatchObject({
|
||||
expect(matrixEventToRaw(makeEditedMessageEvent())).toMatchObject({
|
||||
content: {
|
||||
body: "@bot edited",
|
||||
"m.mentions": { user_ids: ["@bot:example.org"] },
|
||||
@@ -87,25 +88,7 @@ describe("event-helpers", () => {
|
||||
});
|
||||
|
||||
it("can serialize original content for inbound trigger filtering", () => {
|
||||
const event = {
|
||||
getId: () => "$root",
|
||||
getSender: () => "@alice:example.org",
|
||||
getType: () => "m.room.message",
|
||||
getTs: () => 1000,
|
||||
getOriginalContent: () => ({ body: "original", msgtype: "m.text" }),
|
||||
getContent: () => ({
|
||||
body: "@bot edited",
|
||||
"m.mentions": { user_ids: ["@bot:example.org"] },
|
||||
msgtype: "m.text",
|
||||
}),
|
||||
getUnsigned: () => ({
|
||||
"m.relations": {
|
||||
"m.replace": { event_id: "$edit" },
|
||||
},
|
||||
}),
|
||||
} as unknown as MatrixEvent;
|
||||
|
||||
expect(matrixEventToRaw(event, { contentMode: "original" })).toMatchObject({
|
||||
expect(matrixEventToRaw(makeEditedMessageEvent(), { contentMode: "original" })).toMatchObject({
|
||||
content: { body: "original", msgtype: "m.text" },
|
||||
unsigned: {
|
||||
"m.relations": {
|
||||
|
||||
@@ -4,6 +4,43 @@ import { EventType } from "./types.js";
|
||||
|
||||
const { resolveMatrixRoomId, normalizeThreadId } = await import("./targets.js");
|
||||
|
||||
const BOT_USER_ID = "@bot:example.org";
|
||||
|
||||
const makeMappedDirectClient = (params: {
|
||||
userId: string;
|
||||
roomId: string;
|
||||
botId?: string;
|
||||
extra?: Record<string, unknown>;
|
||||
}) =>
|
||||
({
|
||||
getAccountData: vi.fn().mockResolvedValue({
|
||||
[params.userId]: [params.roomId],
|
||||
}),
|
||||
getUserId: vi.fn().mockResolvedValue(params.botId ?? BOT_USER_ID),
|
||||
getJoinedRooms: vi.fn(),
|
||||
getJoinedRoomMembers: vi.fn().mockResolvedValue([params.botId ?? BOT_USER_ID, params.userId]),
|
||||
setAccountData: vi.fn(),
|
||||
...params.extra,
|
||||
}) as unknown as MatrixClient;
|
||||
|
||||
const makeFallbackDirectClient = (params: {
|
||||
userId: string;
|
||||
roomIds: string[];
|
||||
botId?: string;
|
||||
members?: string[];
|
||||
extra?: Record<string, unknown>;
|
||||
}) =>
|
||||
({
|
||||
getAccountData: vi.fn().mockRejectedValue(new Error("nope")),
|
||||
getUserId: vi.fn().mockResolvedValue(params.botId ?? BOT_USER_ID),
|
||||
getJoinedRooms: vi.fn().mockResolvedValue(params.roomIds),
|
||||
getJoinedRoomMembers: vi
|
||||
.fn()
|
||||
.mockResolvedValue(params.members ?? [params.botId ?? BOT_USER_ID, params.userId]),
|
||||
setAccountData: vi.fn().mockResolvedValue(undefined),
|
||||
...params.extra,
|
||||
}) as unknown as MatrixClient;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
@@ -11,15 +48,7 @@ beforeEach(() => {
|
||||
describe("resolveMatrixRoomId", () => {
|
||||
it("uses m.direct when available", async () => {
|
||||
const userId = "@user:example.org";
|
||||
const client = {
|
||||
getAccountData: vi.fn().mockResolvedValue({
|
||||
[userId]: ["!room:example.org"],
|
||||
}),
|
||||
getUserId: vi.fn().mockResolvedValue("@bot:example.org"),
|
||||
getJoinedRooms: vi.fn(),
|
||||
getJoinedRoomMembers: vi.fn().mockResolvedValue(["@bot:example.org", userId]),
|
||||
setAccountData: vi.fn(),
|
||||
} as unknown as MatrixClient;
|
||||
const client = makeMappedDirectClient({ userId, roomId: "!room:example.org" });
|
||||
|
||||
const roomId = await resolveMatrixRoomId(client, userId);
|
||||
|
||||
@@ -31,19 +60,12 @@ describe("resolveMatrixRoomId", () => {
|
||||
it("falls back to joined rooms and persists m.direct", async () => {
|
||||
const userId = "@fallback:example.org";
|
||||
const roomId = "!room:example.org";
|
||||
const setAccountData = vi.fn().mockResolvedValue(undefined);
|
||||
const client = {
|
||||
getAccountData: vi.fn().mockRejectedValue(new Error("nope")),
|
||||
getUserId: vi.fn().mockResolvedValue("@bot:example.org"),
|
||||
getJoinedRooms: vi.fn().mockResolvedValue([roomId]),
|
||||
getJoinedRoomMembers: vi.fn().mockResolvedValue(["@bot:example.org", userId]),
|
||||
setAccountData,
|
||||
} as unknown as MatrixClient;
|
||||
const client = makeFallbackDirectClient({ userId, roomIds: [roomId] });
|
||||
|
||||
const resolved = await resolveMatrixRoomId(client, userId);
|
||||
|
||||
expect(resolved).toBe(roomId);
|
||||
expect(setAccountData).toHaveBeenCalledWith(
|
||||
expect(client.setAccountData).toHaveBeenCalledWith(
|
||||
EventType.Direct,
|
||||
expect.objectContaining({ [userId]: [roomId] }),
|
||||
);
|
||||
@@ -51,20 +73,19 @@ describe("resolveMatrixRoomId", () => {
|
||||
|
||||
it("prefers joined rooms marked direct in local member state over plain strict rooms", async () => {
|
||||
const userId = "@fallback:example.org";
|
||||
const client = {
|
||||
getAccountData: vi.fn().mockRejectedValue(new Error("nope")),
|
||||
getUserId: vi.fn().mockResolvedValue("@bot:example.org"),
|
||||
getJoinedRooms: vi.fn().mockResolvedValue(["!fallback:example.org", "!explicit:example.org"]),
|
||||
getJoinedRoomMembers: vi.fn().mockResolvedValue(["@bot:example.org", userId]),
|
||||
getRoomStateEvent: vi
|
||||
.fn()
|
||||
.mockImplementation(async (roomId: string, _eventType: string, stateKey: string) =>
|
||||
roomId === "!explicit:example.org" && stateKey === "@bot:example.org"
|
||||
? { is_direct: true }
|
||||
: {},
|
||||
),
|
||||
setAccountData: vi.fn().mockResolvedValue(undefined),
|
||||
} as unknown as MatrixClient;
|
||||
const client = makeFallbackDirectClient({
|
||||
userId,
|
||||
roomIds: ["!fallback:example.org", "!explicit:example.org"],
|
||||
extra: {
|
||||
getRoomStateEvent: vi
|
||||
.fn()
|
||||
.mockImplementation(async (roomId: string, _eventType: string, stateKey: string) =>
|
||||
roomId === "!explicit:example.org" && stateKey === BOT_USER_ID
|
||||
? { is_direct: true }
|
||||
: {},
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
const resolved = await resolveMatrixRoomId(client, userId);
|
||||
|
||||
@@ -77,20 +98,19 @@ describe("resolveMatrixRoomId", () => {
|
||||
|
||||
it("ignores remote member-state direct flags when resolving a direct room", async () => {
|
||||
const userId = "@fallback:example.org";
|
||||
const client = {
|
||||
getAccountData: vi.fn().mockRejectedValue(new Error("nope")),
|
||||
getUserId: vi.fn().mockResolvedValue("@bot:example.org"),
|
||||
getJoinedRooms: vi
|
||||
.fn()
|
||||
.mockResolvedValue(["!fallback:example.org", "!remote-marked:example.org"]),
|
||||
getJoinedRoomMembers: vi.fn().mockResolvedValue(["@bot:example.org", userId]),
|
||||
getRoomStateEvent: vi
|
||||
.fn()
|
||||
.mockImplementation(async (roomId: string, _eventType: string, stateKey: string) =>
|
||||
roomId === "!remote-marked:example.org" && stateKey === userId ? { is_direct: true } : {},
|
||||
),
|
||||
setAccountData: vi.fn().mockResolvedValue(undefined),
|
||||
} as unknown as MatrixClient;
|
||||
const client = makeFallbackDirectClient({
|
||||
userId,
|
||||
roomIds: ["!fallback:example.org", "!remote-marked:example.org"],
|
||||
extra: {
|
||||
getRoomStateEvent: vi
|
||||
.fn()
|
||||
.mockImplementation(async (roomId: string, _eventType: string, stateKey: string) =>
|
||||
roomId === "!remote-marked:example.org" && stateKey === userId
|
||||
? { is_direct: true }
|
||||
: {},
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
const resolved = await resolveMatrixRoomId(client, userId);
|
||||
|
||||
@@ -126,15 +146,11 @@ describe("resolveMatrixRoomId", () => {
|
||||
it("does not fall back to larger shared rooms for direct-user sends", async () => {
|
||||
const userId = "@group:example.org";
|
||||
const roomId = "!group:example.org";
|
||||
const client = {
|
||||
getAccountData: vi.fn().mockRejectedValue(new Error("nope")),
|
||||
getUserId: vi.fn().mockResolvedValue("@bot:example.org"),
|
||||
getJoinedRooms: vi.fn().mockResolvedValue([roomId]),
|
||||
getJoinedRoomMembers: vi
|
||||
.fn()
|
||||
.mockResolvedValue(["@bot:example.org", userId, "@extra:example.org"]),
|
||||
setAccountData: vi.fn().mockResolvedValue(undefined),
|
||||
} as unknown as MatrixClient;
|
||||
const client = makeFallbackDirectClient({
|
||||
userId,
|
||||
roomIds: [roomId],
|
||||
members: [BOT_USER_ID, userId, "@extra:example.org"],
|
||||
});
|
||||
|
||||
await expect(resolveMatrixRoomId(client, userId)).rejects.toThrow(
|
||||
`No direct room found for ${userId} (m.direct missing)`,
|
||||
@@ -145,16 +161,13 @@ describe("resolveMatrixRoomId", () => {
|
||||
it("accepts nested Matrix user target prefixes", async () => {
|
||||
const userId = "@prefixed:example.org";
|
||||
const roomId = "!prefixed-room:example.org";
|
||||
const client = {
|
||||
getAccountData: vi.fn().mockResolvedValue({
|
||||
[userId]: [roomId],
|
||||
}),
|
||||
getUserId: vi.fn().mockResolvedValue("@bot:example.org"),
|
||||
getJoinedRooms: vi.fn(),
|
||||
getJoinedRoomMembers: vi.fn().mockResolvedValue(["@bot:example.org", userId]),
|
||||
setAccountData: vi.fn(),
|
||||
resolveRoom: vi.fn(),
|
||||
} as unknown as MatrixClient;
|
||||
const client = makeMappedDirectClient({
|
||||
userId,
|
||||
roomId,
|
||||
extra: {
|
||||
resolveRoom: vi.fn(),
|
||||
},
|
||||
});
|
||||
|
||||
const resolved = await resolveMatrixRoomId(client, `matrix:user:${userId}`);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user