From 3fafa4b58d8a53f57bdb9476e8c67949e8eb2168 Mon Sep 17 00:00:00 2001 From: Kerry Date: Tue, 21 Feb 2023 07:35:39 +1300 Subject: [PATCH] Port location unit tests from enzyme to react-testing-library (#10181) * SmartMarker test to rtl * LocationPicker to rtl * LocationViewDialog to rtl * LocationShareMenu to rtl * use toBeDisabled assertion --- cypress/e2e/location/location.spec.ts | 2 +- .../views/location/EnableLiveShare.tsx | 6 +- .../views/location/LiveDurationDropdown.tsx | 2 +- .../views/location/LocationPicker.tsx | 2 +- src/components/views/location/MapError.tsx | 2 +- .../views/location/ShareDialogButtons.tsx | 7 +- .../views/location/LocationPicker-test.tsx | 128 ++++----- .../views/location/LocationShareMenu-test.tsx | 236 ++++++++--------- .../location/LocationViewDialog-test.tsx | 13 +- .../views/location/SmartMarker-test.tsx | 25 +- .../LocationPicker-test.tsx.snap | 9 + .../LocationShareMenu-test.tsx.snap | 135 +++------- .../LocationViewDialog-test.tsx.snap | 246 +++--------------- .../__snapshots__/MapError-test.tsx.snap | 6 +- .../__snapshots__/SmartMarker-test.tsx.snap | 82 ++---- .../__snapshots__/MBeaconBody-test.tsx.snap | 2 +- 16 files changed, 290 insertions(+), 613 deletions(-) create mode 100644 test/components/views/location/__snapshots__/LocationPicker-test.tsx.snap diff --git a/cypress/e2e/location/location.spec.ts b/cypress/e2e/location/location.spec.ts index 0d512705a0..b716fe543b 100644 --- a/cypress/e2e/location/location.spec.ts +++ b/cypress/e2e/location/location.spec.ts @@ -27,7 +27,7 @@ describe("Location sharing", () => { }; const submitShareLocation = (): void => { - cy.get('[data-test-id="location-picker-submit-button"]').click(); + cy.get('[data-testid="location-picker-submit-button"]').click(); }; beforeEach(() => { diff --git a/src/components/views/location/EnableLiveShare.tsx b/src/components/views/location/EnableLiveShare.tsx index 6b7e0036a9..62a44b12b9 100644 --- a/src/components/views/location/EnableLiveShare.tsx +++ b/src/components/views/location/EnableLiveShare.tsx @@ -29,7 +29,7 @@ interface Props { export const EnableLiveShare: React.FC = ({ onSubmit }) => { const [isEnabled, setEnabled] = useState(false); return ( -
+
{_t("Live location sharing")} @@ -43,13 +43,13 @@ export const EnableLiveShare: React.FC = ({ onSubmit }) => { )}

