Skip to content

Commit

Permalink
Send correct receipts when viewing a room (#10864)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
weeman1337 committed May 15, 2023
1 parent 1c0785c commit 4e5687c
Show file tree
Hide file tree
Showing 4 changed files with 448 additions and 160 deletions.
87 changes: 85 additions & 2 deletions cypress/e2e/read-receipts/read-receipts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ describe("Read receipts", () => {
let selectedRoomId: string;
let bot: MatrixClient | undefined;

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

const botSendThreadMessage = (threadId: string): Cypress.Chainable<ISendEventResponse> => {
Expand Down Expand Up @@ -268,4 +268,87 @@ describe("Read receipts", () => {
});
});
});

/**
* The idea of this test is to intercept the receipt / read read_markers requests and
* assert that the correct ones are sent.
* Prose playbook:
* - Another user sends enough messages that the timeline becomes scrollable
* - The current user looks at the room and jumps directly to the first unread message
* - At this point, a receipt for the last message in the room and
* a fully read marker for the last visible message are expected to be sent
* - Then the user jumps to the end of the timeline
* - A fully read marker for the last message in the room is expected to be sent
*/
it("Should send the correct receipts", () => {
const uriEncodedOtherRoomId = encodeURIComponent(otherRoomId);

cy.intercept({
method: "POST",
url: new RegExp(
`http://localhost:\\d+/_matrix/client/r0/rooms/${uriEncodedOtherRoomId}/receipt/m\\.read/.+`,
),
}).as("receiptRequest");

const numberOfMessages = 20;
const sendMessagePromises = [];

for (let i = 1; i <= numberOfMessages; i++) {
sendMessagePromises.push(botSendMessage(i));
}

cy.all(sendMessagePromises).then((sendMessageResponses) => {
const lastMessageId = sendMessageResponses.at(-1).event_id;
const uriEncodedLastMessageId = encodeURIComponent(lastMessageId);

// wait until all messages have been received
cy.findByLabelText(`${otherRoomName} ${sendMessagePromises.length} unread messages.`).should("exist");

// switch to the room with the messages
cy.visit("/#/room/" + otherRoomId);

cy.wait("@receiptRequest").should((req) => {
// assert the read receipt for the last message in the room
expect(req.request.url).to.contain(uriEncodedLastMessageId);
expect(req.request.body).to.deep.equal({
thread_id: "main",
});
});

// the following code tests the fully read marker somewhere in the middle of the room

cy.intercept({
method: "POST",
url: new RegExp(`http://localhost:\\d+/_matrix/client/r0/rooms/${uriEncodedOtherRoomId}/read_markers`),
}).as("readMarkersRequest");

cy.findByRole("button", { name: "Jump to first unread message." }).click();

cy.wait("@readMarkersRequest").should((req) => {
// since this is not pixel perfect,
// the fully read marker should be +/- 1 around the last visible message
expect(Array.from(Object.keys(req.request.body))).to.deep.equal(["m.fully_read"]);
expect(req.request.body["m.fully_read"]).to.be.oneOf([
sendMessageResponses[11].event_id,
sendMessageResponses[12].event_id,
sendMessageResponses[13].event_id,
]);
});

// the following code tests the fully read marker at the bottom of the room

cy.intercept({
method: "POST",
url: new RegExp(`http://localhost:\\d+/_matrix/client/r0/rooms/${uriEncodedOtherRoomId}/read_markers`),
}).as("readMarkersRequest");

cy.findByRole("button", { name: "Scroll to most recent messages" }).click();

cy.wait("@readMarkersRequest").should((req) => {
expect(req.request.body).to.deep.equal({
["m.fully_read"]: sendMessageResponses.at(-1).event_id,
});
});
});
});
});
Loading

0 comments on commit 4e5687c

Please sign in to comment.