diff --git a/test/components/views/elements/AppTile-test.tsx b/test/components/views/elements/AppTile-test.tsx index 4e3d7000e5..5aaead98fa 100644 --- a/test/components/views/elements/AppTile-test.tsx +++ b/test/components/views/elements/AppTile-test.tsx @@ -15,13 +15,14 @@ limitations under the License. */ import React from "react"; -import TestRenderer from "react-test-renderer"; import { jest } from "@jest/globals"; import { Room } from "matrix-js-sdk/src/models/room"; import { ClientWidgetApi, MatrixWidgetType } from "matrix-widget-api"; -// eslint-disable-next-line deprecate/import -import { mount, ReactWrapper } from "enzyme"; import { Optional } from "matrix-events-sdk"; +import { act, render, RenderResult } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { MatrixClient } from "matrix-js-sdk/src/matrix"; +import { SpiedFunction } from "jest-mock"; import RightPanel from "../../../../src/components/structures/RightPanel"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; @@ -45,7 +46,7 @@ import { ElementWidget } from "../../../../src/stores/widgets/StopGapWidget"; import { WidgetMessagingStore } from "../../../../src/stores/widgets/WidgetMessagingStore"; describe("AppTile", () => { - let cli; + let cli: MatrixClient; let r1: Room; let r2: Room; const resizeNotifier = new ResizeNotifier(); @@ -90,7 +91,7 @@ describe("AppTile", () => { type: MatrixWidgetType.Custom, url: "https://example.com", name: "Example 1", - creatorUserId: cli.getUserId(), + creatorUserId: cli.getSafeUserId(), avatar_url: undefined, }; app2 = { @@ -100,12 +101,13 @@ describe("AppTile", () => { type: MatrixWidgetType.Custom, url: "https://example.com", name: "Example 2", - creatorUserId: cli.getUserId(), + creatorUserId: cli.getSafeUserId(), avatar_url: undefined, }; - jest.spyOn(WidgetStore.instance, "getApps").mockImplementation((roomId) => { + jest.spyOn(WidgetStore.instance, "getApps").mockImplementation((roomId: string): Array => { if (roomId === "r1") return [app1]; if (roomId === "r2") return [app2]; + return []; }); // Wake up various stores we rely on @@ -143,7 +145,7 @@ describe("AppTile", () => { }); // Run initial render with room 1, and also running lifecycle methods - const renderer = TestRenderer.create( + const renderResult = render( , @@ -156,25 +158,25 @@ describe("AppTile", () => { }); await rpsUpdated; + expect(renderResult.getByText("Example 1")).toBeInTheDocument(); expect(ActiveWidgetStore.instance.isLive("1", "r1")).toBe(true); // We want to verify that as we change to room 2, we should close the // right panel and destroy the widget. - const instance = renderer.root.findByType(AppTile).instance; - const endWidgetActions = jest.spyOn(instance, "endWidgetActions"); // Switch to room 2 dis.dispatch({ action: Action.ViewRoom, room_id: "r2", }); - renderer.update( + + renderResult.rerender( , ); - expect(endWidgetActions.mock.calls.length).toBe(1); + expect(renderResult.queryByText("Example 1")).not.toBeInTheDocument(); expect(ActiveWidgetStore.instance.isLive("1", "r1")).toBe(false); mockSettings.mockRestore(); @@ -204,7 +206,7 @@ describe("AppTile", () => { }); // Run initial render with room 1, and also running lifecycle methods - const renderer = TestRenderer.create( + const renderResult = render( , @@ -246,7 +248,7 @@ describe("AppTile", () => { action: Action.ViewRoom, room_id: "r2", }); - renderer.update( + renderResult.rerender( , @@ -274,33 +276,31 @@ describe("AppTile", () => { return null; }); - TestRenderer.act(() => { + act(() => { WidgetLayoutStore.instance.recalculateRoom(r1); }); // Run initial render with room 1, and also running lifecycle methods - const renderer = TestRenderer.create( + const renderResult = render( - + , ); + expect(renderResult.getByText("Example 1")).toBeInTheDocument(); expect(ActiveWidgetStore.instance.isLive("1", "r1")).toBe(true); // We want to verify that as we move the widget to the center container, // the widget frame remains running. - const instance = renderer.root.findByType(AppTile).instance; - const endWidgetActions = jest.spyOn(instance, "endWidgetActions"); - - // Move widget to center // Stop mocking settings so that the widget move can take effect mockSettings.mockRestore(); - TestRenderer.act(() => { + act(() => { + // Move widget to center WidgetLayoutStore.instance.moveToContainer(r1, app1, Container.Center); }); - expect(endWidgetActions.mock.calls.length).toBe(0); + expect(renderResult.getByText("Example 1")).toBeInTheDocument(); expect(ActiveWidgetStore.instance.isLive("1", "r1")).toBe(true); }); @@ -313,11 +313,11 @@ describe("AppTile", () => { }); describe("for a pinned widget", () => { - let wrapper: ReactWrapper; - let moveToContainerSpy; + let renderResult: RenderResult; + let moveToContainerSpy: SpiedFunction; beforeEach(() => { - wrapper = mount( + renderResult = render( , @@ -326,19 +326,17 @@ describe("AppTile", () => { moveToContainerSpy = jest.spyOn(WidgetLayoutStore.instance, "moveToContainer"); }); - it("requiresClient should be true", () => { - expect(wrapper.state("requiresClient")).toBe(true); + it("should not display the »Popout widget« button", () => { + expect(renderResult.queryByLabelText("Popout widget")).not.toBeInTheDocument(); }); - it("clicking 'minimise' should send the widget to the right", () => { - const minimiseButton = wrapper.find(".mx_AppTileMenuBar_iconButton_minimise"); - minimiseButton.first().simulate("click"); + it("clicking 'minimise' should send the widget to the right", async () => { + await userEvent.click(renderResult.getByTitle("Minimise")); expect(moveToContainerSpy).toHaveBeenCalledWith(r1, app1, Container.Right); }); - it("clicking 'maximise' should send the widget to the center", () => { - const minimiseButton = wrapper.find(".mx_AppTileMenuBar_iconButton_maximise"); - minimiseButton.first().simulate("click"); + it("clicking 'maximise' should send the widget to the center", async () => { + await userEvent.click(renderResult.getByTitle("Maximise")); expect(moveToContainerSpy).toHaveBeenCalledWith(r1, app1, Container.Center); }); @@ -351,36 +349,34 @@ describe("AppTile", () => { ); }); - it("clicking 'un-maximise' should send the widget to the top", () => { - const unMaximiseButton = wrapper.find(".mx_AppTileMenuBar_iconButton_collapse"); - unMaximiseButton.first().simulate("click"); + it("clicking 'un-maximise' should send the widget to the top", async () => { + await userEvent.click(renderResult.getByTitle("Un-maximise")); expect(moveToContainerSpy).toHaveBeenCalledWith(r1, app1, Container.Top); }); }); - describe("with an existing widgetApi holding requiresClient = false", () => { - let wrapper: ReactWrapper; - + describe("with an existing widgetApi with requiresClient = false", () => { beforeEach(() => { const api = { hasCapability: (capability: ElementWidgetCapabilities): boolean => { return !(capability === ElementWidgetCapabilities.RequiresClient); }, once: () => {}, + stop: () => {}, } as unknown as ClientWidgetApi; const mockWidget = new ElementWidget(app1); WidgetMessagingStore.instance.storeMessaging(mockWidget, r1.roomId, api); - wrapper = mount( + renderResult = render( , ); }); - it("requiresClient should be false", () => { - expect(wrapper.state("requiresClient")).toBe(false); + it("should display the »Popout widget« button", () => { + expect(renderResult.getByTitle("Popout widget")).toBeInTheDocument(); }); }); });