mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-11-04 01:19:41 +00:00
Absorb the matrix-react-sdk repository (#28192)
Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> Co-authored-by: github-merge-queue <github-merge-queue@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Florian Duros <florian.duros@ormaz.fr> Co-authored-by: Kim Brose <kim.brose@nordeck.net> Co-authored-by: Florian Duros <florianduros@element.io> Co-authored-by: R Midhun Suresh <hi@midhun.dev> Co-authored-by: dbkr <986903+dbkr@users.noreply.github.com> Co-authored-by: ElementRobot <releases@riot.im> Co-authored-by: dbkr <dbkr@users.noreply.github.com> Co-authored-by: David Baker <dbkr@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Co-authored-by: David Langley <davidl@element.io> Co-authored-by: Michael Weimann <michaelw@matrix.org> Co-authored-by: Timshel <Timshel@users.noreply.github.com> Co-authored-by: Sahil Silare <32628578+sahil9001@users.noreply.github.com> Co-authored-by: Will Hunt <will@half-shot.uk> Co-authored-by: Hubert Chathi <hubert@uhoreg.ca> Co-authored-by: Andrew Ferrazzutti <andrewf@element.io> Co-authored-by: Robin <robin@robin.town> Co-authored-by: Tulir Asokan <tulir@maunium.net>
This commit is contained in:
committed by
GitHub
parent
2b99496025
commit
c05c429803
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
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, fireEvent, getByTestId, render } from "jest-matrix-react";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
import { ClientEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
import Map from "../../../../../src/components/views/location/Map";
|
||||
import { getMockClientWithEventEmitter, getMockGeolocationPositionError } from "../../../../test-utils";
|
||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||
import { TILE_SERVER_WK_KEY } from "../../../../../src/utils/WellKnownUtils";
|
||||
import Modal from "../../../../../src/Modal";
|
||||
import ErrorDialog from "../../../../../src/components/views/dialogs/ErrorDialog";
|
||||
|
||||
describe("<Map />", () => {
|
||||
const defaultProps = {
|
||||
centerGeoUri: "geo:52,41",
|
||||
id: "test-123",
|
||||
onError: jest.fn(),
|
||||
onClick: jest.fn(),
|
||||
};
|
||||
const matrixClient = getMockClientWithEventEmitter({
|
||||
getClientWellKnown: jest.fn().mockReturnValue({
|
||||
[TILE_SERVER_WK_KEY.name]: { map_style_url: "maps.com" },
|
||||
}),
|
||||
});
|
||||
const getComponent = (props = {}, renderingFn?: any) =>
|
||||
(renderingFn ?? render)(
|
||||
<MatrixClientContext.Provider value={matrixClient}>
|
||||
<Map {...defaultProps} {...props} />
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
matrixClient.getClientWellKnown.mockReturnValue({
|
||||
[TILE_SERVER_WK_KEY.name]: { map_style_url: "maps.com" },
|
||||
});
|
||||
|
||||
jest.spyOn(logger, "error").mockRestore();
|
||||
mocked(maplibregl.GeolocateControl).mockClear();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.spyOn(logger, "error").mockRestore();
|
||||
});
|
||||
|
||||
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
|
||||
const mockMap = new maplibregl.Map(mapOptions);
|
||||
|
||||
it("renders", () => {
|
||||
const { container } = getComponent();
|
||||
expect(container.firstChild).not.toBeNull();
|
||||
});
|
||||
|
||||
describe("onClientWellKnown emits", () => {
|
||||
it("updates map style when style url is truthy", () => {
|
||||
getComponent();
|
||||
|
||||
act(() => {
|
||||
matrixClient.emit(ClientEvent.ClientWellKnown, {
|
||||
[TILE_SERVER_WK_KEY.name]: { map_style_url: "new.maps.com" },
|
||||
});
|
||||
});
|
||||
|
||||
expect(mockMap.setStyle).toHaveBeenCalledWith("new.maps.com");
|
||||
});
|
||||
|
||||
it("does not update map style when style url is truthy", () => {
|
||||
getComponent();
|
||||
|
||||
act(() => {
|
||||
matrixClient.emit(ClientEvent.ClientWellKnown, {
|
||||
[TILE_SERVER_WK_KEY.name]: { map_style_url: undefined },
|
||||
});
|
||||
});
|
||||
|
||||
expect(mockMap.setStyle).not.toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe("map centering", () => {
|
||||
it("does not try to center when no center uri provided", () => {
|
||||
getComponent({ centerGeoUri: null });
|
||||
expect(mockMap.setCenter).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("sets map center to centerGeoUri", () => {
|
||||
getComponent({ centerGeoUri: "geo:51,42" });
|
||||
expect(mockMap.setCenter).toHaveBeenCalledWith({ lat: 51, lon: 42 });
|
||||
});
|
||||
|
||||
it("handles invalid centerGeoUri", () => {
|
||||
const logSpy = jest.spyOn(logger, "error").mockImplementation();
|
||||
getComponent({ centerGeoUri: "123 Sesame Street" });
|
||||
expect(mockMap.setCenter).not.toHaveBeenCalled();
|
||||
expect(logSpy).toHaveBeenCalledWith("Could not set map center");
|
||||
});
|
||||
|
||||
it("updates map center when centerGeoUri prop changes", () => {
|
||||
const { rerender } = getComponent({ centerGeoUri: "geo:51,42" });
|
||||
|
||||
getComponent({ centerGeoUri: "geo:53,45" }, rerender);
|
||||
getComponent({ centerGeoUri: "geo:56,47" }, rerender);
|
||||
expect(mockMap.setCenter).toHaveBeenCalledWith({ lat: 51, lon: 42 });
|
||||
expect(mockMap.setCenter).toHaveBeenCalledWith({ lat: 53, lon: 45 });
|
||||
expect(mockMap.setCenter).toHaveBeenCalledWith({ lat: 56, lon: 47 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("map bounds", () => {
|
||||
it("does not try to fit map bounds when no bounds provided", () => {
|
||||
getComponent({ bounds: null });
|
||||
expect(mockMap.fitBounds).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("fits map to bounds", () => {
|
||||
const bounds = { north: 51, south: 50, east: 42, west: 41 };
|
||||
getComponent({ bounds });
|
||||
expect(mockMap.fitBounds).toHaveBeenCalledWith(
|
||||
new maplibregl.LngLatBounds([bounds.west, bounds.south], [bounds.east, bounds.north]),
|
||||
{ padding: 100, maxZoom: 15 },
|
||||
);
|
||||
});
|
||||
|
||||
it("handles invalid bounds", () => {
|
||||
const logSpy = jest.spyOn(logger, "error").mockImplementation();
|
||||
const bounds = { north: "a", south: "b", east: 42, west: 41 };
|
||||
getComponent({ bounds });
|
||||
expect(mockMap.fitBounds).not.toHaveBeenCalled();
|
||||
expect(logSpy).toHaveBeenCalledWith("Invalid map bounds");
|
||||
});
|
||||
|
||||
it("updates map bounds when bounds prop changes", () => {
|
||||
const { rerender } = getComponent({ centerGeoUri: "geo:51,42" });
|
||||
|
||||
const bounds = { north: 51, south: 50, east: 42, west: 41 };
|
||||
const bounds2 = { north: 53, south: 51, east: 45, west: 44 };
|
||||
|
||||
getComponent({ bounds }, rerender);
|
||||
getComponent({ bounds: bounds2 }, rerender);
|
||||
expect(mockMap.fitBounds).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("children", () => {
|
||||
it("renders without children", () => {
|
||||
const component = getComponent({ children: null });
|
||||
// no error
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it("renders children with map renderProp", () => {
|
||||
const children = ({ map }: { map: maplibregl.Map }) => (
|
||||
<div data-testid="test-child" data-map={map}>
|
||||
Hello, world
|
||||
</div>
|
||||
);
|
||||
|
||||
const { container } = getComponent({ children });
|
||||
|
||||
// passes the map instance to the react children
|
||||
expect(getByTestId(container, "test-child").dataset.map).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("onClick", () => {
|
||||
it("eats clicks to maplibre attribution button", () => {
|
||||
const onClick = jest.fn();
|
||||
getComponent({ onClick });
|
||||
|
||||
act(() => {
|
||||
// this is added to the dom by maplibregl
|
||||
// which is mocked
|
||||
// just fake the target
|
||||
const fakeEl = document.createElement("div");
|
||||
fakeEl.className = "maplibregl-ctrl-attrib-button";
|
||||
fireEvent.click(fakeEl);
|
||||
});
|
||||
|
||||
expect(onClick).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls onClick", () => {
|
||||
const onClick = jest.fn();
|
||||
const { container } = getComponent({ onClick });
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(container.firstChild);
|
||||
});
|
||||
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("geolocate", () => {
|
||||
it("does not add a geolocate control when allowGeolocate is falsy", () => {
|
||||
getComponent({ allowGeolocate: false });
|
||||
|
||||
// didn't create a geolocation control
|
||||
expect(maplibregl.GeolocateControl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("creates a geolocate control and adds it to the map when allowGeolocate is truthy", () => {
|
||||
getComponent({ allowGeolocate: true });
|
||||
|
||||
// didn't create a geolocation control
|
||||
expect(maplibregl.GeolocateControl).toHaveBeenCalledWith({
|
||||
positionOptions: {
|
||||
enableHighAccuracy: true,
|
||||
},
|
||||
trackUserLocation: false,
|
||||
});
|
||||
|
||||
// mocked maplibregl shares mock for each mocked instance
|
||||
// so we can assert the geolocate control was added using this static mock
|
||||
const mockGeolocate = new maplibregl.GeolocateControl({});
|
||||
expect(mockMap.addControl).toHaveBeenCalledWith(mockGeolocate);
|
||||
});
|
||||
|
||||
it("logs and opens a dialog on a geolocation error", () => {
|
||||
const mockGeolocate = new maplibregl.GeolocateControl({});
|
||||
jest.spyOn(mockGeolocate, "on");
|
||||
const logSpy = jest.spyOn(logger, "error").mockImplementation(() => {});
|
||||
jest.spyOn(Modal, "createDialog");
|
||||
|
||||
const { rerender } = getComponent({ allowGeolocate: true });
|
||||
|
||||
// wait for component to settle
|
||||
getComponent({ allowGeolocate: true }, rerender);
|
||||
expect(mockGeolocate.on).toHaveBeenCalledWith("error", expect.any(Function));
|
||||
const error = getMockGeolocationPositionError(1, "Test");
|
||||
|
||||
// @ts-ignore pretend to have geolocate emit an error
|
||||
mockGeolocate.emit("error", error);
|
||||
|
||||
expect(logSpy).toHaveBeenCalledWith("Could not fetch location", error);
|
||||
|
||||
expect(Modal.createDialog).toHaveBeenCalledWith(ErrorDialog, {
|
||||
title: "Could not fetch location",
|
||||
description:
|
||||
"Element was denied permission to fetch your location. Please allow location access in your browser settings.",
|
||||
});
|
||||
});
|
||||
|
||||
it("unsubscribes from geolocate errors on destroy", () => {
|
||||
const mockGeolocate = new maplibregl.GeolocateControl({});
|
||||
jest.spyOn(mockGeolocate, "on");
|
||||
jest.spyOn(mockGeolocate, "off");
|
||||
jest.spyOn(Modal, "createDialog");
|
||||
|
||||
const { unmount } = getComponent({ allowGeolocate: true });
|
||||
|
||||
expect(mockGeolocate.on).toHaveBeenCalled();
|
||||
|
||||
unmount();
|
||||
|
||||
expect(mockGeolocate.off).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user