Tests for paging up to find old messages (#11650)
* Use longer numbers for many() messages to avoid substring clashes * Tests for paging up
This commit is contained in:
parent
6af4335db1
commit
506f286a3e
3 changed files with 245 additions and 17 deletions
|
@ -18,16 +18,29 @@ limitations under the License.
|
||||||
|
|
||||||
/// <reference types="cypress" />
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
import type { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
import type { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
import { HomeserverInstance } from "../../plugins/utils/homeserver";
|
import { HomeserverInstance } from "../../plugins/utils/homeserver";
|
||||||
import {
|
import {
|
||||||
|
assertMessageLoaded,
|
||||||
|
assertMessageNotLoaded,
|
||||||
assertRead,
|
assertRead,
|
||||||
|
assertReadThread,
|
||||||
assertStillRead,
|
assertStillRead,
|
||||||
assertUnread,
|
assertUnread,
|
||||||
|
assertUnreadGreaterThan,
|
||||||
|
assertUnreadThread,
|
||||||
|
closeThreadsPanel,
|
||||||
customEvent,
|
customEvent,
|
||||||
goTo,
|
goTo,
|
||||||
|
many,
|
||||||
markAsRead,
|
markAsRead,
|
||||||
Message,
|
Message,
|
||||||
|
MessageContentSpec,
|
||||||
|
MessageFinder,
|
||||||
|
openThread,
|
||||||
|
openThreadList,
|
||||||
|
pageUp,
|
||||||
|
saveAndReload,
|
||||||
sendMessageAsClient,
|
sendMessageAsClient,
|
||||||
} from "./read-receipts-utils";
|
} from "./read-receipts-utils";
|
||||||
|
|
||||||
|
@ -42,12 +55,19 @@ describe("Read receipts", () => {
|
||||||
let alphaRoomId: string;
|
let alphaRoomId: string;
|
||||||
let bot: MatrixClient | undefined;
|
let bot: MatrixClient | undefined;
|
||||||
|
|
||||||
/**
|
let messageFinder: MessageFinder;
|
||||||
* Map of message content -> event. Allows us to find e.g. edited or
|
|
||||||
* redacted messages even if their content has changed or disappeared from
|
function threadedOff(rootMessage: string, newMessage: string): MessageContentSpec {
|
||||||
* screen.
|
return messageFinder.threadedOff(rootMessage, newMessage);
|
||||||
*/
|
}
|
||||||
const messages = new Map<String, MatrixEvent>();
|
|
||||||
|
function manyThreadedOff(rootMessage: string, newMessages: Array<string>): Array<MessageContentSpec> {
|
||||||
|
return messageFinder.manyThreadedOff(rootMessage, newMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
function jumpTo(room: string, message: string, includeThreads = false) {
|
||||||
|
return messageFinder.jumpTo(room, message, includeThreads);
|
||||||
|
}
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
// Note: unusually for the Cypress tests in this repo, we share a single
|
// Note: unusually for the Cypress tests in this repo, we share a single
|
||||||
|
@ -68,7 +88,7 @@ describe("Read receipts", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
messages.clear();
|
messageFinder = new MessageFinder();
|
||||||
|
|
||||||
// Create 2 rooms: Alpha & Beta. We join the bot to both of them
|
// Create 2 rooms: Alpha & Beta. We join the bot to both of them
|
||||||
cy.initTestUser(homeserver, userName)
|
cy.initTestUser(homeserver, userName)
|
||||||
|
@ -183,11 +203,219 @@ describe("Read receipts", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Paging up", () => {
|
describe("Paging up", () => {
|
||||||
it.skip("Paging up through old messages after a room is read leaves the room read", () => {});
|
it("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", () => {});
|
// Given lots of messages are in the room, but we have read them
|
||||||
it.skip("Paging up to find old threads that were previously read leaves the room read", () => {});
|
goTo(room1);
|
||||||
it.skip("?? Paging up to find old threads that were never read marks the room unread", () => {});
|
receiveMessages(room2, many("Msg", 110));
|
||||||
it.skip("After marking room as read, paging up to find old threads that were never read leaves the room read", () => {});
|
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();
|
||||||
|
cy.wait(200);
|
||||||
|
pageUp();
|
||||||
|
cy.wait(200);
|
||||||
|
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", () => {
|
describe("Room list order", () => {
|
||||||
|
|
|
@ -176,7 +176,7 @@ describe("Read receipts", () => {
|
||||||
assertUnread(room2, 30);
|
assertUnread(room2, 30);
|
||||||
|
|
||||||
// When I jump to one of the older messages
|
// When I jump to one of the older messages
|
||||||
jumpTo(room2, "Msg1");
|
jumpTo(room2, "Msg0001");
|
||||||
|
|
||||||
// Then the room is still unread, but some messages were read
|
// Then the room is still unread, but some messages were read
|
||||||
assertUnreadLessThan(room2, 30);
|
assertUnreadLessThan(room2, 30);
|
||||||
|
@ -321,7 +321,7 @@ describe("Read receipts", () => {
|
||||||
assertUnread(room2, 21);
|
assertUnread(room2, 21);
|
||||||
|
|
||||||
// When I read an older message in the thread
|
// When I read an older message in the thread
|
||||||
jumpTo(room2, "InThread1", true);
|
jumpTo(room2, "InThread0001", true);
|
||||||
assertUnreadLessThan(room2, 21);
|
assertUnreadLessThan(room2, 21);
|
||||||
// TODO: for some reason, we can't find the first message
|
// TODO: for some reason, we can't find the first message
|
||||||
// "InThread0", so I am using the second here. Also, they appear
|
// "InThread0", so I am using the second here. Also, they appear
|
||||||
|
@ -488,7 +488,7 @@ describe("Read receipts", () => {
|
||||||
assertUnread(room2, 62); // Sanity
|
assertUnread(room2, 62); // Sanity
|
||||||
|
|
||||||
// When I jump to an old message and read the thread
|
// When I jump to an old message and read the thread
|
||||||
jumpTo(room2, "beforeThread0");
|
jumpTo(room2, "beforeThread0000");
|
||||||
openThread("ThreadRoot");
|
openThread("ThreadRoot");
|
||||||
|
|
||||||
// Then the thread root is marked as read in the main timeline,
|
// Then the thread root is marked as read in the main timeline,
|
||||||
|
|
|
@ -372,7 +372,7 @@ export function pageUp() {
|
||||||
* @param howMany the number of strings to generate
|
* @param howMany the number of strings to generate
|
||||||
*/
|
*/
|
||||||
export function many(prefix: string, howMany: number): Array<string> {
|
export 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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue