From 70cdd57a5c61372b9e053edfa57e7a9aed06937e Mon Sep 17 00:00:00 2001
From: Kerry <kerrya@element.io>
Date: Tue, 19 Apr 2022 18:47:19 +0200
Subject: [PATCH] Live location sharing: move test utils into utils (#8365)

* move makeRoomWithState events to test utils

Signed-off-by: Kerry Archibald <kerrya@element.io>

* move beacon test helpers into utils

Signed-off-by: Kerry Archibald <kerrya@element.io>

* remove file

Signed-off-by: Kerry Archibald <kerrya@element.io>

* more types

Signed-off-by: Kerry Archibald <kerrya@element.io>
---
 .../views/beacon/BeaconMarker-test.tsx        | 24 +++++-----
 .../views/beacon/BeaconViewDialog-test.tsx    | 15 +++---
 .../views/messages/MBeaconBody-test.tsx       | 47 ++++++++-----------
 test/test-utils/beacon.ts                     | 27 ++++++++++-
 test/test-utils/room.ts                       | 18 +++++++
 5 files changed, 84 insertions(+), 47 deletions(-)

diff --git a/test/components/views/beacon/BeaconMarker-test.tsx b/test/components/views/beacon/BeaconMarker-test.tsx
index 5b730ff438..efc9c7d22c 100644
--- a/test/components/views/beacon/BeaconMarker-test.tsx
+++ b/test/components/views/beacon/BeaconMarker-test.tsx
@@ -22,12 +22,18 @@ import {
     Beacon,
     Room,
     RoomMember,
+    MatrixEvent,
     getBeaconInfoIdentifier,
 } from 'matrix-js-sdk/src/matrix';
 
 import BeaconMarker from '../../../../src/components/views/beacon/BeaconMarker';
 import MatrixClientContext from '../../../../src/contexts/MatrixClientContext';
-import { getMockClientWithEventEmitter, makeBeaconEvent, makeBeaconInfoEvent } from '../../../test-utils';
+import {
+    getMockClientWithEventEmitter,
+    makeBeaconEvent,
+    makeBeaconInfoEvent,
+    makeRoomWithStateEvents,
+} from '../../../test-utils';
 import { TILE_SERVER_WK_KEY } from '../../../../src/utils/WellKnownUtils';
 
 describe('<BeaconMarker />', () => {
@@ -53,13 +59,9 @@ describe('<BeaconMarker />', () => {
 
     // make fresh rooms every time
     // as we update room state
-    const makeRoomWithStateEvents = (stateEvents = []): Room => {
-        const room1 = new Room(roomId, mockClient, aliceId);
-
-        room1.currentState.setStateEvents(stateEvents);
+    const setupRoom = (stateEvents: MatrixEvent[] = []): Room => {
+        const room1 = makeRoomWithStateEvents(stateEvents, { roomId, mockClient });
         jest.spyOn(room1, 'getMember').mockReturnValue(aliceMember);
-        mockClient.getRoom.mockReturnValue(room1);
-
         return room1;
     };
 
@@ -97,21 +99,21 @@ describe('<BeaconMarker />', () => {
     });
 
     it('renders nothing when beacon is not live', () => {
-        const room = makeRoomWithStateEvents([notLiveEvent]);
+        const room = setupRoom([notLiveEvent]);
         const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(notLiveEvent));
         const component = getComponent({ beacon });
         expect(component.html()).toBe(null);
     });
 
     it('renders nothing when beacon has no location', () => {
-        const room = makeRoomWithStateEvents([defaultEvent]);
+        const room = setupRoom([defaultEvent]);
         const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
         const component = getComponent({ beacon });
         expect(component.html()).toBe(null);
     });
 
     it('renders marker when beacon has location', () => {
-        const room = makeRoomWithStateEvents([defaultEvent]);
+        const room = setupRoom([defaultEvent]);
         const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
         beacon.addLocations([location1]);
         const component = getComponent({ beacon });
@@ -119,7 +121,7 @@ describe('<BeaconMarker />', () => {
     });
 
     it('updates with new locations', () => {
-        const room = makeRoomWithStateEvents([defaultEvent]);
+        const room = setupRoom([defaultEvent]);
         const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
         beacon.addLocations([location1]);
         const component = getComponent({ beacon });
diff --git a/test/components/views/beacon/BeaconViewDialog-test.tsx b/test/components/views/beacon/BeaconViewDialog-test.tsx
index b3573de0f9..197c0b7e7f 100644
--- a/test/components/views/beacon/BeaconViewDialog-test.tsx
+++ b/test/components/views/beacon/BeaconViewDialog-test.tsx
@@ -19,6 +19,7 @@ import { mount } from 'enzyme';
 import { act } from 'react-dom/test-utils';
 import {
     MatrixClient,
+    MatrixEvent,
     Room,
     RoomMember,
     getBeaconInfoIdentifier,
@@ -30,6 +31,7 @@ import {
     getMockClientWithEventEmitter,
     makeBeaconEvent,
     makeBeaconInfoEvent,
+    makeRoomWithStateEvents,
 } from '../../../test-utils';
 import { TILE_SERVER_WK_KEY } from '../../../../src/utils/WellKnownUtils';
 
@@ -55,12 +57,9 @@ describe('<BeaconViewDialog />', () => {
 
     // make fresh rooms every time
     // as we update room state
-    const makeRoomWithStateEvents = (stateEvents = []): Room => {
-        const room1 = new Room(roomId, mockClient, aliceId);
-
-        room1.currentState.setStateEvents(stateEvents);
+    const setupRoom = (stateEvents: MatrixEvent[] = []): Room => {
+        const room1 = makeRoomWithStateEvents(stateEvents, { roomId, mockClient });
         jest.spyOn(room1, 'getMember').mockReturnValue(aliceMember);
-        mockClient.getRoom.mockReturnValue(room1);
 
         return room1;
     };
@@ -85,7 +84,7 @@ describe('<BeaconViewDialog />', () => {
         mount(<BeaconViewDialog {...defaultProps} {...props} />);
 
     it('renders a map with markers', () => {
-        const room = makeRoomWithStateEvents([defaultEvent]);
+        const room = setupRoom([defaultEvent]);
         const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
         beacon.addLocations([location1]);
         const component = getComponent();
@@ -97,7 +96,7 @@ describe('<BeaconViewDialog />', () => {
     });
 
     it('updates markers on changes to beacons', () => {
-        const room = makeRoomWithStateEvents([defaultEvent]);
+        const room = setupRoom([defaultEvent]);
         const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
         beacon.addLocations([location1]);
         const component = getComponent();
@@ -122,7 +121,7 @@ describe('<BeaconViewDialog />', () => {
 
     it('renders a fallback when no live beacons remain', () => {
         const onFinished = jest.fn();
-        const room = makeRoomWithStateEvents([defaultEvent]);
+        const room = setupRoom([defaultEvent]);
         const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
         beacon.addLocations([location1]);
         const component = getComponent({ onFinished });
diff --git a/test/components/views/messages/MBeaconBody-test.tsx b/test/components/views/messages/MBeaconBody-test.tsx
index b37bf65bbd..5afbb05c78 100644
--- a/test/components/views/messages/MBeaconBody-test.tsx
+++ b/test/components/views/messages/MBeaconBody-test.tsx
@@ -20,12 +20,16 @@ import { act } from 'react-dom/test-utils';
 import maplibregl from 'maplibre-gl';
 import {
     BeaconEvent,
-    Room,
     getBeaconInfoIdentifier,
 } from 'matrix-js-sdk/src/matrix';
 
 import MBeaconBody from '../../../../src/components/views/messages/MBeaconBody';
-import { getMockClientWithEventEmitter, makeBeaconEvent, makeBeaconInfoEvent } from '../../../test-utils';
+import {
+    getMockClientWithEventEmitter,
+    makeBeaconEvent,
+    makeBeaconInfoEvent,
+    makeRoomWithStateEvents,
+} from '../../../test-utils';
 import { RoomPermalinkCreator } from '../../../../src/utils/permalinks/Permalinks';
 import { MediaEventHelper } from '../../../../src/utils/MediaEventHelper';
 import MatrixClientContext from '../../../../src/contexts/MatrixClientContext';
@@ -51,17 +55,6 @@ describe('<MBeaconBody />', () => {
         getRoom: jest.fn(),
     });
 
-    // make fresh rooms every time
-    // as we update room state
-    const makeRoomWithStateEvents = (stateEvents = []): Room => {
-        const room1 = new Room(roomId, mockClient, aliceId);
-
-        room1.currentState.setStateEvents(stateEvents);
-        mockClient.getRoom.mockReturnValue(room1);
-
-        return room1;
-    };
-
     const defaultEvent = makeBeaconInfoEvent(aliceId,
         roomId,
         { isLive: true },
@@ -96,7 +89,7 @@ describe('<MBeaconBody />', () => {
             { isLive: false },
             '$alice-room1-1',
         );
-        makeRoomWithStateEvents([beaconInfoEvent]);
+        makeRoomWithStateEvents([beaconInfoEvent], { roomId, mockClient });
         const component = getComponent({ mxEvent: beaconInfoEvent });
         expect(component.text()).toEqual("Live location ended");
     });
@@ -108,7 +101,7 @@ describe('<MBeaconBody />', () => {
             { isLive: true, timestamp: now - 600000, timeout: 500 },
             '$alice-room1-1',
         );
-        makeRoomWithStateEvents([beaconInfoEvent]);
+        makeRoomWithStateEvents([beaconInfoEvent], { roomId, mockClient });
         const component = getComponent({ mxEvent: beaconInfoEvent });
         expect(component.text()).toEqual("Live location ended");
     });
@@ -120,7 +113,7 @@ describe('<MBeaconBody />', () => {
             { isLive: true, timestamp: now - 600000, timeout: 500 },
             '$alice-room1-1',
         );
-        makeRoomWithStateEvents([beaconInfoEvent]);
+        makeRoomWithStateEvents([beaconInfoEvent], { roomId, mockClient });
         const component = getComponent({ mxEvent: beaconInfoEvent });
         act(() => {
             component.find('.mx_MBeaconBody_map').simulate('click');
@@ -145,7 +138,7 @@ describe('<MBeaconBody />', () => {
             '$alice-room1-2',
         );
 
-        makeRoomWithStateEvents([aliceBeaconInfo1, aliceBeaconInfo2]);
+        makeRoomWithStateEvents([aliceBeaconInfo1, aliceBeaconInfo2], { roomId, mockClient });
 
         const component = getComponent({ mxEvent: aliceBeaconInfo1 });
         // beacon1 has been superceded by beacon2
@@ -168,7 +161,7 @@ describe('<MBeaconBody />', () => {
             '$alice-room1-2',
         );
 
-        const room = makeRoomWithStateEvents([aliceBeaconInfo1]);
+        const room = makeRoomWithStateEvents([aliceBeaconInfo1], { roomId, mockClient });
         const component = getComponent({ mxEvent: aliceBeaconInfo1 });
 
         const beaconInstance = room.currentState.beacons.get(getBeaconInfoIdentifier(aliceBeaconInfo1));
@@ -193,7 +186,7 @@ describe('<MBeaconBody />', () => {
                 '$alice-room1-1',
             );
 
-            const room = makeRoomWithStateEvents([aliceBeaconInfo]);
+            const room = makeRoomWithStateEvents([aliceBeaconInfo], { roomId, mockClient });
             const beaconInstance = room.currentState.beacons.get(getBeaconInfoIdentifier(aliceBeaconInfo));
             const component = getComponent({ mxEvent: aliceBeaconInfo });
 
@@ -226,14 +219,14 @@ describe('<MBeaconBody />', () => {
         );
 
         it('renders a live beacon without a location correctly', () => {
-            makeRoomWithStateEvents([aliceBeaconInfo]);
+            makeRoomWithStateEvents([aliceBeaconInfo], { roomId, mockClient });
             const component = getComponent({ mxEvent: aliceBeaconInfo });
 
             expect(component.text()).toEqual("Loading live location...");
         });
 
         it('does nothing on click when a beacon has no location', () => {
-            makeRoomWithStateEvents([aliceBeaconInfo]);
+            makeRoomWithStateEvents([aliceBeaconInfo], { roomId, mockClient });
             const component = getComponent({ mxEvent: aliceBeaconInfo });
 
             act(() => {
@@ -244,7 +237,7 @@ describe('<MBeaconBody />', () => {
         });
 
         it('renders a live beacon with a location correctly', () => {
-            const room = makeRoomWithStateEvents([aliceBeaconInfo]);
+            const room = makeRoomWithStateEvents([aliceBeaconInfo], { roomId, mockClient });
             const beaconInstance = room.currentState.beacons.get(getBeaconInfoIdentifier(aliceBeaconInfo));
             beaconInstance.addLocations([location1]);
             const component = getComponent({ mxEvent: aliceBeaconInfo });
@@ -253,7 +246,7 @@ describe('<MBeaconBody />', () => {
         });
 
         it('opens maximised map view on click when beacon has a live location', () => {
-            const room = makeRoomWithStateEvents([aliceBeaconInfo]);
+            const room = makeRoomWithStateEvents([aliceBeaconInfo], { roomId, mockClient });
             const beaconInstance = room.currentState.beacons.get(getBeaconInfoIdentifier(aliceBeaconInfo));
             beaconInstance.addLocations([location1]);
             const component = getComponent({ mxEvent: aliceBeaconInfo });
@@ -267,7 +260,7 @@ describe('<MBeaconBody />', () => {
         });
 
         it('does nothing on click when a beacon has no location', () => {
-            makeRoomWithStateEvents([aliceBeaconInfo]);
+            makeRoomWithStateEvents([aliceBeaconInfo], { roomId, mockClient });
             const component = getComponent({ mxEvent: aliceBeaconInfo });
 
             act(() => {
@@ -278,7 +271,7 @@ describe('<MBeaconBody />', () => {
         });
 
         it('renders a live beacon with a location correctly', () => {
-            const room = makeRoomWithStateEvents([aliceBeaconInfo]);
+            const room = makeRoomWithStateEvents([aliceBeaconInfo], { roomId, mockClient });
             const beaconInstance = room.currentState.beacons.get(getBeaconInfoIdentifier(aliceBeaconInfo));
             beaconInstance.addLocations([location1]);
             const component = getComponent({ mxEvent: aliceBeaconInfo });
@@ -287,7 +280,7 @@ describe('<MBeaconBody />', () => {
         });
 
         it('opens maximised map view on click when beacon has a live location', () => {
-            const room = makeRoomWithStateEvents([aliceBeaconInfo]);
+            const room = makeRoomWithStateEvents([aliceBeaconInfo], { roomId, mockClient });
             const beaconInstance = room.currentState.beacons.get(getBeaconInfoIdentifier(aliceBeaconInfo));
             beaconInstance.addLocations([location1]);
             const component = getComponent({ mxEvent: aliceBeaconInfo });
@@ -301,7 +294,7 @@ describe('<MBeaconBody />', () => {
         });
 
         it('updates latest location', () => {
-            const room = makeRoomWithStateEvents([aliceBeaconInfo]);
+            const room = makeRoomWithStateEvents([aliceBeaconInfo], { roomId, mockClient });
             const component = getComponent({ mxEvent: aliceBeaconInfo });
 
             const beaconInstance = room.currentState.beacons.get(getBeaconInfoIdentifier(aliceBeaconInfo));
diff --git a/test/test-utils/beacon.ts b/test/test-utils/beacon.ts
index 19764a2600..3eee57b39f 100644
--- a/test/test-utils/beacon.ts
+++ b/test/test-utils/beacon.ts
@@ -16,11 +16,17 @@ limitations under the License.
 
 import { MockedObject } from "jest-mock";
 import { makeBeaconInfoContent, makeBeaconContent } from "matrix-js-sdk/src/content-helpers";
-import { MatrixEvent } from "matrix-js-sdk/src/matrix";
+import {
+    MatrixClient,
+    MatrixEvent,
+    Beacon,
+    getBeaconInfoIdentifier,
+} from "matrix-js-sdk/src/matrix";
 import { M_BEACON, M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon";
 import { LocationAssetType } from "matrix-js-sdk/src/@types/location";
 
 import { getMockGeolocationPositionError } from "./location";
+import { makeRoomWithStateEvents } from "./room";
 
 type InfoContentProps = {
     timeout: number;
@@ -182,3 +188,22 @@ export const watchPositionMockImplementation = (delays: number[], errorCodes: nu
         });
     };
 };
+
+/**
+ * Creates a room with beacon events
+ * sets given locations on beacons
+ * returns beacons
+ */
+export const makeRoomWithBeacons = (
+    roomId: string,
+    mockClient: MockedObject<MatrixClient>,
+    beaconInfoEvents: MatrixEvent[],
+    locationEvents?: MatrixEvent[],
+): Beacon[] => {
+    const room = makeRoomWithStateEvents(beaconInfoEvents, { roomId, mockClient });
+    const beacons = beaconInfoEvents.map(event => room.currentState.beacons.get(getBeaconInfoIdentifier(event)));
+    if (locationEvents) {
+        beacons.forEach(beacon => beacon.addLocations(locationEvents));
+    }
+    return beacons;
+};
diff --git a/test/test-utils/room.ts b/test/test-utils/room.ts
index 022f13e6c1..b9224e3871 100644
--- a/test/test-utils/room.ts
+++ b/test/test-utils/room.ts
@@ -14,8 +14,12 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
+import { MockedObject } from "jest-mock";
 import {
+    MatrixClient,
+    MatrixEvent,
     EventType,
+    Room,
 } from "matrix-js-sdk/src/matrix";
 
 import { mkEvent } from "./test-utils";
@@ -32,3 +36,17 @@ export const makeMembershipEvent = (
     ts: Date.now(),
 });
 
+/**
+ * Creates a room
+ * sets state events on the room
+ * Sets client getRoom to return room
+ * returns room
+ */
+export const makeRoomWithStateEvents = (
+    stateEvents: MatrixEvent[] = [],
+    { roomId, mockClient }: { roomId: string, mockClient: MockedObject<MatrixClient>}): Room => {
+    const room1 = new Room(roomId, mockClient, '@user:server.org');
+    room1.currentState.setStateEvents(stateEvents);
+    mockClient.getRoom.mockReturnValue(room1);
+    return room1;
+};