mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-06-08 15:21:53 +03:00
* Bump eslint-plugin-matrix-org to enable @typescript-eslint/consistent-type-imports rule * Re-lint after merge
687 lines
25 KiB
TypeScript
687 lines
25 KiB
TypeScript
/*
|
||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||
|
||
Licensed under the Apache License, Version 2.0 (the "License");
|
||
you may not use this file except in compliance with the License.
|
||
You may obtain a copy of the License at
|
||
|
||
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
||
Unless required by applicable law or agreed to in writing, software
|
||
distributed under the License is distributed on an "AS IS" BASIS,
|
||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
See the License for the specific language governing permissions and
|
||
limitations under the License.
|
||
*/
|
||
|
||
import fetchMock from "fetch-mock-jest";
|
||
|
||
import * as utils from "../test-utils/test-utils";
|
||
import { RoomMember, RoomMemberEvent } from "../../src/models/room-member";
|
||
import {
|
||
createClient,
|
||
EventType,
|
||
type MatrixClient,
|
||
type RoomState,
|
||
UNSTABLE_MSC2666_MUTUAL_ROOMS,
|
||
UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS,
|
||
UNSTABLE_MSC2666_SHARED_ROOMS,
|
||
} from "../../src";
|
||
import { KnownMembership } from "../../src/@types/membership";
|
||
|
||
describe("RoomMember", function () {
|
||
const roomId = "!foo:bar";
|
||
const userA = "@alice:bar";
|
||
const userB = "@bertha:bar";
|
||
const userC = "@clarissa:bar";
|
||
let member = new RoomMember(roomId, userA);
|
||
|
||
beforeEach(function () {
|
||
member = new RoomMember(roomId, userA);
|
||
});
|
||
|
||
describe("getAvatarUrl", function () {
|
||
const hsUrl = "https://my.home.server";
|
||
|
||
it("should return the URL from m.room.member preferentially", function () {
|
||
member.events.member = utils.mkEvent({
|
||
event: true,
|
||
type: "m.room.member",
|
||
skey: userA,
|
||
room: roomId,
|
||
user: userA,
|
||
content: {
|
||
membership: KnownMembership.Join,
|
||
avatar_url: "mxc://flibble/wibble",
|
||
},
|
||
});
|
||
const url = member.getAvatarUrl(hsUrl, 1, 1, "", false, false);
|
||
// we don't care about how the mxc->http conversion is done, other
|
||
// than it contains the mxc body.
|
||
expect(url?.indexOf("flibble/wibble")).not.toEqual(-1);
|
||
});
|
||
|
||
it("should return nothing if there is no m.room.member and allowDefault=false", function () {
|
||
const url = member.getAvatarUrl(hsUrl, 64, 64, "crop", false, false);
|
||
expect(url).toEqual(null);
|
||
});
|
||
|
||
it("should return unauthenticated media URL if useAuthentication is not set", function () {
|
||
member.events.member = utils.mkEvent({
|
||
event: true,
|
||
type: "m.room.member",
|
||
skey: userA,
|
||
room: roomId,
|
||
user: userA,
|
||
content: {
|
||
membership: KnownMembership.Join,
|
||
avatar_url: "mxc://flibble/wibble",
|
||
},
|
||
});
|
||
const url = member.getAvatarUrl(hsUrl, 1, 1, "", false, false);
|
||
// Check for unauthenticated media prefix
|
||
expect(url?.indexOf("/_matrix/media/v3/")).not.toEqual(-1);
|
||
});
|
||
|
||
it("should return authenticated media URL if useAuthentication=true", function () {
|
||
member.events.member = utils.mkEvent({
|
||
event: true,
|
||
type: "m.room.member",
|
||
skey: userA,
|
||
room: roomId,
|
||
user: userA,
|
||
content: {
|
||
membership: KnownMembership.Join,
|
||
avatar_url: "mxc://flibble/wibble",
|
||
},
|
||
});
|
||
const url = member.getAvatarUrl(hsUrl, 1, 1, "", false, false, true);
|
||
// Check for authenticated media prefix
|
||
expect(url?.indexOf("/_matrix/client/v1/media/")).not.toEqual(-1);
|
||
});
|
||
});
|
||
|
||
describe("setPowerLevelEvent", function () {
|
||
it("should set 'powerLevel' and 'powerLevelNorm'.", function () {
|
||
const event = utils.mkEvent({
|
||
type: "m.room.power_levels",
|
||
room: roomId,
|
||
user: userA,
|
||
content: {
|
||
users_default: 20,
|
||
users: {
|
||
"@bertha:bar": 200,
|
||
"@invalid:user": 10, // shouldn't barf on this.
|
||
},
|
||
},
|
||
event: true,
|
||
});
|
||
member.setPowerLevelEvent(event);
|
||
expect(member.powerLevel).toEqual(20);
|
||
expect(member.powerLevelNorm).toEqual(10);
|
||
|
||
const memberB = new RoomMember(roomId, userB);
|
||
memberB.setPowerLevelEvent(event);
|
||
expect(memberB.powerLevel).toEqual(200);
|
||
expect(memberB.powerLevelNorm).toEqual(100);
|
||
});
|
||
|
||
it("should emit 'RoomMember.powerLevel' if the power level changes.", function () {
|
||
const event = utils.mkEvent({
|
||
type: "m.room.power_levels",
|
||
room: roomId,
|
||
user: userA,
|
||
content: {
|
||
users_default: 20,
|
||
users: {
|
||
"@bertha:bar": 200,
|
||
"@invalid:user": 10, // shouldn't barf on this.
|
||
},
|
||
},
|
||
event: true,
|
||
});
|
||
let emitCount = 0;
|
||
|
||
member.on(RoomMemberEvent.PowerLevel, function (emitEvent, emitMember) {
|
||
emitCount += 1;
|
||
expect(emitMember).toEqual(member);
|
||
expect(emitEvent).toEqual(event);
|
||
});
|
||
|
||
member.setPowerLevelEvent(event);
|
||
expect(emitCount).toEqual(1);
|
||
member.setPowerLevelEvent(event); // no-op
|
||
expect(emitCount).toEqual(1);
|
||
});
|
||
|
||
it("should honour power levels of zero.", function () {
|
||
const event = utils.mkEvent({
|
||
type: "m.room.power_levels",
|
||
room: roomId,
|
||
user: userA,
|
||
content: {
|
||
users_default: 20,
|
||
users: {
|
||
"@alice:bar": 0,
|
||
},
|
||
},
|
||
event: true,
|
||
});
|
||
let emitCount = 0;
|
||
|
||
// set the power level to something other than zero or we
|
||
// won't get an event
|
||
member.powerLevel = 1;
|
||
member.on(RoomMemberEvent.PowerLevel, function (emitEvent, emitMember) {
|
||
emitCount += 1;
|
||
expect(emitMember.userId).toEqual("@alice:bar");
|
||
expect(emitMember.powerLevel).toEqual(0);
|
||
expect(emitEvent).toEqual(event);
|
||
});
|
||
|
||
member.setPowerLevelEvent(event);
|
||
expect(member.powerLevel).toEqual(0);
|
||
expect(emitCount).toEqual(1);
|
||
});
|
||
|
||
it("should not honor string power levels.", function () {
|
||
const event = utils.mkEvent({
|
||
type: "m.room.power_levels",
|
||
room: roomId,
|
||
user: userA,
|
||
content: {
|
||
users_default: 20,
|
||
users: {
|
||
"@alice:bar": "5",
|
||
},
|
||
},
|
||
event: true,
|
||
});
|
||
let emitCount = 0;
|
||
|
||
member.on(RoomMemberEvent.PowerLevel, function (emitEvent, emitMember) {
|
||
emitCount += 1;
|
||
expect(emitMember.userId).toEqual("@alice:bar");
|
||
expect(emitMember.powerLevel).toEqual(20);
|
||
expect(emitEvent).toEqual(event);
|
||
});
|
||
|
||
member.setPowerLevelEvent(event);
|
||
expect(member.powerLevel).toEqual(20);
|
||
expect(emitCount).toEqual(1);
|
||
});
|
||
|
||
it("should no-op if given a non-state or unrelated event", () => {
|
||
const fn = jest.spyOn(member, "emit");
|
||
expect(fn).not.toHaveBeenCalledWith(RoomMemberEvent.PowerLevel);
|
||
member.setPowerLevelEvent(
|
||
utils.mkEvent({
|
||
type: EventType.RoomPowerLevels,
|
||
room: roomId,
|
||
user: userA,
|
||
content: {
|
||
users_default: 20,
|
||
users: {
|
||
"@alice:bar": "5",
|
||
},
|
||
},
|
||
skey: "invalid",
|
||
event: true,
|
||
}),
|
||
);
|
||
const nonStateEv = utils.mkEvent({
|
||
type: EventType.RoomPowerLevels,
|
||
room: roomId,
|
||
user: userA,
|
||
content: {
|
||
users_default: 20,
|
||
users: {
|
||
"@alice:bar": "5",
|
||
},
|
||
},
|
||
event: true,
|
||
});
|
||
delete nonStateEv.event.state_key;
|
||
member.setPowerLevelEvent(nonStateEv);
|
||
member.setPowerLevelEvent(
|
||
utils.mkEvent({
|
||
type: EventType.Sticker,
|
||
room: roomId,
|
||
user: userA,
|
||
content: {},
|
||
event: true,
|
||
}),
|
||
);
|
||
expect(fn).not.toHaveBeenCalledWith(RoomMemberEvent.PowerLevel);
|
||
});
|
||
});
|
||
|
||
describe("setTypingEvent", function () {
|
||
it("should set 'typing'", function () {
|
||
member.typing = false;
|
||
const memberB = new RoomMember(roomId, userB);
|
||
memberB.typing = true;
|
||
const memberC = new RoomMember(roomId, userC);
|
||
memberC.typing = true;
|
||
|
||
const event = utils.mkEvent({
|
||
type: "m.typing",
|
||
user: userA,
|
||
room: roomId,
|
||
content: {
|
||
user_ids: [userA, userC],
|
||
},
|
||
event: true,
|
||
});
|
||
member.setTypingEvent(event);
|
||
memberB.setTypingEvent(event);
|
||
memberC.setTypingEvent(event);
|
||
|
||
expect(member.typing).toEqual(true);
|
||
expect(memberB.typing).toEqual(false);
|
||
expect(memberC.typing).toEqual(true);
|
||
});
|
||
|
||
it("should emit 'RoomMember.typing' if the typing state changes", function () {
|
||
const event = utils.mkEvent({
|
||
type: "m.typing",
|
||
room: roomId,
|
||
content: {
|
||
user_ids: [userA, userC],
|
||
},
|
||
event: true,
|
||
});
|
||
let emitCount = 0;
|
||
member.on(RoomMemberEvent.Typing, function (ev, mem) {
|
||
expect(mem).toEqual(member);
|
||
expect(ev).toEqual(event);
|
||
emitCount += 1;
|
||
});
|
||
member.typing = false;
|
||
member.setTypingEvent(event);
|
||
expect(emitCount).toEqual(1);
|
||
member.setTypingEvent(event); // no-op
|
||
expect(emitCount).toEqual(1);
|
||
});
|
||
});
|
||
|
||
describe("isOutOfBand", function () {
|
||
it("should be set by markOutOfBand", function () {
|
||
const member = new RoomMember(roomId, userA);
|
||
expect(member.isOutOfBand()).toEqual(false);
|
||
member.markOutOfBand();
|
||
expect(member.isOutOfBand()).toEqual(true);
|
||
});
|
||
});
|
||
|
||
describe("isKicked", () => {
|
||
it("should return false if membership is not `leave`", () => {
|
||
const member1 = new RoomMember(roomId, userA);
|
||
member1.membership = KnownMembership.Join;
|
||
expect(member1.isKicked()).toBeFalsy();
|
||
|
||
const member2 = new RoomMember(roomId, userA);
|
||
member2.membership = KnownMembership.Invite;
|
||
expect(member2.isKicked()).toBeFalsy();
|
||
|
||
const member3 = new RoomMember(roomId, userA);
|
||
expect(member3.isKicked()).toBeFalsy();
|
||
});
|
||
|
||
it("should return false if the membership event is unknown", () => {
|
||
const member = new RoomMember(roomId, userA);
|
||
member.membership = KnownMembership.Leave;
|
||
expect(member.isKicked()).toBeFalsy();
|
||
});
|
||
|
||
it("should return false if the member left of their own accord", () => {
|
||
const member = new RoomMember(roomId, userA);
|
||
member.membership = KnownMembership.Leave;
|
||
member.events.member = utils.mkMembership({
|
||
event: true,
|
||
sender: userA,
|
||
mship: KnownMembership.Leave,
|
||
skey: userA,
|
||
});
|
||
expect(member.isKicked()).toBeFalsy();
|
||
});
|
||
|
||
it("should return true if the member's leave was sent by another user", () => {
|
||
const member = new RoomMember(roomId, userA);
|
||
member.membership = KnownMembership.Leave;
|
||
member.events.member = utils.mkMembership({
|
||
event: true,
|
||
sender: userB,
|
||
mship: KnownMembership.Leave,
|
||
skey: userA,
|
||
});
|
||
expect(member.isKicked()).toBeTruthy();
|
||
});
|
||
});
|
||
|
||
describe("getDMInviter", () => {
|
||
it("should return userId of the sender of the invite if is_direct=true", () => {
|
||
const member = new RoomMember(roomId, userA);
|
||
member.membership = KnownMembership.Invite;
|
||
member.events.member = utils.mkMembership({
|
||
event: true,
|
||
sender: userB,
|
||
mship: KnownMembership.Invite,
|
||
skey: userA,
|
||
});
|
||
member.events.member.event.content!.is_direct = true;
|
||
expect(member.getDMInviter()).toBe(userB);
|
||
});
|
||
|
||
it("should not return userId of the sender of the invite if is_direct=false", () => {
|
||
const member = new RoomMember(roomId, userA);
|
||
member.membership = KnownMembership.Invite;
|
||
member.events.member = utils.mkMembership({
|
||
event: true,
|
||
sender: userB,
|
||
mship: KnownMembership.Invite,
|
||
skey: userA,
|
||
});
|
||
member.events.member.event.content!.is_direct = false;
|
||
expect(member.getDMInviter()).toBeUndefined();
|
||
});
|
||
});
|
||
|
||
describe("setMembershipEvent", function () {
|
||
const joinEvent = utils.mkMembership({
|
||
event: true,
|
||
mship: KnownMembership.Join,
|
||
user: userA,
|
||
room: roomId,
|
||
name: "Alice",
|
||
});
|
||
|
||
const inviteEvent = utils.mkMembership({
|
||
event: true,
|
||
mship: KnownMembership.Invite,
|
||
user: userB,
|
||
skey: userA,
|
||
room: roomId,
|
||
});
|
||
|
||
it("should set 'membership' and assign the event to 'events.member'.", function () {
|
||
member.setMembershipEvent(inviteEvent);
|
||
expect(member.membership).toEqual(KnownMembership.Invite);
|
||
expect(member.events.member).toEqual(inviteEvent);
|
||
member.setMembershipEvent(joinEvent);
|
||
expect(member.membership).toEqual(KnownMembership.Join);
|
||
expect(member.events.member).toEqual(joinEvent);
|
||
});
|
||
|
||
it("should set 'name' based on user_id, displayname and room state", function () {
|
||
const roomState = {
|
||
getStateEvents: function (type: string) {
|
||
if (type !== "m.room.member") {
|
||
return [];
|
||
}
|
||
return [
|
||
utils.mkMembership({
|
||
event: true,
|
||
mship: KnownMembership.Join,
|
||
room: roomId,
|
||
user: userB,
|
||
}),
|
||
utils.mkMembership({
|
||
event: true,
|
||
mship: KnownMembership.Join,
|
||
room: roomId,
|
||
user: userC,
|
||
name: "Alice",
|
||
}),
|
||
joinEvent,
|
||
];
|
||
},
|
||
getUserIdsWithDisplayName: function (displayName: string) {
|
||
return [userA, userC];
|
||
},
|
||
} as unknown as RoomState;
|
||
expect(member.name).toEqual(userA); // default = user_id
|
||
member.setMembershipEvent(joinEvent);
|
||
expect(member.name).toEqual("Alice"); // prefer displayname
|
||
member.setMembershipEvent(joinEvent, roomState);
|
||
expect(member.name).not.toEqual("Alice"); // it should disambig.
|
||
// user_id should be there somewhere
|
||
expect(member.name.indexOf(userA)).not.toEqual(-1);
|
||
});
|
||
|
||
it("should emit 'RoomMember.membership' if the membership changes", function () {
|
||
let emitCount = 0;
|
||
member.on(RoomMemberEvent.Membership, function (ev, mem) {
|
||
emitCount += 1;
|
||
expect(mem).toEqual(member);
|
||
expect(ev).toEqual(inviteEvent);
|
||
});
|
||
member.setMembershipEvent(inviteEvent);
|
||
expect(emitCount).toEqual(1);
|
||
member.setMembershipEvent(inviteEvent); // no-op
|
||
expect(emitCount).toEqual(1);
|
||
});
|
||
|
||
it("should emit 'RoomMember.name' if the name changes", function () {
|
||
let emitCount = 0;
|
||
member.on(RoomMemberEvent.Name, function (ev, mem) {
|
||
emitCount += 1;
|
||
expect(mem).toEqual(member);
|
||
expect(ev).toEqual(joinEvent);
|
||
});
|
||
member.setMembershipEvent(joinEvent);
|
||
expect(emitCount).toEqual(1);
|
||
member.setMembershipEvent(joinEvent); // no-op
|
||
expect(emitCount).toEqual(1);
|
||
});
|
||
|
||
it("should set 'name' to user_id if it is just whitespace", function () {
|
||
const joinEvent = utils.mkMembership({
|
||
event: true,
|
||
mship: KnownMembership.Join,
|
||
user: userA,
|
||
room: roomId,
|
||
name: " \u200b ",
|
||
});
|
||
|
||
expect(member.name).toEqual(userA); // default = user_id
|
||
member.setMembershipEvent(joinEvent);
|
||
expect(member.name).toEqual(userA); // it should fallback because all whitespace
|
||
});
|
||
|
||
it("should disambiguate users on a fuzzy displayname match", function () {
|
||
const joinEvent = utils.mkMembership({
|
||
event: true,
|
||
mship: KnownMembership.Join,
|
||
user: userA,
|
||
room: roomId,
|
||
name: "Alíce\u200b", // note diacritic and zero width char
|
||
});
|
||
|
||
const roomState = {
|
||
getStateEvents: function (type: string) {
|
||
if (type !== "m.room.member") {
|
||
return [];
|
||
}
|
||
return [
|
||
utils.mkMembership({
|
||
event: true,
|
||
mship: KnownMembership.Join,
|
||
room: roomId,
|
||
user: userC,
|
||
name: "Alice",
|
||
}),
|
||
joinEvent,
|
||
];
|
||
},
|
||
getUserIdsWithDisplayName: function (displayName: string) {
|
||
return [userA, userC];
|
||
},
|
||
} as unknown as RoomState;
|
||
expect(member.name).toEqual(userA); // default = user_id
|
||
member.setMembershipEvent(joinEvent, roomState);
|
||
expect(member.name).toEqual("Alíce (@alice:bar)"); // it should disambig.
|
||
// user_id should be there somewhere
|
||
expect(member.name.indexOf(userA)).not.toEqual(-1);
|
||
});
|
||
|
||
it("should disambiguate a user when their displayname looks like an MXID which isn't theirs", function () {
|
||
const joinEvent = utils.mkMembership({
|
||
event: true,
|
||
mship: KnownMembership.Join,
|
||
user: userA,
|
||
room: roomId,
|
||
name: "@clarissa\u0a83bar",
|
||
});
|
||
|
||
const roomState = {
|
||
getStateEvents: function (type: string) {
|
||
if (type !== "m.room.member") {
|
||
return [];
|
||
}
|
||
return [
|
||
utils.mkMembership({
|
||
event: true,
|
||
mship: KnownMembership.Join,
|
||
room: roomId,
|
||
user: userC,
|
||
name: "Alice",
|
||
}),
|
||
joinEvent,
|
||
];
|
||
},
|
||
getUserIdsWithDisplayName: function (displayName: string) {
|
||
return [userA, userC];
|
||
},
|
||
} as unknown as RoomState;
|
||
expect(member.name).toEqual(userA); // default = user_id
|
||
member.setMembershipEvent(joinEvent, roomState);
|
||
expect(member.name).toEqual("@clarissaઃbar (@alice:bar)"); // it should disambig.
|
||
// user_id should be there somewhere
|
||
expect(member.name.indexOf(userA)).not.toEqual(-1);
|
||
});
|
||
});
|
||
});
|
||
|
||
describe("MutualRooms", () => {
|
||
let client: MatrixClient;
|
||
const HS_URL = "https://example.com";
|
||
const TEST_USER_ID = "@alice:localhost";
|
||
const TEST_DEVICE_ID = "xzcvb";
|
||
const QUERIED_USER = "@user:example.com";
|
||
|
||
beforeEach(async () => {
|
||
// anything that we don't have a specific matcher for silently returns a 404
|
||
fetchMock.catch(404);
|
||
fetchMock.config.warnOnFallback = true;
|
||
|
||
client = createClient({
|
||
baseUrl: HS_URL,
|
||
userId: TEST_USER_ID,
|
||
accessToken: "akjgkrgjs",
|
||
deviceId: TEST_DEVICE_ID,
|
||
});
|
||
});
|
||
|
||
afterEach(async () => {
|
||
await client.stopClient();
|
||
fetchMock.mockReset();
|
||
});
|
||
|
||
function enableFeature(feature: string) {
|
||
const mapping: Record<string, boolean> = {};
|
||
|
||
mapping[feature] = true;
|
||
|
||
fetchMock.get(`${HS_URL}/_matrix/client/versions`, {
|
||
unstable_features: mapping,
|
||
versions: ["v1.1"],
|
||
});
|
||
}
|
||
|
||
it("supports the initial MSC version (shared rooms)", async () => {
|
||
enableFeature(UNSTABLE_MSC2666_SHARED_ROOMS);
|
||
|
||
fetchMock.get("express:/_matrix/client/unstable/uk.half-shot.msc2666/user/shared_rooms/:user_id", (rawUrl) => {
|
||
const segments = rawUrl.split("/");
|
||
const lastSegment = decodeURIComponent(segments[segments.length - 1]);
|
||
|
||
expect(lastSegment).toEqual(QUERIED_USER);
|
||
|
||
return {
|
||
joined: ["!test:example.com"],
|
||
};
|
||
});
|
||
|
||
const rooms = await client._unstable_getSharedRooms(QUERIED_USER);
|
||
|
||
expect(rooms).toEqual(["!test:example.com"]);
|
||
});
|
||
|
||
it("supports the renaming MSC version (mutual rooms)", async () => {
|
||
enableFeature(UNSTABLE_MSC2666_MUTUAL_ROOMS);
|
||
|
||
fetchMock.get("express:/_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms/:user_id", (rawUrl) => {
|
||
const segments = rawUrl.split("/");
|
||
const lastSegment = decodeURIComponent(segments[segments.length - 1]);
|
||
|
||
expect(lastSegment).toEqual(QUERIED_USER);
|
||
|
||
return {
|
||
joined: ["!test2:example.com"],
|
||
};
|
||
});
|
||
|
||
const rooms = await client._unstable_getSharedRooms(QUERIED_USER);
|
||
|
||
expect(rooms).toEqual(["!test2:example.com"]);
|
||
});
|
||
|
||
describe("can work the latest MSC version (query mutual rooms)", () => {
|
||
beforeEach(() => {
|
||
enableFeature(UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS);
|
||
});
|
||
|
||
it("works with a simple response", async () => {
|
||
fetchMock.get("express:/_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms", (rawUrl) => {
|
||
const url = new URL(rawUrl);
|
||
|
||
expect(url.searchParams.get("user_id")).toEqual(QUERIED_USER);
|
||
|
||
return {
|
||
joined: ["!test3:example.com"],
|
||
};
|
||
});
|
||
|
||
const rooms = await client._unstable_getSharedRooms(QUERIED_USER);
|
||
|
||
expect(rooms).toEqual(["!test3:example.com"]);
|
||
});
|
||
|
||
it("works with a paginated response", async () => {
|
||
fetchMock.get("express:/_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms", (rawUrl) => {
|
||
const url = new URL(rawUrl);
|
||
|
||
expect(url.searchParams.get("user_id")).toEqual(QUERIED_USER);
|
||
|
||
const token = url.searchParams.get("batch_token");
|
||
|
||
if (token == "yahaha") {
|
||
return {
|
||
joined: ["!korok:example.com"],
|
||
};
|
||
} else {
|
||
return {
|
||
joined: ["!rock:example.com"],
|
||
next_batch_token: "yahaha",
|
||
};
|
||
}
|
||
});
|
||
|
||
const rooms = await client._unstable_getSharedRooms(QUERIED_USER);
|
||
|
||
expect(rooms).toEqual(["!rock:example.com", "!korok:example.com"]);
|
||
});
|
||
});
|
||
});
|