/* 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 { mocked } from "jest-mock"; import { Beacon } from "matrix-js-sdk/src/matrix"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import OwnBeaconStatus from "../../../../src/components/views/beacon/OwnBeaconStatus"; import { BeaconDisplayStatus } from "../../../../src/components/views/beacon/displayStatus"; import { useOwnLiveBeacons } from "../../../../src/utils/beacon"; import { makeBeaconInfoEvent } from "../../../test-utils"; jest.mock("../../../../src/utils/beacon/useOwnLiveBeacons", () => ({ useOwnLiveBeacons: jest.fn(), })); const defaultLiveBeaconsState = { onStopSharing: jest.fn(), onResetLocationPublishError: jest.fn(), stoppingInProgress: false, hasStopSharingError: false, hasLocationPublishError: false, }; describe("", () => { const defaultProps = { displayStatus: BeaconDisplayStatus.Loading, }; const userId = "@user:server"; const roomId = "!room:server"; let defaultBeacon: Beacon; const renderComponent = (props: Partial> = {}) => render(); const getRetryButton = () => screen.getByRole("button", { name: "Retry" }); const getStopButton = () => screen.getByRole("button", { name: "Stop" }); beforeEach(() => { jest.spyOn(global.Date, "now").mockReturnValue(123456789); mocked(useOwnLiveBeacons).mockClear().mockReturnValue(defaultLiveBeaconsState); defaultBeacon = new Beacon(makeBeaconInfoEvent(userId, roomId)); }); it("renders without a beacon instance", () => { const { asFragment } = renderComponent(); expect(asFragment()).toMatchSnapshot(); }); describe("Active state", () => { it("renders stop button", () => { const displayStatus = BeaconDisplayStatus.Active; mocked(useOwnLiveBeacons).mockReturnValue({ ...defaultLiveBeaconsState, onStopSharing: jest.fn(), }); renderComponent({ displayStatus, beacon: defaultBeacon }); expect(screen.getByText("Live location enabled")).toBeInTheDocument(); expect(getStopButton()).toBeInTheDocument(); }); it("stops sharing on stop button click", async () => { const displayStatus = BeaconDisplayStatus.Active; const onStopSharing = jest.fn(); mocked(useOwnLiveBeacons).mockReturnValue({ ...defaultLiveBeaconsState, onStopSharing, }); renderComponent({ displayStatus, beacon: defaultBeacon }); await userEvent.click(getStopButton()); expect(onStopSharing).toHaveBeenCalled(); }); }); describe("errors", () => { it("renders in error mode when displayStatus is error", () => { const displayStatus = BeaconDisplayStatus.Error; renderComponent({ displayStatus }); expect(screen.getByText("Live location error")).toBeInTheDocument(); // no actions for plain error expect(screen.queryByRole("button")).not.toBeInTheDocument(); }); describe("with location publish error", () => { it("renders in error mode", () => { const displayStatus = BeaconDisplayStatus.Active; mocked(useOwnLiveBeacons).mockReturnValue({ ...defaultLiveBeaconsState, hasLocationPublishError: true, onResetLocationPublishError: jest.fn(), }); renderComponent({ displayStatus, beacon: defaultBeacon }); expect(screen.getByText("Live location error")).toBeInTheDocument(); // retry button expect(getRetryButton()).toBeInTheDocument(); }); it("retry button resets location publish error", async () => { const displayStatus = BeaconDisplayStatus.Active; const onResetLocationPublishError = jest.fn(); mocked(useOwnLiveBeacons).mockReturnValue({ ...defaultLiveBeaconsState, hasLocationPublishError: true, onResetLocationPublishError, }); renderComponent({ displayStatus, beacon: defaultBeacon }); await userEvent.click(getRetryButton()); expect(onResetLocationPublishError).toHaveBeenCalled(); }); }); describe("with stopping error", () => { it("renders in error mode", () => { const displayStatus = BeaconDisplayStatus.Active; mocked(useOwnLiveBeacons).mockReturnValue({ ...defaultLiveBeaconsState, hasLocationPublishError: false, hasStopSharingError: true, onStopSharing: jest.fn(), }); renderComponent({ displayStatus, beacon: defaultBeacon }); expect(screen.getByText("Live location error")).toBeInTheDocument(); // retry button expect(getRetryButton()).toBeInTheDocument(); }); it("retry button retries stop sharing", async () => { const displayStatus = BeaconDisplayStatus.Active; const onStopSharing = jest.fn(); mocked(useOwnLiveBeacons).mockReturnValue({ ...defaultLiveBeaconsState, hasStopSharingError: true, onStopSharing, }); renderComponent({ displayStatus, beacon: defaultBeacon }); await userEvent.click(getRetryButton()); expect(onStopSharing).toHaveBeenCalled(); }); }); }); it("renders loading state correctly", () => { const component = renderComponent(); expect(component).toBeTruthy(); }); });