Skip to content

Ensure rooms are recalculated on re-invites #2374

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 107 additions & 2 deletions spec/integ/matrix-client-syncing.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { MatrixEvent } from "../../src/models/event";
import { EventTimeline } from "../../src/models/event-timeline";
import { EventTimeline, MatrixEvent, RoomEvent } from "../../src";
import * as utils from "../test-utils/test-utils";
import { TestClient } from "../TestClient";

Expand Down Expand Up @@ -60,6 +59,112 @@ describe("MatrixClient syncing", function() {
done();
});
});

it("should emit Room.myMembership for invite->leave->invite cycles", async () => {
const roomId = "!cycles:example.org";

// First sync: an invite
const inviteSyncRoomSection = {
invite: {
[roomId]: {
invite_state: {
events: [{
type: "m.room.member",
state_key: selfUserId,
content: {
membership: "invite",
},
}],
},
},
},
};
httpBackend.when("GET", "/sync").respond(200, {
...syncData,
rooms: inviteSyncRoomSection,
});

// Second sync: a leave (reject of some kind)
httpBackend.when("POST", "/leave").respond(200, {});
httpBackend.when("GET", "/sync").respond(200, {
...syncData,
rooms: {
leave: {
[roomId]: {
account_data: { events: [] },
ephemeral: { events: [] },
state: {
events: [{
type: "m.room.member",
state_key: selfUserId,
content: {
membership: "leave",
},
prev_content: {
membership: "invite",
},
// XXX: And other fields required on an event
}],
},
timeline: {
limited: false,
events: [{
type: "m.room.member",
state_key: selfUserId,
content: {
membership: "leave",
},
prev_content: {
membership: "invite",
},
// XXX: And other fields required on an event
}],
},
},
},
},
});

// Third sync: another invite
httpBackend.when("GET", "/sync").respond(200, {
...syncData,
rooms: inviteSyncRoomSection,
});

// First fire: an initial invite
let fires = 0;
client.once(RoomEvent.MyMembership, (room, membership, oldMembership) => { // Room, string, string
fires++;
expect(room.roomId).toBe(roomId);
expect(membership).toBe("invite");
expect(oldMembership).toBeFalsy();

// Second fire: a leave
client.once(RoomEvent.MyMembership, (room, membership, oldMembership) => {
fires++;
expect(room.roomId).toBe(roomId);
expect(membership).toBe("leave");
expect(oldMembership).toBe("invite");

// Third/final fire: a second invite
client.once(RoomEvent.MyMembership, (room, membership, oldMembership) => {
fires++;
expect(room.roomId).toBe(roomId);
expect(membership).toBe("invite");
expect(oldMembership).toBe("leave");
});
});

// For maximum safety, "leave" the room after we register the handler
client.leave(roomId);
});

// noinspection ES6MissingAwait
client.startClient();
await httpBackend.flushAllExpected();

expect(fires).toBe(3);
});
});

describe("resolving invites to profile info", function() {
Expand Down
3 changes: 3 additions & 0 deletions src/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,9 @@ export class SyncApi {
room.recalculate();
client.store.storeRoom(room);
client.emit(ClientEvent.Room, room);
} else {
// Update room state for invite->reject->invite cycles
room.recalculate();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not just move the recalculate out to before the if?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can, but then the comment is less clear imo

}
stateEvents.forEach(function(e) {
client.emit(ClientEvent.Event, e);
Expand Down