Skip to content

Commit 662fe0b

Browse files
committed
tests for thread list pagination
1 parent b3baf5a commit 662fe0b

File tree

1 file changed

+275
-1
lines changed

1 file changed

+275
-1
lines changed

spec/integ/matrix-client-event-timeline.spec.ts

Lines changed: 275 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,19 @@ limitations under the License.
1515
*/
1616

1717
import * as utils from "../test-utils/test-utils";
18-
import { ClientEvent, EventTimeline, Filter, IEvent, MatrixClient, MatrixEvent, Room } from "../../src/matrix";
18+
import {
19+
ClientEvent,
20+
Direction,
21+
EventTimeline,
22+
EventTimelineSet,
23+
Filter,
24+
IEvent,
25+
MatrixClient,
26+
MatrixEvent,
27+
Room,
28+
} from "../../src/matrix";
1929
import { logger } from "../../src/logger";
30+
import { encodeUri } from "../../src/utils";
2031
import { TestClient } from "../TestClient";
2132
import { FeatureSupport, Thread, THREAD_RELATION_TYPE } from "../../src/models/thread";
2233

@@ -133,6 +144,44 @@ const THREAD_REPLY = utils.mkEvent({
133144

134145
THREAD_ROOT.unsigned["m.relations"]["io.element.thread"].latest_event = THREAD_REPLY;
135146

147+
const STABLE_THREAD_ROOT = utils.mkEvent({
148+
room: roomId,
149+
user: userId,
150+
type: "m.room.message",
151+
content: {
152+
"body": "thread root",
153+
"msgtype": "m.text",
154+
},
155+
unsigned: {
156+
"m.relations": {
157+
"m.thread": {
158+
//"latest_event": undefined,
159+
"count": 1,
160+
"current_user_participated": true,
161+
},
162+
},
163+
},
164+
event: false,
165+
});
166+
167+
const STABLE_THREAD_REPLY = utils.mkEvent({
168+
room: roomId,
169+
user: userId,
170+
type: "m.room.message",
171+
content: {
172+
"body": "thread reply",
173+
"msgtype": "m.text",
174+
"m.relates_to": {
175+
// We can't use the const here because we change server support mode for test
176+
rel_type: "m.thread",
177+
event_id: THREAD_ROOT.event_id,
178+
},
179+
},
180+
event: false,
181+
});
182+
183+
STABLE_THREAD_ROOT.unsigned["m.relations"]["m.thread"].latest_event = STABLE_THREAD_REPLY;
184+
136185
const SYNC_THREAD_ROOT = withoutRoomId(THREAD_ROOT);
137186
const SYNC_THREAD_REPLY = withoutRoomId(THREAD_REPLY);
138187
SYNC_THREAD_ROOT.unsigned = {
@@ -925,6 +974,231 @@ describe("MatrixClient event timelines", function() {
925974
});
926975
});
927976

977+
describe("paginateEventTimeline for thread list timeline", function() {
978+
async function flushHttp<T>(promise: Promise<T>): Promise<T> {
979+
return Promise.all([promise, httpBackend.flushAllExpected()]).then(([result]) => result);
980+
}
981+
982+
describe("with server compatibility", function() {
983+
async function testPagination(timelineSet: EventTimelineSet, direction: Direction) {
984+
const RANDOM_TOKEN = "7280349c7bee430f91defe2a38a0a08c";
985+
function respondToThreads() {
986+
httpBackend.when("GET", encodeUri("/_matrix/client/r0/rooms/$roomId/threads", {
987+
$roomId: roomId,
988+
})).respond(200, {
989+
chunk: [STABLE_THREAD_ROOT],
990+
state: [],
991+
next_batch: RANDOM_TOKEN,
992+
});
993+
}
994+
function respondToContext() {
995+
httpBackend.when("GET", encodeUri("/_matrix/client/r0/rooms/$roomId/context/$eventId", {
996+
$roomId: roomId,
997+
$eventId: STABLE_THREAD_ROOT.event_id!,
998+
})).respond(200, {
999+
end: "",
1000+
start: "",
1001+
state: [],
1002+
events_before: [],
1003+
events_after: [],
1004+
event: STABLE_THREAD_ROOT,
1005+
});
1006+
}
1007+
1008+
respondToContext();
1009+
await flushHttp(client.getEventTimeline(timelineSet, STABLE_THREAD_ROOT.event_id!));
1010+
respondToThreads();
1011+
const timeline = await flushHttp(client.getLatestTimeline(timelineSet));
1012+
expect(timeline).not.toBeNull();
1013+
1014+
respondToThreads();
1015+
const success = await flushHttp(client.paginateEventTimeline(timeline!, {
1016+
backwards: direction === Direction.Backward,
1017+
}));
1018+
expect(success).toBeTruthy();
1019+
expect(timeline!.getEvents().length).toEqual(1);
1020+
expect(timeline!.getEvents()[0].event).toEqual(STABLE_THREAD_ROOT);
1021+
expect(timeline!.getPaginationToken(direction)).toEqual(RANDOM_TOKEN);
1022+
}
1023+
1024+
it("should allow you to paginate all threads backwards", async function() {
1025+
// @ts-ignore
1026+
client.clientOpts.experimentalThreadSupport = true;
1027+
Thread.setServerSideSupport(FeatureSupport.Experimental);
1028+
Thread.setServerSideListSupport(FeatureSupport.Stable);
1029+
1030+
const room = client.getRoom(roomId);
1031+
const timelineSets = await (room?.createThreadsTimelineSets());
1032+
expect(timelineSets).not.toBeNull();
1033+
const [allThreads, myThreads] = timelineSets!;
1034+
await testPagination(allThreads, Direction.Backward);
1035+
await testPagination(myThreads, Direction.Backward);
1036+
});
1037+
1038+
it("should allow you to paginate all threads forwards", async function() {
1039+
// @ts-ignore
1040+
client.clientOpts.experimentalThreadSupport = true;
1041+
Thread.setServerSideSupport(FeatureSupport.Experimental);
1042+
Thread.setServerSideListSupport(FeatureSupport.Stable);
1043+
1044+
const room = client.getRoom(roomId);
1045+
const timelineSets = await (room?.createThreadsTimelineSets());
1046+
expect(timelineSets).not.toBeNull();
1047+
const [allThreads, myThreads] = timelineSets!;
1048+
1049+
await testPagination(allThreads, Direction.Forward);
1050+
await testPagination(myThreads, Direction.Forward);
1051+
});
1052+
1053+
it("should allow fetching all threads", async function() {
1054+
// @ts-ignore
1055+
client.clientOpts.experimentalThreadSupport = true;
1056+
Thread.setServerSideSupport(FeatureSupport.Experimental);
1057+
Thread.setServerSideListSupport(FeatureSupport.Stable);
1058+
1059+
const RANDOM_TOKEN = "7280349c7bee430f91defe2a38a0a08c";
1060+
function respondToThreads() {
1061+
httpBackend.when("GET", encodeUri("/_matrix/client/r0/rooms/$roomId/threads", {
1062+
$roomId: roomId,
1063+
})).respond(200, {
1064+
chunk: [STABLE_THREAD_ROOT],
1065+
state: [],
1066+
next_batch: RANDOM_TOKEN,
1067+
});
1068+
}
1069+
const room = client.getRoom(roomId);
1070+
const timelineSets = await room?.createThreadsTimelineSets();
1071+
expect(timelineSets).not.toBeNull();
1072+
respondToThreads();
1073+
respondToThreads();
1074+
httpBackend.when("GET", "/sync").respond(200, INITIAL_SYNC_DATA);
1075+
await flushHttp(room.fetchRoomThreads());
1076+
});
1077+
});
1078+
1079+
describe("without server compatibility", function() {
1080+
async function testPagination(timelineSet: EventTimelineSet, direction: Direction) {
1081+
const RANDOM_TOKEN = "7280349c7bee430f91defe2a38a0a08c";
1082+
function respondToMessagesRequest() {
1083+
httpBackend.when("GET", encodeUri("/_matrix/client/r0/rooms/$roomId/messages", {
1084+
$roomId: roomId,
1085+
})).respond(200, {
1086+
chunk: [THREAD_ROOT],
1087+
state: [],
1088+
start: `${Direction.Forward}${RANDOM_TOKEN}2`,
1089+
end: `${Direction.Backward}${RANDOM_TOKEN}2`,
1090+
});
1091+
}
1092+
function respondToContext() {
1093+
httpBackend.when("GET", encodeUri("/_matrix/client/r0/rooms/$roomId/context/$eventId", {
1094+
$roomId: roomId,
1095+
$eventId: THREAD_ROOT.event_id!,
1096+
})).respond(200, {
1097+
end: `${Direction.Forward}${RANDOM_TOKEN}1`,
1098+
start: `${Direction.Backward}${RANDOM_TOKEN}1`,
1099+
state: [],
1100+
events_before: [],
1101+
events_after: [],
1102+
event: THREAD_ROOT,
1103+
});
1104+
}
1105+
function respondToSync() {
1106+
httpBackend.when("GET", "/sync").respond(200, INITIAL_SYNC_DATA);
1107+
}
1108+
1109+
respondToContext();
1110+
respondToSync();
1111+
await flushHttp(client.getEventTimeline(timelineSet, THREAD_ROOT.event_id!));
1112+
1113+
respondToMessagesRequest();
1114+
const timeline = await flushHttp(client.getLatestTimeline(timelineSet));
1115+
expect(timeline).not.toBeNull();
1116+
1117+
respondToMessagesRequest();
1118+
const success = await flushHttp(client.paginateEventTimeline(timeline!, {
1119+
backwards: direction === Direction.Backward,
1120+
}));
1121+
1122+
expect(success).toBeTruthy();
1123+
expect(timeline!.getEvents().length).toEqual(1);
1124+
expect(timeline!.getEvents()[0].event).toEqual(THREAD_ROOT);
1125+
expect(timeline!.getPaginationToken(direction)).toEqual(`${direction}${RANDOM_TOKEN}2`);
1126+
}
1127+
1128+
it("should allow you to paginate all threads", async function() {
1129+
// @ts-ignore
1130+
client.clientOpts.experimentalThreadSupport = true;
1131+
Thread.setServerSideSupport(FeatureSupport.Experimental);
1132+
Thread.setServerSideListSupport(FeatureSupport.None);
1133+
1134+
function respondToFilter() {
1135+
httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
1136+
}
1137+
function respondToSync() {
1138+
httpBackend.when("GET", "/sync").respond(200, INITIAL_SYNC_DATA);
1139+
}
1140+
1141+
const room = client.getRoom(roomId);
1142+
1143+
respondToFilter();
1144+
respondToSync();
1145+
respondToFilter();
1146+
respondToSync();
1147+
1148+
const timelineSetsPromise = room?.createThreadsTimelineSets();
1149+
expect(timelineSetsPromise).not.toBeNull();
1150+
const timelineSets = await flushHttp(timelineSetsPromise!);
1151+
expect(timelineSets).not.toBeNull();
1152+
const [allThreads, myThreads] = timelineSets!;
1153+
1154+
await testPagination(allThreads, Direction.Backward);
1155+
await testPagination(myThreads, Direction.Backward);
1156+
});
1157+
1158+
it("should allow fetching all threads", async function() {
1159+
// @ts-ignore
1160+
client.clientOpts.experimentalThreadSupport = true;
1161+
Thread.setServerSideSupport(FeatureSupport.Experimental);
1162+
Thread.setServerSideListSupport(FeatureSupport.None);
1163+
1164+
const room = client.getRoom(roomId);
1165+
1166+
const RANDOM_TOKEN = "7280349c7bee430f91defe2a38a0a08c";
1167+
function respondToMessagesRequest() {
1168+
httpBackend.when("GET", encodeUri("/_matrix/client/r0/rooms/$roomId/messages", {
1169+
$roomId: roomId,
1170+
})).respond(200, {
1171+
chunk: [STABLE_THREAD_ROOT],
1172+
state: [],
1173+
start: `${Direction.Forward}${RANDOM_TOKEN}2`,
1174+
end: `${Direction.Backward}${RANDOM_TOKEN}2`,
1175+
});
1176+
}
1177+
function respondToFilter() {
1178+
httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
1179+
}
1180+
function respondToSync() {
1181+
httpBackend.when("GET", "/sync").respond(200, INITIAL_SYNC_DATA);
1182+
}
1183+
1184+
respondToFilter();
1185+
respondToSync();
1186+
respondToFilter();
1187+
respondToSync();
1188+
1189+
const timelineSetsPromise = room?.createThreadsTimelineSets();
1190+
expect(timelineSetsPromise).not.toBeNull();
1191+
await flushHttp(timelineSetsPromise!);
1192+
respondToFilter();
1193+
respondToSync();
1194+
respondToSync();
1195+
respondToSync();
1196+
respondToMessagesRequest();
1197+
await flushHttp(room.fetchRoomThreads());
1198+
});
1199+
});
1200+
});
1201+
9281202
describe("event timeline for sent events", function() {
9291203
const TXN_ID = "txn1";
9301204
const event = utils.mkMessage({

0 commit comments

Comments
 (0)