Remove virtual rooms (#29635)
* Remove virtual rooms from the timelinePanel and RoomView * Remove VoipUserMapper * Remove some unneeded imports * Remove tovirtual slash command test * Remove getSupportsVirtualRooms and virtualLookup * lint * Remove PROTOCOL_SIP_NATIVE * Remove native/virtual looks fields and fix tests * Remove unused lookup fields
This commit is contained in:
@@ -29,8 +29,6 @@ import LegacyCallHandler, {
|
||||
LegacyCallHandlerEvent,
|
||||
PROTOCOL_PSTN,
|
||||
PROTOCOL_PSTN_PREFIXED,
|
||||
PROTOCOL_SIP_NATIVE,
|
||||
PROTOCOL_SIP_VIRTUAL,
|
||||
} from "../../src/LegacyCallHandler";
|
||||
import { mkStubRoom, stubClient, untilDispatch } from "../test-utils";
|
||||
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
||||
@@ -75,9 +73,6 @@ const NATIVE_ALICE = "@alice:example.org";
|
||||
const NATIVE_BOB = "@bob:example.org";
|
||||
const NATIVE_CHARLIE = "@charlie:example.org";
|
||||
|
||||
// Virtual user for Bob
|
||||
const VIRTUAL_BOB = "@virtual_bob:example.org";
|
||||
|
||||
//const REAL_ROOM_ID = "$room1:example.org";
|
||||
// The rooms the user sees when they're communicating with these users
|
||||
const NATIVE_ROOM_ALICE = "$alice_room:example.org";
|
||||
@@ -86,10 +81,6 @@ const NATIVE_ROOM_CHARLIE = "$charlie_room:example.org";
|
||||
|
||||
const FUNCTIONAL_USER = "@bot:example.com";
|
||||
|
||||
// The room we use to talk to virtual Bob (but that the user does not see)
|
||||
// Bob has a virtual room, but Alice doesn't
|
||||
const VIRTUAL_ROOM_BOB = "$virtual_bob_room:example.org";
|
||||
|
||||
// Bob's phone number
|
||||
const BOB_PHONE_NUMBER = "01818118181";
|
||||
|
||||
@@ -146,14 +137,6 @@ class FakeCall extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
function untilCallHandlerEvent(callHandler: LegacyCallHandler, event: LegacyCallHandlerEvent): Promise<void> {
|
||||
return new Promise<void>((resolve) => {
|
||||
callHandler.addListener(event, () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe("LegacyCallHandler", () => {
|
||||
let dmRoomMap;
|
||||
let callHandler: LegacyCallHandler;
|
||||
@@ -162,7 +145,6 @@ describe("LegacyCallHandler", () => {
|
||||
|
||||
// what addresses the app has looked up via pstn and native lookup
|
||||
let pstnLookup: string | null;
|
||||
let nativeLookup: string | null;
|
||||
const deviceId = "my-device";
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -180,8 +162,6 @@ describe("LegacyCallHandler", () => {
|
||||
MatrixClientPeg.safeGet().getThirdpartyProtocols = () => {
|
||||
return Promise.resolve({
|
||||
"m.id.phone": {} as IProtocol,
|
||||
"im.vector.protocol.sip_native": {} as IProtocol,
|
||||
"im.vector.protocol.sip_virtual": {} as IProtocol,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -193,7 +173,6 @@ describe("LegacyCallHandler", () => {
|
||||
const nativeRoomAlice = mkStubDM(NATIVE_ROOM_ALICE, NATIVE_ALICE);
|
||||
const nativeRoomBob = mkStubDM(NATIVE_ROOM_BOB, NATIVE_BOB);
|
||||
const nativeRoomCharie = mkStubDM(NATIVE_ROOM_CHARLIE, NATIVE_CHARLIE);
|
||||
const virtualBobRoom = mkStubDM(VIRTUAL_ROOM_BOB, VIRTUAL_BOB);
|
||||
|
||||
MatrixClientPeg.safeGet().getRoom = (roomId: string): Room | null => {
|
||||
switch (roomId) {
|
||||
@@ -203,8 +182,6 @@ describe("LegacyCallHandler", () => {
|
||||
return nativeRoomBob;
|
||||
case NATIVE_ROOM_CHARLIE:
|
||||
return nativeRoomCharie;
|
||||
case VIRTUAL_ROOM_BOB:
|
||||
return virtualBobRoom;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -218,8 +195,6 @@ describe("LegacyCallHandler", () => {
|
||||
return NATIVE_BOB;
|
||||
} else if (roomId === NATIVE_ROOM_CHARLIE) {
|
||||
return NATIVE_CHARLIE;
|
||||
} else if (roomId === VIRTUAL_ROOM_BOB) {
|
||||
return VIRTUAL_BOB;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -231,8 +206,6 @@ describe("LegacyCallHandler", () => {
|
||||
return [NATIVE_ROOM_BOB];
|
||||
} else if (userId === NATIVE_CHARLIE) {
|
||||
return [NATIVE_ROOM_CHARLIE];
|
||||
} else if (userId === VIRTUAL_BOB) {
|
||||
return [VIRTUAL_ROOM_BOB];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@@ -241,52 +214,18 @@ describe("LegacyCallHandler", () => {
|
||||
DMRoomMap.setShared(dmRoomMap);
|
||||
|
||||
pstnLookup = null;
|
||||
nativeLookup = null;
|
||||
|
||||
MatrixClientPeg.safeGet().getThirdpartyUser = (proto: string, params: any) => {
|
||||
if ([PROTOCOL_PSTN, PROTOCOL_PSTN_PREFIXED].includes(proto)) {
|
||||
pstnLookup = params["m.id.phone"];
|
||||
return Promise.resolve([
|
||||
{
|
||||
userid: VIRTUAL_BOB,
|
||||
userid: NATIVE_BOB,
|
||||
protocol: "m.id.phone",
|
||||
fields: {
|
||||
is_native: true,
|
||||
lookup_success: true,
|
||||
},
|
||||
fields: {},
|
||||
},
|
||||
]);
|
||||
} else if (proto === PROTOCOL_SIP_NATIVE) {
|
||||
nativeLookup = params["virtual_mxid"];
|
||||
if (params["virtual_mxid"] === VIRTUAL_BOB) {
|
||||
return Promise.resolve([
|
||||
{
|
||||
userid: NATIVE_BOB,
|
||||
protocol: "im.vector.protocol.sip_native",
|
||||
fields: {
|
||||
is_native: true,
|
||||
lookup_success: true,
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
} else if (proto === PROTOCOL_SIP_VIRTUAL) {
|
||||
if (params["native_mxid"] === NATIVE_BOB) {
|
||||
return Promise.resolve([
|
||||
{
|
||||
userid: VIRTUAL_BOB,
|
||||
protocol: "im.vector.protocol.sip_virtual",
|
||||
fields: {
|
||||
is_virtual: true,
|
||||
lookup_success: true,
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
|
||||
@@ -312,16 +251,14 @@ describe("LegacyCallHandler", () => {
|
||||
await callHandler.dialNumber(BOB_PHONE_NUMBER);
|
||||
|
||||
expect(pstnLookup).toEqual(BOB_PHONE_NUMBER);
|
||||
expect(nativeLookup).toEqual(VIRTUAL_BOB);
|
||||
|
||||
// we should have switched to the native room for Bob
|
||||
const viewRoomPayload = await untilDispatch(Action.ViewRoom);
|
||||
expect(viewRoomPayload.room_id).toEqual(NATIVE_ROOM_BOB);
|
||||
|
||||
// Check that a call was started: its room on the protocol level
|
||||
// should be the virtual room
|
||||
expect(fakeCall).not.toBeNull();
|
||||
expect(fakeCall?.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
expect(fakeCall?.roomId).toEqual(NATIVE_ROOM_BOB);
|
||||
|
||||
// but it should appear to the user to be in thw native room for Bob
|
||||
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB);
|
||||
@@ -338,7 +275,7 @@ describe("LegacyCallHandler", () => {
|
||||
expect(viewRoomPayload.room_id).toEqual(NATIVE_ROOM_BOB);
|
||||
|
||||
expect(fakeCall).not.toBeNull();
|
||||
expect(fakeCall!.roomId).toEqual(VIRTUAL_ROOM_BOB);
|
||||
expect(fakeCall!.roomId).toEqual(NATIVE_ROOM_BOB);
|
||||
|
||||
expect(callHandler.roomIdForCall(fakeCall!)).toEqual(NATIVE_ROOM_BOB);
|
||||
});
|
||||
@@ -346,8 +283,6 @@ describe("LegacyCallHandler", () => {
|
||||
it("should move calls between rooms when remote asserted identity changes", async () => {
|
||||
callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice);
|
||||
|
||||
await untilCallHandlerEvent(callHandler, LegacyCallHandlerEvent.CallState);
|
||||
|
||||
// We placed the call in Alice's room so it should start off there
|
||||
expect(callHandler.getCallForRoom(NATIVE_ROOM_ALICE)).toBe(fakeCall);
|
||||
|
||||
@@ -517,10 +452,7 @@ describe("LegacyCallHandler without third party protocols", () => {
|
||||
it("should still start a native call", async () => {
|
||||
callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice);
|
||||
|
||||
await untilCallHandlerEvent(callHandler, LegacyCallHandlerEvent.CallState);
|
||||
|
||||
// Check that a call was started: its room on the protocol level
|
||||
// should be the virtual room
|
||||
expect(fakeCall).not.toBeNull();
|
||||
expect(fakeCall!.roomId).toEqual(NATIVE_ROOM_ALICE);
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import { type Command, Commands, getCommand } from "../../src/SlashCommands";
|
||||
import { createTestClient } from "../test-utils";
|
||||
import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../src/models/LocalRoom";
|
||||
import SettingsStore from "../../src/settings/SettingsStore";
|
||||
import LegacyCallHandler from "../../src/LegacyCallHandler";
|
||||
import { SdkContextClass } from "../../src/contexts/SDKContext";
|
||||
import Modal from "../../src/Modal";
|
||||
import WidgetUtils from "../../src/utils/WidgetUtils";
|
||||
@@ -196,46 +195,6 @@ describe("SlashCommands", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("/tovirtual", () => {
|
||||
beforeEach(() => {
|
||||
command = findCommand("tovirtual")!;
|
||||
});
|
||||
|
||||
describe("isEnabled", () => {
|
||||
describe("when virtual rooms are supported", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(LegacyCallHandler.instance, "getSupportsVirtualRooms").mockReturnValue(true);
|
||||
});
|
||||
|
||||
it("should return true for Room", () => {
|
||||
setCurrentRoom();
|
||||
expect(command.isEnabled(client)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for LocalRoom", () => {
|
||||
setCurrentLocalRoom();
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when virtual rooms are not supported", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(LegacyCallHandler.instance, "getSupportsVirtualRooms").mockReturnValue(false);
|
||||
});
|
||||
|
||||
it("should return false for Room", () => {
|
||||
setCurrentRoom();
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false for LocalRoom", () => {
|
||||
setCurrentLocalRoom();
|
||||
expect(command.isEnabled(client)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("/part", () => {
|
||||
it("should part room matching alias if found", async () => {
|
||||
const room1 = new Room("room-id", client, client.getSafeUserId());
|
||||
|
||||
@@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { createRef, type RefObject } from "react";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import {
|
||||
ClientEvent,
|
||||
EventTimeline,
|
||||
EventType,
|
||||
type IEvent,
|
||||
@@ -68,7 +67,6 @@ import { DirectoryMember } from "../../../../src/utils/direct-messages";
|
||||
import { createDmLocalRoom } from "../../../../src/utils/dm/createDmLocalRoom";
|
||||
import { UPDATE_EVENT } from "../../../../src/stores/AsyncStore";
|
||||
import { SDKContext, SdkContextClass } from "../../../../src/contexts/SDKContext";
|
||||
import VoipUserMapper from "../../../../src/VoipUserMapper";
|
||||
import WidgetUtils from "../../../../src/utils/WidgetUtils";
|
||||
import { WidgetType } from "../../../../src/widgets/WidgetType";
|
||||
import WidgetStore from "../../../../src/stores/WidgetStore";
|
||||
@@ -119,7 +117,6 @@ describe("RoomView", () => {
|
||||
stores.client = cli;
|
||||
stores.rightPanelStore.useUnitTestClient(cli);
|
||||
|
||||
jest.spyOn(VoipUserMapper.sharedInstance(), "getVirtualRoomForRoom").mockResolvedValue(undefined);
|
||||
crypto = cli.getCrypto()!;
|
||||
jest.spyOn(cli, "getCrypto").mockReturnValue(undefined);
|
||||
});
|
||||
@@ -417,26 +414,6 @@ describe("RoomView", () => {
|
||||
await waitFor(() => expect(container.querySelector(".mx_E2EIcon_verified")).toBeInTheDocument());
|
||||
});
|
||||
|
||||
describe("with virtual rooms", () => {
|
||||
it("checks for a virtual room on initial load", async () => {
|
||||
const { container } = await renderRoomView();
|
||||
expect(VoipUserMapper.sharedInstance().getVirtualRoomForRoom).toHaveBeenCalledWith(room.roomId);
|
||||
|
||||
// quick check that rendered without error
|
||||
expect(container.querySelector(".mx_ErrorBoundary")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("checks for a virtual room on room event", async () => {
|
||||
await renderRoomView();
|
||||
expect(VoipUserMapper.sharedInstance().getVirtualRoomForRoom).toHaveBeenCalledWith(room.roomId);
|
||||
|
||||
act(() => cli.emit(ClientEvent.Room, room));
|
||||
|
||||
// called again after room event
|
||||
expect(VoipUserMapper.sharedInstance().getVirtualRoomForRoom).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("video rooms", () => {
|
||||
beforeEach(async () => {
|
||||
await setupAsyncStoreWithClient(CallStore.instance, MatrixClientPeg.safeGet());
|
||||
|
||||
@@ -35,7 +35,6 @@ import { forEachRight } from "lodash";
|
||||
import TimelinePanel from "../../../../src/components/structures/TimelinePanel";
|
||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import { isCallEvent } from "../../../../src/components/structures/LegacyCallEventGrouper";
|
||||
import {
|
||||
filterConsole,
|
||||
flushPromises,
|
||||
@@ -115,22 +114,6 @@ const setupTestData = (): [MatrixClient, Room, MatrixEvent[]] => {
|
||||
return [client, room, events];
|
||||
};
|
||||
|
||||
const setupOverlayTestData = (client: MatrixClient, mainEvents: MatrixEvent[]): [Room, MatrixEvent[]] => {
|
||||
const virtualRoom = mkRoom(client, "virtualRoomId");
|
||||
const overlayEvents = mockEvents(virtualRoom, 5);
|
||||
|
||||
// Set the event order that we'll be looking for in the timeline
|
||||
overlayEvents[0].localTimestamp = 1000;
|
||||
mainEvents[0].localTimestamp = 2000;
|
||||
overlayEvents[1].localTimestamp = 3000;
|
||||
overlayEvents[2].localTimestamp = 4000;
|
||||
overlayEvents[3].localTimestamp = 5000;
|
||||
mainEvents[1].localTimestamp = 6000;
|
||||
overlayEvents[4].localTimestamp = 7000;
|
||||
|
||||
return [virtualRoom, overlayEvents];
|
||||
};
|
||||
|
||||
const expectEvents = (container: HTMLElement, events: MatrixEvent[]): void => {
|
||||
const eventTiles = container.querySelectorAll(".mx_EventTile");
|
||||
const eventTileIds = [...eventTiles].map((tileElement) => tileElement.getAttribute("data-event-id"));
|
||||
@@ -518,298 +501,6 @@ describe("TimelinePanel", () => {
|
||||
|
||||
expect(paginateSpy).toHaveBeenCalledWith(EventTimeline.FORWARDS, 1, false);
|
||||
});
|
||||
|
||||
it("advances the overlay timeline window", async () => {
|
||||
const [client, room, events] = setupTestData();
|
||||
|
||||
const virtualRoom = mkRoom(client, "virtualRoomId");
|
||||
const virtualEvents = mockEvents(virtualRoom);
|
||||
const { timelineSet: overlayTimelineSet } = getProps(virtualRoom, virtualEvents);
|
||||
|
||||
const props = {
|
||||
...getProps(room, events),
|
||||
overlayTimelineSet,
|
||||
};
|
||||
|
||||
const paginateSpy = jest.spyOn(TimelineWindow.prototype, "paginate").mockClear();
|
||||
|
||||
render(<TimelinePanel {...props} />);
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const event = new MatrixEvent({ type: RoomEvent.Timeline, origin_server_ts: 0 });
|
||||
const data = { timeline: props.timelineSet.getLiveTimeline(), liveEvent: true };
|
||||
client.emit(RoomEvent.Timeline, event, room, false, false, data);
|
||||
|
||||
await flushPromises();
|
||||
|
||||
expect(paginateSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with overlayTimeline", () => {
|
||||
it("renders merged timeline", async () => {
|
||||
const [client, room, events] = setupTestData();
|
||||
const virtualRoom = mkRoom(client, "virtualRoomId");
|
||||
const virtualCallInvite = new MatrixEvent({
|
||||
type: "m.call.invite",
|
||||
room_id: virtualRoom.roomId,
|
||||
event_id: `virtualCallEvent1`,
|
||||
origin_server_ts: 0,
|
||||
});
|
||||
virtualCallInvite.localTimestamp = 2;
|
||||
const virtualCallMetaEvent = new MatrixEvent({
|
||||
type: "org.matrix.call.sdp_stream_metadata_changed",
|
||||
room_id: virtualRoom.roomId,
|
||||
event_id: `virtualCallEvent2`,
|
||||
origin_server_ts: 0,
|
||||
});
|
||||
virtualCallMetaEvent.localTimestamp = 2;
|
||||
const virtualEvents = [virtualCallInvite, ...mockEvents(virtualRoom), virtualCallMetaEvent];
|
||||
const { timelineSet: overlayTimelineSet } = getProps(virtualRoom, virtualEvents);
|
||||
|
||||
const { container } = render(
|
||||
<TimelinePanel
|
||||
{...getProps(room, events)}
|
||||
overlayTimelineSet={overlayTimelineSet}
|
||||
overlayTimelineSetFilter={isCallEvent}
|
||||
/>,
|
||||
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
|
||||
);
|
||||
await waitFor(() =>
|
||||
expectEvents(container, [
|
||||
// main timeline events are included
|
||||
events[0],
|
||||
events[1],
|
||||
// virtual timeline call event is included
|
||||
virtualCallInvite,
|
||||
// virtual call event has no tile renderer => not rendered
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["when it starts with no overlay events", true],
|
||||
["to get enough overlay events", false],
|
||||
])("expands the initial window %s", async (_s, startWithEmptyOverlayWindow) => {
|
||||
const [client, room, events] = setupTestData();
|
||||
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
|
||||
|
||||
let overlayEventsPage1: MatrixEvent[];
|
||||
let overlayEventsPage2: MatrixEvent[];
|
||||
let overlayEventsPage3: MatrixEvent[];
|
||||
if (startWithEmptyOverlayWindow) {
|
||||
overlayEventsPage1 = overlayEvents.slice(0, 3);
|
||||
overlayEventsPage2 = [];
|
||||
overlayEventsPage3 = overlayEvents.slice(3, 5);
|
||||
} else {
|
||||
overlayEventsPage1 = overlayEvents.slice(0, 2);
|
||||
overlayEventsPage2 = overlayEvents.slice(2, 3);
|
||||
overlayEventsPage3 = overlayEvents.slice(3, 5);
|
||||
}
|
||||
|
||||
// Start with only page 2 of the overlay events in the window
|
||||
const [overlayTimeline, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEventsPage2);
|
||||
setupPagination(client, overlayTimeline, overlayEventsPage1, overlayEventsPage3);
|
||||
|
||||
const { container } = render(
|
||||
<TimelinePanel {...getProps(room, events)} overlayTimelineSet={overlayTimelineSet} />,
|
||||
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expectEvents(container, [
|
||||
overlayEvents[0],
|
||||
events[0],
|
||||
overlayEvents[1],
|
||||
overlayEvents[2],
|
||||
overlayEvents[3],
|
||||
events[1],
|
||||
overlayEvents[4],
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("extends overlay window beyond main window at the start of the timeline", async () => {
|
||||
const [client, room, events] = setupTestData();
|
||||
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
|
||||
// Delete event 0 so the TimelinePanel will still leave some stuff
|
||||
// unloaded for us to test with
|
||||
events.shift();
|
||||
|
||||
const overlayEventsPage1 = overlayEvents.slice(0, 2);
|
||||
const overlayEventsPage2 = overlayEvents.slice(2, 5);
|
||||
|
||||
// Start with only page 2 of the overlay events in the window
|
||||
const [overlayTimeline, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEventsPage2);
|
||||
setupPagination(client, overlayTimeline, overlayEventsPage1, null);
|
||||
|
||||
const { container } = render(
|
||||
<TimelinePanel {...getProps(room, events)} overlayTimelineSet={overlayTimelineSet} />,
|
||||
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expectEvents(container, [
|
||||
// These first two are the newly loaded events
|
||||
overlayEvents[0],
|
||||
overlayEvents[1],
|
||||
overlayEvents[2],
|
||||
overlayEvents[3],
|
||||
events[0],
|
||||
overlayEvents[4],
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("extends overlay window beyond main window at the end of the timeline", async () => {
|
||||
const [client, room, events] = setupTestData();
|
||||
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
|
||||
// Delete event 1 so the TimelinePanel will still leave some stuff
|
||||
// unloaded for us to test with
|
||||
events.pop();
|
||||
|
||||
const overlayEventsPage1 = overlayEvents.slice(0, 2);
|
||||
const overlayEventsPage2 = overlayEvents.slice(2, 5);
|
||||
|
||||
// Start with only page 1 of the overlay events in the window
|
||||
const [overlayTimeline, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEventsPage1);
|
||||
setupPagination(client, overlayTimeline, null, overlayEventsPage2);
|
||||
|
||||
const { container } = render(
|
||||
<TimelinePanel {...getProps(room, events)} overlayTimelineSet={overlayTimelineSet} />,
|
||||
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expectEvents(container, [
|
||||
overlayEvents[0],
|
||||
events[0],
|
||||
overlayEvents[1],
|
||||
// These are the newly loaded events
|
||||
overlayEvents[2],
|
||||
overlayEvents[3],
|
||||
overlayEvents[4],
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("paginates", async () => {
|
||||
const [client, room, events] = setupTestData();
|
||||
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
|
||||
|
||||
const eventsPage1 = events.slice(0, 1);
|
||||
const eventsPage2 = events.slice(1, 2);
|
||||
|
||||
// Start with only page 1 of the main events in the window
|
||||
const [timeline, timelineSet] = mkTimeline(room, eventsPage1);
|
||||
const [, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEvents);
|
||||
setupPagination(client, timeline, null, eventsPage2);
|
||||
|
||||
await withScrollPanelMountSpy(async (mountSpy) => {
|
||||
const { container } = render(
|
||||
<TimelinePanel
|
||||
{...getProps(room, events)}
|
||||
timelineSet={timelineSet}
|
||||
overlayTimelineSet={overlayTimelineSet}
|
||||
/>,
|
||||
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
|
||||
);
|
||||
|
||||
await waitFor(() => expectEvents(container, [overlayEvents[0], events[0]]));
|
||||
|
||||
// ScrollPanel has no chance of working in jsdom, so we've no choice
|
||||
// but to do some shady stuff to trigger the fill callback by hand
|
||||
const scrollPanel = mountSpy.mock.contexts[0] as ScrollPanel;
|
||||
scrollPanel.props.onFillRequest!(false);
|
||||
|
||||
await waitFor(() =>
|
||||
expectEvents(container, [
|
||||
overlayEvents[0],
|
||||
events[0],
|
||||
overlayEvents[1],
|
||||
overlayEvents[2],
|
||||
overlayEvents[3],
|
||||
events[1],
|
||||
overlayEvents[4],
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it.each([
|
||||
["down", "main", true, false],
|
||||
["down", "overlay", true, true],
|
||||
["up", "main", false, false],
|
||||
["up", "overlay", false, true],
|
||||
])("unpaginates %s to an event from the %s timeline", async (_s1, _s2, backwards, fromOverlay) => {
|
||||
const [client, room, events] = setupTestData();
|
||||
const [virtualRoom, overlayEvents] = setupOverlayTestData(client, events);
|
||||
|
||||
let marker: MatrixEvent;
|
||||
let expectedEvents: MatrixEvent[];
|
||||
if (backwards) {
|
||||
if (fromOverlay) {
|
||||
marker = overlayEvents[1];
|
||||
// Overlay events 0−1 and event 0 should be unpaginated
|
||||
// Overlay events 2−3 should be hidden since they're at the edge of the window
|
||||
expectedEvents = [events[1], overlayEvents[4]];
|
||||
} else {
|
||||
marker = events[0];
|
||||
// Overlay event 0 and event 0 should be unpaginated
|
||||
// Overlay events 1−3 should be hidden since they're at the edge of the window
|
||||
expectedEvents = [events[1], overlayEvents[4]];
|
||||
}
|
||||
} else {
|
||||
if (fromOverlay) {
|
||||
marker = overlayEvents[4];
|
||||
// Only the last overlay event should be unpaginated
|
||||
expectedEvents = [
|
||||
overlayEvents[0],
|
||||
events[0],
|
||||
overlayEvents[1],
|
||||
overlayEvents[2],
|
||||
overlayEvents[3],
|
||||
events[1],
|
||||
];
|
||||
} else {
|
||||
// Get rid of overlay event 4 so we can test the case where no overlay events get unpaginated
|
||||
overlayEvents.pop();
|
||||
marker = events[1];
|
||||
// Only event 1 should be unpaginated
|
||||
// Overlay events 1−2 should be hidden since they're at the edge of the window
|
||||
expectedEvents = [overlayEvents[0], events[0]];
|
||||
}
|
||||
}
|
||||
|
||||
const [, overlayTimelineSet] = mkTimeline(virtualRoom, overlayEvents);
|
||||
|
||||
await withScrollPanelMountSpy(async (mountSpy) => {
|
||||
const { container } = render(
|
||||
<TimelinePanel {...getProps(room, events)} overlayTimelineSet={overlayTimelineSet} />,
|
||||
withClientContextRenderOptions(MatrixClientPeg.safeGet()),
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expectEvents(container, [
|
||||
overlayEvents[0],
|
||||
events[0],
|
||||
overlayEvents[1],
|
||||
overlayEvents[2],
|
||||
overlayEvents[3],
|
||||
events[1],
|
||||
...(!backwards && !fromOverlay ? [] : [overlayEvents[4]]),
|
||||
]),
|
||||
);
|
||||
|
||||
// ScrollPanel has no chance of working in jsdom, so we've no choice
|
||||
// but to do some shady stuff to trigger the unfill callback by hand
|
||||
const scrollPanel = mountSpy.mock.contexts[0] as ScrollPanel;
|
||||
scrollPanel.props.onUnfillRequest!(backwards, marker.getId()!);
|
||||
|
||||
await waitFor(() => expectEvents(container, expectedEvents));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when a thread updates", () => {
|
||||
|
||||
@@ -1952,7 +1952,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
aria-label="Open room settings"
|
||||
aria-live="off"
|
||||
class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52"
|
||||
data-color="5"
|
||||
data-color="3"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="button"
|
||||
@@ -1979,7 +1979,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
<span
|
||||
class="mx_RoomHeader_truncated mx_lineClamp"
|
||||
>
|
||||
!18:example.org
|
||||
!16:example.org
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,22 +10,10 @@ import { mocked } from "jest-mock";
|
||||
import { type Room, RoomType } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { VisibilityProvider } from "../../../../../src/stores/room-list/filters/VisibilityProvider";
|
||||
import LegacyCallHandler from "../../../../../src/LegacyCallHandler";
|
||||
import VoipUserMapper from "../../../../../src/VoipUserMapper";
|
||||
import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../../../../src/models/LocalRoom";
|
||||
import { RoomListCustomisations } from "../../../../../src/customisations/RoomList";
|
||||
import { createTestClient } from "../../../../test-utils";
|
||||
|
||||
jest.mock("../../../../../src/VoipUserMapper", () => ({
|
||||
sharedInstance: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../../../../../src/LegacyCallHandler", () => ({
|
||||
instance: {
|
||||
getSupportsVirtualRooms: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock("../../../../../src/customisations/RoomList", () => ({
|
||||
RoomListCustomisations: {
|
||||
isRoomVisible: jest.fn(),
|
||||
@@ -46,16 +34,6 @@ const createLocalRoom = (): LocalRoom => {
|
||||
};
|
||||
|
||||
describe("VisibilityProvider", () => {
|
||||
let mockVoipUserMapper: VoipUserMapper;
|
||||
|
||||
beforeEach(() => {
|
||||
mockVoipUserMapper = {
|
||||
onNewInvitedRoom: jest.fn(),
|
||||
isVirtualRoom: jest.fn(),
|
||||
} as unknown as VoipUserMapper;
|
||||
mocked(VoipUserMapper.sharedInstance).mockReturnValue(mockVoipUserMapper);
|
||||
});
|
||||
|
||||
describe("instance", () => {
|
||||
it("should return an instance", () => {
|
||||
const visibilityProvider = VisibilityProvider.instance;
|
||||
@@ -64,28 +42,7 @@ describe("VisibilityProvider", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("onNewInvitedRoom", () => {
|
||||
it("should call onNewInvitedRoom on VoipUserMapper.sharedInstance", async () => {
|
||||
const room = {} as unknown as Room;
|
||||
await VisibilityProvider.instance.onNewInvitedRoom(room);
|
||||
expect(mockVoipUserMapper.onNewInvitedRoom).toHaveBeenCalledWith(room);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isRoomVisible", () => {
|
||||
describe("for a virtual room", () => {
|
||||
beforeEach(() => {
|
||||
mocked(LegacyCallHandler.instance.getSupportsVirtualRooms).mockReturnValue(true);
|
||||
mocked(mockVoipUserMapper.isVirtualRoom).mockReturnValue(true);
|
||||
});
|
||||
|
||||
it("should return return false", () => {
|
||||
const room = createRoom();
|
||||
expect(VisibilityProvider.instance.isRoomVisible(room)).toBe(false);
|
||||
expect(mockVoipUserMapper.isVirtualRoom).toHaveBeenCalledWith(room);
|
||||
});
|
||||
});
|
||||
|
||||
it("should return false without room", () => {
|
||||
expect(VisibilityProvider.instance.isRoomVisible()).toBe(false);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user