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

Commit

Permalink
Tests for paging up to find old messages
Browse files Browse the repository at this point in the history
  • Loading branch information
andybalaam committed Sep 20, 2023
1 parent 51ec7f0 commit 3f17a93
Showing 1 changed file with 263 additions and 14 deletions.
277 changes: 263 additions & 14 deletions cypress/e2e/read-receipts/high-level.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,18 +180,18 @@ describe("Read receipts", () => {
}

function sendMessageAsClient(cli: MatrixClient, room: string, messages: Message[]) {
findRoomByName(room).then(async ({ roomId }) => {
const room = cli.getRoom(roomId);
for (const message of messages) {
const roomIdFinder = findRoomByName(room);
for (const message of messages) {
roomIdFinder.then(async (room) => {
if (typeof message === "string") {
await cli.sendTextMessage(roomId, message);
await cli.sendTextMessage(room.roomId, message);
} else if (message instanceof MessageContentSpec) {
await cli.sendMessage(roomId, await message.getContent(room));
await cli.sendMessage(room.roomId, await message.getContent(room));
} else {
await message.performAction(cli, room);
}
}
});
});
}
}

/**
Expand Down Expand Up @@ -339,7 +339,7 @@ describe("Read receipts", () => {
* @param howMany the number of strings to generate
*/
function many(prefix: string, howMany: number): Array<string> {
return Array.from(Array(howMany).keys()).map((i) => prefix + i.toFixed());
return Array.from(Array(howMany).keys()).map((i) => prefix + i.toString().padStart(4, "0"));
}

/**
Expand Down Expand Up @@ -441,14 +441,30 @@ describe("Read receipts", () => {
* @param lessThan - the number of unread messages that is too many
*/
function assertUnreadLessThan(room: string, lessThan: number) {
cy.log("Assert room some unread", room);
cy.log("Assert unread less than", room, lessThan);
return getRoomListTile(room).within(() => {
cy.get(".mx_NotificationBadge_count").should(($count) =>
expect(parseInt($count.get(0).textContent, 10)).to.be.lessThan(lessThan),
);
});
}

/**
* Assert a given room is marked as unread, and the number of unread
* messages is greater than the supplied count.
*
* @param room - the name of the room to check
* @param greaterThan - the number of unread messages that is too few
*/
function assertUnreadGreaterThan(room: string, greaterThan: number) {
cy.log("Assert unread greater than", room, greaterThan);
return getRoomListTile(room).within(() => {
cy.get(".mx_NotificationBadge_count").should(($count) =>
expect(parseInt($count.get(0).textContent, 10)).to.be.greaterThan(greaterThan),
);
});
}

function openThreadList() {
cy.log("Open threads list");

Expand Down Expand Up @@ -825,6 +841,15 @@ describe("Read receipts", () => {
// Then the room is still read
assertRead(room2);
});
it.skip("A room with unread threads shows them unread after restart", () => {
// Given I have lots of messages in threads and they are unread
// And I have read the main timeline
// When I restart
// Then the same list of threads are unread
// (In the app I sometimes observe that only the latest thread
// is unread, until I enter and leave that thread, and then the
// others become unread.)
});
});

