diff --git a/extensions/matrix/src/matrix/monitor/direct.test.ts b/extensions/matrix/src/matrix/monitor/direct.test.ts index 298b3996837..6688f76e649 100644 --- a/extensions/matrix/src/matrix/monitor/direct.test.ts +++ b/extensions/matrix/src/matrix/monitor/direct.test.ts @@ -7,6 +7,8 @@ import { createDirectRoomTracker } from "./direct.js"; type StateEvent = Record; type DmMap = Record; +const brokenDmRoomId = "!broken-dm:example.org"; +const defaultBrokenDmMembers = ["@alice:example.org", "@bot:example.org"]; function createMockClient(opts: { dmRooms?: DmMap; @@ -50,6 +52,21 @@ function createMockClient(opts: { }; } +function createBrokenDmClient(roomNameEvent?: StateEvent) { + return createMockClient({ + dmRooms: {}, + membersByRoom: { + [brokenDmRoomId]: defaultBrokenDmMembers, + }, + stateEvents: { + // is_direct not set on either member (e.g. Continuwuity bug) + [`${brokenDmRoomId}|m.room.member|@alice:example.org`]: {}, + [`${brokenDmRoomId}|m.room.member|@bot:example.org`]: {}, + ...(roomNameEvent ? { [`${brokenDmRoomId}|m.room.name|`]: roomNameEvent } : {}), + }, + }); +} + // --------------------------------------------------------------------------- // Tests -- isDirectMessage // --------------------------------------------------------------------------- @@ -131,22 +148,11 @@ describe("createDirectRoomTracker", () => { describe("conservative fallback (memberCount + room name)", () => { it("returns true for 2-member room WITHOUT a room name (broken flags)", async () => { - const client = createMockClient({ - dmRooms: {}, - membersByRoom: { - "!broken-dm:example.org": ["@alice:example.org", "@bot:example.org"], - }, - stateEvents: { - // is_direct not set on either member (e.g. Continuwuity bug) - "!broken-dm:example.org|m.room.member|@alice:example.org": {}, - "!broken-dm:example.org|m.room.member|@bot:example.org": {}, - // No m.room.name -> getRoomStateEvent will throw (event not found) - }, - }); + const client = createBrokenDmClient(); const tracker = createDirectRoomTracker(client as never); const result = await tracker.isDirectMessage({ - roomId: "!broken-dm:example.org", + roomId: brokenDmRoomId, senderId: "@alice:example.org", }); @@ -154,21 +160,11 @@ describe("createDirectRoomTracker", () => { }); it("returns true for 2-member room with empty room name", async () => { - const client = createMockClient({ - dmRooms: {}, - membersByRoom: { - "!broken-dm:example.org": ["@alice:example.org", "@bot:example.org"], - }, - stateEvents: { - "!broken-dm:example.org|m.room.member|@alice:example.org": {}, - "!broken-dm:example.org|m.room.member|@bot:example.org": {}, - "!broken-dm:example.org|m.room.name|": { name: "" }, - }, - }); + const client = createBrokenDmClient({ name: "" }); const tracker = createDirectRoomTracker(client as never); const result = await tracker.isDirectMessage({ - roomId: "!broken-dm:example.org", + roomId: brokenDmRoomId, senderId: "@alice:example.org", }); diff --git a/extensions/matrix/src/matrix/monitor/events.test.ts b/extensions/matrix/src/matrix/monitor/events.test.ts index 9179cf69ee3..3c08a0230d1 100644 --- a/extensions/matrix/src/matrix/monitor/events.test.ts +++ b/extensions/matrix/src/matrix/monitor/events.test.ts @@ -12,6 +12,8 @@ vi.mock("../send.js", () => ({ })); describe("registerMatrixMonitorEvents", () => { + const roomId = "!room:example.org"; + beforeEach(() => { sendReadReceiptMatrixMock.mockClear(); }); @@ -53,6 +55,16 @@ describe("registerMatrixMonitorEvents", () => { return { client, getUserId, onRoomMessage, roomMessageHandler, logVerboseMessage }; } + async function expectForwardedWithoutReadReceipt(event: MatrixRawEvent) { + const { onRoomMessage, roomMessageHandler } = createHarness(); + + roomMessageHandler(roomId, event); + await vi.waitFor(() => { + expect(onRoomMessage).toHaveBeenCalledWith(roomId, event); + }); + expect(sendReadReceiptMatrixMock).not.toHaveBeenCalled(); + } + it("sends read receipt immediately for non-self messages", async () => { const { client, onRoomMessage, roomMessageHandler } = createHarness(); const event = { @@ -69,30 +81,16 @@ describe("registerMatrixMonitorEvents", () => { }); it("does not send read receipts for self messages", async () => { - const { onRoomMessage, roomMessageHandler } = createHarness(); - const event = { + await expectForwardedWithoutReadReceipt({ event_id: "$e2", sender: "@bot:example.org", - } as MatrixRawEvent; - - roomMessageHandler("!room:example.org", event); - await vi.waitFor(() => { - expect(onRoomMessage).toHaveBeenCalledWith("!room:example.org", event); }); - expect(sendReadReceiptMatrixMock).not.toHaveBeenCalled(); }); it("skips receipt when message lacks sender or event id", async () => { - const { onRoomMessage, roomMessageHandler } = createHarness(); - const event = { + await expectForwardedWithoutReadReceipt({ sender: "@alice:example.org", - } as MatrixRawEvent; - - roomMessageHandler("!room:example.org", event); - await vi.waitFor(() => { - expect(onRoomMessage).toHaveBeenCalledWith("!room:example.org", event); }); - expect(sendReadReceiptMatrixMock).not.toHaveBeenCalled(); }); it("caches self user id across messages", async () => {