1 | "use strict";
|
2 | import 'source-map-support/register';
|
3 | import Promise from 'bluebird';
|
4 | const sdk = require("../..");
|
5 | const HttpBackend = require("matrix-mock-request");
|
6 | const utils = require("../test-utils");
|
7 | const EventTimeline = sdk.EventTimeline;
|
8 | import logger from '../../src/logger';
|
9 |
|
10 | const baseUrl = "http://localhost.or.something";
|
11 | const userId = "@alice:localhost";
|
12 | const userName = "Alice";
|
13 | const accessToken = "aseukfgwef";
|
14 | const roomId = "!foo:bar";
|
15 | const otherUserId = "@bob:localhost";
|
16 |
|
17 | const USER_MEMBERSHIP_EVENT = utils.mkMembership({
|
18 | room: roomId, mship: "join", user: userId, name: userName,
|
19 | });
|
20 |
|
21 | const ROOM_NAME_EVENT = utils.mkEvent({
|
22 | type: "m.room.name", room: roomId, user: otherUserId,
|
23 | content: {
|
24 | name: "Old room name",
|
25 | },
|
26 | });
|
27 |
|
28 | const INITIAL_SYNC_DATA = {
|
29 | next_batch: "s_5_3",
|
30 | rooms: {
|
31 | join: {
|
32 | "!foo:bar": {
|
33 | timeline: {
|
34 | events: [
|
35 | utils.mkMessage({
|
36 | room: roomId, user: otherUserId, msg: "hello",
|
37 | }),
|
38 | ],
|
39 | prev_batch: "f_1_1",
|
40 | },
|
41 | state: {
|
42 | events: [
|
43 | ROOM_NAME_EVENT,
|
44 | utils.mkMembership({
|
45 | room: roomId, mship: "join",
|
46 | user: otherUserId, name: "Bob",
|
47 | }),
|
48 | USER_MEMBERSHIP_EVENT,
|
49 | utils.mkEvent({
|
50 | type: "m.room.create", room: roomId, user: userId,
|
51 | content: {
|
52 | creator: userId,
|
53 | },
|
54 | }),
|
55 | ],
|
56 | },
|
57 | },
|
58 | },
|
59 | },
|
60 | };
|
61 |
|
62 | const EVENTS = [
|
63 | utils.mkMessage({
|
64 | room: roomId, user: userId, msg: "we",
|
65 | }),
|
66 | utils.mkMessage({
|
67 | room: roomId, user: userId, msg: "could",
|
68 | }),
|
69 | utils.mkMessage({
|
70 | room: roomId, user: userId, msg: "be",
|
71 | }),
|
72 | utils.mkMessage({
|
73 | room: roomId, user: userId, msg: "heroes",
|
74 | }),
|
75 | ];
|
76 |
|
77 |
|
78 | function startClient(httpBackend, client) {
|
79 | httpBackend.when("GET", "/pushrules").respond(200, {});
|
80 | httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
|
81 | httpBackend.when("GET", "/sync").respond(200, INITIAL_SYNC_DATA);
|
82 |
|
83 | client.startClient();
|
84 |
|
85 |
|
86 | const deferred = Promise.defer();
|
87 | client.on("sync", function(state) {
|
88 | logger.log("sync", state);
|
89 | if (state != "SYNCING") {
|
90 | return;
|
91 | }
|
92 | deferred.resolve();
|
93 | });
|
94 |
|
95 | return Promise.all([
|
96 | httpBackend.flushAllExpected(),
|
97 | deferred.promise,
|
98 | ]);
|
99 | }
|
100 |
|
101 | describe("getEventTimeline support", function() {
|
102 | let httpBackend;
|
103 | let client;
|
104 |
|
105 | beforeEach(function() {
|
106 | utils.beforeEach(this);
|
107 | httpBackend = new HttpBackend();
|
108 | sdk.request(httpBackend.requestFn);
|
109 | });
|
110 |
|
111 | afterEach(function() {
|
112 | if (client) {
|
113 | client.stopClient();
|
114 | }
|
115 | return httpBackend.stop();
|
116 | });
|
117 |
|
118 | it("timeline support must be enabled to work", function(done) {
|
119 | client = sdk.createClient({
|
120 | baseUrl: baseUrl,
|
121 | userId: userId,
|
122 | accessToken: accessToken,
|
123 | });
|
124 |
|
125 | startClient(httpBackend, client,
|
126 | ).then(function() {
|
127 | const room = client.getRoom(roomId);
|
128 | const timelineSet = room.getTimelineSets()[0];
|
129 | expect(function() {
|
130 | client.getEventTimeline(timelineSet, "event");
|
131 | }).toThrow();
|
132 | }).nodeify(done);
|
133 | });
|
134 |
|
135 | it("timeline support works when enabled", function() {
|
136 | client = sdk.createClient({
|
137 | baseUrl: baseUrl,
|
138 | userId: userId,
|
139 | accessToken: accessToken,
|
140 | timelineSupport: true,
|
141 | });
|
142 |
|
143 | return startClient(httpBackend, client).then(() => {
|
144 | const room = client.getRoom(roomId);
|
145 | const timelineSet = room.getTimelineSets()[0];
|
146 | expect(function() {
|
147 | client.getEventTimeline(timelineSet, "event");
|
148 | }).toNotThrow();
|
149 | });
|
150 | });
|
151 |
|
152 |
|
153 | it("scrollback should be able to scroll back to before a gappy /sync",
|
154 | function(done) {
|
155 |
|
156 | client = sdk.createClient({
|
157 | baseUrl: baseUrl,
|
158 | userId: userId,
|
159 | accessToken: accessToken,
|
160 | });
|
161 | let room;
|
162 |
|
163 | startClient(httpBackend, client,
|
164 | ).then(function() {
|
165 | room = client.getRoom(roomId);
|
166 |
|
167 | httpBackend.when("GET", "/sync").respond(200, {
|
168 | next_batch: "s_5_4",
|
169 | rooms: {
|
170 | join: {
|
171 | "!foo:bar": {
|
172 | timeline: {
|
173 | events: [
|
174 | EVENTS[0],
|
175 | ],
|
176 | prev_batch: "f_1_1",
|
177 | },
|
178 | },
|
179 | },
|
180 | },
|
181 | });
|
182 |
|
183 | httpBackend.when("GET", "/sync").respond(200, {
|
184 | next_batch: "s_5_5",
|
185 | rooms: {
|
186 | join: {
|
187 | "!foo:bar": {
|
188 | timeline: {
|
189 | events: [
|
190 | EVENTS[1],
|
191 | ],
|
192 | limited: true,
|
193 | prev_batch: "f_1_2",
|
194 | },
|
195 | },
|
196 | },
|
197 | },
|
198 | });
|
199 |
|
200 | return Promise.all([
|
201 | httpBackend.flushAllExpected(),
|
202 | utils.syncPromise(client, 2),
|
203 | ]);
|
204 | }).then(function() {
|
205 | expect(room.timeline.length).toEqual(1);
|
206 | expect(room.timeline[0].event).toEqual(EVENTS[1]);
|
207 |
|
208 | httpBackend.when("GET", "/messages").respond(200, {
|
209 | chunk: [EVENTS[0]],
|
210 | start: "pagin_start",
|
211 | end: "pagin_end",
|
212 | });
|
213 | httpBackend.flush("/messages", 1);
|
214 | return client.scrollback(room);
|
215 | }).then(function() {
|
216 | expect(room.timeline.length).toEqual(2);
|
217 | expect(room.timeline[0].event).toEqual(EVENTS[0]);
|
218 | expect(room.timeline[1].event).toEqual(EVENTS[1]);
|
219 | expect(room.oldState.paginationToken).toEqual("pagin_end");
|
220 | }).nodeify(done);
|
221 | });
|
222 | });
|
223 |
|
224 | import expect from 'expect';
|
225 |
|
226 | describe("MatrixClient event timelines", function() {
|
227 | let client = null;
|
228 | let httpBackend = null;
|
229 |
|
230 | beforeEach(function() {
|
231 | utils.beforeEach(this);
|
232 | httpBackend = new HttpBackend();
|
233 | sdk.request(httpBackend.requestFn);
|
234 |
|
235 | client = sdk.createClient({
|
236 | baseUrl: baseUrl,
|
237 | userId: userId,
|
238 | accessToken: accessToken,
|
239 | timelineSupport: true,
|
240 | });
|
241 |
|
242 | return startClient(httpBackend, client);
|
243 | });
|
244 |
|
245 | afterEach(function() {
|
246 | httpBackend.verifyNoOutstandingExpectation();
|
247 | client.stopClient();
|
248 | });
|
249 |
|
250 | describe("getEventTimeline", function() {
|
251 | it("should create a new timeline for new events", function() {
|
252 | const room = client.getRoom(roomId);
|
253 | const timelineSet = room.getTimelineSets()[0];
|
254 | httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1%3Abar")
|
255 | .respond(200, function() {
|
256 | return {
|
257 | start: "start_token",
|
258 | events_before: [EVENTS[1], EVENTS[0]],
|
259 | event: EVENTS[2],
|
260 | events_after: [EVENTS[3]],
|
261 | state: [
|
262 | ROOM_NAME_EVENT,
|
263 | USER_MEMBERSHIP_EVENT,
|
264 | ],
|
265 | end: "end_token",
|
266 | };
|
267 | });
|
268 |
|
269 | return Promise.all([
|
270 | client.getEventTimeline(timelineSet, "event1:bar").then(function(tl) {
|
271 | expect(tl.getEvents().length).toEqual(4);
|
272 | for (let i = 0; i < 4; i++) {
|
273 | expect(tl.getEvents()[i].event).toEqual(EVENTS[i]);
|
274 | expect(tl.getEvents()[i].sender.name).toEqual(userName);
|
275 | }
|
276 | expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
|
277 | .toEqual("start_token");
|
278 | expect(tl.getPaginationToken(EventTimeline.FORWARDS))
|
279 | .toEqual("end_token");
|
280 | }),
|
281 | httpBackend.flushAllExpected(),
|
282 | ]);
|
283 | });
|
284 |
|
285 | it("should return existing timeline for known events", function() {
|
286 | const room = client.getRoom(roomId);
|
287 | const timelineSet = room.getTimelineSets()[0];
|
288 | httpBackend.when("GET", "/sync").respond(200, {
|
289 | next_batch: "s_5_4",
|
290 | rooms: {
|
291 | join: {
|
292 | "!foo:bar": {
|
293 | timeline: {
|
294 | events: [
|
295 | EVENTS[0],
|
296 | ],
|
297 | prev_batch: "f_1_2",
|
298 | },
|
299 | },
|
300 | },
|
301 | },
|
302 | });
|
303 |
|
304 | return Promise.all([
|
305 | httpBackend.flush("/sync"),
|
306 | utils.syncPromise(client),
|
307 | ]).then(function() {
|
308 | return client.getEventTimeline(timelineSet, EVENTS[0].event_id);
|
309 | }).then(function(tl) {
|
310 | expect(tl.getEvents().length).toEqual(2);
|
311 | expect(tl.getEvents()[1].event).toEqual(EVENTS[0]);
|
312 | expect(tl.getEvents()[1].sender.name).toEqual(userName);
|
313 | expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
|
314 | .toEqual("f_1_1");
|
315 |
|
316 |
|
317 | });
|
318 | });
|
319 |
|
320 | it("should update timelines where they overlap a previous /sync", function() {
|
321 | const room = client.getRoom(roomId);
|
322 | const timelineSet = room.getTimelineSets()[0];
|
323 | httpBackend.when("GET", "/sync").respond(200, {
|
324 | next_batch: "s_5_4",
|
325 | rooms: {
|
326 | join: {
|
327 | "!foo:bar": {
|
328 | timeline: {
|
329 | events: [
|
330 | EVENTS[3],
|
331 | ],
|
332 | prev_batch: "f_1_2",
|
333 | },
|
334 | },
|
335 | },
|
336 | },
|
337 | });
|
338 |
|
339 | httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
340 | encodeURIComponent(EVENTS[2].event_id))
|
341 | .respond(200, function() {
|
342 | return {
|
343 | start: "start_token",
|
344 | events_before: [EVENTS[1]],
|
345 | event: EVENTS[2],
|
346 | events_after: [EVENTS[3]],
|
347 | end: "end_token",
|
348 | state: [],
|
349 | };
|
350 | });
|
351 |
|
352 | const deferred = Promise.defer();
|
353 | client.on("sync", function() {
|
354 | client.getEventTimeline(timelineSet, EVENTS[2].event_id,
|
355 | ).then(function(tl) {
|
356 | expect(tl.getEvents().length).toEqual(4);
|
357 | expect(tl.getEvents()[0].event).toEqual(EVENTS[1]);
|
358 | expect(tl.getEvents()[1].event).toEqual(EVENTS[2]);
|
359 | expect(tl.getEvents()[3].event).toEqual(EVENTS[3]);
|
360 | expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
|
361 | .toEqual("start_token");
|
362 |
|
363 |
|
364 | }).done(() => deferred.resolve(),
|
365 | (e) => deferred.reject(e));
|
366 | });
|
367 |
|
368 | return Promise.all([
|
369 | httpBackend.flushAllExpected(),
|
370 | deferred.promise,
|
371 | ]);
|
372 | });
|
373 |
|
374 | it("should join timelines where they overlap a previous /context",
|
375 | function() {
|
376 | const room = client.getRoom(roomId);
|
377 | const timelineSet = room.getTimelineSets()[0];
|
378 |
|
379 |
|
380 |
|
381 | httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
382 | encodeURIComponent(EVENTS[0].event_id))
|
383 | .respond(200, function() {
|
384 | return {
|
385 | start: "start_token0",
|
386 | events_before: [],
|
387 | event: EVENTS[0],
|
388 | events_after: [],
|
389 | end: "end_token0",
|
390 | state: [],
|
391 | };
|
392 | });
|
393 |
|
394 | httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
395 | encodeURIComponent(EVENTS[2].event_id))
|
396 | .respond(200, function() {
|
397 | return {
|
398 | start: "start_token2",
|
399 | events_before: [],
|
400 | event: EVENTS[2],
|
401 | events_after: [],
|
402 | end: "end_token2",
|
403 | state: [],
|
404 | };
|
405 | });
|
406 |
|
407 | httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
408 | encodeURIComponent(EVENTS[3].event_id))
|
409 | .respond(200, function() {
|
410 | return {
|
411 | start: "start_token3",
|
412 | events_before: [],
|
413 | event: EVENTS[3],
|
414 | events_after: [],
|
415 | end: "end_token3",
|
416 | state: [],
|
417 | };
|
418 | });
|
419 |
|
420 | httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
421 | encodeURIComponent(EVENTS[1].event_id))
|
422 | .respond(200, function() {
|
423 | return {
|
424 | start: "start_token4",
|
425 | events_before: [EVENTS[0]],
|
426 | event: EVENTS[1],
|
427 | events_after: [EVENTS[2], EVENTS[3]],
|
428 | end: "end_token4",
|
429 | state: [],
|
430 | };
|
431 | });
|
432 |
|
433 | let tl0;
|
434 | let tl3;
|
435 | return Promise.all([
|
436 | client.getEventTimeline(timelineSet, EVENTS[0].event_id,
|
437 | ).then(function(tl) {
|
438 | expect(tl.getEvents().length).toEqual(1);
|
439 | tl0 = tl;
|
440 | return client.getEventTimeline(timelineSet, EVENTS[2].event_id);
|
441 | }).then(function(tl) {
|
442 | expect(tl.getEvents().length).toEqual(1);
|
443 | return client.getEventTimeline(timelineSet, EVENTS[3].event_id);
|
444 | }).then(function(tl) {
|
445 | expect(tl.getEvents().length).toEqual(1);
|
446 | tl3 = tl;
|
447 | return client.getEventTimeline(timelineSet, EVENTS[1].event_id);
|
448 | }).then(function(tl) {
|
449 |
|
450 | expect(tl.getEvents().length).toEqual(2);
|
451 | expect(tl.getEvents()[0].event).toEqual(EVENTS[1]);
|
452 | expect(tl.getEvents()[1].event).toEqual(EVENTS[2]);
|
453 | expect(tl.getNeighbouringTimeline(EventTimeline.BACKWARDS))
|
454 | .toBe(tl0);
|
455 | expect(tl.getNeighbouringTimeline(EventTimeline.FORWARDS))
|
456 | .toBe(tl3);
|
457 | expect(tl0.getPaginationToken(EventTimeline.BACKWARDS))
|
458 | .toEqual("start_token0");
|
459 | expect(tl0.getPaginationToken(EventTimeline.FORWARDS))
|
460 | .toBe(null);
|
461 | expect(tl3.getPaginationToken(EventTimeline.BACKWARDS))
|
462 | .toBe(null);
|
463 | expect(tl3.getPaginationToken(EventTimeline.FORWARDS))
|
464 | .toEqual("end_token3");
|
465 | }),
|
466 | httpBackend.flushAllExpected(),
|
467 | ]);
|
468 | });
|
469 |
|
470 | it("should fail gracefully if there is no event field", function() {
|
471 | const room = client.getRoom(roomId);
|
472 | const timelineSet = room.getTimelineSets()[0];
|
473 |
|
474 |
|
475 | httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1")
|
476 | .respond(200, function() {
|
477 | return {
|
478 | start: "start_token",
|
479 | events_before: [],
|
480 | events_after: [],
|
481 | end: "end_token",
|
482 | state: [],
|
483 | };
|
484 | });
|
485 |
|
486 | return Promise.all([
|
487 | client.getEventTimeline(timelineSet, "event1",
|
488 | ).then(function(tl) {
|
489 |
|
490 | expect(true).toBeFalsy();
|
491 | }, function(e) {
|
492 | expect(String(e)).toMatch(/'event'/);
|
493 | }),
|
494 | httpBackend.flushAllExpected(),
|
495 | ]);
|
496 | });
|
497 | });
|
498 |
|
499 | describe("paginateEventTimeline", function() {
|
500 | it("should allow you to paginate backwards", function() {
|
501 | const room = client.getRoom(roomId);
|
502 | const timelineSet = room.getTimelineSets()[0];
|
503 |
|
504 | httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
505 | encodeURIComponent(EVENTS[0].event_id))
|
506 | .respond(200, function() {
|
507 | return {
|
508 | start: "start_token0",
|
509 | events_before: [],
|
510 | event: EVENTS[0],
|
511 | events_after: [],
|
512 | end: "end_token0",
|
513 | state: [],
|
514 | };
|
515 | });
|
516 |
|
517 | httpBackend.when("GET", "/rooms/!foo%3Abar/messages")
|
518 | .check(function(req) {
|
519 | const params = req.queryParams;
|
520 | expect(params.dir).toEqual("b");
|
521 | expect(params.from).toEqual("start_token0");
|
522 | expect(params.limit).toEqual(30);
|
523 | }).respond(200, function() {
|
524 | return {
|
525 | chunk: [EVENTS[1], EVENTS[2]],
|
526 | end: "start_token1",
|
527 | };
|
528 | });
|
529 |
|
530 | let tl;
|
531 | return Promise.all([
|
532 | client.getEventTimeline(timelineSet, EVENTS[0].event_id,
|
533 | ).then(function(tl0) {
|
534 | tl = tl0;
|
535 | return client.paginateEventTimeline(tl, {backwards: true});
|
536 | }).then(function(success) {
|
537 | expect(success).toBeTruthy();
|
538 | expect(tl.getEvents().length).toEqual(3);
|
539 | expect(tl.getEvents()[0].event).toEqual(EVENTS[2]);
|
540 | expect(tl.getEvents()[1].event).toEqual(EVENTS[1]);
|
541 | expect(tl.getEvents()[2].event).toEqual(EVENTS[0]);
|
542 | expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
|
543 | .toEqual("start_token1");
|
544 | expect(tl.getPaginationToken(EventTimeline.FORWARDS))
|
545 | .toEqual("end_token0");
|
546 | }),
|
547 | httpBackend.flushAllExpected(),
|
548 | ]);
|
549 | });
|
550 |
|
551 |
|
552 | it("should allow you to paginate forwards", function() {
|
553 | const room = client.getRoom(roomId);
|
554 | const timelineSet = room.getTimelineSets()[0];
|
555 |
|
556 | httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
557 | encodeURIComponent(EVENTS[0].event_id))
|
558 | .respond(200, function() {
|
559 | return {
|
560 | start: "start_token0",
|
561 | events_before: [],
|
562 | event: EVENTS[0],
|
563 | events_after: [],
|
564 | end: "end_token0",
|
565 | state: [],
|
566 | };
|
567 | });
|
568 |
|
569 | httpBackend.when("GET", "/rooms/!foo%3Abar/messages")
|
570 | .check(function(req) {
|
571 | const params = req.queryParams;
|
572 | expect(params.dir).toEqual("f");
|
573 | expect(params.from).toEqual("end_token0");
|
574 | expect(params.limit).toEqual(20);
|
575 | }).respond(200, function() {
|
576 | return {
|
577 | chunk: [EVENTS[1], EVENTS[2]],
|
578 | end: "end_token1",
|
579 | };
|
580 | });
|
581 |
|
582 | let tl;
|
583 | return Promise.all([
|
584 | client.getEventTimeline(timelineSet, EVENTS[0].event_id,
|
585 | ).then(function(tl0) {
|
586 | tl = tl0;
|
587 | return client.paginateEventTimeline(
|
588 | tl, {backwards: false, limit: 20});
|
589 | }).then(function(success) {
|
590 | expect(success).toBeTruthy();
|
591 | expect(tl.getEvents().length).toEqual(3);
|
592 | expect(tl.getEvents()[0].event).toEqual(EVENTS[0]);
|
593 | expect(tl.getEvents()[1].event).toEqual(EVENTS[1]);
|
594 | expect(tl.getEvents()[2].event).toEqual(EVENTS[2]);
|
595 | expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
|
596 | .toEqual("start_token0");
|
597 | expect(tl.getPaginationToken(EventTimeline.FORWARDS))
|
598 | .toEqual("end_token1");
|
599 | }),
|
600 | httpBackend.flushAllExpected(),
|
601 | ]);
|
602 | });
|
603 | });
|
604 |
|
605 | describe("event timeline for sent events", function() {
|
606 | const TXN_ID = "txn1";
|
607 | const event = utils.mkMessage({
|
608 | room: roomId, user: userId, msg: "a body",
|
609 | });
|
610 | event.unsigned = {transaction_id: TXN_ID};
|
611 |
|
612 | beforeEach(function() {
|
613 |
|
614 |
|
615 | httpBackend.when("PUT", "/send/m.room.message/" + TXN_ID)
|
616 | .respond(200, {
|
617 | event_id: event.event_id,
|
618 | });
|
619 | httpBackend.when("GET", "/sync").respond(200, {
|
620 | next_batch: "s_5_4",
|
621 | rooms: {
|
622 | join: {
|
623 | "!foo:bar": {
|
624 | timeline: {
|
625 | events: [
|
626 | event,
|
627 | ],
|
628 | prev_batch: "f_1_1",
|
629 | },
|
630 | },
|
631 | },
|
632 | },
|
633 | });
|
634 | });
|
635 |
|
636 | it("should work when /send returns before /sync", function() {
|
637 | const room = client.getRoom(roomId);
|
638 | const timelineSet = room.getTimelineSets()[0];
|
639 |
|
640 | return Promise.all([
|
641 | client.sendTextMessage(roomId, "a body", TXN_ID).then(function(res) {
|
642 | expect(res.event_id).toEqual(event.event_id);
|
643 | return client.getEventTimeline(timelineSet, event.event_id);
|
644 | }).then(function(tl) {
|
645 |
|
646 | expect(tl.getEvents().length).toEqual(2);
|
647 | expect(tl.getEvents()[1].getContent().body).toEqual("a body");
|
648 |
|
649 |
|
650 | return Promise.all([
|
651 | httpBackend.flush("/sync", 1),
|
652 | utils.syncPromise(client),
|
653 | ]);
|
654 | }).then(function() {
|
655 | return client.getEventTimeline(timelineSet, event.event_id);
|
656 | }).then(function(tl) {
|
657 | expect(tl.getEvents().length).toEqual(2);
|
658 | expect(tl.getEvents()[1].event).toEqual(event);
|
659 | }),
|
660 |
|
661 | httpBackend.flush("/send/m.room.message/" + TXN_ID, 1),
|
662 | ]);
|
663 | });
|
664 |
|
665 | it("should work when /send returns after /sync", function() {
|
666 | const room = client.getRoom(roomId);
|
667 | const timelineSet = room.getTimelineSets()[0];
|
668 |
|
669 | return Promise.all([
|
670 |
|
671 |
|
672 | client.sendTextMessage(roomId, "a body", TXN_ID).then(function(res) {
|
673 | logger.log("sendTextMessage completed");
|
674 | expect(res.event_id).toEqual(event.event_id);
|
675 | return client.getEventTimeline(timelineSet, event.event_id);
|
676 | }).then(function(tl) {
|
677 | logger.log("getEventTimeline completed (2)");
|
678 | expect(tl.getEvents().length).toEqual(2);
|
679 | expect(tl.getEvents()[1].getContent().body).toEqual("a body");
|
680 | }),
|
681 |
|
682 | Promise.all([
|
683 | httpBackend.flush("/sync", 1),
|
684 | utils.syncPromise(client),
|
685 | ]).then(function() {
|
686 | return client.getEventTimeline(timelineSet, event.event_id);
|
687 | }).then(function(tl) {
|
688 | logger.log("getEventTimeline completed (1)");
|
689 | expect(tl.getEvents().length).toEqual(2);
|
690 | expect(tl.getEvents()[1].event).toEqual(event);
|
691 |
|
692 |
|
693 | return httpBackend.flush("/send/m.room.message/" + TXN_ID, 1);
|
694 | }),
|
695 | ]);
|
696 | });
|
697 | });
|
698 |
|
699 |
|
700 | it("should handle gappy syncs after redactions", function(done) {
|
701 |
|
702 |
|
703 |
|
704 | const event = utils.mkMembership({
|
705 | room: roomId, mship: "join", user: otherUserId,
|
706 | });
|
707 | const redaction = utils.mkEvent({
|
708 | type: "m.room.redaction",
|
709 | room_id: roomId,
|
710 | sender: otherUserId,
|
711 | content: {},
|
712 | });
|
713 | redaction.redacts = event.event_id;
|
714 |
|
715 | const syncData = {
|
716 | next_batch: "batch1",
|
717 | rooms: {
|
718 | join: {},
|
719 | },
|
720 | };
|
721 | syncData.rooms.join[roomId] = {
|
722 | timeline: {
|
723 | events: [
|
724 | event,
|
725 | redaction,
|
726 | ],
|
727 | limited: false,
|
728 | },
|
729 | };
|
730 | httpBackend.when("GET", "/sync").respond(200, syncData);
|
731 |
|
732 | Promise.all([
|
733 | httpBackend.flushAllExpected(),
|
734 | utils.syncPromise(client),
|
735 | ]).then(function() {
|
736 | const room = client.getRoom(roomId);
|
737 | const tl = room.getLiveTimeline();
|
738 | expect(tl.getEvents().length).toEqual(3);
|
739 | expect(tl.getEvents()[1].isRedacted()).toBe(true);
|
740 |
|
741 | const sync2 = {
|
742 | next_batch: "batch2",
|
743 | rooms: {
|
744 | join: {},
|
745 | },
|
746 | };
|
747 | sync2.rooms.join[roomId] = {
|
748 | timeline: {
|
749 | events: [
|
750 | utils.mkMessage({
|
751 | room: roomId, user: otherUserId, msg: "world",
|
752 | }),
|
753 | ],
|
754 | limited: true,
|
755 | prev_batch: "newerTok",
|
756 | },
|
757 | };
|
758 | httpBackend.when("GET", "/sync").respond(200, sync2);
|
759 |
|
760 | return Promise.all([
|
761 | httpBackend.flushAllExpected(),
|
762 | utils.syncPromise(client),
|
763 | ]);
|
764 | }).then(function() {
|
765 | const room = client.getRoom(roomId);
|
766 | const tl = room.getLiveTimeline();
|
767 | expect(tl.getEvents().length).toEqual(1);
|
768 | }).nodeify(done);
|
769 | });
|
770 | });
|