describe("thread roots", () => {
Expand Down Expand Up @@ -2344,12 +2369,236 @@ describe("Read receipts", () => {
it.skip("A receipt for the last unimportant event makes the room read, even if all are unimportant", () => {});
});

function assertMessageLoaded(messagePart: string) {
cy.get(".mx_EventTile_body").contains(messagePart).should("exist");
}

function assertMessageNotLoaded(messagePart: string) {
cy.get(".mx_EventTile_body").contains(messagePart).should("not.exist");
}

function pageUp() {
cy.get(".mx_RoomView_messagePanel").then((refs) =>
refs.each((_, messagePanel) => {
console.log(`AJB ${messagePanel.scrollTop}`);
messagePanel.scrollTop -= 1000;
console.log(`AJB ${messagePanel.scrollTop}`);
}),
);
}

describe("Paging up", () => {
it.skip("Paging up through old messages after a room is read leaves the room read", () => {});
it.skip("Paging up through old messages of an unread room leaves the room unread", () => {});
it.skip("Paging up to find old threads that were previously read leaves the room read", () => {});
it.skip("?? Paging up to find old threads that were never read marks the room unread", () => {});
it.skip("After marking room as read, paging up to find old threads that were never read leaves the room read", () => {});
it("Paging up through old messages after a room is read leaves the room read", () => {
// Given lots of messages are in the room, but we have read them
goTo(room1);
receiveMessages(room2, many("Msg", 110));
assertUnread(room2, 110);
goTo(room2);
assertRead(room2);
goTo(room1);

// When we restart, so only recent messages are loaded
saveAndReload();
goTo(room2);
assertMessageNotLoaded("Msg0010");

// And we page up, loading in old messages
pageUp();
pageUp();
pageUp();
assertMessageLoaded("Msg0010");

// Then the room remains read
assertStillRead(room2);
});
it("Paging up through old messages of an unread room leaves the room unread", () => {
// Given lots of messages are in the room, and they are not read
goTo(room1);
receiveMessages(room2, many("x\ny\nz\nMsg", 40)); // newline to spread out messages
assertUnread(room2, 40);

// When I jump to a message in the middle and page up
jumpTo(room2, "x\ny\nz\nMsg0020");
pageUp();

// Then the room is still unread
assertUnreadGreaterThan(room2, 1);
});
it("Paging up to find old threads that were previously read leaves the room read", () => {
// Given lots of messages in threads are all read
goTo(room1);
receiveMessages(room2, [
"Root1",
"Root2",
"Root3",
...manyThreadedOff("Root1", many("T", 20)),
...manyThreadedOff("Root2", many("T", 20)),
...manyThreadedOff("Root3", many("T", 20)),
]);
goTo(room2);
assertUnread(room2, 60);
openThread("Root1");
assertUnread(room2, 40);
assertReadThread("Root1");
openThread("Root2");
assertUnread(room2, 20);
assertReadThread("Root2");
openThread("Root3");
assertRead(room2);
assertReadThread("Root3");

// When I restart and page up to load old thread roots
goTo(room1);
saveAndReload();
goTo(room2);
pageUp();

// Then the room and threads remain read
assertRead(room2);
assertReadThread("Root1");
assertReadThread("Root2");
assertReadThread("Root3");
});
it("Paging up to find old threads that were never read keeps the room unread", () => {
// Given lots of messages in threads that are unread
goTo(room1);
receiveMessages(room2, [
"Root1",
"Root2",
"Root3",
...manyThreadedOff("Root1", many("T", 2)),
...manyThreadedOff("Root2", many("T", 2)),
...manyThreadedOff("Root3", many("T", 2)),
...many("Msg", 100),
]);
goTo(room2);
assertUnread(room2, 6);
assertUnreadThread("Root1");
assertUnreadThread("Root2");
assertUnreadThread("Root3");

// When I restart
closeThreadsPanel();
goTo(room1);
saveAndReload();

// Then the room remembers it's unread
// TODO: I (andyb) think this will fall in an encrypted room
assertUnread(room2, 6);

// And when I page up to load old thread roots
goTo(room2);
pageUp();

// Then the room remains unread
assertUnread(room2, 6);
assertUnreadThread("Root1");
assertUnreadThread("Root2");
assertUnreadThread("Root3");
});
it("Looking in thread view to find old threads that were never read makes the room unread", () => {
// Given lots of messages in threads that are unread
goTo(room1);
receiveMessages(room2, [
"Root1",
"Root2",
"Root3",
...manyThreadedOff("Root1", many("T", 2)),
...manyThreadedOff("Root2", many("T", 2)),
...manyThreadedOff("Root3", many("T", 2)),
...many("Msg", 100),
]);
goTo(room2);
assertUnread(room2, 6);
assertUnreadThread("Root1");
assertUnreadThread("Root2");
assertUnreadThread("Root3");

// When I restart
closeThreadsPanel();
goTo(room1);
saveAndReload();

// Then the room remembers it's unread
// TODO: I (andyb) think this will fall in an encrypted room
assertUnread(room2, 6);

// And when I open the threads view
goTo(room2);
openThreadList();

// Then the room remains unread
assertUnread(room2, 6);
assertUnreadThread("Root1");
assertUnreadThread("Root2");
assertUnreadThread("Root3");
});
it("After marking room as read, paging up to find old threads that were never read leaves the room read", () => {
// Given lots of messages in threads that are unread but I marked as read on a main timeline message
goTo(room1);
receiveMessages(room2, [
"Root1",
"Root2",
"Root3",
...manyThreadedOff("Root1", many("T", 2)),
...manyThreadedOff("Root2", many("T", 2)),
...manyThreadedOff("Root3", many("T", 2)),
...many("Msg", 100),
]);
markAsRead(room2);
assertRead(room2);

// When I restart
saveAndReload();

// Then the room remembers it's read
assertRead(room2);

// And when I page up to load old thread roots
goTo(room2);
pageUp();
pageUp();
pageUp();

// Then the room remains read
assertStillRead(room2);
assertReadThread("Root1");
assertReadThread("Root2");
assertReadThread("Root3");
});
// XXX: fails because we see a dot instead of an unread number - probably the server and client disagree
it.skip("After marking room as read based on a thread message, opening threads view to find old threads that were never read leaves the room read", () => {
// Given lots of messages in threads that are unread but I marked as read on a thread message
goTo(room1);
receiveMessages(room2, [
"Root1",
"Root2",
"Root3",
...manyThreadedOff("Root1", many("T1-", 2)),
...manyThreadedOff("Root2", many("T2-", 2)),
...manyThreadedOff("Root3", many("T3-", 2)),
...many("Msg", 100),
threadedOff("Msg0099", "Thread off 99"),
]);
markAsRead(room2);
assertRead(room2);

// When I restart
saveAndReload();

// Then the room remembers it's read
assertRead(room2);

// And when I page up to load old thread roots
goTo(room2);
openThreadList();

// Then the room remains read
assertStillRead(room2);
assertReadThread("Root1");
assertReadThread("Root2");
assertReadThread("Root3");
});
});

describe("Room list order", () => {
Expand Down

0 comments on commit 3f17a93

Please sign in to comment.