You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-12-01 04:43:29 +03:00
When we got a redaction event, we were adding the entire (circular) MatrixEvent object for the redaction to the redacted event, which would then cause exceptions down the line (particularly when dealing with gappy timelines). We should only be adding the raw event. Fixes (hopefully) https://github.com/vector-im/vector-web/issues/1389.
725 lines
26 KiB
JavaScript
725 lines
26 KiB
JavaScript
"use strict";
|
|
var q = require("q");
|
|
var sdk = require("../..");
|
|
var HttpBackend = require("../mock-request");
|
|
var utils = require("../test-utils");
|
|
var EventTimeline = sdk.EventTimeline;
|
|
|
|
var baseUrl = "http://localhost.or.something";
|
|
var userId = "@alice:localhost";
|
|
var userName = "Alice";
|
|
var accessToken = "aseukfgwef";
|
|
var roomId = "!foo:bar";
|
|
var otherUserId = "@bob:localhost";
|
|
|
|
var USER_MEMBERSHIP_EVENT = utils.mkMembership({
|
|
room: roomId, mship: "join", user: userId, name: userName
|
|
});
|
|
|
|
var ROOM_NAME_EVENT = utils.mkEvent({
|
|
type: "m.room.name", room: roomId, user: otherUserId,
|
|
content: {
|
|
name: "Old room name"
|
|
}
|
|
});
|
|
|
|
var INITIAL_SYNC_DATA = {
|
|
next_batch: "s_5_3",
|
|
rooms: {
|
|
join: {
|
|
"!foo:bar": { // roomId
|
|
timeline: {
|
|
events: [
|
|
utils.mkMessage({
|
|
room: roomId, user: otherUserId, msg: "hello"
|
|
})
|
|
],
|
|
prev_batch: "f_1_1"
|
|
},
|
|
state: {
|
|
events: [
|
|
ROOM_NAME_EVENT,
|
|
utils.mkMembership({
|
|
room: roomId, mship: "join",
|
|
user: otherUserId, name: "Bob"
|
|
}),
|
|
USER_MEMBERSHIP_EVENT,
|
|
utils.mkEvent({
|
|
type: "m.room.create", room: roomId, user: userId,
|
|
content: {
|
|
creator: userId
|
|
}
|
|
})
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var EVENTS = [
|
|
utils.mkMessage({
|
|
room: roomId, user: userId, msg: "we",
|
|
}),
|
|
utils.mkMessage({
|
|
room: roomId, user: userId, msg: "could",
|
|
}),
|
|
utils.mkMessage({
|
|
room: roomId, user: userId, msg: "be",
|
|
}),
|
|
utils.mkMessage({
|
|
room: roomId, user: userId, msg: "heroes",
|
|
}),
|
|
];
|
|
|
|
// start the client, and wait for it to initialise
|
|
function startClient(httpBackend, client) {
|
|
httpBackend.when("GET", "/pushrules").respond(200, {});
|
|
httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
|
|
httpBackend.when("GET", "/sync").respond(200, INITIAL_SYNC_DATA);
|
|
|
|
client.startClient();
|
|
|
|
// set up a promise which will resolve once the client is initialised
|
|
var deferred = q.defer();
|
|
client.on("sync", function(state) {
|
|
console.log("sync", state);
|
|
if (state != "SYNCING") {
|
|
return;
|
|
}
|
|
deferred.resolve();
|
|
});
|
|
|
|
httpBackend.flush();
|
|
return deferred.promise;
|
|
}
|
|
|
|
|
|
describe("getEventTimeline support", function() {
|
|
var httpBackend;
|
|
var client;
|
|
|
|
beforeEach(function() {
|
|
utils.beforeEach(this);
|
|
httpBackend = new HttpBackend();
|
|
sdk.request(httpBackend.requestFn);
|
|
});
|
|
|
|
afterEach(function() {
|
|
if (client) {
|
|
client.stopClient();
|
|
}
|
|
});
|
|
|
|
it("timeline support must be enabled to work", function(done) {
|
|
client = sdk.createClient({
|
|
baseUrl: baseUrl,
|
|
userId: userId,
|
|
accessToken: accessToken,
|
|
});
|
|
|
|
startClient(httpBackend, client
|
|
).then(function() {
|
|
var room = client.getRoom(roomId);
|
|
expect(function() { client.getEventTimeline(room, "event"); })
|
|
.toThrow();
|
|
}).catch(utils.failTest).done(done);
|
|
});
|
|
|
|
it("timeline support works when enabled", function(done) {
|
|
client = sdk.createClient({
|
|
baseUrl: baseUrl,
|
|
userId: userId,
|
|
accessToken: accessToken,
|
|
timelineSupport: true,
|
|
});
|
|
|
|
startClient(httpBackend, client
|
|
).then(function() {
|
|
var room = client.getRoom(roomId);
|
|
expect(function() { client.getEventTimeline(room, "event"); })
|
|
.not.toThrow();
|
|
}).catch(utils.failTest).done(done);
|
|
|
|
httpBackend.flush().catch(utils.failTest);
|
|
});
|
|
|
|
|
|
it("scrollback should be able to scroll back to before a gappy /sync",
|
|
function(done) {
|
|
// need a client with timelineSupport disabled to make this work
|
|
client = sdk.createClient({
|
|
baseUrl: baseUrl,
|
|
userId: userId,
|
|
accessToken: accessToken,
|
|
});
|
|
var room;
|
|
|
|
startClient(httpBackend, client
|
|
).then(function() {
|
|
room = client.getRoom(roomId);
|
|
|
|
httpBackend.when("GET", "/sync").respond(200, {
|
|
next_batch: "s_5_4",
|
|
rooms: {
|
|
join: {
|
|
"!foo:bar": {
|
|
timeline: {
|
|
events: [
|
|
EVENTS[0],
|
|
],
|
|
prev_batch: "f_1_1",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
httpBackend.when("GET", "/sync").respond(200, {
|
|
next_batch: "s_5_5",
|
|
rooms: {
|
|
join: {
|
|
"!foo:bar": {
|
|
timeline: {
|
|
events: [
|
|
EVENTS[1],
|
|
],
|
|
limited: true,
|
|
prev_batch: "f_1_2",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
httpBackend.when("GET", "/messages").respond(200, {
|
|
chunk: [EVENTS[0]],
|
|
start: "pagin_start",
|
|
end: "pagin_end",
|
|
});
|
|
|
|
|
|
return httpBackend.flush("/sync", 2);
|
|
}).then(function() {
|
|
expect(room.timeline.length).toEqual(1);
|
|
expect(room.timeline[0].event).toEqual(EVENTS[1]);
|
|
|
|
httpBackend.flush("/messages", 1);
|
|
return client.scrollback(room);
|
|
}).then(function() {
|
|
expect(room.timeline.length).toEqual(2);
|
|
expect(room.timeline[0].event).toEqual(EVENTS[0]);
|
|
expect(room.timeline[1].event).toEqual(EVENTS[1]);
|
|
expect(room.oldState.paginationToken).toEqual("pagin_end");
|
|
}).catch(utils.failTest).done(done);
|
|
});
|
|
});
|
|
|
|
describe("MatrixClient event timelines", function() {
|
|
var client, httpBackend;
|
|
|
|
beforeEach(function(done) {
|
|
utils.beforeEach(this);
|
|
httpBackend = new HttpBackend();
|
|
sdk.request(httpBackend.requestFn);
|
|
|
|
client = sdk.createClient({
|
|
baseUrl: baseUrl,
|
|
userId: userId,
|
|
accessToken: accessToken,
|
|
timelineSupport: true,
|
|
});
|
|
|
|
startClient(httpBackend, client)
|
|
.catch(utils.failTest).done(done);
|
|
});
|
|
|
|
afterEach(function() {
|
|
httpBackend.verifyNoOutstandingExpectation();
|
|
client.stopClient();
|
|
});
|
|
|
|
describe("getEventTimeline", function() {
|
|
it("should create a new timeline for new events", function(done) {
|
|
var room = client.getRoom(roomId);
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1%3Abar")
|
|
.respond(200, function() {
|
|
return {
|
|
start: "start_token",
|
|
events_before: [EVENTS[1], EVENTS[0]],
|
|
event: EVENTS[2],
|
|
events_after: [EVENTS[3]],
|
|
state: [
|
|
ROOM_NAME_EVENT,
|
|
USER_MEMBERSHIP_EVENT,
|
|
],
|
|
end: "end_token",
|
|
};
|
|
});
|
|
|
|
client.getEventTimeline(room, "event1:bar").then(function(tl) {
|
|
expect(tl.getEvents().length).toEqual(4);
|
|
for (var i = 0; i < 4; i++) {
|
|
expect(tl.getEvents()[i].event).toEqual(EVENTS[i]);
|
|
expect(tl.getEvents()[i].sender.name).toEqual(userName);
|
|
}
|
|
expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
|
|
.toEqual("start_token");
|
|
expect(tl.getPaginationToken(EventTimeline.FORWARDS))
|
|
.toEqual("end_token");
|
|
}).catch(utils.failTest).done(done);
|
|
|
|
httpBackend.flush().catch(utils.failTest);
|
|
});
|
|
|
|
it("should return existing timeline for known events", function(done) {
|
|
var room = client.getRoom(roomId);
|
|
httpBackend.when("GET", "/sync").respond(200, {
|
|
next_batch: "s_5_4",
|
|
rooms: {
|
|
join: {
|
|
"!foo:bar": {
|
|
timeline: {
|
|
events: [
|
|
EVENTS[0],
|
|
],
|
|
prev_batch: "f_1_2",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
httpBackend.flush("/sync").then(function() {
|
|
return client.getEventTimeline(room, EVENTS[0].event_id);
|
|
}).then(function(tl) {
|
|
expect(tl.getEvents().length).toEqual(2);
|
|
expect(tl.getEvents()[1].event).toEqual(EVENTS[0]);
|
|
expect(tl.getEvents()[1].sender.name).toEqual(userName);
|
|
expect(tl.getPaginationToken(EventTimeline.BACKWARDS)).toEqual("f_1_1");
|
|
// expect(tl.getPaginationToken(EventTimeline.FORWARDS)).toEqual("s_5_4");
|
|
}).catch(utils.failTest).done(done);
|
|
|
|
httpBackend.flush().catch(utils.failTest);
|
|
});
|
|
|
|
it("should update timelines where they overlap a previous /sync", function(done) {
|
|
var room = client.getRoom(roomId);
|
|
httpBackend.when("GET", "/sync").respond(200, {
|
|
next_batch: "s_5_4",
|
|
rooms: {
|
|
join: {
|
|
"!foo:bar": {
|
|
timeline: {
|
|
events: [
|
|
EVENTS[3],
|
|
],
|
|
prev_batch: "f_1_2",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
|
encodeURIComponent(EVENTS[2].event_id))
|
|
.respond(200, function() {
|
|
return {
|
|
start: "start_token",
|
|
events_before: [EVENTS[1]],
|
|
event: EVENTS[2],
|
|
events_after: [EVENTS[3]],
|
|
end: "end_token",
|
|
state: [],
|
|
};
|
|
});
|
|
|
|
client.on("sync", function() {
|
|
client.getEventTimeline(room, EVENTS[2].event_id
|
|
).then(function(tl) {
|
|
expect(tl.getEvents().length).toEqual(4);
|
|
expect(tl.getEvents()[0].event).toEqual(EVENTS[1]);
|
|
expect(tl.getEvents()[1].event).toEqual(EVENTS[2]);
|
|
expect(tl.getEvents()[3].event).toEqual(EVENTS[3]);
|
|
expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
|
|
.toEqual("start_token");
|
|
// expect(tl.getPaginationToken(EventTimeline.FORWARDS))
|
|
// .toEqual("s_5_4");
|
|
}).catch(utils.failTest).done(done);
|
|
});
|
|
|
|
httpBackend.flush().catch(utils.failTest);
|
|
});
|
|
|
|
it("should join timelines where they overlap a previous /context",
|
|
function(done) {
|
|
var room = client.getRoom(roomId);
|
|
|
|
// we fetch event 0, then 2, then 3, and finally 1. 1 is returned
|
|
// with context which joins them all up.
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
|
encodeURIComponent(EVENTS[0].event_id))
|
|
.respond(200, function() {
|
|
return {
|
|
start: "start_token0",
|
|
events_before: [],
|
|
event: EVENTS[0],
|
|
events_after: [],
|
|
end: "end_token0",
|
|
state: [],
|
|
};
|
|
});
|
|
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
|
encodeURIComponent(EVENTS[2].event_id))
|
|
.respond(200, function() {
|
|
return {
|
|
start: "start_token2",
|
|
events_before: [],
|
|
event: EVENTS[2],
|
|
events_after: [],
|
|
end: "end_token2",
|
|
state: [],
|
|
};
|
|
});
|
|
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
|
encodeURIComponent(EVENTS[3].event_id))
|
|
.respond(200, function() {
|
|
return {
|
|
start: "start_token3",
|
|
events_before: [],
|
|
event: EVENTS[3],
|
|
events_after: [],
|
|
end: "end_token3",
|
|
state: [],
|
|
};
|
|
});
|
|
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
|
encodeURIComponent(EVENTS[1].event_id))
|
|
.respond(200, function() {
|
|
return {
|
|
start: "start_token4",
|
|
events_before: [EVENTS[0]],
|
|
event: EVENTS[1],
|
|
events_after: [EVENTS[2], EVENTS[3]],
|
|
end: "end_token4",
|
|
state: [],
|
|
};
|
|
});
|
|
|
|
var tl0, tl2, tl3;
|
|
client.getEventTimeline(room, EVENTS[0].event_id
|
|
).then(function(tl) {
|
|
expect(tl.getEvents().length).toEqual(1);
|
|
tl0 = tl;
|
|
return client.getEventTimeline(room, EVENTS[2].event_id);
|
|
}).then(function(tl) {
|
|
expect(tl.getEvents().length).toEqual(1);
|
|
tl2 = tl;
|
|
return client.getEventTimeline(room, EVENTS[3].event_id);
|
|
}).then(function(tl) {
|
|
expect(tl.getEvents().length).toEqual(1);
|
|
tl3 = tl;
|
|
return client.getEventTimeline(room, EVENTS[1].event_id);
|
|
}).then(function(tl) {
|
|
// we expect it to get merged in with event 2
|
|
expect(tl.getEvents().length).toEqual(2);
|
|
expect(tl.getEvents()[0].event).toEqual(EVENTS[1]);
|
|
expect(tl.getEvents()[1].event).toEqual(EVENTS[2]);
|
|
expect(tl.getNeighbouringTimeline(EventTimeline.BACKWARDS))
|
|
.toBe(tl0);
|
|
expect(tl.getNeighbouringTimeline(EventTimeline.FORWARDS))
|
|
.toBe(tl3);
|
|
expect(tl0.getPaginationToken(EventTimeline.BACKWARDS))
|
|
.toEqual("start_token0");
|
|
expect(tl0.getPaginationToken(EventTimeline.FORWARDS))
|
|
.toBe(null);
|
|
expect(tl3.getPaginationToken(EventTimeline.BACKWARDS))
|
|
.toBe(null);
|
|
expect(tl3.getPaginationToken(EventTimeline.FORWARDS))
|
|
.toEqual("end_token3");
|
|
}).catch(utils.failTest).done(done);
|
|
|
|
httpBackend.flush().catch(utils.failTest);
|
|
});
|
|
|
|
it("should fail gracefully if there is no event field", function(done) {
|
|
var room = client.getRoom(roomId);
|
|
// we fetch event 0, then 2, then 3, and finally 1. 1 is returned
|
|
// with context which joins them all up.
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1")
|
|
.respond(200, function() {
|
|
return {
|
|
start: "start_token",
|
|
events_before: [],
|
|
events_after: [],
|
|
end: "end_token",
|
|
state: [],
|
|
};
|
|
});
|
|
|
|
client.getEventTimeline(room, "event1"
|
|
).then(function(tl) {
|
|
// could do with a fail()
|
|
expect(true).toBeFalsy();
|
|
}).catch(function(e) {
|
|
expect(String(e)).toMatch(/'event'/);
|
|
}).catch(utils.failTest).done(done);
|
|
|
|
httpBackend.flush().catch(utils.failTest);
|
|
});
|
|
});
|
|
|
|
describe("paginateEventTimeline", function() {
|
|
it("should allow you to paginate backwards", function(done) {
|
|
var room = client.getRoom(roomId);
|
|
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
|
encodeURIComponent(EVENTS[0].event_id))
|
|
.respond(200, function() {
|
|
return {
|
|
start: "start_token0",
|
|
events_before: [],
|
|
event: EVENTS[0],
|
|
events_after: [],
|
|
end: "end_token0",
|
|
state: [],
|
|
};
|
|
});
|
|
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/messages")
|
|
.check(function(req) {
|
|
var params = req.queryParams;
|
|
expect(params.dir).toEqual("b");
|
|
expect(params.from).toEqual("start_token0");
|
|
expect(params.limit).toEqual(30);
|
|
}).respond(200, function() {
|
|
return {
|
|
chunk: [EVENTS[1], EVENTS[2]],
|
|
end: "start_token1",
|
|
};
|
|
});
|
|
|
|
var tl;
|
|
client.getEventTimeline(room, EVENTS[0].event_id
|
|
).then(function(tl0) {
|
|
tl = tl0;
|
|
return client.paginateEventTimeline(tl, {backwards: true});
|
|
}).then(function(success) {
|
|
expect(success).toBeTruthy();
|
|
expect(tl.getEvents().length).toEqual(3);
|
|
expect(tl.getEvents()[0].event).toEqual(EVENTS[2]);
|
|
expect(tl.getEvents()[1].event).toEqual(EVENTS[1]);
|
|
expect(tl.getEvents()[2].event).toEqual(EVENTS[0]);
|
|
expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
|
|
.toEqual("start_token1");
|
|
expect(tl.getPaginationToken(EventTimeline.FORWARDS))
|
|
.toEqual("end_token0");
|
|
}).catch(utils.failTest).done(done);
|
|
|
|
httpBackend.flush().catch(utils.failTest);
|
|
});
|
|
|
|
|
|
it("should allow you to paginate forwards", function(done) {
|
|
var room = client.getRoom(roomId);
|
|
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
|
|
encodeURIComponent(EVENTS[0].event_id))
|
|
.respond(200, function() {
|
|
return {
|
|
start: "start_token0",
|
|
events_before: [],
|
|
event: EVENTS[0],
|
|
events_after: [],
|
|
end: "end_token0",
|
|
state: [],
|
|
};
|
|
});
|
|
|
|
httpBackend.when("GET", "/rooms/!foo%3Abar/messages")
|
|
.check(function(req) {
|
|
var params = req.queryParams;
|
|
expect(params.dir).toEqual("f");
|
|
expect(params.from).toEqual("end_token0");
|
|
expect(params.limit).toEqual(20);
|
|
}).respond(200, function() {
|
|
return {
|
|
chunk: [EVENTS[1], EVENTS[2]],
|
|
end: "end_token1",
|
|
};
|
|
});
|
|
|
|
var tl;
|
|
client.getEventTimeline(room, EVENTS[0].event_id
|
|
).then(function(tl0) {
|
|
tl = tl0;
|
|
return client.paginateEventTimeline(
|
|
tl, {backwards: false, limit: 20});
|
|
}).then(function(success) {
|
|
expect(success).toBeTruthy();
|
|
expect(tl.getEvents().length).toEqual(3);
|
|
expect(tl.getEvents()[0].event).toEqual(EVENTS[0]);
|
|
expect(tl.getEvents()[1].event).toEqual(EVENTS[1]);
|
|
expect(tl.getEvents()[2].event).toEqual(EVENTS[2]);
|
|
expect(tl.getPaginationToken(EventTimeline.BACKWARDS))
|
|
.toEqual("start_token0");
|
|
expect(tl.getPaginationToken(EventTimeline.FORWARDS))
|
|
.toEqual("end_token1");
|
|
}).catch(utils.failTest).done(done);
|
|
|
|
httpBackend.flush().catch(utils.failTest);
|
|
});
|
|
});
|
|
|
|
describe("event timeline for sent events", function() {
|
|
var TXN_ID = "txn1";
|
|
var event = utils.mkMessage({
|
|
room: roomId, user: userId, msg: "a body",
|
|
});
|
|
event.unsigned = {transaction_id: TXN_ID};
|
|
|
|
beforeEach(function() {
|
|
// set up handlers for both the message send, and the
|
|
// /sync
|
|
httpBackend.when("PUT", "/send/m.room.message/" + TXN_ID)
|
|
.respond(200, {
|
|
event_id: event.event_id,
|
|
});
|
|
httpBackend.when("GET", "/sync").respond(200, {
|
|
next_batch: "s_5_4",
|
|
rooms: {
|
|
join: {
|
|
"!foo:bar": {
|
|
timeline: {
|
|
events: [
|
|
event
|
|
],
|
|
prev_batch: "f_1_1",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
});
|
|
|
|
it("should work when /send returns before /sync", function(done) {
|
|
var room = client.getRoom(roomId);
|
|
|
|
client.sendTextMessage(roomId, "a body", TXN_ID).then(function(res) {
|
|
expect(res.event_id).toEqual(event.event_id);
|
|
return client.getEventTimeline(room, event.event_id);
|
|
}).then(function(tl) {
|
|
// 2 because the initial sync contained an event
|
|
expect(tl.getEvents().length).toEqual(2);
|
|
expect(tl.getEvents()[1].getContent().body).toEqual("a body");
|
|
|
|
// now let the sync complete, and check it again
|
|
return httpBackend.flush("/sync", 1);
|
|
}).then(function() {
|
|
return client.getEventTimeline(room, event.event_id);
|
|
}).then(function(tl) {
|
|
expect(tl.getEvents().length).toEqual(2);
|
|
expect(tl.getEvents()[1].event).toEqual(event);
|
|
}).catch(utils.failTest).done(done);
|
|
|
|
httpBackend.flush("/send/m.room.message/" + TXN_ID, 1).catch(utils.failTest);
|
|
});
|
|
|
|
it("should work when /send returns after /sync", function(done) {
|
|
var room = client.getRoom(roomId);
|
|
|
|
// initiate the send, and set up checks to be done when it completes
|
|
// - but note that it won't complete until after the /sync does, below.
|
|
client.sendTextMessage(roomId, "a body", TXN_ID).then(function(res) {
|
|
console.log("sendTextMessage completed");
|
|
expect(res.event_id).toEqual(event.event_id);
|
|
return client.getEventTimeline(room, event.event_id);
|
|
}).then(function(tl) {
|
|
console.log("getEventTimeline completed (2)");
|
|
expect(tl.getEvents().length).toEqual(2);
|
|
expect(tl.getEvents()[1].getContent().body).toEqual("a body");
|
|
}).catch(utils.failTest).done(done);
|
|
|
|
httpBackend.flush("/sync", 1).then(function() {
|
|
return client.getEventTimeline(room, event.event_id);
|
|
}).then(function(tl) {
|
|
console.log("getEventTimeline completed (1)");
|
|
expect(tl.getEvents().length).toEqual(2);
|
|
expect(tl.getEvents()[1].event).toEqual(event);
|
|
|
|
// now let the send complete.
|
|
return httpBackend.flush("/send/m.room.message/" + TXN_ID, 1);
|
|
}).catch(utils.failTest);
|
|
});
|
|
});
|
|
|
|
|
|
it("should handle gappy syncs after redactions", function(done) {
|
|
// https://github.com/vector-im/vector-web/issues/1389
|
|
|
|
// a state event, followed by a redaction thereof
|
|
var event = utils.mkMembership({
|
|
room: roomId, mship: "join", user: otherUserId
|
|
});
|
|
var redaction = utils.mkEvent({
|
|
type: "m.room.redaction",
|
|
room_id: roomId,
|
|
sender: otherUserId,
|
|
content: {}
|
|
});
|
|
redaction.redacts = event.event_id;
|
|
|
|
var syncData = {
|
|
next_batch: "batch1",
|
|
rooms: {
|
|
join: {},
|
|
},
|
|
};
|
|
syncData.rooms.join[roomId] = {
|
|
timeline: {
|
|
events: [
|
|
event,
|
|
redaction,
|
|
],
|
|
limited: false,
|
|
},
|
|
};
|
|
httpBackend.when("GET", "/sync").respond(200, syncData);
|
|
|
|
httpBackend.flush().then(function() {
|
|
var room = client.getRoom(roomId);
|
|
var tl = room.getLiveTimeline();
|
|
expect(tl.getEvents().length).toEqual(3);
|
|
expect(tl.getEvents()[1].isRedacted()).toBe(true);
|
|
|
|
var sync2 = {
|
|
next_batch: "batch2",
|
|
rooms: {
|
|
join: {},
|
|
},
|
|
};
|
|
sync2.rooms.join[roomId] = {
|
|
timeline: {
|
|
events: [
|
|
utils.mkMessage({
|
|
room: roomId, user: otherUserId, msg: "world"
|
|
}),
|
|
],
|
|
limited: true,
|
|
prev_batch: "newerTok",
|
|
},
|
|
};
|
|
httpBackend.when("GET", "/sync").respond(200, sync2);
|
|
|
|
return httpBackend.flush();
|
|
}).then(function() {
|
|
var room = client.getRoom(roomId);
|
|
var tl = room.getLiveTimeline();
|
|
expect(tl.getEvents().length).toEqual(1);
|
|
}).catch(utils.failTest).done(done);
|
|
});
|
|
});
|