= ({ timeout, onChange }) => { return ( { )} = ({ error, isMinimised, className, onFinished, onClick }) => (
diff --git a/src/components/views/location/ShareDialogButtons.tsx b/src/components/views/location/ShareDialogButtons.tsx index 398d274c8d..e282660215 100644 --- a/src/components/views/location/ShareDialogButtons.tsx +++ b/src/components/views/location/ShareDialogButtons.tsx @@ -19,6 +19,7 @@ import React from "react"; import AccessibleButton from "../elements/AccessibleButton"; import { Icon as BackIcon } from "../../../../res/img/element-icons/caret-left.svg"; import { Icon as CloseIcon } from "../../../../res/img/element-icons/cancel-rounded.svg"; +import { _t } from "../../../languageHandler"; interface Props { onCancel: () => void; @@ -32,7 +33,8 @@ const ShareDialogButtons: React.FC = ({ onBack, onCancel, displayBack }) {displayBack && ( @@ -41,7 +43,8 @@ const ShareDialogButtons: React.FC = ({ onBack, onCancel, displayBack }) )} diff --git a/test/components/views/location/LocationPicker-test.tsx b/test/components/views/location/LocationPicker-test.tsx index d4e2daa102..97f21ffe7a 100644 --- a/test/components/views/location/LocationPicker-test.tsx +++ b/test/components/views/location/LocationPicker-test.tsx @@ -15,9 +15,8 @@ limitations under the License. */ import React from "react"; +import { fireEvent, render, RenderResult } from "@testing-library/react"; import * as maplibregl from "maplibre-gl"; -// eslint-disable-next-line deprecate/import -import { mount, ReactWrapper } from "enzyme"; import { act } from "react-dom/test-utils"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { MatrixClient } from "matrix-js-sdk/src/client"; @@ -28,7 +27,7 @@ import LocationPicker from "../../../../src/components/views/location/LocationPi import { LocationShareType } from "../../../../src/components/views/location/shareLocation"; import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; -import { findById, findByTestId, mockPlatformPeg } from "../../../test-utils"; +import { getMockClientWithEventEmitter, mockPlatformPeg } from "../../../test-utils"; import { findMapStyleUrl, LocationShareError } from "../../../../src/utils/location"; jest.mock("../../../../src/utils/location/findMapStyleUrl", () => ({ @@ -49,17 +48,15 @@ describe("LocationPicker", () => { onChoose: jest.fn(), onFinished: jest.fn(), }; - const mockClient = { - on: jest.fn(), - removeListener: jest.fn(), - off: jest.fn(), + const mockClient = getMockClientWithEventEmitter({ isGuest: jest.fn(), getClientWellKnown: jest.fn(), - }; - const getComponent = (props = {}) => - mount(, { - wrappingComponent: MatrixClientContext.Provider, - wrappingComponentProps: { value: mockClient }, + }); + const getComponent = (props = {}): RenderResult => + render(, { + wrapper: ({ children }) => ( + {children} + ), }); const mapOptions = { container: {} as unknown as HTMLElement, style: "" }; @@ -94,18 +91,20 @@ describe("LocationPicker", () => { it("displays error when map emits an error", () => { // suppress expected error log jest.spyOn(logger, "error").mockImplementation(() => {}); - const wrapper = getComponent(); + const { getByTestId, getByText } = getComponent(); act(() => { // @ts-ignore mocked(mockMap).emit("error", { error: "Something went wrong" }); - wrapper.setProps({}); }); - expect(findByTestId(wrapper, "map-rendering-error").find("p").text()).toEqual( - "This homeserver is not configured correctly to display maps, " + - "or the configured map server may be unreachable.", - ); + expect(getByTestId("map-rendering-error")).toBeInTheDocument(); + expect( + getByText( + "This homeserver is not configured correctly to display maps, " + + "or the configured map server may be unreachable.", + ), + ).toBeInTheDocument(); }); it("displays error when map display is not configured properly", () => { @@ -115,12 +114,9 @@ describe("LocationPicker", () => { throw new Error(LocationShareError.MapStyleUrlNotConfigured); }); - const wrapper = getComponent(); - wrapper.setProps({}); + const { getByText } = getComponent(); - expect(findByTestId(wrapper, "map-rendering-error").find("p").text()).toEqual( - "This homeserver is not configured to display maps.", - ); + expect(getByText("This homeserver is not configured to display maps.")).toBeInTheDocument(); }); it("displays error when map setup throws", () => { @@ -132,13 +128,14 @@ describe("LocationPicker", () => { throw new Error("oups"); }); - const wrapper = getComponent(); - wrapper.setProps({}); + const { getByText } = getComponent(); - expect(findByTestId(wrapper, "map-rendering-error").find("p").text()).toEqual( - "This homeserver is not configured correctly to display maps, " + - "or the configured map server may be unreachable.", - ); + expect( + getByText( + "This homeserver is not configured correctly to display maps, " + + "or the configured map server may be unreachable.", + ), + ).toBeInTheDocument(); }); it("initiates map with geolocation", () => { @@ -174,57 +171,49 @@ describe("LocationPicker", () => { }); it("sets position on geolocate event", () => { - const wrapper = getComponent({ shareType }); + const { container, getByTestId } = getComponent({ shareType }); act(() => { // @ts-ignore mocked(mockGeolocate).emit("geolocate", mockGeolocationPosition); - wrapper.setProps({}); }); // marker added expect(maplibregl.Marker).toHaveBeenCalled(); expect(mockMarker.setLngLat).toHaveBeenCalledWith(new maplibregl.LngLat(12.4, 43.2)); // submit button is enabled when position is truthy - expect(findByTestId(wrapper, "location-picker-submit-button").at(0).props().disabled).toBeFalsy(); - expect(wrapper.find("MemberAvatar").length).toBeTruthy(); + expect(getByTestId("location-picker-submit-button")).not.toBeDisabled(); + expect(container.querySelector(".mx_BaseAvatar")).toBeInTheDocument(); }); it("disables submit button until geolocation completes", () => { const onChoose = jest.fn(); - const wrapper = getComponent({ shareType, onChoose }); + const { getByTestId } = getComponent({ shareType, onChoose }); - // submit button is enabled when position is truthy - expect(findByTestId(wrapper, "location-picker-submit-button").at(0).props().disabled).toBeTruthy(); - act(() => { - findByTestId(wrapper, "location-picker-submit-button").at(0).simulate("click"); - }); + // button is disabled + expect(getByTestId("location-picker-submit-button")).toBeDisabled(); + fireEvent.click(getByTestId("location-picker-submit-button")); // nothing happens on button click expect(onChoose).not.toHaveBeenCalled(); act(() => { // @ts-ignore mocked(mockGeolocate).emit("geolocate", mockGeolocationPosition); - wrapper.setProps({}); }); // submit button is enabled when position is truthy - expect(findByTestId(wrapper, "location-picker-submit-button").at(0).props().disabled).toBeFalsy(); + expect(getByTestId("location-picker-submit-button")).not.toBeDisabled(); }); it("submits location", () => { const onChoose = jest.fn(); - const wrapper = getComponent({ onChoose, shareType }); + const { getByTestId } = getComponent({ onChoose, shareType }); act(() => { // @ts-ignore mocked(mockGeolocate).emit("geolocate", mockGeolocationPosition); // make sure button is enabled - wrapper.setProps({}); - }); - - act(() => { - findByTestId(wrapper, "location-picker-submit-button").at(0).simulate("click"); }); + fireEvent.click(getByTestId("location-picker-submit-button")); // content of this call is tested in LocationShareMenu-test expect(onChoose).toHaveBeenCalled(); }); @@ -239,34 +228,21 @@ describe("LocationPicker", () => { const shareType = LocationShareType.Live; testUserLocationShareTypes(shareType); - const getOption = (wrapper: ReactWrapper, timeout: number) => - findById(wrapper, `live-duration__${timeout}`).at(0); - const getDropdown = (wrapper: ReactWrapper) => findByTestId(wrapper, "live-duration-dropdown"); - const getSelectedOption = (wrapper: ReactWrapper) => findById(wrapper, "live-duration_value"); - - const openDropdown = (wrapper: ReactWrapper) => - act(() => { - const dropdown = getDropdown(wrapper); - dropdown.find('[role="button"]').at(0).simulate("click"); - wrapper.setProps({}); - }); - it("renders live duration dropdown with default option", () => { - const wrapper = getComponent({ shareType }); - expect(getSelectedOption(getDropdown(wrapper)).text()).toEqual("Share for 15m"); + const { getByText } = getComponent({ shareType }); + expect(getByText("Share for 15m")).toBeInTheDocument(); }); it("updates selected duration", () => { - const wrapper = getComponent({ shareType }); + const { getByText, getByLabelText } = getComponent({ shareType }); - openDropdown(wrapper); - const dropdown = getDropdown(wrapper); - act(() => { - getOption(dropdown, 3600000).simulate("click"); - }); + // open dropdown + fireEvent.click(getByLabelText("Share for 15m")); + + fireEvent.click(getByText("Share for 1h")); // value updated - expect(getSelectedOption(getDropdown(wrapper)).text()).toEqual("Share for 1h"); + expect(getByText("Share for 1h")).toMatchSnapshot(); }); }); @@ -303,22 +279,21 @@ describe("LocationPicker", () => { it("does not set position on geolocate event", () => { mocked(maplibregl.Marker).mockClear(); - const wrapper = getComponent({ shareType }); + const { container } = getComponent({ shareType }); act(() => { // @ts-ignore mocked(mockGeolocate).emit("geolocate", mockGeolocationPosition); }); // marker not added - expect(wrapper.find("Marker").length).toBeFalsy(); + expect(container.querySelector("mx_Marker")).not.toBeInTheDocument(); }); it("sets position on click event", () => { - const wrapper = getComponent({ shareType }); + const { container } = getComponent({ shareType }); act(() => { // @ts-ignore mocked(mockMap).emit("click", mockClickEvent); - wrapper.setProps({}); }); // marker added @@ -326,21 +301,18 @@ describe("LocationPicker", () => { expect(mockMarker.setLngLat).toHaveBeenCalledWith(new maplibregl.LngLat(12.4, 43.2)); // marker is set, icon not avatar - expect(wrapper.find(".mx_Marker_icon").length).toBeTruthy(); + expect(container.querySelector(".mx_Marker_icon")).toBeInTheDocument(); }); it("submits location", () => { const onChoose = jest.fn(); - const wrapper = getComponent({ onChoose, shareType }); + const { getByTestId } = getComponent({ onChoose, shareType }); act(() => { // @ts-ignore mocked(mockMap).emit("click", mockClickEvent); - wrapper.setProps({}); }); - act(() => { - findByTestId(wrapper, "location-picker-submit-button").at(0).simulate("click"); - }); + fireEvent.click(getByTestId("location-picker-submit-button")); // content of this call is tested in LocationShareMenu-test expect(onChoose).toHaveBeenCalled(); diff --git a/test/components/views/location/LocationShareMenu-test.tsx b/test/components/views/location/LocationShareMenu-test.tsx index 567fffa591..00df011f35 100644 --- a/test/components/views/location/LocationShareMenu-test.tsx +++ b/test/components/views/location/LocationShareMenu-test.tsx @@ -15,8 +15,6 @@ limitations under the License. */ import React from "react"; -// eslint-disable-next-line deprecate/import -import { mount, ReactWrapper } from "enzyme"; import { mocked } from "jest-mock"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { MatrixClient } from "matrix-js-sdk/src/client"; @@ -24,6 +22,8 @@ import { RelationType } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { M_ASSET, LocationAssetType } from "matrix-js-sdk/src/@types/location"; import { act } from "react-dom/test-utils"; +import { fireEvent, render, RenderResult } from "@testing-library/react"; +import * as maplibregl from "maplibre-gl"; import LocationShareMenu from "../../../../src/components/views/location/LocationShareMenu"; import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; @@ -32,8 +32,6 @@ import SettingsStore from "../../../../src/settings/SettingsStore"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import { LocationShareType } from "../../../../src/components/views/location/shareLocation"; import { - findByTagAndTestId, - findByTestId, flushPromisesWithFakeTimers, getMockClientWithEventEmitter, setupAsyncStoreWithClient, @@ -99,6 +97,12 @@ describe("", () => { sender: new RoomMember("!room:server.org", userId), }; + const mockGeolocate = new maplibregl.GeolocateControl({}); + jest.spyOn(mockGeolocate, "on"); + const mapOptions = { container: {} as unknown as HTMLElement, style: "" }; + const mockMap = new maplibregl.Map(mapOptions); + jest.spyOn(mockMap, "on"); + const position = { coords: { latitude: -36.24484561954707, @@ -116,10 +120,11 @@ describe("", () => { return store; }; - const getComponent = (props = {}) => - mount(, { - wrappingComponent: MatrixClientContext.Provider, - wrappingComponentProps: { value: mockClient }, + const getComponent = (props = {}): RenderResult => + render(, { + wrapper: ({ children }) => ( + {children} + ), }); beforeEach(async () => { @@ -135,74 +140,74 @@ describe("", () => { await makeOwnBeaconStore(); }); - const getShareTypeOption = (component: ReactWrapper, shareType: LocationShareType) => - findByTagAndTestId(component, `share-location-option-${shareType}`, "button"); + const getBackButton = (getByLabelText: RenderResult["getByLabelText"]) => getByLabelText("Back"); - const getBackButton = (component: ReactWrapper) => - findByTagAndTestId(component, "share-dialog-buttons-back", "button"); + const getCancelButton = (getByLabelText: RenderResult["getByLabelText"]) => getByLabelText("Close"); - const getCancelButton = (component: ReactWrapper) => - findByTagAndTestId(component, "share-dialog-buttons-cancel", "button"); + const setLocationGeolocate = () => { + // get the callback LocationShareMenu registered for geolocate + expect(mocked(mockGeolocate.on)).toHaveBeenCalledWith("geolocate", expect.any(Function)); + const [, onGeolocateCallback] = mocked(mockGeolocate.on).mock.calls.find(([event]) => event === "geolocate"); - const getSubmitButton = (component: ReactWrapper) => - findByTagAndTestId(component, "location-picker-submit-button", "button"); - - const setLocation = (component: ReactWrapper) => { // set the location - const locationPickerInstance = component.find("LocationPicker").instance(); - act(() => { - // @ts-ignore - locationPickerInstance.onGeolocate(position); - // make sure button gets enabled - component.setProps({}); - }); + onGeolocateCallback(position); }; - const setShareType = (component: ReactWrapper, shareType: LocationShareType) => - act(() => { - getShareTypeOption(component, shareType).at(0).simulate("click"); - component.setProps({}); - }); + const setLocationClick = () => { + // get the callback LocationShareMenu registered for geolocate + expect(mocked(mockMap.on)).toHaveBeenCalledWith("click", expect.any(Function)); + const [, onMapClickCallback] = mocked(mockMap.on).mock.calls.find(([event]) => event === "click"); + + const event = { + lngLat: { lng: position.coords.longitude, lat: position.coords.latitude }, + } as unknown as maplibregl.MapMouseEvent; + // set the location + onMapClickCallback(event); + }; + + const shareTypeLabels: Record = { + [LocationShareType.Own]: "My current location", + [LocationShareType.Live]: "My live location", + [LocationShareType.Pin]: "Drop a Pin", + }; + const setShareType = (getByText: RenderResult["getByText"], shareType: LocationShareType) => { + fireEvent.click(getByText(shareTypeLabels[shareType])); + }; describe("when only Own share type is enabled", () => { beforeEach(() => enableSettings([])); it("renders own and live location options", () => { - const component = getComponent(); - expect(getShareTypeOption(component, LocationShareType.Own).length).toBe(1); - expect(getShareTypeOption(component, LocationShareType.Live).length).toBe(1); + const { getByText } = getComponent(); + expect(getByText(shareTypeLabels[LocationShareType.Own])).toBeInTheDocument(); + expect(getByText(shareTypeLabels[LocationShareType.Live])).toBeInTheDocument(); }); it("renders back button from location picker screen", () => { - const component = getComponent(); - setShareType(component, LocationShareType.Own); + const { getByText, getByLabelText } = getComponent(); + setShareType(getByText, LocationShareType.Own); - expect(getBackButton(component).length).toBe(1); + expect(getBackButton(getByLabelText)).toBeInTheDocument(); }); it("clicking cancel button from location picker closes dialog", () => { const onFinished = jest.fn(); - const component = getComponent({ onFinished }); + const { getByLabelText } = getComponent({ onFinished }); - act(() => { - getCancelButton(component).at(0).simulate("click"); - }); + fireEvent.click(getCancelButton(getByLabelText)); expect(onFinished).toHaveBeenCalled(); }); it("creates static own location share event on submission", () => { const onFinished = jest.fn(); - const component = getComponent({ onFinished }); + const { getByText } = getComponent({ onFinished }); - setShareType(component, LocationShareType.Own); + setShareType(getByText, LocationShareType.Own); - setLocation(component); + setLocationGeolocate(); - act(() => { - getSubmitButton(component).at(0).simulate("click"); - component.setProps({}); - }); + fireEvent.click(getByText("Share location")); expect(onFinished).toHaveBeenCalled(); const [messageRoomId, relation, messageBody] = mockClient.sendMessage.mock.calls[0]; @@ -220,68 +225,60 @@ describe("", () => { describe("with pin drop share type enabled", () => { it("renders share type switch with own and pin drop options", () => { - const component = getComponent(); - expect(component.find("LocationPicker").length).toBe(0); + const { getByText } = getComponent(); + expect(document.querySelector(".mx_LocationPicker")).not.toBeInTheDocument(); - expect(getShareTypeOption(component, LocationShareType.Own).length).toBe(1); - expect(getShareTypeOption(component, LocationShareType.Pin).length).toBe(1); + expect(getByText(shareTypeLabels[LocationShareType.Own])).toBeInTheDocument(); + expect(getByText(shareTypeLabels[LocationShareType.Pin])).toBeInTheDocument(); }); it("does not render back button on share type screen", () => { - const component = getComponent(); - expect(getBackButton(component).length).toBe(0); + const { queryByLabelText } = getComponent(); + expect(queryByLabelText("Back")).not.toBeInTheDocument(); }); it("clicking cancel button from share type screen closes dialog", () => { const onFinished = jest.fn(); - const component = getComponent({ onFinished }); + const { getByLabelText } = getComponent({ onFinished }); - act(() => { - getCancelButton(component).at(0).simulate("click"); - }); + fireEvent.click(getCancelButton(getByLabelText)); expect(onFinished).toHaveBeenCalled(); }); it("selecting own location share type advances to location picker", () => { - const component = getComponent(); + const { getByText } = getComponent(); - setShareType(component, LocationShareType.Own); + setShareType(getByText, LocationShareType.Own); - expect(component.find("LocationPicker").length).toBe(1); + expect(document.querySelector(".mx_LocationPicker")).toBeInTheDocument(); }); it("clicking back button from location picker screen goes back to share screen", () => { const onFinished = jest.fn(); - const component = getComponent({ onFinished }); + const { getByText, getByLabelText } = getComponent({ onFinished }); // advance to location picker - setShareType(component, LocationShareType.Own); + setShareType(getByText, LocationShareType.Own); - expect(component.find("LocationPicker").length).toBe(1); + expect(document.querySelector(".mx_LocationPicker")).toBeInTheDocument(); - act(() => { - getBackButton(component).at(0).simulate("click"); - component.setProps({}); - }); + fireEvent.click(getBackButton(getByLabelText)); // back to share type - expect(component.find("ShareType").length).toBe(1); + expect(getByText("What location type do you want to share?")).toBeInTheDocument(); }); it("creates pin drop location share event on submission", () => { const onFinished = jest.fn(); - const component = getComponent({ onFinished }); + const { getByText } = getComponent({ onFinished }); // advance to location picker - setShareType(component, LocationShareType.Pin); + setShareType(getByText, LocationShareType.Pin); - setLocation(component); + setLocationClick(); - act(() => { - getSubmitButton(component).at(0).simulate("click"); - component.setProps({}); - }); + fireEvent.click(getByText("Share location")); expect(onFinished).toHaveBeenCalled(); const [messageRoomId, relation, messageBody] = mockClient.sendMessage.mock.calls[0]; @@ -300,53 +297,41 @@ describe("", () => { describe("with live location disabled", () => { beforeEach(() => enableSettings([])); - const getToggle = (component: ReactWrapper) => - findByTestId(component, "enable-live-share-toggle").find('[role="switch"]').at(0); - const getSubmitEnableButton = (component: ReactWrapper) => - findByTestId(component, "enable-live-share-submit").at(0); - it("goes to labs flag screen after live options is clicked", () => { const onFinished = jest.fn(); - const component = getComponent({ onFinished }); + const { getByText, getByTestId } = getComponent({ onFinished }); - setShareType(component, LocationShareType.Live); + setShareType(getByText, LocationShareType.Live); - expect(findByTestId(component, "location-picker-enable-live-share")).toMatchSnapshot(); + expect(getByTestId("location-picker-enable-live-share")).toMatchSnapshot(); }); it("disables OK button when labs flag is not enabled", () => { - const component = getComponent(); + const { getByText } = getComponent(); - setShareType(component, LocationShareType.Live); + setShareType(getByText, LocationShareType.Live); - expect(getSubmitEnableButton(component).props()["disabled"]).toBeTruthy(); + expect(getByText("OK").hasAttribute("disabled")).toBeTruthy(); }); it("enables OK button when labs flag is toggled to enabled", () => { - const component = getComponent(); + const { getByText, getByLabelText } = getComponent(); - setShareType(component, LocationShareType.Live); + setShareType(getByText, LocationShareType.Live); - act(() => { - getToggle(component).simulate("click"); - component.setProps({}); - }); - expect(getSubmitEnableButton(component).props()["disabled"]).toBeFalsy(); + fireEvent.click(getByLabelText("Enable live location sharing")); + + expect(getByText("OK").hasAttribute("disabled")).toBeFalsy(); }); it("enables live share setting on ok button submit", () => { - const component = getComponent(); + const { getByText, getByLabelText } = getComponent(); - setShareType(component, LocationShareType.Live); + setShareType(getByText, LocationShareType.Live); - act(() => { - getToggle(component).simulate("click"); - component.setProps({}); - }); + fireEvent.click(getByLabelText("Enable live location sharing")); - act(() => { - getSubmitEnableButton(component).simulate("click"); - }); + fireEvent.click(getByText("OK")); expect(SettingsStore.setValue).toHaveBeenCalledWith( "feature_location_share_live", @@ -365,12 +350,12 @@ describe("", () => { }, 1000); }); mocked(SettingsStore.getValue).mockReturnValue(false); - const component = getComponent(); + const { getByText, getByLabelText } = getComponent(); - setShareType(component, LocationShareType.Live); + setShareType(getByText, LocationShareType.Live); // we're on enable live share screen - expect(findByTestId(component, "location-picker-enable-live-share").length).toBeTruthy(); + expect(getByLabelText("Enable live location sharing")).toBeInTheDocument(); act(() => { mocked(SettingsStore.getValue).mockReturnValue(true); @@ -378,10 +363,8 @@ describe("", () => { jest.runAllTimers(); }); - component.setProps({}); - // advanced to location picker - expect(component.find("LocationPicker").length).toBeTruthy(); + expect(document.querySelector(".mx_LocationPicker")).toBeInTheDocument(); }); }); @@ -393,23 +376,20 @@ describe("", () => { rel_type: RelationType.Thread, event_id: "12345", }; - const component = getComponent({ relation }); + const { queryByText } = getComponent({ relation }); - expect(getShareTypeOption(component, LocationShareType.Live).length).toBeFalsy(); + expect(queryByText(shareTypeLabels[LocationShareType.Live])).not.toBeInTheDocument(); }); it("creates beacon info event on submission", async () => { const onFinished = jest.fn(); - const component = getComponent({ onFinished }); + const { getByText } = getComponent({ onFinished }); // advance to location picker - setShareType(component, LocationShareType.Live); - setLocation(component); + setShareType(getByText, LocationShareType.Live); + setLocationGeolocate(); - act(() => { - getSubmitButton(component).at(0).simulate("click"); - component.setProps({}); - }); + fireEvent.click(getByText("Share location")); // flush stopping existing beacons promises await flushPromisesWithFakeTimers(); @@ -435,16 +415,13 @@ describe("", () => { const logSpy = jest.spyOn(logger, "error").mockReturnValue(undefined); const error = new Error("oh no"); mockClient.unstable_createLiveBeacon.mockRejectedValue(error); - const component = getComponent(); + const { getByText } = getComponent(); // advance to location picker - setShareType(component, LocationShareType.Live); - setLocation(component); + setShareType(getByText, LocationShareType.Live); + setLocationGeolocate(); - act(() => { - getSubmitButton(component).at(0).simulate("click"); - component.setProps({}); - }); + fireEvent.click(getByText("Share location")); await flushPromisesWithFakeTimers(); await flushPromisesWithFakeTimers(); @@ -467,16 +444,13 @@ describe("", () => { const logSpy = jest.spyOn(logger, "error").mockReturnValue(undefined); const error = { errcode: "M_FORBIDDEN" } as unknown as Error; mockClient.unstable_createLiveBeacon.mockRejectedValue(error); - const component = getComponent(); + const { getByText } = getComponent(); // advance to location picker - setShareType(component, LocationShareType.Live); - setLocation(component); + setShareType(getByText, LocationShareType.Live); + setLocationGeolocate(); - act(() => { - getSubmitButton(component).at(0).simulate("click"); - component.setProps({}); - }); + fireEvent.click(getByText("Share location")); await flushPromisesWithFakeTimers(); await flushPromisesWithFakeTimers(); diff --git a/test/components/views/location/LocationViewDialog-test.tsx b/test/components/views/location/LocationViewDialog-test.tsx index 5dee559bc0..bcf8f8ec8d 100644 --- a/test/components/views/location/LocationViewDialog-test.tsx +++ b/test/components/views/location/LocationViewDialog-test.tsx @@ -15,8 +15,7 @@ limitations under the License. */ import React from "react"; -// eslint-disable-next-line deprecate/import -import { mount } from "enzyme"; +import { render, RenderResult } from "@testing-library/react"; import { RoomMember } from "matrix-js-sdk/src/matrix"; import { LocationAssetType } from "matrix-js-sdk/src/@types/location"; @@ -39,11 +38,11 @@ describe("", () => { mxEvent: defaultEvent, onFinished: jest.fn(), }; - const getComponent = (props = {}) => mount(); + const getComponent = (props = {}): RenderResult => render(); it("renders map correctly", () => { - const component = getComponent(); - expect(component.find("Map")).toMatchSnapshot(); + const { container } = getComponent(); + expect(container.querySelector(".mx_Map")).toMatchSnapshot(); }); it("renders marker correctly for self share", () => { @@ -51,7 +50,7 @@ describe("", () => { const member = new RoomMember(roomId, userId); // @ts-ignore cheat assignment to property selfShareEvent.sender = member; - const component = getComponent({ mxEvent: selfShareEvent }); - expect(component.find("SmartMarker").prop("roomMember")).toEqual(member); + const { container } = getComponent({ mxEvent: selfShareEvent }); + expect(container.querySelector(".mx_BaseAvatar_image").getAttribute("title")).toEqual(userId); }); }); diff --git a/test/components/views/location/SmartMarker-test.tsx b/test/components/views/location/SmartMarker-test.tsx index 8ddcafb00f..93233dad35 100644 --- a/test/components/views/location/SmartMarker-test.tsx +++ b/test/components/views/location/SmartMarker-test.tsx @@ -15,8 +15,7 @@ limitations under the License. */ import React from "react"; -// eslint-disable-next-line deprecate/import -import { mount } from "enzyme"; +import { render } from "@testing-library/react"; import { mocked } from "jest-mock"; import * as maplibregl from "maplibre-gl"; @@ -35,17 +34,15 @@ describe("", () => { map: mockMap, geoUri: "geo:43.2,54.6", }; - const getComponent = (props = {}) => mount(); + const getComponent = (props = {}): JSX.Element => ; beforeEach(() => { jest.clearAllMocks(); }); it("creates a marker on mount", () => { - const component = getComponent(); - expect(component).toMatchSnapshot(); - - component.setProps({}); + const { container } = render(getComponent()); + expect(container).toMatchSnapshot(); // marker added only once expect(maplibregl.Marker).toHaveBeenCalledTimes(1); @@ -56,10 +53,10 @@ describe("", () => { }); it("updates marker position on change", () => { - const component = getComponent({ geoUri: "geo:40,50" }); + const { rerender } = render(getComponent({ geoUri: "geo:40,50" })); - component.setProps({ geoUri: "geo:41,51" }); - component.setProps({ geoUri: "geo:42,52" }); + rerender(getComponent({ geoUri: "geo:41,51" })); + rerender(getComponent({ geoUri: "geo:42,52" })); // marker added only once expect(maplibregl.Marker).toHaveBeenCalledTimes(1); @@ -70,12 +67,10 @@ describe("", () => { }); it("removes marker on unmount", () => { - const component = getComponent(); - expect(component).toMatchSnapshot(); + const { unmount, container } = render(getComponent()); + expect(container).toMatchSnapshot(); - component.setProps({}); - - component.unmount(); + unmount(); expect(mockMarker.remove).toHaveBeenCalled(); }); }); diff --git a/test/components/views/location/__snapshots__/LocationPicker-test.tsx.snap b/test/components/views/location/__snapshots__/LocationPicker-test.tsx.snap new file mode 100644 index 0000000000..1b21e9b48d --- /dev/null +++ b/test/components/views/location/__snapshots__/LocationPicker-test.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LocationPicker for Live location share type updates selected duration 1`] = ` +
+ Share for 1h +
+`; diff --git a/test/components/views/location/__snapshots__/LocationShareMenu-test.tsx.snap b/test/components/views/location/__snapshots__/LocationShareMenu-test.tsx.snap index f30cdac00a..cd492db7a2 100644 --- a/test/components/views/location/__snapshots__/LocationShareMenu-test.tsx.snap +++ b/test/components/views/location/__snapshots__/LocationShareMenu-test.tsx.snap @@ -2,116 +2,53 @@ exports[` with live location disabled goes to labs flag screen after live options is clicked 1`] = `
- +

-
- - -

- Live location sharing -

-
+ Live location sharing +

Please note: this is a labs feature using a temporary implementation. This means you will not be able to delete your location history, and advanced users will be able to see your location history even after you stop sharing your live location with this room.

- + + Enable live location sharing +
- - Enable live location sharing - - <_default - checked={false} - onChange={[Function]} - title="Enable live location sharing" - > - - -
-
-
- - - +
- - + - + OK +
`; diff --git a/test/components/views/location/__snapshots__/LocationViewDialog-test.tsx.snap b/test/components/views/location/__snapshots__/LocationViewDialog-test.tsx.snap index 115dc41203..62847f2dc4 100644 --- a/test/components/views/location/__snapshots__/LocationViewDialog-test.tsx.snap +++ b/test/components/views/location/__snapshots__/LocationViewDialog-test.tsx.snap @@ -1,219 +1,49 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[` renders map correctly 1`] = ` - -
- +
- - -
- -
-
-
- -
- - - -
- -
-
-
- - -
-
-
- +
- +
+ +
+
+
+
+
+
+
- +
`; diff --git a/test/components/views/location/__snapshots__/MapError-test.tsx.snap b/test/components/views/location/__snapshots__/MapError-test.tsx.snap index 4fdef3e5d3..427da8ffef 100644 --- a/test/components/views/location/__snapshots__/MapError-test.tsx.snap +++ b/test/components/views/location/__snapshots__/MapError-test.tsx.snap @@ -4,7 +4,7 @@ exports[` applies class when isMinimised is truthy 1`] = `
renders correctly for MapStyleUrlNotConfigured 1`] = `
renders correctly for MapStyleUrlNotReachable 1`] = `
creates a marker on mount 1`] = ` - +
- +
- -
-
-
- +
- +
- +
`; exports[` removes marker on unmount 1`] = ` - +
- +
- -
-
-
- +
- +
- +
`; diff --git a/test/components/views/messages/__snapshots__/MBeaconBody-test.tsx.snap b/test/components/views/messages/__snapshots__/MBeaconBody-test.tsx.snap index a9acf277c6..703f91ceff 100644 --- a/test/components/views/messages/__snapshots__/MBeaconBody-test.tsx.snap +++ b/test/components/views/messages/__snapshots__/MBeaconBody-test.tsx.snap @@ -9,7 +9,7 @@ exports[` when map display is not configured renders maps unavail >