Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 4e5687c

Browse files
authored
Send correct receipts when viewing a room (#10864)
* Send correct receipts when viewing a room * Fix strict type issues * Handle promises * Handle more primises * Add generic array type * Replace existende check with type predicate * Fix wrong variable check * Improve comment about initial read marker * Use read_markers API for fully read receipts * Log public receipt fallback * Rename variables in new code to be aligned to the spec * Add end-2-end test for read markers and receipts
1 parent 1c0785c commit 4e5687c

File tree

4 files changed

+448
-160
lines changed

4 files changed

+448
-160
lines changed

cypress/e2e/read-receipts/read-receipts.spec.ts

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ describe("Read receipts", () => {
3232
let selectedRoomId: string;
3333
let bot: MatrixClient | undefined;
3434

35-
const botSendMessage = (): Cypress.Chainable<ISendEventResponse> => {
36-
return cy.botSendMessage(bot, otherRoomId, "Message");
35+
const botSendMessage = (no = 1): Cypress.Chainable<ISendEventResponse> => {
36+
return cy.botSendMessage(bot, otherRoomId, `Message ${no}`);
3737
};
3838

3939
const botSendThreadMessage = (threadId: string): Cypress.Chainable<ISendEventResponse> => {
@@ -268,4 +268,87 @@ describe("Read receipts", () => {
268268
});
269269
});
270270
});
271+
272+
/**
273+
* The idea of this test is to intercept the receipt / read read_markers requests and
274+
* assert that the correct ones are sent.
275+
* Prose playbook:
276+
* - Another user sends enough messages that the timeline becomes scrollable
277+
* - The current user looks at the room and jumps directly to the first unread message
278+
* - At this point, a receipt for the last message in the room and
279+
* a fully read marker for the last visible message are expected to be sent
280+
* - Then the user jumps to the end of the timeline
281+
* - A fully read marker for the last message in the room is expected to be sent
282+
*/
283+
it("Should send the correct receipts", () => {
284+
const uriEncodedOtherRoomId = encodeURIComponent(otherRoomId);
285+
286+
cy.intercept({
287+
method: "POST",
288+
url: new RegExp(
289+
`http://localhost:\\d+/_matrix/client/r0/rooms/${uriEncodedOtherRoomId}/receipt/m\\.read/.+`,
290+
),
291+
}).as("receiptRequest");
292+
293+
const numberOfMessages = 20;
294+
const sendMessagePromises = [];
295+
296+
for (let i = 1; i <= numberOfMessages; i++) {
297+
sendMessagePromises.push(botSendMessage(i));
298+
}
299+
300+
cy.all(sendMessagePromises).then((sendMessageResponses) => {
301+
const lastMessageId = sendMessageResponses.at(-1).event_id;
302+
const uriEncodedLastMessageId = encodeURIComponent(lastMessageId);
303+
304+
// wait until all messages have been received
305+
cy.findByLabelText(`${otherRoomName} ${sendMessagePromises.length} unread messages.`).should("exist");
306+
307+
// switch to the room with the messages
308+
cy.visit("/#/room/" + otherRoomId);
309+
310+
cy.wait("@receiptRequest").should((req) => {
311+
// assert the read receipt for the last message in the room
312+
expect(req.request.url).to.contain(uriEncodedLastMessageId);
313+
expect(req.request.body).to.deep.equal({
314+
thread_id: "main",
315+
});
316+
});
317+
318+
// the following code tests the fully read marker somewhere in the middle of the room
319+
320+
cy.intercept({
321+
method: "POST",
322+
url: new RegExp(`http://localhost:\\d+/_matrix/client/r0/rooms/${uriEncodedOtherRoomId}/read_markers`),
323+
}).as("readMarkersRequest");
324+
325+
cy.findByRole("button", { name: "Jump to first unread message." }).click();
326+
327+
cy.wait("@readMarkersRequest").should((req) => {
328+
// since this is not pixel perfect,
329+
// the fully read marker should be +/- 1 around the last visible message
330+
expect(Array.from(Object.keys(req.request.body))).to.deep.equal(["m.fully_read"]);
331+
expect(req.request.body["m.fully_read"]).to.be.oneOf([
332+
sendMessageResponses[11].event_id,
333+
sendMessageResponses[12].event_id,
334+
sendMessageResponses[13].event_id,
335+
]);
336+
});
337+
338+
// the following code tests the fully read marker at the bottom of the room
339+
340+
cy.intercept({
341+
method: "POST",
342+
url: new RegExp(`http://localhost:\\d+/_matrix/client/r0/rooms/${uriEncodedOtherRoomId}/read_markers`),
343+
}).as("readMarkersRequest");
344+
345+
cy.findByRole("button", { name: "Scroll to most recent messages" }).click();
346+
347+
cy.wait("@readMarkersRequest").should((req) => {
348+
expect(req.request.body).to.deep.equal({
349+
["m.fully_read"]: sendMessageResponses.at(-1).event_id,
350+
});
351+
});
352+
});
353+
});
271354
});

0 commit comments

Comments
 (0)