/* Copyright 2024 New Vector Ltd. Copyright 2022 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ import React from "react"; import { act, render, screen, waitFor } from "@testing-library/react"; import * as maplibregl from "maplibre-gl"; 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, makeRoomWithStateEvents, } from "../../../test-utils"; import { TILE_SERVER_WK_KEY } from "../../../../src/utils/WellKnownUtils"; describe("", () => { // 14.03.2022 16:15 const now = 1647270879403; // stable date for snapshots jest.spyOn(global.Date, "now").mockReturnValue(now); const roomId = "!room:server"; const aliceId = "@alice:server"; const aliceMember = new RoomMember(roomId, aliceId); const mapOptions = { container: {} as unknown as HTMLElement, style: "" }; const mockMap = new maplibregl.Map(mapOptions); const mockMarker = new maplibregl.Marker(); const mockClient = getMockClientWithEventEmitter({ getClientWellKnown: jest.fn().mockReturnValue({ [TILE_SERVER_WK_KEY.name]: { map_style_url: "maps.com" }, }), getUserId: jest.fn().mockReturnValue(aliceId), getRoom: jest.fn(), isGuest: jest.fn().mockReturnValue(false), }); // make fresh rooms every time // as we update room state const setupRoom = (stateEvents: MatrixEvent[] = []): Room => { const room1 = makeRoomWithStateEvents(stateEvents, { roomId, mockClient }); jest.spyOn(room1, "getMember").mockReturnValue(aliceMember); return room1; }; const defaultEvent = makeBeaconInfoEvent(aliceId, roomId, { isLive: true }, "$alice-room1-1"); const notLiveEvent = makeBeaconInfoEvent(aliceId, roomId, { isLive: false }, "$alice-room1-2"); const geoUri1 = "geo:51,41"; const location1 = makeBeaconEvent(aliceId, { beaconInfoId: defaultEvent.getId(), geoUri: geoUri1, timestamp: now + 1, }); const geoUri2 = "geo:52,42"; const location2 = makeBeaconEvent(aliceId, { beaconInfoId: defaultEvent.getId(), geoUri: geoUri2, timestamp: now + 10000, }); const defaultProps = { map: mockMap, beacon: new Beacon(defaultEvent), }; const renderComponent = (props = {}) => { const Wrapper = (wrapperProps = {}) => { return ; }; return render(, { wrapper: Wrapper, }); }; beforeEach(() => { jest.clearAllMocks(); }); it("renders nothing when beacon is not live", () => { const room = setupRoom([notLiveEvent]); const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(notLiveEvent)); const { asFragment } = renderComponent({ beacon }); expect(asFragment()).toMatchInlineSnapshot(``); expect(screen.queryByTestId("avatar-img")).not.toBeInTheDocument(); }); it("renders nothing when beacon has no location", () => { const room = setupRoom([defaultEvent]); const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent)); const { asFragment } = renderComponent({ beacon }); expect(asFragment()).toMatchInlineSnapshot(``); expect(screen.queryByTestId("avatar-img")).not.toBeInTheDocument(); }); it("renders marker when beacon has location", async () => { const room = setupRoom([defaultEvent]); const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent)); beacon?.addLocations([location1]); const { asFragment } = renderComponent({ beacon }); await waitFor(() => { expect(screen.getByTestId("avatar-img")).toBeInTheDocument(); }); expect(asFragment()).toMatchSnapshot(); }); it("updates with new locations", () => { const lonLat1 = { lon: 41, lat: 51 }; const lonLat2 = { lon: 42, lat: 52 }; const room = setupRoom([defaultEvent]); const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent)); beacon?.addLocations([location1]); // render the component then add a new location, check mockMarker called as expected renderComponent({ beacon }); expect(mockMarker.setLngLat).toHaveBeenLastCalledWith(lonLat1); expect(mockMarker.addTo).toHaveBeenCalledWith(mockMap); // add a location, check mockMarker called with new location details act(() => { beacon?.addLocations([location2]); }); expect(mockMarker.setLngLat).toHaveBeenLastCalledWith(lonLat2); expect(mockMarker.addTo).toHaveBeenCalledWith(mockMap); }); });