From f40d15388c59a0d88fe9ae7ee8c202c349685941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Telaty=C5=84ski?= <7t3chguy@gmail.com> Date: Tue, 28 Feb 2023 08:58:23 +0000 Subject: [PATCH] Update tests to prefer RTL over Enzyme (#10247 * Update tests to prefer RTL over Enzyme * Strict types --- .../views/audio_messages/PlayPauseButton.tsx | 2 +- .../audio_messages/RecordingPlayback-test.tsx | 59 +- .../views/auth/RegistrationToken-test.tsx | 32 +- .../views/beacon/BeaconViewDialog-test.tsx | 3 +- .../views/dialogs/ExportDialog-test.tsx | 1 + .../views/elements/EventListSummary-test.tsx | 149 ++--- .../views/elements/PollCreateDialog-test.tsx | 122 ++-- .../PollCreateDialog-test.tsx.snap | 559 ++++++++++++++++- .../views/messages/MBeaconBody-test.tsx | 79 +-- .../views/messages/MLocationBody-test.tsx | 1 + .../__snapshots__/MBeaconBody-test.tsx.snap | 43 +- .../views/rooms/MemberList-test.tsx | 1 + .../views/rooms/RoomHeader-test.tsx | 563 +++++++++--------- .../rooms/VoiceRecordComposerTile-test.tsx | 52 +- .../SpaceSettingsVisibilityTab-test.tsx | 13 +- test/test-utils/composer.ts | 22 +- test/test-utils/test-utils.ts | 3 +- test/test-utils/utilities.ts | 13 - test/utils/DMRoomMap-test.ts | 2 +- test/utils/export-test.tsx | 8 +- 20 files changed, 1095 insertions(+), 632 deletions(-) diff --git a/src/components/views/audio_messages/PlayPauseButton.tsx b/src/components/views/audio_messages/PlayPauseButton.tsx index a865f0aeef..4f2fddc4ab 100644 --- a/src/components/views/audio_messages/PlayPauseButton.tsx +++ b/src/components/views/audio_messages/PlayPauseButton.tsx @@ -60,7 +60,7 @@ export default class PlayPauseButton extends React.PureComponent { return ( ({ createAudioContext: jest.fn(), @@ -57,12 +53,13 @@ describe("", () => { const mockChannelData = new Float32Array(); - const defaultRoom = { roomId: "!room:server.org", timelineRenderingType: TimelineRenderingType.File }; + const defaultRoom = { roomId: "!room:server.org", timelineRenderingType: TimelineRenderingType.File } as IRoomState; const getComponent = (props: React.ComponentProps, room = defaultRoom) => - mount(, { - wrappingComponent: RoomContext.Provider, - wrappingComponentProps: { value: room }, - }); + render( + + + , + ); beforeEach(() => { jest.spyOn(logger, "error").mockRestore(); @@ -71,7 +68,7 @@ describe("", () => { mocked(createAudioContext).mockReturnValue(mockAudioContext as unknown as AudioContext); }); - const getPlayButton = (component: ReactWrapper) => findByTestId(component, "play-pause-button").at(0); + const getPlayButton = (component: RenderResult) => component.getByTestId("play-pause-button"); it("renders recording playback", () => { const playback = new Playback(new ArrayBuffer(8)); @@ -82,15 +79,16 @@ describe("", () => { it("disables play button while playback is decoding", async () => { const playback = new Playback(new ArrayBuffer(8)); const component = getComponent({ playback }); - expect(getPlayButton(component).props().disabled).toBeTruthy(); + expect(getPlayButton(component)).toHaveAttribute("disabled"); + expect(getPlayButton(component)).toHaveAttribute("aria-disabled", "true"); }); it("enables play button when playback is finished decoding", async () => { const playback = new Playback(new ArrayBuffer(8)); const component = getComponent({ playback }); await flushPromises(); - component.setProps({}); - expect(getPlayButton(component).props().disabled).toBeFalsy(); + expect(getPlayButton(component)).not.toHaveAttribute("disabled"); + expect(getPlayButton(component)).not.toHaveAttribute("aria-disabled", "true"); }); it("displays error when playback decoding fails", async () => { @@ -101,7 +99,7 @@ describe("", () => { const playback = new Playback(new ArrayBuffer(8)); const component = getComponent({ playback }); await flushPromises(); - expect(component.find(".text-warning").length).toBeFalsy(); + expect(component.container.querySelector(".text-warning")).toBeDefined(); }); it("displays pre-prepared playback with correct playback phase", async () => { @@ -109,8 +107,9 @@ describe("", () => { await playback.prepare(); const component = getComponent({ playback }); // playback already decoded, button is not disabled - expect(getPlayButton(component).props().disabled).toBeFalsy(); - expect(component.find(".text-warning").length).toBeFalsy(); + expect(getPlayButton(component)).not.toHaveAttribute("disabled"); + expect(getPlayButton(component)).not.toHaveAttribute("aria-disabled", "true"); + expect(component.container.querySelector(".text-warning")).toBeFalsy(); }); it("toggles playback on play pause button click", async () => { @@ -119,9 +118,7 @@ describe("", () => { await playback.prepare(); const component = getComponent({ playback }); - act(() => { - getPlayButton(component).simulate("click"); - }); + fireEvent.click(getPlayButton(component)); expect(playback.toggle).toHaveBeenCalled(); }); @@ -131,9 +128,9 @@ describe("", () => { const playback = new Playback(new ArrayBuffer(8)); const component = getComponent({ playback, layout: PlaybackLayout.Composer }); - expect(component.find(PlaybackClock).length).toBeTruthy(); - expect(component.find(PlaybackWaveform).length).toBeTruthy(); - expect(component.find(SeekBar).length).toBeFalsy(); + expect(component.container.querySelector(".mx_Clock")).toBeDefined(); + expect(component.container.querySelector(".mx_Waveform")).toBeDefined(); + expect(component.container.querySelector(".mx_SeekBar")).toBeFalsy(); }); }); @@ -142,18 +139,18 @@ describe("", () => { const playback = new Playback(new ArrayBuffer(8)); const component = getComponent({ playback, layout: PlaybackLayout.Timeline }); - expect(component.find(PlaybackClock).length).toBeTruthy(); - expect(component.find(PlaybackWaveform).length).toBeTruthy(); - expect(component.find(SeekBar).length).toBeTruthy(); + expect(component.container.querySelector(".mx_Clock")).toBeDefined(); + expect(component.container.querySelector(".mx_Waveform")).toBeDefined(); + expect(component.container.querySelector(".mx_SeekBar")).toBeDefined(); }); it("should be the default", () => { const playback = new Playback(new ArrayBuffer(8)); const component = getComponent({ playback }); // no layout set for test - expect(component.find(PlaybackClock).length).toBeTruthy(); - expect(component.find(PlaybackWaveform).length).toBeTruthy(); - expect(component.find(SeekBar).length).toBeTruthy(); + expect(component.container.querySelector(".mx_Clock")).toBeDefined(); + expect(component.container.querySelector(".mx_Waveform")).toBeDefined(); + expect(component.container.querySelector(".mx_SeekBar")).toBeDefined(); }); }); }); diff --git a/test/components/views/auth/RegistrationToken-test.tsx b/test/components/views/auth/RegistrationToken-test.tsx index bbe6ebfe36..fef05dd180 100644 --- a/test/components/views/auth/RegistrationToken-test.tsx +++ b/test/components/views/auth/RegistrationToken-test.tsx @@ -17,9 +17,7 @@ limitations under the License. */ import React from "react"; -import { act } from "react-dom/test-utils"; -// eslint-disable-next-line deprecate/import -import { mount, ReactWrapper } from "enzyme"; +import { fireEvent, render, RenderResult } from "@testing-library/react"; import InteractiveAuthComponent from "../../../../src/components/structures/InteractiveAuth"; import { flushPromises, getMockClientWithEventEmitter, unmockClientPeg } from "../../../test-utils"; @@ -34,7 +32,7 @@ describe("InteractiveAuthComponent", function () { makeRequest: jest.fn().mockResolvedValue(undefined), onAuthFinished: jest.fn(), }; - const getComponent = (props = {}) => mount(); + const getComponent = (props = {}) => render(); beforeEach(function () { jest.clearAllMocks(); @@ -44,9 +42,10 @@ describe("InteractiveAuthComponent", function () { unmockClientPeg(); }); - const getSubmitButton = (wrapper: ReactWrapper) => wrapper.find('AccessibleButton[kind="primary"]').at(0); - const getRegistrationTokenInput = (wrapper: ReactWrapper) => - wrapper.find('input[name="registrationTokenField"]').at(0); + const getSubmitButton = ({ container }: RenderResult) => + container.querySelector(".mx_AccessibleButton_kind_primary"); + const getRegistrationTokenInput = ({ container }: RenderResult) => + container.querySelector('input[name="registrationTokenField"]'); it("Should successfully complete a registration token flow", async () => { const onAuthFinished = jest.fn(); @@ -61,28 +60,25 @@ describe("InteractiveAuthComponent", function () { const registrationTokenNode = getRegistrationTokenInput(wrapper); const submitNode = getSubmitButton(wrapper); - const formNode = wrapper.find("form").at(0); + const formNode = wrapper.container.querySelector("form"); expect(registrationTokenNode).toBeTruthy(); expect(submitNode).toBeTruthy(); expect(formNode).toBeTruthy(); // submit should be disabled - expect(submitNode.props().disabled).toBe(true); + expect(submitNode).toHaveAttribute("disabled"); + expect(submitNode).toHaveAttribute("aria-disabled", "true"); // put something in the registration token box - act(() => { - registrationTokenNode.simulate("change", { target: { value: "s3kr3t" } }); - wrapper.setProps({}); - }); + fireEvent.change(registrationTokenNode!, { target: { value: "s3kr3t" } }); - expect(getRegistrationTokenInput(wrapper).props().value).toEqual("s3kr3t"); - expect(getSubmitButton(wrapper).props().disabled).toBe(false); + expect(getRegistrationTokenInput(wrapper)).toHaveValue("s3kr3t"); + expect(submitNode).not.toHaveAttribute("disabled"); + expect(submitNode).not.toHaveAttribute("aria-disabled", "true"); // hit enter; that should trigger a request - act(() => { - formNode.simulate("submit"); - }); + fireEvent.submit(formNode!); // wait for auth request to resolve await flushPromises(); diff --git a/test/components/views/beacon/BeaconViewDialog-test.tsx b/test/components/views/beacon/BeaconViewDialog-test.tsx index 11c1863a57..cee880c966 100644 --- a/test/components/views/beacon/BeaconViewDialog-test.tsx +++ b/test/components/views/beacon/BeaconViewDialog-test.tsx @@ -15,8 +15,7 @@ limitations under the License. */ import React from "react"; -import { act } from "react-dom/test-utils"; -import { fireEvent, render, RenderResult } from "@testing-library/react"; +import { act, fireEvent, render, RenderResult } from "@testing-library/react"; import { MatrixClient, MatrixEvent, Room, RoomMember, getBeaconInfoIdentifier } from "matrix-js-sdk/src/matrix"; import * as maplibregl from "maplibre-gl"; import { mocked } from "jest-mock"; diff --git a/test/components/views/dialogs/ExportDialog-test.tsx b/test/components/views/dialogs/ExportDialog-test.tsx index afc490546f..401dcf8770 100644 --- a/test/components/views/dialogs/ExportDialog-test.tsx +++ b/test/components/views/dialogs/ExportDialog-test.tsx @@ -18,6 +18,7 @@ import React from "react"; // eslint-disable-next-line deprecate/import import { mount, ReactWrapper } from "enzyme"; import { mocked } from "jest-mock"; +// eslint-disable-next-line deprecate/import import { act } from "react-dom/test-utils"; import { Room } from "matrix-js-sdk/src/matrix"; diff --git a/test/components/views/elements/EventListSummary-test.tsx b/test/components/views/elements/EventListSummary-test.tsx index 81fc59e2aa..0f666bfd8b 100644 --- a/test/components/views/elements/EventListSummary-test.tsx +++ b/test/components/views/elements/EventListSummary-test.tsx @@ -15,8 +15,7 @@ limitations under the License. */ import React, { ComponentProps } from "react"; -// eslint-disable-next-line deprecate/import -import { mount, ReactWrapper } from "enzyme"; +import { render, RenderResult } from "@testing-library/react"; import { MatrixEvent, RoomMember } from "matrix-js-sdk/src/matrix"; import { @@ -124,8 +123,8 @@ describe("EventListSummary", function () { events: [], children: [], }; - const renderComponent = (props = {}): ReactWrapper => { - return mount( + const renderComponent = (props = {}): RenderResult => { + return render( , @@ -150,13 +149,11 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); // matrix cli context wrapper + const { container } = renderComponent(props); // matrix cli context wrapper - expect(wrapper.find("GenericEventListSummary").props().children).toEqual([ -
- Expanded membership -
, - ]); + const children = container.querySelector(".mx_GenericEventListSummary_unstyledList")!.children; + expect(children).toHaveLength(1); + expect(children[0]).toHaveTextContent("Expanded membership"); }); it("renders expanded events if there are less than props.threshold", function () { @@ -172,16 +169,12 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); // matrix cli context wrapper + const { container } = renderComponent(props); // matrix cli context wrapper - expect(wrapper.find("GenericEventListSummary").props().children).toEqual([ -
- Expanded membership -
, -
- Expanded membership -
, - ]); + const children = container.querySelector(".mx_GenericEventListSummary_unstyledList")!.children; + expect(children).toHaveLength(2); + expect(children[0]).toHaveTextContent("Expanded membership"); + expect(children[1]).toHaveTextContent("Expanded membership"); }); it("renders collapsed events if events.length = props.threshold", function () { @@ -198,11 +191,9 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_1 joined and left and joined"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent("user_1 joined and left and joined"); }); it("truncates long join,leave repetitions", function () { @@ -230,11 +221,9 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_1 joined and left 7 times"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent("user_1 joined and left 7 times"); }); it("truncates long join,leave repetitions between other events", function () { @@ -274,11 +263,9 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_1 was unbanned, joined and left 7 times and was invited"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent("user_1 was unbanned, joined and left 7 times and was invited"); }); it("truncates multiple sequences of repetitions with other events between", function () { @@ -320,11 +307,9 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe( + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent( "user_1 was unbanned, joined and left 2 times, was banned, " + "joined and left 3 times and was invited", ); }); @@ -374,11 +359,11 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_1 and one other were unbanned, joined and left 2 times and were banned"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent( + "user_1 and one other were unbanned, joined and left 2 times and were banned", + ); }); it("handles many users following the same sequence of memberships", function () { @@ -406,11 +391,11 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_0 and 19 others were unbanned, joined and left 2 times and were banned"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent( + "user_0 and 19 others were unbanned, joined and left 2 times and were banned", + ); }); it("correctly orders sequences of transitions by the order of their first event", function () { @@ -450,11 +435,9 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe( + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent( "user_2 was unbanned and joined and left 2 times, user_1 was unbanned, " + "joined and left 2 times and was banned", ); @@ -520,11 +503,9 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe( + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent( "user_1 was invited, was banned, joined, rejected their invitation, left, " + "had their invitation withdrawn, was unbanned, was removed, left and was removed", ); @@ -563,11 +544,11 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_1 and one other rejected their invitations and had their invitations withdrawn"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent( + "user_1 and one other rejected their invitations and had their invitations withdrawn", + ); }); it("handles invitation plurals correctly when there are multiple invites", function () { @@ -591,11 +572,9 @@ describe("EventListSummary", function () { threshold: 1, // threshold = 1 to force collapse }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_1 rejected their invitation 2 times"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent("user_1 rejected their invitation 2 times"); }); it('handles a summary length = 2, with no "others"', function () { @@ -613,11 +592,9 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_1 and user_2 joined 2 times"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent("user_1 and user_2 joined 2 times"); }); it('handles a summary length = 2, with 1 "other"', function () { @@ -634,11 +611,9 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_1, user_2 and one other joined"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent("user_1, user_2 and one other joined"); }); it('handles a summary length = 2, with many "others"', function () { @@ -651,11 +626,9 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("user_0, user_1 and 18 others joined"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent("user_0, user_1 and 18 others joined"); }); it("should not blindly group 3pid invites and treat them as distinct users instead", () => { @@ -703,10 +676,8 @@ describe("EventListSummary", function () { threshold: 3, }; - const wrapper = renderComponent(props); - const summary = wrapper.find(".mx_GenericEventListSummary_summary"); - const summaryText = summary.text(); - - expect(summaryText).toBe("n...@d... was invited 2 times, d...@w... was invited"); + const { container } = renderComponent(props); + const summary = container.querySelector(".mx_GenericEventListSummary_summary"); + expect(summary).toHaveTextContent("n...@d... was invited 2 times, d...@w... was invited"); }); }); diff --git a/test/components/views/elements/PollCreateDialog-test.tsx b/test/components/views/elements/PollCreateDialog-test.tsx index 2a0087b355..551aae01aa 100644 --- a/test/components/views/elements/PollCreateDialog-test.tsx +++ b/test/components/views/elements/PollCreateDialog-test.tsx @@ -15,15 +15,14 @@ limitations under the License. */ import React from "react"; -// eslint-disable-next-line deprecate/import -import { mount, ReactWrapper } from "enzyme"; +import { fireEvent, render, RenderResult } from "@testing-library/react"; import { Room } from "matrix-js-sdk/src/models/room"; import { M_POLL_KIND_DISCLOSED, M_POLL_KIND_UNDISCLOSED, M_POLL_START } from "matrix-js-sdk/src/@types/polls"; import { PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { M_TEXT } from "matrix-js-sdk/src/@types/extensible_events"; -import { findById, getMockClientWithEventEmitter } from "../../../test-utils"; +import { getMockClientWithEventEmitter } from "../../../test-utils"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import PollCreateDialog from "../../../../src/components/views/elements/PollCreateDialog"; import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; @@ -51,40 +50,41 @@ describe("PollCreateDialog", () => { }); it("renders a blank poll", () => { - const dialog = mount(, { - wrappingComponent: MatrixClientContext.Provider, - wrappingComponentProps: { value: mockClient }, - }); - expect(dialog.html()).toMatchSnapshot(); + const dialog = render( + + + , + ); + expect(dialog.asFragment()).toMatchSnapshot(); }); it("autofocuses the poll topic on mount", () => { - const dialog = mount(); - expect(findById(dialog, "poll-topic-input").at(0).props().autoFocus).toEqual(true); + const dialog = render(); + expect(dialog.container.querySelector("#poll-topic-input")).toHaveFocus(); }); it("autofocuses the new poll option field after clicking add option button", () => { - const dialog = mount(); - expect(findById(dialog, "poll-topic-input").at(0).props().autoFocus).toEqual(true); + const dialog = render(); + expect(dialog.container.querySelector("#poll-topic-input")).toHaveFocus(); - dialog.find("div.mx_PollCreateDialog_addOption").simulate("click"); + fireEvent.click(dialog.container.querySelector("div.mx_PollCreateDialog_addOption")!); - expect(findById(dialog, "poll-topic-input").at(0).props().autoFocus).toEqual(false); - expect(findById(dialog, "pollcreate_option_1").at(0).props().autoFocus).toEqual(false); - expect(findById(dialog, "pollcreate_option_2").at(0).props().autoFocus).toEqual(true); + expect(dialog.container.querySelector("#poll-topic-input")).not.toHaveFocus(); + expect(dialog.container.querySelector("#pollcreate_option_1")).not.toHaveFocus(); + expect(dialog.container.querySelector("#pollcreate_option_2")).toHaveFocus(); }); it("renders a question and some options", () => { - const dialog = mount(); - expect(submitIsDisabled(dialog)).toBe(true); + const dialog = render(); + expectSubmitToBeDisabled(dialog, true); // When I set some values in the boxes changeValue(dialog, "Question or topic", "How many turnips is the optimal number?"); changeValue(dialog, "Option 1", "As many as my neighbour"); changeValue(dialog, "Option 2", "The question is meaningless"); - dialog.find("div.mx_PollCreateDialog_addOption").simulate("click"); + fireEvent.click(dialog.container.querySelector("div.mx_PollCreateDialog_addOption")!); changeValue(dialog, "Option 3", "Mu"); - expect(dialog.html()).toMatchSnapshot(); + expect(dialog.asFragment()).toMatchSnapshot(); }); it("renders info from a previous event", () => { @@ -92,23 +92,23 @@ describe("PollCreateDialog", () => { PollStartEvent.from("Poll Q", ["Answer 1", "Answer 2"], M_POLL_KIND_DISCLOSED).serialize(), ); - const dialog = mount( + const dialog = render( , ); - expect(submitIsDisabled(dialog)).toBe(false); - expect(dialog.html()).toMatchSnapshot(); + expectSubmitToBeDisabled(dialog, false); + expect(dialog.asFragment()).toMatchSnapshot(); }); it("doesn't allow submitting until there are options", () => { - const dialog = mount(); - expect(submitIsDisabled(dialog)).toBe(true); + const dialog = render(); + expectSubmitToBeDisabled(dialog, true); }); it("does allow submitting when there are options and a question", () => { // Given a dialog with no info in (which I am unable to submit) - const dialog = mount(); - expect(submitIsDisabled(dialog)).toBe(true); + const dialog = render(); + expectSubmitToBeDisabled(dialog, true); // When I set some values in the boxes changeValue(dialog, "Question or topic", "Q"); @@ -116,28 +116,30 @@ describe("PollCreateDialog", () => { changeValue(dialog, "Option 2", "A2"); // Then I am able to submit - expect(submitIsDisabled(dialog)).toBe(false); + expectSubmitToBeDisabled(dialog, false); }); it("shows the open poll description at first", () => { - const dialog = mount(); - expect(dialog.find("select").prop("value")).toEqual(M_POLL_KIND_DISCLOSED.name); - expect(dialog.find("p").text()).toEqual("Voters see results as soon as they have voted"); + const dialog = render(); + expect(dialog.container.querySelector("select")).toHaveValue(M_POLL_KIND_DISCLOSED.name); + expect(dialog.container.querySelector("p")).toHaveTextContent("Voters see results as soon as they have voted"); }); it("shows the closed poll description if we choose it", () => { - const dialog = mount(); + const dialog = render(); changeKind(dialog, M_POLL_KIND_UNDISCLOSED.name); - expect(dialog.find("select").prop("value")).toEqual(M_POLL_KIND_UNDISCLOSED.name); - expect(dialog.find("p").text()).toEqual("Results are only revealed when you end the poll"); + expect(dialog.container.querySelector("select")).toHaveValue(M_POLL_KIND_UNDISCLOSED.name); + expect(dialog.container.querySelector("p")).toHaveTextContent( + "Results are only revealed when you end the poll", + ); }); it("shows the open poll description if we choose it", () => { - const dialog = mount(); + const dialog = render(); changeKind(dialog, M_POLL_KIND_UNDISCLOSED.name); changeKind(dialog, M_POLL_KIND_DISCLOSED.name); - expect(dialog.find("select").prop("value")).toEqual(M_POLL_KIND_DISCLOSED.name); - expect(dialog.find("p").text()).toEqual("Voters see results as soon as they have voted"); + expect(dialog.container.querySelector("select")).toHaveValue(M_POLL_KIND_DISCLOSED.name); + expect(dialog.container.querySelector("p")).toHaveTextContent("Voters see results as soon as they have voted"); }); it("shows the closed poll description when editing a closed poll", () => { @@ -146,32 +148,34 @@ describe("PollCreateDialog", () => { ); previousEvent.event.event_id = "$prevEventId"; - const dialog = mount( + const dialog = render( , ); - expect(dialog.find("select").prop("value")).toEqual(M_POLL_KIND_UNDISCLOSED.name); - expect(dialog.find("p").text()).toEqual("Results are only revealed when you end the poll"); + expect(dialog.container.querySelector("select")).toHaveValue(M_POLL_KIND_UNDISCLOSED.name); + expect(dialog.container.querySelector("p")).toHaveTextContent( + "Results are only revealed when you end the poll", + ); }); it("displays a spinner after submitting", () => { - const dialog = mount(); + const dialog = render(); changeValue(dialog, "Question or topic", "Q"); changeValue(dialog, "Option 1", "A1"); changeValue(dialog, "Option 2", "A2"); - expect(dialog.find("Spinner").length).toBe(0); + expect(dialog.container.querySelector(".mx_Spinner")).toBeFalsy(); - dialog.find("button").simulate("click"); - expect(dialog.find("Spinner").length).toBe(1); + fireEvent.click(dialog.container.querySelector("button")!); + expect(dialog.container.querySelector(".mx_Spinner")).toBeDefined(); }); it("sends a poll create event when submitted", () => { - const dialog = mount(); + const dialog = render(); changeValue(dialog, "Question or topic", "Q"); changeValue(dialog, "Option 1", "A1"); changeValue(dialog, "Option 2", "A2"); - dialog.find("button").simulate("click"); + fireEvent.click(dialog.container.querySelector("button")!); const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0]; expect(M_POLL_START.matches(eventType)).toBeTruthy(); expect(sentEventContent).toEqual({ @@ -206,14 +210,14 @@ describe("PollCreateDialog", () => { ); previousEvent.event.event_id = "$prevEventId"; - const dialog = mount( + const dialog = render( , ); changeValue(dialog, "Question or topic", "Poll Q updated"); changeValue(dialog, "Option 2", "Answer 2 updated"); changeKind(dialog, M_POLL_KIND_UNDISCLOSED.name); - dialog.find("button").simulate("click"); + fireEvent.click(dialog.container.querySelector("button")!); const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0]; expect(M_POLL_START.matches(eventType)).toBeTruthy(); @@ -255,12 +259,12 @@ describe("PollCreateDialog", () => { ); previousEvent.event.event_id = "$prevEventId"; - const dialog = mount( + const dialog = render( , ); changeValue(dialog, "Question or topic", "Poll Q updated"); - dialog.find("button").simulate("click"); + fireEvent.click(dialog.container.querySelector("button")!); const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0]; expect(M_POLL_START.matches(eventType)).toBeTruthy(); @@ -273,14 +277,20 @@ function createRoom(): Room { return new Room("roomid", MatrixClientPeg.get(), "@name:example.com", {}); } -function changeValue(wrapper: ReactWrapper, labelText: string, value: string) { - wrapper.find(`input[label="${labelText}"]`).simulate("change", { target: { value: value } }); +function changeValue(wrapper: RenderResult, labelText: string, value: string) { + fireEvent.change(wrapper.container.querySelector(`input[label="${labelText}"]`)!, { + target: { value: value }, + }); } -function changeKind(wrapper: ReactWrapper, value: string) { - wrapper.find("select").simulate("change", { target: { value: value } }); +function changeKind(wrapper: RenderResult, value: string) { + fireEvent.change(wrapper.container.querySelector("select")!, { target: { value: value } }); } -function submitIsDisabled(wrapper: ReactWrapper) { - return wrapper.find('button[type="submit"]').prop("aria-disabled") === true; +function expectSubmitToBeDisabled(wrapper: RenderResult, disabled: boolean) { + if (disabled) { + expect(wrapper.container.querySelector('button[type="submit"]')).toHaveAttribute("aria-disabled", "true"); + } else { + expect(wrapper.container.querySelector('button[type="submit"]')).not.toHaveAttribute("aria-disabled", "true"); + } } diff --git a/test/components/views/elements/__snapshots__/PollCreateDialog-test.tsx.snap b/test/components/views/elements/__snapshots__/PollCreateDialog-test.tsx.snap index 6fdf8bfb29..ef2306ccdc 100644 --- a/test/components/views/elements/__snapshots__/PollCreateDialog-test.tsx.snap +++ b/test/components/views/elements/__snapshots__/PollCreateDialog-test.tsx.snap @@ -1,7 +1,560 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PollCreateDialog renders a blank poll 1`] = `"
"`; +exports[`PollCreateDialog renders a blank poll 1`] = ` + +
+