145 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			5.5 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 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("<BeaconMarker />", () => {
 | 
						|
    // 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 <MatrixClientContext.Provider value={mockClient} {...wrapperProps} />;
 | 
						|
        };
 | 
						|
 | 
						|
        return render(<BeaconMarker {...defaultProps} {...props} />, {
 | 
						|
            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(`<DocumentFragment />`);
 | 
						|
        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(`<DocumentFragment />`);
 | 
						|
        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);
 | 
						|
    });
 | 
						|
});
 |