2023-12-05 10:37:23 +00:00
/*
2024-09-09 14:57:16 +01:00
Copyright 2024 New Vector Ltd.
2023-12-05 10:37:23 +00:00
Copyright 2023 The Matrix.org Foundation C.I.C.
2025-01-06 11:18:54 +00:00
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
2024-09-09 14:57:16 +01:00
Please see LICENSE files in the repository root for full details.
2023-12-05 10:37:23 +00:00
*/
/* See readme.md for tips on writing these tests. */
2026-07-30 10:07:03 +01:00
import { many , test } from "." ;
2025-01-14 18:00:30 +00:00
import { isDendrite } from "../../plugins/homeserver/dendrite" ;
2023-12-05 10:37:23 +00:00
2024-12-05 14:30:28 +00:00
test . describe ( "Read receipts" , { tag : "@mergequeue" }, () => {
2025-01-14 18:00:30 +00:00
test . skip ( isDendrite , "due to Dendrite bug https://github.com/element-hq/dendrite/issues/2970" );
2025-01-06 13:31:33 +00:00
test . slow ();
2023-12-05 10:37:23 +00:00
test . describe ( "Ignored events" , () => {
test ( "If all events after receipt are unimportant, the room is read" , async ({
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
2026-07-30 10:07:03 +01:00
msg ,
2023-12-05 10:37:23 +00:00
}) => {
await util . goTo ( room1 );
await util . assertRead ( room2 );
await util . receiveMessages ( room2 , [ "Msg1" , "Msg2" ]);
await util . assertUnread ( room2 , 2 );
await util . markAsRead ( room2 );
await util . assertRead ( room2 );
2026-07-30 10:07:03 +01:00
await util . receiveMessages ( room2 , [ msg . customEvent ( "org.custom.event" , { body : "foobar" })]);
2023-12-05 10:37:23 +00:00
await util . assertRead ( room2 );
});
test ( "Sending an important event after unimportant ones makes the room unread" , async ({
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
2026-07-30 10:07:03 +01:00
msg ,
2023-12-05 10:37:23 +00:00
}) => {
// Given We have read the important messages
await util . goTo ( room1 );
await util . assertRead ( room2 );
await util . receiveMessages ( room2 , [ "Msg1" , "Msg2" ]);
await util . assertUnread ( room2 , 2 );
await util . goTo ( room2 );
await util . assertRead ( room2 );
await util . goTo ( room1 );
// When we receive unimportant messages
2026-07-30 10:07:03 +01:00
await util . receiveMessages ( room2 , [ msg . customEvent ( "org.custom.event" , { body : "foobar" })]);
2023-12-05 10:37:23 +00:00
// Then the room is still read
await util . assertStillRead ( room2 );
// And when we receive more important ones
await util . receiveMessages ( room2 , [ "Hello" ]);
// The room is unread again
await util . assertUnread ( room2 , 1 );
});
test ( "A receipt for the last unimportant event makes the room read, even if all are unimportant" , async ({
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
2026-07-30 10:07:03 +01:00
msg ,
2023-12-05 10:37:23 +00:00
}) => {
// Display room 1
await util . goTo ( room1 );
// The room 2 is read
await util . assertRead ( room2 );
// We received 3 unimportant messages to room2
await util . receiveMessages ( room2 , [
2026-07-30 10:07:03 +01:00
msg . customEvent ( "org.custom.event" , { body : "foobar1" }),
msg . customEvent ( "org.custom.event" , { body : "foobar2" }),
msg . customEvent ( "org.custom.event" , { body : "foobar3" }),
2023-12-05 10:37:23 +00:00
]);
// The room 2 is still read
await util . assertStillRead ( room2 );
});
});
test . describe ( "Paging up" , () => {
2023-12-11 11:11:26 +01:00
test ( "Paging up through old messages after a room is read leaves the room read" , async ({
2023-12-05 10:37:23 +00:00
page ,
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
}) => {
// Given lots of messages are in the room, but we have read them
await util . goTo ( room1 );
await util . receiveMessages ( room2 , many ( "Msg" , 110 ));
await util . assertUnread ( room2 , 110 );
await util . goTo ( room2 );
await util . assertRead ( room2 );
await util . goTo ( room1 );
// When we restart, so only recent messages are loaded
await util . saveAndReload ();
await util . goTo ( room2 );
await util . assertMessageNotLoaded ( "Msg0010" );
// And we page up, loading in old messages
await util . pageUp ();
await page . waitForTimeout ( 200 );
await util . pageUp ();
await page . waitForTimeout ( 200 );
await util . pageUp ();
await util . assertMessageLoaded ( "Msg0010" );
// Then the room remains read
await util . assertStillRead ( room2 );
});
test ( "Paging up through old messages of an unread room leaves the room unread" , async ({
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
msg ,
}) => {
// Given lots of messages are in the room, and they are not read
await util . goTo ( room1 );
await util . receiveMessages ( room2 , many ( "x\ny\nz\nMsg" , 40 )); // newline to spread out messages
await util . assertUnread ( room2 , 40 );
// When I jump to a message in the middle and page up
2025-01-02 15:24:09 +00:00
await msg . jumpTo ( room2 , "x\ny\nz\nMsg0020" );
2023-12-05 10:37:23 +00:00
await util . pageUp ();
// Then the room is still unread
await util . assertUnreadGreaterThan ( room2 , 1 );
});
test ( "Paging up to find old threads that were previously read leaves the room read" , async ({
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
msg ,
}) => {
test . slow ();
// Given lots of messages in threads are all read
await util . goTo ( room1 );
await util . receiveMessages ( room2 , [
"Root1" ,
"Root2" ,
"Root3" ,
... msg . manyThreadedOff ( "Root1" , many ( "T" , 20 )),
... msg . manyThreadedOff ( "Root2" , many ( "T" , 20 )),
... msg . manyThreadedOff ( "Root3" , many ( "T" , 20 )),
]);
await util . goTo ( room2 );
2024-04-29 16:30:19 +01:00
await util . assertRead ( room2 );
await util . assertUnreadThread ( "Root1" );
await util . assertUnreadThread ( "Root2" );
await util . assertUnreadThread ( "Root3" );
2023-12-05 10:37:23 +00:00
await util . openThread ( "Root1" );
await util . assertReadThread ( "Root1" );
await util . openThread ( "Root2" );
await util . assertReadThread ( "Root2" );
await util . openThread ( "Root3" );
await util . assertReadThread ( "Root3" );
// When I restart and page up to load old thread roots
await util . goTo ( room1 );
await util . saveAndReload ();
await util . goTo ( room2 );
await util . pageUp ();
// Then the room and threads remain read
await util . assertRead ( room2 );
await util . assertReadThread ( "Root1" );
await util . assertReadThread ( "Root2" );
await util . assertReadThread ( "Root3" );
});
2024-04-29 16:30:19 +01:00
2023-12-05 10:37:23 +00:00
test ( "Paging up to find old threads that were never read keeps the room unread" , async ({
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
msg ,
}) => {
test . slow ();
// Given lots of messages in threads that are unread
await util . goTo ( room1 );
await util . receiveMessages ( room2 , [
"Root1" ,
"Root2" ,
"Root3" ,
... msg . manyThreadedOff ( "Root1" , many ( "T" , 2 )),
... msg . manyThreadedOff ( "Root2" , many ( "T" , 2 )),
... msg . manyThreadedOff ( "Root3" , many ( "T" , 2 )),
... many ( "Msg" , 100 ),
]);
await util . goTo ( room2 );
2024-04-29 16:30:19 +01:00
await util . assertRead ( room2 );
2023-12-05 10:37:23 +00:00
await util . assertUnreadThread ( "Root1" );
await util . assertUnreadThread ( "Root2" );
await util . assertUnreadThread ( "Root3" );
// When I restart
await util . closeThreadsPanel ();
await util . goTo ( room1 );
await util . saveAndReload ();
2024-04-29 16:30:19 +01:00
// Then the room remembers it's read
2023-12-05 10:37:23 +00:00
// TODO: I (andyb) think this will fall in an encrypted room
2024-04-29 16:30:19 +01:00
await util . assertRead ( room2 );
2023-12-05 10:37:23 +00:00
// And when I page up to load old thread roots
await util . goTo ( room2 );
await util . pageUp ();
2024-04-29 16:30:19 +01:00
// Then the room remains read
await util . assertRead ( room2 );
2023-12-05 10:37:23 +00:00
await util . assertUnreadThread ( "Root1" );
await util . assertUnreadThread ( "Root2" );
await util . assertUnreadThread ( "Root3" );
});
2024-04-29 16:30:19 +01:00
2023-12-11 11:11:26 +01:00
test ( "Looking in thread view to find old threads that were never read makes the room unread" , async ({
2023-12-05 10:37:23 +00:00
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
msg ,
}) => {
// Given lots of messages in threads that are unread
await util . goTo ( room1 );
await util . receiveMessages ( room2 , [
"Root1" ,
"Root2" ,
"Root3" ,
... msg . manyThreadedOff ( "Root1" , many ( "T" , 2 )),
... msg . manyThreadedOff ( "Root2" , many ( "T" , 2 )),
... msg . manyThreadedOff ( "Root3" , many ( "T" , 2 )),
... many ( "Msg" , 100 ),
]);
await util . goTo ( room2 );
2024-04-29 16:30:19 +01:00
await util . assertRead ( room2 );
2023-12-05 10:37:23 +00:00
await util . assertUnreadThread ( "Root1" );
await util . assertUnreadThread ( "Root2" );
await util . assertUnreadThread ( "Root3" );
// When I restart
await util . closeThreadsPanel ();
await util . goTo ( room1 );
await util . saveAndReload ();
2024-04-29 16:30:19 +01:00
// Then the room remembers it's read
2023-12-05 10:37:23 +00:00
// TODO: I (andyb) think this will fall in an encrypted room
2024-04-29 16:30:19 +01:00
await util . assertRead ( room2 );
2023-12-05 10:37:23 +00:00
// And when I open the threads view
await util . goTo ( room2 );
await util . openThreadList ();
2024-04-29 16:30:19 +01:00
// Then the room remains read
await util . assertRead ( room2 );
2023-12-05 10:37:23 +00:00
await util . assertUnreadThread ( "Root1" );
await util . assertUnreadThread ( "Root2" );
await util . assertUnreadThread ( "Root3" );
});
2024-04-29 16:30:19 +01:00
2023-12-05 10:37:23 +00:00
test ( "After marking room as read, paging up to find old threads that were never read leaves the room read" , async ({
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
msg ,
}) => {
test . slow ();
// Given lots of messages in threads that are unread but I marked as read on a main timeline message
await util . goTo ( room1 );
await util . receiveMessages ( room2 , [
"Root1" ,
"Root2" ,
"Root3" ,
... msg . manyThreadedOff ( "Root1" , many ( "T" , 2 )),
... msg . manyThreadedOff ( "Root2" , many ( "T" , 2 )),
... msg . manyThreadedOff ( "Root3" , many ( "T" , 2 )),
... many ( "Msg" , 100 ),
]);
await util . markAsRead ( room2 );
await util . assertRead ( room2 );
// When I restart
await util . saveAndReload ();
// Then the room remembers it's read
await util . assertRead ( room2 );
// And when I page up to load old thread roots
await util . goTo ( room2 );
await util . pageUp ();
await util . pageUp ();
await util . pageUp ();
// Then the room remains read
await util . assertStillRead ( room2 );
await util . assertReadThread ( "Root1" );
await util . assertReadThread ( "Root2" );
await util . assertReadThread ( "Root3" );
});
2023-12-11 11:11:26 +01:00
test ( "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" , async ({
2023-12-05 10:37:23 +00:00
roomAlpha : room1 ,
roomBeta : room2 ,
util ,
msg ,
}) => {
// Given lots of messages in threads that are unread but I marked as read on a thread message
await util . goTo ( room1 );
await util . receiveMessages ( room2 , [
"Root1" ,
"Root2" ,
"Root3" ,
... msg . manyThreadedOff ( "Root1" , many ( "T1-" , 2 )),
... msg . manyThreadedOff ( "Root2" , many ( "T2-" , 2 )),
... msg . manyThreadedOff ( "Root3" , many ( "T3-" , 2 )),
... many ( "Msg" , 100 ),
msg . threadedOff ( "Msg0099" , "Thread off 99" ),
]);
await util . markAsRead ( room2 );
await util . assertRead ( room2 );
// When I restart
await util . saveAndReload ();
// Then the room remembers it's read
await util . assertRead ( room2 );
// And when I page up to load old thread roots
await util . goTo ( room2 );
await util . openThreadList ();
// Then the room remains read
await util . assertStillRead ( room2 );
await util . assertReadThread ( "Root1" );
await util . assertReadThread ( "Root2" );
await util . assertReadThread ( "Root3" );
});
});
});