From 5cece105524c7411998f2ce9ebce707ac2d13d95 Mon Sep 17 00:00:00 2001 From: Kerry Date: Wed, 4 May 2022 11:29:13 +0200 Subject: [PATCH] test typescriptification - Permalinks (#8481) * test/utils/permalinks/Permalinks-test.js -> test/utils/permalinks/Permalinks-test.ts Signed-off-by: Kerry Archibald * fix ts issues in Permalinks Signed-off-by: Kerry Archibald --- test/utils/permalinks/Permalinks-test.js | 465 ----------------------- test/utils/permalinks/Permalinks-test.ts | 378 ++++++++++++++++++ 2 files changed, 378 insertions(+), 465 deletions(-) delete mode 100644 test/utils/permalinks/Permalinks-test.js create mode 100644 test/utils/permalinks/Permalinks-test.ts diff --git a/test/utils/permalinks/Permalinks-test.js b/test/utils/permalinks/Permalinks-test.js deleted file mode 100644 index ddca34fb76..0000000000 --- a/test/utils/permalinks/Permalinks-test.js +++ /dev/null @@ -1,465 +0,0 @@ -/* -Copyright 2018 New Vector Ltd -Copyright 2019 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 { MatrixClientPeg as peg } from '../../../src/MatrixClientPeg'; -import { - makeRoomPermalink, - makeUserPermalink, - parsePermalink, - RoomPermalinkCreator, -} from "../../../src/utils/permalinks/Permalinks"; -import * as testUtils from "../../test-utils"; - -function mockRoom(roomId, members, serverACL) { - members.forEach(m => m.membership = "join"); - const powerLevelsUsers = members.reduce((pl, member) => { - if (Number.isFinite(member.powerLevel)) { - pl[member.userId] = member.powerLevel; - } - return pl; - }, {}); - - return { - roomId, - getCanonicalAlias: () => null, - getJoinedMembers: () => members, - getMember: (userId) => members.find(m => m.userId === userId), - currentState: { - getStateEvents: (type, key) => { - if (key) { - return null; - } - let content; - switch (type) { - case "m.room.server_acl": - content = serverACL; - break; - case "m.room.power_levels": - content = { users: powerLevelsUsers, users_default: 0 }; - break; - } - if (content) { - return { - getContent: () => content, - }; - } else { - return null; - } - }, - }, - on: () => undefined, - removeListener: () => undefined, - }; -} - -describe('Permalinks', function() { - beforeEach(function() { - testUtils.stubClient(); - peg.get().credentials = { userId: "@test:example.com" }; - }); - - it('should pick no candidate servers when the room has no members', function() { - const room = mockRoom("!fake:example.org", []); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(0); - }); - - it('should pick a candidate server for the highest power level user in the room', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:pl_50", - powerLevel: 50, - }, - { - userId: "@alice:pl_75", - powerLevel: 75, - }, - { - userId: "@alice:pl_95", - powerLevel: 95, - }, - ]); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(3); - expect(creator._serverCandidates[0]).toBe("pl_95"); - // we don't check the 2nd and 3rd servers because that is done by the next test - }); - - it('should change candidate server when highest power level user leaves the room', function() { - const roomId = "!fake:example.org"; - const member95 = { - userId: "@alice:pl_95", - powerLevel: 95, - roomId, - }; - const room = mockRoom(roomId, [ - { - userId: "@alice:pl_50", - powerLevel: 50, - roomId, - }, - { - userId: "@alice:pl_75", - powerLevel: 75, - roomId, - }, - member95, - ]); - const creator = new RoomPermalinkCreator(room, null); - creator.load(); - expect(creator._serverCandidates[0]).toBe("pl_95"); - member95.membership = "left"; - creator.onRoomStateUpdate(); - expect(creator._serverCandidates[0]).toBe("pl_75"); - member95.membership = "join"; - creator.onRoomStateUpdate(); - expect(creator._serverCandidates[0]).toBe("pl_95"); - }); - - it('should pick candidate servers based on user population', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:first", - powerLevel: 0, - }, - { - userId: "@bob:first", - powerLevel: 0, - }, - { - userId: "@charlie:first", - powerLevel: 0, - }, - { - userId: "@alice:second", - powerLevel: 0, - }, - { - userId: "@bob:second", - powerLevel: 0, - }, - { - userId: "@charlie:third", - powerLevel: 0, - }, - ]); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(3); - expect(creator._serverCandidates[0]).toBe("first"); - expect(creator._serverCandidates[1]).toBe("second"); - expect(creator._serverCandidates[2]).toBe("third"); - }); - - it('should pick prefer candidate servers with higher power levels', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:first", - powerLevel: 100, - }, - { - userId: "@alice:second", - powerLevel: 0, - }, - { - userId: "@bob:second", - powerLevel: 0, - }, - { - userId: "@charlie:third", - powerLevel: 0, - }, - ]); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates.length).toBe(3); - expect(creator._serverCandidates[0]).toBe("first"); - expect(creator._serverCandidates[1]).toBe("second"); - expect(creator._serverCandidates[2]).toBe("third"); - }); - - it('should pick a maximum of 3 candidate servers', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:alpha", - powerLevel: 100, - }, - { - userId: "@alice:bravo", - powerLevel: 0, - }, - { - userId: "@alice:charlie", - powerLevel: 0, - }, - { - userId: "@alice:delta", - powerLevel: 0, - }, - { - userId: "@alice:echo", - powerLevel: 0, - }, - ]); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(3); - }); - - it('should not consider IPv4 hosts', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:127.0.0.1", - powerLevel: 100, - }, - ]); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(0); - }); - - it('should not consider IPv6 hosts', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:[::1]", - powerLevel: 100, - }, - ]); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(0); - }); - - it('should not consider IPv4 hostnames with ports', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:127.0.0.1:8448", - powerLevel: 100, - }, - ]); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(0); - }); - - it('should not consider IPv6 hostnames with ports', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:[::1]:8448", - powerLevel: 100, - }, - ]); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(0); - }); - - it('should work with hostnames with ports', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:example.org:8448", - powerLevel: 100, - }, - ]); - - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(1); - expect(creator._serverCandidates[0]).toBe("example.org:8448"); - }); - - it('should not consider servers explicitly denied by ACLs', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:evilcorp.com", - powerLevel: 100, - }, - { - userId: "@bob:chat.evilcorp.com", - powerLevel: 0, - }, - ], { - deny: ["evilcorp.com", "*.evilcorp.com"], - allow: ["*"], - }); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(0); - }); - - it('should not consider servers not allowed by ACLs', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:evilcorp.com", - powerLevel: 100, - }, - { - userId: "@bob:chat.evilcorp.com", - powerLevel: 0, - }, - ], { - deny: [], - allow: [], // implies "ban everyone" - }); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(0); - }); - - it('should consider servers not explicitly banned by ACLs', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:evilcorp.com", - powerLevel: 100, - }, - { - userId: "@bob:chat.evilcorp.com", - powerLevel: 0, - }, - ], { - deny: ["*.evilcorp.com"], // evilcorp.com is still good though - allow: ["*"], - }); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(1); - expect(creator._serverCandidates[0]).toEqual("evilcorp.com"); - }); - - it('should consider servers not disallowed by ACLs', function() { - const room = mockRoom("!fake:example.org", [ - { - userId: "@alice:evilcorp.com", - powerLevel: 100, - }, - { - userId: "@bob:chat.evilcorp.com", - powerLevel: 0, - }, - ], { - deny: [], - allow: ["evilcorp.com"], // implies "ban everyone else" - }); - const creator = new RoomPermalinkCreator(room); - creator.load(); - expect(creator._serverCandidates).toBeTruthy(); - expect(creator._serverCandidates.length).toBe(1); - expect(creator._serverCandidates[0]).toEqual("evilcorp.com"); - }); - - it('should generate an event permalink for room IDs with no candidate servers', function() { - const room = mockRoom("!somewhere:example.org", []); - const creator = new RoomPermalinkCreator(room); - creator.load(); - const result = creator.forEvent("$something:example.com"); - expect(result).toBe("https://matrix.to/#/!somewhere:example.org/$something:example.com"); - }); - - it('should generate an event permalink for room IDs with some candidate servers', function() { - const room = mockRoom("!somewhere:example.org", [ - { - userId: "@alice:first", - powerLevel: 100, - }, - { - userId: "@bob:second", - powerLevel: 0, - }, - ]); - const creator = new RoomPermalinkCreator(room); - creator.load(); - const result = creator.forEvent("$something:example.com"); - expect(result).toBe("https://matrix.to/#/!somewhere:example.org/$something:example.com?via=first&via=second"); - }); - - it('should generate a room permalink for room IDs with some candidate servers', function() { - peg.get().getRoom = (roomId) => { - return mockRoom(roomId, [ - { - userId: "@alice:first", - powerLevel: 100, - }, - { - userId: "@bob:second", - powerLevel: 0, - }, - ]); - }; - const result = makeRoomPermalink("!somewhere:example.org"); - expect(result).toBe("https://matrix.to/#/!somewhere:example.org?via=first&via=second"); - }); - - it('should generate a room permalink for room aliases with no candidate servers', function() { - peg.get().getRoom = () => null; - const result = makeRoomPermalink("#somewhere:example.org"); - expect(result).toBe("https://matrix.to/#/#somewhere:example.org"); - }); - - it('should generate a room permalink for room aliases without candidate servers', function() { - peg.get().getRoom = (roomId) => { - return mockRoom(roomId, [ - { - userId: "@alice:first", - powerLevel: 100, - }, - { - userId: "@bob:second", - powerLevel: 0, - }, - ]); - }; - const result = makeRoomPermalink("#somewhere:example.org"); - expect(result).toBe("https://matrix.to/#/#somewhere:example.org"); - }); - - it('should generate a user permalink', function() { - const result = makeUserPermalink("@someone:example.org"); - expect(result).toBe("https://matrix.to/#/@someone:example.org"); - }); - - it('should correctly parse room permalinks with a via argument', () => { - const result = parsePermalink("https://matrix.to/#/!room_id:server?via=some.org"); - expect(result.roomIdOrAlias).toBe("!room_id:server"); - expect(result.viaServers).toEqual(["some.org"]); - }); - - it('should correctly parse room permalink via arguments', () => { - const result = parsePermalink("https://matrix.to/#/!room_id:server?via=foo.bar&via=bar.foo"); - expect(result.roomIdOrAlias).toBe("!room_id:server"); - expect(result.viaServers).toEqual(["foo.bar", "bar.foo"]); - }); - - it('should correctly parse event permalink via arguments', () => { - const result = parsePermalink("https://matrix.to/#/!room_id:server/$event_id/some_thing_here/foobar" + - "?via=m1.org&via=m2.org"); - expect(result.eventId).toBe("$event_id/some_thing_here/foobar"); - expect(result.roomIdOrAlias).toBe("!room_id:server"); - expect(result.viaServers).toEqual(["m1.org", "m2.org"]); - }); -}); diff --git a/test/utils/permalinks/Permalinks-test.ts b/test/utils/permalinks/Permalinks-test.ts new file mode 100644 index 0000000000..0c1104d285 --- /dev/null +++ b/test/utils/permalinks/Permalinks-test.ts @@ -0,0 +1,378 @@ +/* +Copyright 2018 New Vector Ltd +Copyright 2019, 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 { + Room, + RoomMember, + EventType, + MatrixEvent, +} from 'matrix-js-sdk/src/matrix'; + +import { MatrixClientPeg } from '../../../src/MatrixClientPeg'; +import { + makeRoomPermalink, + makeUserPermalink, + parsePermalink, + RoomPermalinkCreator, +} from "../../../src/utils/permalinks/Permalinks"; +import { getMockClientWithEventEmitter } from '../../test-utils'; + +describe('Permalinks', function() { + const userId = '@test:example.com'; + const mockClient = getMockClientWithEventEmitter({ + getUserId: jest.fn().mockReturnValue(userId), + getRoom: jest.fn(), + }); + mockClient.credentials = { userId }; + + const makeMemberWithPL = (roomId: Room['roomId'], userId: string, powerLevel: number): RoomMember => { + const member = new RoomMember(roomId, userId); + member.powerLevel = powerLevel; + return member; + }; + + function mockRoom( + roomId: Room['roomId'], members: RoomMember[], serverACLContent?: { deny?: string[], allow?: string[]}, + ): Room { + members.forEach(m => m.membership = "join"); + const powerLevelsUsers = members.reduce((pl, member) => { + if (Number.isFinite(member.powerLevel)) { + pl[member.userId] = member.powerLevel; + } + return pl; + }, {}); + + const room = new Room(roomId, mockClient, userId); + + const powerLevels = new MatrixEvent({ + type: EventType.RoomPowerLevels, + room_id: roomId, + state_key: '', + content: { + users: powerLevelsUsers, users_default: 0, + }, + }); + const serverACL = serverACLContent ? new MatrixEvent({ + type: EventType.RoomServerAcl, + room_id: roomId, + state_key: '', + content: serverACLContent, + }) : undefined; + const stateEvents = serverACL ? [powerLevels, serverACL] : [powerLevels]; + room.currentState.setStateEvents(stateEvents); + + jest.spyOn(room, 'getCanonicalAlias').mockReturnValue(null); + jest.spyOn(room, 'getJoinedMembers').mockReturnValue(members); + jest.spyOn(room, 'getMember').mockImplementation((userId) => members.find(m => m.userId === userId)); + + return room; + } + beforeEach(function() { + jest.clearAllMocks(); + }); + + afterAll(() => { + jest.spyOn(MatrixClientPeg, 'get').mockRestore(); + }); + + it('should pick no candidate servers when the room has no members', function() { + const room = mockRoom("!fake:example.org", []); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(0); + }); + + it('should pick a candidate server for the highest power level user in the room', function() { + const roomId = "!fake:example.org"; + const alice50 = makeMemberWithPL(roomId, "@alice:pl_50", 50); + const alice75 = makeMemberWithPL(roomId, "@alice:pl_75", 75); + const alice95 = makeMemberWithPL(roomId, "@alice:pl_95", 95); + const room = mockRoom("!fake:example.org", [ + alice50, + alice75, + alice95, + ]); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(3); + expect(creator.serverCandidates[0]).toBe("pl_95"); + // we don't check the 2nd and 3rd servers because that is done by the next test + }); + + it('should change candidate server when highest power level user leaves the room', function() { + const roomId = "!fake:example.org"; + const member95 = makeMemberWithPL(roomId, "@alice:pl_95", 95); + + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:pl_50", 50), + makeMemberWithPL(roomId, "@alice:pl_75", 75), + member95, + ]); + const creator = new RoomPermalinkCreator(room, null); + creator.load(); + expect(creator.serverCandidates[0]).toBe("pl_95"); + member95.membership = "left"; + // @ts-ignore illegal private property + creator.onRoomStateUpdate(); + expect(creator.serverCandidates[0]).toBe("pl_75"); + member95.membership = "join"; + // @ts-ignore illegal private property + creator.onRoomStateUpdate(); + expect(creator.serverCandidates[0]).toBe("pl_95"); + }); + + it('should pick candidate servers based on user population', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:first", 0), + makeMemberWithPL(roomId, "@bob:first", 0), + makeMemberWithPL(roomId, "@charlie:first", 0), + makeMemberWithPL(roomId, "@alice:second", 0), + makeMemberWithPL(roomId, "@bob:second", 0), + makeMemberWithPL(roomId, "@charlie:third", 0), + ]); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(3); + expect(creator.serverCandidates[0]).toBe("first"); + expect(creator.serverCandidates[1]).toBe("second"); + expect(creator.serverCandidates[2]).toBe("third"); + }); + + it('should pick prefer candidate servers with higher power levels', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:first", 100), + makeMemberWithPL(roomId, "@alice:second", 0), + makeMemberWithPL(roomId, "@bob:second", 0), + makeMemberWithPL(roomId, "@charlie:third", 0), + ]); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates.length).toBe(3); + expect(creator.serverCandidates[0]).toBe("first"); + expect(creator.serverCandidates[1]).toBe("second"); + expect(creator.serverCandidates[2]).toBe("third"); + }); + + it('should pick a maximum of 3 candidate servers', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:alpha", 100), + makeMemberWithPL(roomId, "@alice:bravo", 0), + makeMemberWithPL(roomId, "@alice:charlie", 0), + makeMemberWithPL(roomId, "@alice:delta", 0), + makeMemberWithPL(roomId, "@alice:echo", 0), + ]); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(3); + }); + + it('should not consider IPv4 hosts', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:127.0.0.1", 100), + ]); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(0); + }); + + it('should not consider IPv6 hosts', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:[::1]", 100), + ]); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(0); + }); + + it('should not consider IPv4 hostnames with ports', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:127.0.0.1:8448", 100), + ]); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(0); + }); + + it('should not consider IPv6 hostnames with ports', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:[::1]:8448", 100), + ]); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(0); + }); + + it('should work with hostnames with ports', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:example.org:8448", 100), + ]); + + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(1); + expect(creator.serverCandidates[0]).toBe("example.org:8448"); + }); + + it('should not consider servers explicitly denied by ACLs', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:evilcorp.com", 100), + makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0), + ], { + deny: ["evilcorp.com", "*.evilcorp.com"], + allow: ["*"], + }); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(0); + }); + + it('should not consider servers not allowed by ACLs', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:evilcorp.com", 100), + makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0), + ], { + deny: [], + allow: [], // implies "ban everyone" + }); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(0); + }); + + it('should consider servers not explicitly banned by ACLs', function() { + const roomId = "!fake:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:evilcorp.com", 100), + makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0), + ], { + deny: ["*.evilcorp.com"], // evilcorp.com is still good though + allow: ["*"], + }); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(1); + expect(creator.serverCandidates[0]).toEqual("evilcorp.com"); + }); + + it('should consider servers not disallowed by ACLs', function() { + const roomId = "!fake:example.org"; + const room = mockRoom("!fake:example.org", [ + makeMemberWithPL(roomId, "@alice:evilcorp.com", 100), + makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0), + ], { + deny: [], + allow: ["evilcorp.com"], // implies "ban everyone else" + }); + const creator = new RoomPermalinkCreator(room); + creator.load(); + expect(creator.serverCandidates).toBeTruthy(); + expect(creator.serverCandidates.length).toBe(1); + expect(creator.serverCandidates[0]).toEqual("evilcorp.com"); + }); + + it('should generate an event permalink for room IDs with no candidate servers', function() { + const room = mockRoom("!somewhere:example.org", []); + const creator = new RoomPermalinkCreator(room); + creator.load(); + const result = creator.forEvent("$something:example.com"); + expect(result).toBe("https://matrix.to/#/!somewhere:example.org/$something:example.com"); + }); + + it('should generate an event permalink for room IDs with some candidate servers', function() { + const roomId = "!somewhere:example.org"; + const room = mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:first", 100), + makeMemberWithPL(roomId, "@bob:second", 0), + ]); + const creator = new RoomPermalinkCreator(room); + creator.load(); + const result = creator.forEvent("$something:example.com"); + expect(result).toBe("https://matrix.to/#/!somewhere:example.org/$something:example.com?via=first&via=second"); + }); + + it('should generate a room permalink for room IDs with some candidate servers', function() { + mockClient.getRoom.mockImplementation((roomId: Room['roomId']) => { + return mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:first", 100), + makeMemberWithPL(roomId, "@bob:second", 0), + ]); + }); + const result = makeRoomPermalink("!somewhere:example.org"); + expect(result).toBe("https://matrix.to/#/!somewhere:example.org?via=first&via=second"); + }); + + it('should generate a room permalink for room aliases with no candidate servers', function() { + mockClient.getRoom.mockReturnValue(null); + const result = makeRoomPermalink("#somewhere:example.org"); + expect(result).toBe("https://matrix.to/#/#somewhere:example.org"); + }); + + it('should generate a room permalink for room aliases without candidate servers', function() { + mockClient.getRoom.mockImplementation((roomId: Room['roomId']) => { + return mockRoom(roomId, [ + makeMemberWithPL(roomId, "@alice:first", 100), + makeMemberWithPL(roomId, "@bob:second", 0), + ]); + }); + const result = makeRoomPermalink("#somewhere:example.org"); + expect(result).toBe("https://matrix.to/#/#somewhere:example.org"); + }); + + it('should generate a user permalink', function() { + const result = makeUserPermalink("@someone:example.org"); + expect(result).toBe("https://matrix.to/#/@someone:example.org"); + }); + + it('should correctly parse room permalinks with a via argument', () => { + const result = parsePermalink("https://matrix.to/#/!room_id:server?via=some.org"); + expect(result.roomIdOrAlias).toBe("!room_id:server"); + expect(result.viaServers).toEqual(["some.org"]); + }); + + it('should correctly parse room permalink via arguments', () => { + const result = parsePermalink("https://matrix.to/#/!room_id:server?via=foo.bar&via=bar.foo"); + expect(result.roomIdOrAlias).toBe("!room_id:server"); + expect(result.viaServers).toEqual(["foo.bar", "bar.foo"]); + }); + + it('should correctly parse event permalink via arguments', () => { + const result = parsePermalink("https://matrix.to/#/!room_id:server/$event_id/some_thing_here/foobar" + + "?via=m1.org&via=m2.org"); + expect(result.eventId).toBe("$event_id/some_thing_here/foobar"); + expect(result.roomIdOrAlias).toBe("!room_id:server"); + expect(result.viaServers).toEqual(["m1.org", "m2.org"]); + }); +});