Migrate some tests to React Testing Library (#9584)

This commit is contained in:
Germain 2022-11-18 09:16:11 +00:00 committed by GitHub
parent ef548a4843
commit 38dbe8ed33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 325 additions and 527 deletions

View file

@ -136,6 +136,7 @@ export default class SearchBox extends React.Component<IProps, IState> {
placeholder={this.state.blurred ? (blurredPlaceholder || placeholder) : placeholder} placeholder={this.state.blurred ? (blurredPlaceholder || placeholder) : placeholder}
autoComplete="off" autoComplete="off"
autoFocus={this.props.autoFocus} autoFocus={this.props.autoFocus}
data-testid="searchbox-input"
/> />
{ clearButton } { clearButton }
</div> </div>

View file

@ -15,12 +15,12 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
// eslint-disable-next-line deprecate/import
import { mount, ReactWrapper } from "enzyme";
import { act } from "react-dom/test-utils"; import { act } from "react-dom/test-utils";
import { MatrixEvent, EventType } from "matrix-js-sdk/src/matrix"; import { MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
import { LocationAssetType, M_ASSET, M_LOCATION, M_TIMESTAMP } from "matrix-js-sdk/src/@types/location"; import { LocationAssetType, M_ASSET, M_LOCATION, M_TIMESTAMP } from "matrix-js-sdk/src/@types/location";
import { TEXT_NODE_TYPE } from "matrix-js-sdk/src/@types/extensible_events"; import { TEXT_NODE_TYPE } from "matrix-js-sdk/src/@types/extensible_events";
import { fireEvent, getByTestId, render, RenderResult, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import ForwardDialog from "../../../../src/components/views/dialogs/ForwardDialog"; import ForwardDialog from "../../../../src/components/views/dialogs/ForwardDialog";
@ -34,6 +34,7 @@ import {
mkEvent, mkEvent,
mkMessage, mkMessage,
mkStubRoom, mkStubRoom,
mockPlatformPeg,
} from "../../../test-utils"; } from "../../../test-utils";
import { TILE_SERVER_WK_KEY } from "../../../../src/utils/WellKnownUtils"; import { TILE_SERVER_WK_KEY } from "../../../../src/utils/WellKnownUtils";
@ -71,24 +72,18 @@ describe("ForwardDialog", () => {
}); });
const defaultRooms = ["a", "A", "b"].map(name => mkStubRoom(name, name, mockClient)); const defaultRooms = ["a", "A", "b"].map(name => mkStubRoom(name, name, mockClient));
const mountForwardDialog = async (message = defaultMessage, rooms = defaultRooms) => { const mountForwardDialog = (message = defaultMessage, rooms = defaultRooms) => {
mockClient.getVisibleRooms.mockReturnValue(rooms); mockClient.getVisibleRooms.mockReturnValue(rooms);
mockClient.getRoom.mockImplementation(roomId => rooms.find(room => room.roomId === roomId)); mockClient.getRoom.mockImplementation(roomId => rooms.find(room => room.roomId === roomId));
let wrapper; const wrapper: RenderResult = render(
await act(async () => { <ForwardDialog
wrapper = mount( matrixClient={mockClient}
<ForwardDialog event={message}
matrixClient={mockClient} permalinkCreator={new RoomPermalinkCreator(undefined, sourceRoom)}
event={message} onFinished={jest.fn()}
permalinkCreator={new RoomPermalinkCreator(undefined, sourceRoom)} />,
onFinished={jest.fn()} );
/>,
);
// Wait one tick for our profile data to load so the state update happens within act
await new Promise(resolve => setImmediate(resolve));
});
wrapper.update();
return wrapper; return wrapper;
}; };
@ -105,30 +100,29 @@ describe("ForwardDialog", () => {
}); });
it("shows a preview with us as the sender", async () => { it("shows a preview with us as the sender", async () => {
const wrapper = await mountForwardDialog(); const { container } = mountForwardDialog();
const previewBody = wrapper.find(".mx_EventTile_body"); expect(screen.queryByText("Hello world!")).toBeInTheDocument();
expect(previewBody.text()).toBe("Hello world!");
// We would just test SenderProfile for the user ID, but it's stubbed // We would just test SenderProfile for the user ID, but it's stubbed
const previewAvatar = wrapper.find(".mx_EventTile_avatar .mx_BaseAvatar_image"); const previewAvatar = container.querySelector(".mx_EventTile_avatar .mx_BaseAvatar_image");
expect(previewAvatar.prop("title")).toBe("@bob:example.org"); expect(previewAvatar?.getAttribute("title")).toBe("@bob:example.org");
}); });
it("filters the rooms", async () => { it("filters the rooms", async () => {
const wrapper = await mountForwardDialog(); const { container } = mountForwardDialog();
expect(wrapper.find("Entry")).toHaveLength(3); expect(container.querySelectorAll(".mx_ForwardList_entry")).toHaveLength(3);
const searchInput = wrapper.find("SearchBox input"); const searchInput = getByTestId(container, "searchbox-input");
searchInput.instance().value = "a"; act(() => userEvent.type(searchInput, "a"));
searchInput.simulate("change");
expect(wrapper.find("Entry")).toHaveLength(2); expect(container.querySelectorAll(".mx_ForwardList_entry")).toHaveLength(3);
}); });
it("tracks message sending progress across multiple rooms", async () => { it("tracks message sending progress across multiple rooms", async () => {
const wrapper = await mountForwardDialog(); mockPlatformPeg();
const { container } = mountForwardDialog();
// Make sendEvent require manual resolution so we can see the sending state // Make sendEvent require manual resolution so we can see the sending state
let finishSend; let finishSend;
@ -141,17 +135,15 @@ describe("ForwardDialog", () => {
let firstButton; let firstButton;
let secondButton; let secondButton;
const update = () => { const update = () => {
wrapper.update(); [firstButton, secondButton] = container.querySelectorAll(".mx_ForwardList_sendButton");
firstButton = wrapper.find("AccessibleButton.mx_ForwardList_sendButton").first();
secondButton = wrapper.find("AccessibleButton.mx_ForwardList_sendButton").at(1);
}; };
update(); update();
expect(firstButton.is(".mx_ForwardList_canSend")).toBe(true); expect(firstButton.className).toContain("mx_ForwardList_canSend");
act(() => { firstButton.simulate("click"); }); act(() => { fireEvent.click(firstButton); });
update(); update();
expect(firstButton.is(".mx_ForwardList_sending")).toBe(true); expect(firstButton.className).toContain("mx_ForwardList_sending");
await act(async () => { await act(async () => {
cancelSend(); cancelSend();
@ -159,13 +151,13 @@ describe("ForwardDialog", () => {
await new Promise(resolve => setImmediate(resolve)); await new Promise(resolve => setImmediate(resolve));
}); });
update(); update();
expect(firstButton.is(".mx_ForwardList_sendFailed")).toBe(true); expect(firstButton.className).toContain("mx_ForwardList_sendFailed");
expect(secondButton.is(".mx_ForwardList_canSend")).toBe(true); expect(secondButton.className).toContain("mx_ForwardList_canSend");
act(() => { secondButton.simulate("click"); }); act(() => { fireEvent.click(secondButton); });
update(); update();
expect(secondButton.is(".mx_ForwardList_sending")).toBe(true); expect(secondButton.className).toContain("mx_ForwardList_sending");
await act(async () => { await act(async () => {
finishSend(); finishSend();
@ -173,7 +165,7 @@ describe("ForwardDialog", () => {
await new Promise(resolve => setImmediate(resolve)); await new Promise(resolve => setImmediate(resolve));
}); });
update(); update();
expect(secondButton.is(".mx_ForwardList_sent")).toBe(true); expect(secondButton.className).toContain("mx_ForwardList_sent");
}); });
it("can render replies", async () => { it("can render replies", async () => {
@ -193,8 +185,9 @@ describe("ForwardDialog", () => {
event: true, event: true,
}); });
const wrapper = await mountForwardDialog(replyMessage); mountForwardDialog(replyMessage);
expect(wrapper.find("ReplyChain")).toBeTruthy();
expect(screen.queryByText("Hi Alice!", { exact: false })).toBeInTheDocument();
}); });
it("disables buttons for rooms without send permissions", async () => { it("disables buttons for rooms without send permissions", async () => {
@ -202,12 +195,12 @@ describe("ForwardDialog", () => {
readOnlyRoom.maySendMessage = jest.fn().mockReturnValue(false); readOnlyRoom.maySendMessage = jest.fn().mockReturnValue(false);
const rooms = [readOnlyRoom, mkStubRoom("b", "b", mockClient)]; const rooms = [readOnlyRoom, mkStubRoom("b", "b", mockClient)];
const wrapper = await mountForwardDialog(undefined, rooms); const { container } = mountForwardDialog(undefined, rooms);
const firstButton = wrapper.find("AccessibleButton.mx_ForwardList_sendButton").first(); const [firstButton, secondButton] = container.querySelectorAll<HTMLButtonElement>(".mx_ForwardList_sendButton");
expect(firstButton.prop("disabled")).toBe(true);
const secondButton = wrapper.find("AccessibleButton.mx_ForwardList_sendButton").last(); expect(firstButton.getAttribute("aria-disabled")).toBeTruthy();
expect(secondButton.prop("disabled")).toBe(false); expect(secondButton.getAttribute("aria-disabled")).toBeFalsy();
}); });
describe('Location events', () => { describe('Location events', () => {
@ -229,17 +222,17 @@ describe("ForwardDialog", () => {
jest.spyOn(Date, 'now').mockRestore(); jest.spyOn(Date, 'now').mockRestore();
}); });
const sendToFirstRoom = (wrapper: ReactWrapper): void => const sendToFirstRoom = (container: HTMLElement): void =>
act(() => { act(() => {
const sendToFirstRoomButton = wrapper.find("AccessibleButton.mx_ForwardList_sendButton").first(); const sendToFirstRoomButton = container.querySelector(".mx_ForwardList_sendButton");
sendToFirstRoomButton.simulate("click"); fireEvent.click(sendToFirstRoomButton!);
}); });
it('converts legacy location events to pin drop shares', async () => { it('converts legacy location events to pin drop shares', async () => {
const wrapper = await mountForwardDialog(legacyLocationEvent); const { container } = mountForwardDialog(legacyLocationEvent);
expect(wrapper.find('MLocationBody').length).toBeTruthy(); expect(container.querySelector(".mx_MLocationBody")).toBeTruthy();
sendToFirstRoom(wrapper); sendToFirstRoom(container);
// text and description from original event are removed // text and description from original event are removed
// text gets new default message from event values // text gets new default message from event values
@ -262,10 +255,10 @@ describe("ForwardDialog", () => {
}); });
it('removes personal information from static self location shares', async () => { it('removes personal information from static self location shares', async () => {
const wrapper = await mountForwardDialog(modernLocationEvent); const { container } = mountForwardDialog(modernLocationEvent);
expect(wrapper.find('MLocationBody').length).toBeTruthy(); expect(container.querySelector(".mx_MLocationBody")).toBeTruthy();
sendToFirstRoom(wrapper); sendToFirstRoom(container);
const timestamp = M_TIMESTAMP.findIn<number>(modernLocationEvent.getContent()); const timestamp = M_TIMESTAMP.findIn<number>(modernLocationEvent.getContent());
// text and description from original event are removed // text and description from original event are removed
@ -302,11 +295,11 @@ describe("ForwardDialog", () => {
geo_uri: geoUri, geo_uri: geoUri,
[M_TIMESTAMP.name]: timestamp, [M_TIMESTAMP.name]: timestamp,
}; };
const wrapper = await mountForwardDialog(beaconEvent); const { container } = mountForwardDialog(beaconEvent);
expect(wrapper.find('MLocationBody').length).toBeTruthy(); expect(container.querySelector(".mx_MLocationBody")).toBeTruthy();
sendToFirstRoom(wrapper); sendToFirstRoom(container);
expect(mockClient.sendEvent).toHaveBeenCalledWith( expect(mockClient.sendEvent).toHaveBeenCalledWith(
roomId, EventType.RoomMessage, expectedContent, roomId, EventType.RoomMessage, expectedContent,
@ -314,11 +307,11 @@ describe("ForwardDialog", () => {
}); });
it('forwards pin drop event', async () => { it('forwards pin drop event', async () => {
const wrapper = await mountForwardDialog(pinDropLocationEvent); const { container } = mountForwardDialog(pinDropLocationEvent);
expect(wrapper.find('MLocationBody').length).toBeTruthy(); expect(container.querySelector(".mx_MLocationBody")).toBeTruthy();
sendToFirstRoom(wrapper); sendToFirstRoom(container);
expect(mockClient.sendEvent).toHaveBeenCalledWith( expect(mockClient.sendEvent).toHaveBeenCalledWith(
roomId, pinDropLocationEvent.getType(), pinDropLocationEvent.getContent(), roomId, pinDropLocationEvent.getType(), pinDropLocationEvent.getContent(),

View file

@ -15,9 +15,8 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
// eslint-disable-next-line deprecate/import
import { mount, ReactWrapper } from "enzyme";
import { MatrixEvent } from 'matrix-js-sdk/src/matrix'; import { MatrixEvent } from 'matrix-js-sdk/src/matrix';
import { render, RenderResult } from '@testing-library/react';
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks"; import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks";
@ -36,12 +35,13 @@ describe("MVideoBody", () => {
it('does not crash when given a portrait image', () => { it('does not crash when given a portrait image', () => {
// Check for an unreliable crash caused by a fractional-sized // Check for an unreliable crash caused by a fractional-sized
// image dimension being used for a CanvasImageData. // image dimension being used for a CanvasImageData.
expect(makeMVideoBody(720, 1280).html()).toMatchSnapshot(); const { asFragment } = makeMVideoBody(720, 1280);
expect(asFragment()).toMatchSnapshot();
// If we get here, we did not crash. // If we get here, we did not crash.
}); });
}); });
function makeMVideoBody(w: number, h: number): ReactWrapper<any, Readonly<{}>, MVideoBody> { function makeMVideoBody(w: number, h: number): RenderResult {
const content = { const content = {
info: { info: {
"w": w, "w": w,
@ -79,8 +79,9 @@ function makeMVideoBody(w: number, h: number): ReactWrapper<any, Readonly<{}>, M
mxcUrlToHttp: jest.fn(), mxcUrlToHttp: jest.fn(),
}); });
return mount(<MVideoBody {...defaultProps} />, { return render(
wrappingComponent: MatrixClientContext.Provider, <MatrixClientContext.Provider value={mockClient}>
wrappingComponentProps: { value: mockClient }, <MVideoBody {...defaultProps} />
}); </MatrixClientContext.Provider>,
);
} }

View file

@ -1,3 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MVideoBody does not crash when given a portrait image 1`] = `"<span class="mx_MVideoBody"><div class="mx_MVideoBody_container" style="max-width: 182px; max-height: 324px;"><video class="mx_MVideoBody" controls="" controlslist="nodownload" preload="none" poster="data:image/png;base64,00"></video><div style="width: 182px; height: 324px;"></div></div></span>"`; exports[`MVideoBody does not crash when given a portrait image 1`] = `
<DocumentFragment>
<span
class="mx_MVideoBody"
>
<div
class="mx_MVideoBody_container"
style="max-width: 182px; max-height: 324px;"
>
<video
class="mx_MVideoBody"
controls=""
controlslist="nodownload"
poster="data:image/png;base64,00"
preload="none"
/>
<div
style="width: 182px; height: 324px;"
/>
</div>
</span>
</DocumentFragment>
`;

View file

@ -15,17 +15,12 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
// eslint-disable-next-line deprecate/import import { fireEvent, render } from '@testing-library/react';
import { mount } from "enzyme";
import SearchWarning from "../../../../src/components/views/elements/SearchWarning";
import { PosthogScreenTracker } from "../../../../src/PosthogTrackers";
import SearchBar, { SearchScope } from "../../../../src/components/views/rooms/SearchBar"; import SearchBar, { SearchScope } from "../../../../src/components/views/rooms/SearchBar";
import { KeyBindingAction } from "../../../../src/accessibility/KeyboardShortcuts"; import { KeyBindingAction } from "../../../../src/accessibility/KeyboardShortcuts";
let mockCurrentEvent = KeyBindingAction.Enter; let mockCurrentEvent = KeyBindingAction.Enter;
const mockWarningKind = true;
let wrapper: any = null;
const searchProps = { const searchProps = {
onCancelClick: jest.fn(), onCancelClick: jest.fn(),
@ -40,95 +35,63 @@ jest.mock("../../../../src/KeyBindingsManager", () => ({
{ getAccessibilityAction: jest.fn(() => mockCurrentEvent) })), { getAccessibilityAction: jest.fn(() => mockCurrentEvent) })),
})); }));
/** mock out SearchWarning component so it doesn't affect the result of our test */
jest.mock('../../../../src/components/views/elements/SearchWarning', () => ({
__esModule: true,
WarningKind: {
get Search() { // eslint-disable-line @typescript-eslint/naming-convention
return mockWarningKind;
},
},
default: jest.fn(({ children }) => (
<div>{ children }</div>
)),
}));
/** mock out PosthogTrackers component so it doesn't affect the result of our test */
jest.mock('../../../../src/PosthogTrackers', () => ({
__esModule: true,
PosthogScreenTracker: jest.fn(({ children }) => (
<div>{ children }</div>
)),
}));
describe("SearchBar", () => { describe("SearchBar", () => {
beforeEach(() => {
wrapper = mount(<SearchBar {...searchProps} />);
});
afterEach(() => { afterEach(() => {
wrapper.unmount();
searchProps.onCancelClick.mockClear(); searchProps.onCancelClick.mockClear();
searchProps.onSearch.mockClear(); searchProps.onSearch.mockClear();
}); });
it("must render child components and pass necessary props", () => {
const postHogScreenTracker = wrapper.find(PosthogScreenTracker);
const searchWarning = wrapper.find(SearchWarning);
expect(postHogScreenTracker.length).toBe(1);
expect(searchWarning.length).toBe(1);
expect(postHogScreenTracker.props().screenName).toEqual("RoomSearch");
expect(searchWarning.props().isRoomEncrypted).toEqual(searchProps.isRoomEncrypted);
expect(searchWarning.props().kind).toEqual(mockWarningKind);
});
it("must not search when input value is empty", () => { it("must not search when input value is empty", () => {
const roomButtons = wrapper.find(".mx_SearchBar_button"); const { container } = render(<SearchBar {...searchProps} />);
const searchButton = wrapper.find(".mx_SearchBar_searchButton"); const roomButtons = container.querySelectorAll(".mx_SearchBar_button");
const searchButton = container.querySelectorAll(".mx_SearchBar_searchButton");
expect(roomButtons.length).toEqual(4); expect(roomButtons.length).toEqual(2);
searchButton.at(0).simulate("click"); fireEvent.click(searchButton[0]);
roomButtons.at(0).simulate("click"); fireEvent.click(roomButtons[0]);
roomButtons.at(2).simulate("click"); fireEvent.click(roomButtons[1]);
expect(searchProps.onSearch).not.toHaveBeenCalled(); expect(searchProps.onSearch).not.toHaveBeenCalled();
}); });
it("must trigger onSearch when value is not empty", () => { it("must trigger onSearch when value is not empty", () => {
const { container } = render(<SearchBar {...searchProps} />);
const searchValue = "abcd"; const searchValue = "abcd";
const roomButtons = wrapper.find(".mx_SearchBar_button"); const roomButtons = container.querySelectorAll(".mx_SearchBar_button");
const searchButton = wrapper.find(".mx_SearchBar_searchButton"); const searchButton = container.querySelectorAll(".mx_SearchBar_searchButton");
const input = wrapper.find(".mx_SearchBar_input input"); const input = container.querySelector<HTMLInputElement>(".mx_SearchBar_input input");
input.instance().value = searchValue; input!.value = searchValue;
expect(roomButtons.length).toEqual(4); expect(roomButtons.length).toEqual(2);
searchButton.at(0).simulate("click"); fireEvent.click(searchButton[0]);
expect(searchProps.onSearch).toHaveBeenCalledTimes(1); expect(searchProps.onSearch).toHaveBeenCalledTimes(1);
expect(searchProps.onSearch).toHaveBeenNthCalledWith(1, searchValue, SearchScope.Room); expect(searchProps.onSearch).toHaveBeenNthCalledWith(1, searchValue, SearchScope.Room);
roomButtons.at(0).simulate("click"); fireEvent.click(roomButtons[0]);
expect(searchProps.onSearch).toHaveBeenCalledTimes(2); expect(searchProps.onSearch).toHaveBeenCalledTimes(2);
expect(searchProps.onSearch).toHaveBeenNthCalledWith(2, searchValue, SearchScope.Room); expect(searchProps.onSearch).toHaveBeenNthCalledWith(2, searchValue, SearchScope.Room);
roomButtons.at(2).simulate("click"); fireEvent.click(roomButtons[1]);
expect(searchProps.onSearch).toHaveBeenCalledTimes(3); expect(searchProps.onSearch).toHaveBeenCalledTimes(3);
expect(searchProps.onSearch).toHaveBeenNthCalledWith(3, searchValue, SearchScope.All); expect(searchProps.onSearch).toHaveBeenNthCalledWith(3, searchValue, SearchScope.All);
}); });
it("cancel button and esc key should trigger onCancelClick", () => { it("cancel button and esc key should trigger onCancelClick", async () => {
mockCurrentEvent = KeyBindingAction.Escape; mockCurrentEvent = KeyBindingAction.Escape;
const cancelButton = wrapper.find(".mx_SearchBar_cancel"); const { container } = render(<SearchBar {...searchProps} />);
const input = wrapper.find(".mx_SearchBar_input input"); const cancelButton = container.querySelector(".mx_SearchBar_cancel");
input.simulate("focus"); const input = container.querySelector(".mx_SearchBar_input input");
input.simulate("keydown", { key: "ESC" }); fireEvent.click(cancelButton!);
cancelButton.at(0).simulate("click"); expect(searchProps.onCancelClick).toHaveBeenCalledTimes(1);
fireEvent.focus(input!);
fireEvent.keyDown(input!, { key: 'Escape', code: 'Escape', charCode: 27 });
expect(searchProps.onCancelClick).toHaveBeenCalledTimes(2); expect(searchProps.onCancelClick).toHaveBeenCalledTimes(2);
}); });

View file

@ -15,14 +15,12 @@ limitations under the License.
*/ */
import * as React from "react"; import * as React from "react";
// eslint-disable-next-line deprecate/import
import { mount } from "enzyme";
import { SearchResult } from "matrix-js-sdk/src/models/search-result"; import { SearchResult } from "matrix-js-sdk/src/models/search-result";
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { EventType } from "matrix-js-sdk/src/@types/event"; import { EventType } from "matrix-js-sdk/src/@types/event";
import { render } from "@testing-library/react";
import { createTestClient } from "../../../test-utils"; import { createTestClient } from "../../../test-utils";
import EventTile from "../../../../src/components/views/rooms/EventTile";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import SearchResultTile from "../../../../src/components/views/rooms/SearchResultTile"; import SearchResultTile from "../../../../src/components/views/rooms/SearchResultTile";
@ -32,7 +30,7 @@ describe("SearchResultTile", () => {
}); });
it("Sets up appropriate callEventGrouper for m.call. events", () => { it("Sets up appropriate callEventGrouper for m.call. events", () => {
const wrapper = mount( const { container } = render(
<SearchResultTile <SearchResultTile
searchResult={SearchResult.fromJson({ searchResult={SearchResult.fromJson({
rank: 0.00424866, rank: 0.00424866,
@ -77,11 +75,9 @@ describe("SearchResultTile", () => {
/>, />,
); );
const tiles = wrapper.find(EventTile); const tiles = container.querySelectorAll<HTMLElement>(".mx_EventTile");
expect(tiles.length).toEqual(2); expect(tiles.length).toEqual(2);
expect(tiles.at(0).prop("mxEvent").getId()).toBe("$1:server"); expect(tiles[0].dataset.eventId).toBe("$1:server");
// @ts-ignore accessing private property expect(tiles[1].dataset.eventId).toBe("$144429830826TWwbB:localhost");
expect(tiles.at(0).prop("callEventGrouper").events.size).toBe(2);
expect(tiles.at(1).prop("mxEvent").getId()).toBe("$144429830826TWwbB:localhost");
}); });
}); });

View file

@ -15,8 +15,7 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
// eslint-disable-next-line deprecate/import import { render } from '@testing-library/react';
import { mount } from "enzyme";
import * as TestUtils from "../../../test-utils"; import * as TestUtils from "../../../test-utils";
import FontScalingPanel from '../../../../src/components/views/settings/FontScalingPanel'; import FontScalingPanel from '../../../../src/components/views/settings/FontScalingPanel';
@ -34,9 +33,9 @@ jest.mock(
describe('FontScalingPanel', () => { describe('FontScalingPanel', () => {
it('renders the font scaling UI', () => { it('renders the font scaling UI', () => {
TestUtils.stubClient(); TestUtils.stubClient();
const wrapper = mount( const { asFragment } = render(
<FontScalingPanel />, <FontScalingPanel />,
); );
expect(wrapper).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
}); });

View file

@ -15,8 +15,7 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
// eslint-disable-next-line deprecate/import import { render } from '@testing-library/react';
import { mount } from "enzyme";
import * as TestUtils from "../../../test-utils"; import * as TestUtils from "../../../test-utils";
import ThemeChoicePanel from '../../../../src/components/views/settings/ThemeChoicePanel'; import ThemeChoicePanel from '../../../../src/components/views/settings/ThemeChoicePanel';
@ -34,9 +33,9 @@ jest.mock(
describe('ThemeChoicePanel', () => { describe('ThemeChoicePanel', () => {
it('renders the theme choice UI', () => { it('renders the theme choice UI', () => {
TestUtils.stubClient(); TestUtils.stubClient();
const wrapper = mount( const { asFragment } = render(
<ThemeChoicePanel />, <ThemeChoicePanel />,
); );
expect(wrapper).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
}); });

View file

@ -15,8 +15,7 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
// eslint-disable-next-line deprecate/import import { render } from '@testing-library/react';
import { mount } from 'enzyme';
import SettingsStore from '../../../../src/settings/SettingsStore'; import SettingsStore from '../../../../src/settings/SettingsStore';
import UiFeatureSettingWrapper from '../../../../src/components/views/settings/UiFeatureSettingWrapper'; import UiFeatureSettingWrapper from '../../../../src/components/views/settings/UiFeatureSettingWrapper';
@ -29,29 +28,29 @@ describe('<UiFeatureSettingWrapper>', () => {
uiFeature: UIFeature.Feedback, uiFeature: UIFeature.Feedback,
children: <div>test</div>, children: <div>test</div>,
}; };
const getComponent = (props = {}) => mount(<UiFeatureSettingWrapper {...defaultProps} {...props} />); const getComponent = (props = {}) => render(<UiFeatureSettingWrapper {...defaultProps} {...props} />);
beforeEach(() => { beforeEach(() => {
(SettingsStore.getValue as jest.Mock).mockClear().mockReturnValue(true); (SettingsStore.getValue as jest.Mock).mockClear().mockReturnValue(true);
}); });
it('renders children when setting is truthy', () => { it('renders children when setting is truthy', () => {
const component = getComponent(); const { asFragment } = getComponent();
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
expect(SettingsStore.getValue).toHaveBeenCalledWith(defaultProps.uiFeature); expect(SettingsStore.getValue).toHaveBeenCalledWith(defaultProps.uiFeature);
}); });
it('returns null when setting is truthy but children are undefined', () => { it('returns null when setting is truthy but children are undefined', () => {
const component = getComponent({ children: undefined }); const { asFragment } = getComponent({ children: undefined });
expect(component.html()).toBeNull(); expect(asFragment()).toMatchSnapshot();
}); });
it('returns null when setting is falsy', () => { it('returns null when setting is falsy', () => {
(SettingsStore.getValue as jest.Mock).mockReturnValue(false); (SettingsStore.getValue as jest.Mock).mockReturnValue(false);
const component = getComponent(); const { asFragment } = getComponent();
expect(component.html()).toBeNull(); expect(asFragment()).toMatchSnapshot();
}); });
}); });

View file

@ -1,313 +1,186 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FontScalingPanel renders the font scaling UI 1`] = ` exports[`FontScalingPanel renders the font scaling UI 1`] = `
<FontScalingPanel> <DocumentFragment>
<div <div
className="mx_SettingsTab_section mx_FontScalingPanel" class="mx_SettingsTab_section mx_FontScalingPanel"
> >
<span <span
className="mx_SettingsTab_subheading" class="mx_SettingsTab_subheading"
> >
Font size Font size
</span> </span>
<EventTilePreview
avatarUrl={null}
className="mx_FontScalingPanel_preview"
displayName={null}
layout="group"
message="Hey you. You're the best!"
userId={null}
>
<div
className="mx_FontScalingPanel_preview mx_EventTilePreview_loader"
>
<Spinner
h={32}
w={32}
>
<div
className="mx_Spinner"
>
<div
aria-label="Loading..."
className="mx_Spinner_icon"
data-testid="spinner"
role="progressbar"
style={
{
"height": 32,
"width": 32,
}
}
/>
</div>
</Spinner>
</div>
</EventTilePreview>
<div <div
className="mx_FontScalingPanel_fontSlider" class="mx_FontScalingPanel_preview mx_EventTilePreview_loader"
> >
<div <div
className="mx_FontScalingPanel_fontSlider_smallText" class="mx_Spinner"
>
<div
aria-label="Loading..."
class="mx_Spinner_icon"
data-testid="spinner"
role="progressbar"
style="width: 32px; height: 32px;"
/>
</div>
</div>
<div
class="mx_FontScalingPanel_fontSlider"
>
<div
class="mx_FontScalingPanel_fontSlider_smallText"
> >
Aa Aa
</div> </div>
<Slider <div
disabled={false} class="mx_Slider"
displayFunc={[Function]}
onSelectionChange={[Function]}
value={15}
values={
[
13,
14,
15,
16,
18,
]
}
> >
<div <div>
className="mx_Slider" <div
> class="mx_Slider_bar"
<div> >
<hr />
<div <div
className="mx_Slider_bar" class="mx_Slider_selection"
> >
<hr
onClick={[Function]}
/>
<div <div
className="mx_Slider_selection" class="mx_Slider_selectionDot"
style="left: calc(-1.195em + 50%);"
> >
<div <div
className="mx_Slider_selectionDot" class="mx_Slider_selectionText"
style={
{
"left": "calc(-1.195em + 50%)",
}
}
> >
<div 15
className="mx_Slider_selectionText"
>
15
</div>
</div> </div>
<hr
style={
{
"width": "50%",
}
}
/>
</div> </div>
</div> <hr
<div style="width: 50%;"
className="mx_Slider_dotContainer" />
>
<Dot
active={true}
disabled={false}
key="13"
label=""
onClick={[Function]}
>
<span
className="mx_Slider_dotValue"
onClick={[Function]}
>
<div
className="mx_Slider_dot mx_Slider_dotActive"
/>
<div
className="mx_Slider_labelContainer"
>
<div
className="mx_Slider_label"
/>
</div>
</span>
</Dot>
<Dot
active={true}
disabled={false}
key="14"
label=""
onClick={[Function]}
>
<span
className="mx_Slider_dotValue"
onClick={[Function]}
>
<div
className="mx_Slider_dot mx_Slider_dotActive"
/>
<div
className="mx_Slider_labelContainer"
>
<div
className="mx_Slider_label"
/>
</div>
</span>
</Dot>
<Dot
active={true}
disabled={false}
key="15"
label=""
onClick={[Function]}
>
<span
className="mx_Slider_dotValue"
onClick={[Function]}
>
<div
className="mx_Slider_dot mx_Slider_dotActive"
/>
<div
className="mx_Slider_labelContainer"
>
<div
className="mx_Slider_label"
/>
</div>
</span>
</Dot>
<Dot
active={false}
disabled={false}
key="16"
label=""
onClick={[Function]}
>
<span
className="mx_Slider_dotValue"
onClick={[Function]}
>
<div
className="mx_Slider_dot"
/>
<div
className="mx_Slider_labelContainer"
>
<div
className="mx_Slider_label"
/>
</div>
</span>
</Dot>
<Dot
active={false}
disabled={false}
key="18"
label=""
onClick={[Function]}
>
<span
className="mx_Slider_dotValue"
onClick={[Function]}
>
<div
className="mx_Slider_dot"
/>
<div
className="mx_Slider_labelContainer"
>
<div
className="mx_Slider_label"
/>
</div>
</span>
</Dot>
</div> </div>
</div> </div>
<div
class="mx_Slider_dotContainer"
>
<span
class="mx_Slider_dotValue"
>
<div
class="mx_Slider_dot mx_Slider_dotActive"
/>
<div
class="mx_Slider_labelContainer"
>
<div
class="mx_Slider_label"
/>
</div>
</span>
<span
class="mx_Slider_dotValue"
>
<div
class="mx_Slider_dot mx_Slider_dotActive"
/>
<div
class="mx_Slider_labelContainer"
>
<div
class="mx_Slider_label"
/>
</div>
</span>
<span
class="mx_Slider_dotValue"
>
<div
class="mx_Slider_dot mx_Slider_dotActive"
/>
<div
class="mx_Slider_labelContainer"
>
<div
class="mx_Slider_label"
/>
</div>
</span>
<span
class="mx_Slider_dotValue"
>
<div
class="mx_Slider_dot"
/>
<div
class="mx_Slider_labelContainer"
>
<div
class="mx_Slider_label"
/>
</div>
</span>
<span
class="mx_Slider_dotValue"
>
<div
class="mx_Slider_dot"
/>
<div
class="mx_Slider_labelContainer"
>
<div
class="mx_Slider_label"
/>
</div>
</span>
</div>
</div> </div>
</Slider> </div>
<div <div
className="mx_FontScalingPanel_fontSlider_largeText" class="mx_FontScalingPanel_fontSlider_largeText"
> >
Aa Aa
</div> </div>
</div> </div>
<SettingsFlag <span
level="account" class="mx_Checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
name="useCustomFontSize"
onChange={[Function]}
useCheckbox={true}
> >
<StyledCheckbox <input
checked={false} id="checkbox_abdefghi"
className="" type="checkbox"
disabled={false} />
onChange={[Function]} <label
for="checkbox_abdefghi"
> >
<span <div
className="mx_Checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid" class="mx_Checkbox_background"
> >
<input <div
checked={false} class="mx_Checkbox_checkmark"
disabled={false}
id="checkbox_abdefghi"
onChange={[Function]}
type="checkbox"
/> />
<label </div>
htmlFor="checkbox_abdefghi" <div>
> Use custom size
<div </div>
className="mx_Checkbox_background" </label>
> </span>
<div <div
className="mx_Checkbox_checkmark" class="mx_Field mx_Field_input mx_FontScalingPanel_customFontSizeField"
/>
</div>
<div>
Use custom size
</div>
</label>
</span>
</StyledCheckbox>
</SettingsFlag>
<Field
autoComplete="off"
className="mx_FontScalingPanel_customFontSizeField"
disabled={true}
element="input"
id="font_size_field"
label="Font size"
onChange={[Function]}
onValidate={[Function]}
placeholder="15"
type="number"
validateOnBlur={true}
validateOnChange={true}
validateOnFocus={true}
value="15"
> >
<div <input
className="mx_Field mx_Field_input mx_FontScalingPanel_customFontSizeField" autocomplete="off"
disabled=""
id="font_size_field"
label="Font size"
placeholder="15"
type="number"
value="15"
/>
<label
for="font_size_field"
> >
<input Font size
autoComplete="off" </label>
disabled={true} </div>
id="font_size_field"
label="Font size"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
placeholder="15"
type="number"
value="15"
/>
<label
htmlFor="font_size_field"
>
Font size
</label>
</div>
</Field>
</div> </div>
</FontScalingPanel> </DocumentFragment>
`; `;

View file

@ -1,113 +1,63 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ThemeChoicePanel renders the theme choice UI 1`] = ` exports[`ThemeChoicePanel renders the theme choice UI 1`] = `
<ThemeChoicePanel> <DocumentFragment>
<div <div
className="mx_SettingsTab_section mx_ThemeChoicePanel" class="mx_SettingsTab_section mx_ThemeChoicePanel"
> >
<span <span
className="mx_SettingsTab_subheading" class="mx_SettingsTab_subheading"
> >
Theme Theme
</span> </span>
<div <div
className="mx_ThemeSelectors" class="mx_ThemeSelectors"
> >
<StyledRadioGroup <label
definitions={ class="mx_StyledRadioButton mx_ThemeSelector_light mx_StyledRadioButton_disabled mx_StyledRadioButton_outlined"
[
{
"className": "mx_ThemeSelector_light",
"disabled": true,
"label": "Light",
"value": "light",
},
{
"className": "mx_ThemeSelector_dark",
"disabled": true,
"label": "Dark",
"value": "dark",
},
]
}
name="theme"
onChange={[Function]}
outlined={true}
> >
<StyledRadioButton <input
checked={false} disabled=""
childrenInLabel={true}
className="mx_ThemeSelector_light"
disabled={true}
id="theme-light" id="theme-light"
name="theme" name="theme"
onChange={[Function]} type="radio"
outlined={true}
value="light" value="light"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
> >
<label Light
className="mx_StyledRadioButton mx_ThemeSelector_light mx_StyledRadioButton_disabled mx_StyledRadioButton_outlined" </div>
> <div
<input class="mx_StyledRadioButton_spacer"
checked={false} />
disabled={true} </label>
id="theme-light" <label
name="theme" class="mx_StyledRadioButton mx_ThemeSelector_dark mx_StyledRadioButton_disabled mx_StyledRadioButton_outlined"
onChange={[Function]} >
type="radio" <input
value="light" disabled=""
/>
<div>
<div />
</div>
<div
className="mx_StyledRadioButton_content"
>
Light
</div>
<div
className="mx_StyledRadioButton_spacer"
/>
</label>
</StyledRadioButton>
<StyledRadioButton
checked={false}
childrenInLabel={true}
className="mx_ThemeSelector_dark"
disabled={true}
id="theme-dark" id="theme-dark"
name="theme" name="theme"
onChange={[Function]} type="radio"
outlined={true}
value="dark" value="dark"
/>
<div>
<div />
</div>
<div
class="mx_StyledRadioButton_content"
> >
<label Dark
className="mx_StyledRadioButton mx_ThemeSelector_dark mx_StyledRadioButton_disabled mx_StyledRadioButton_outlined" </div>
> <div
<input class="mx_StyledRadioButton_spacer"
checked={false} />
disabled={true} </label>
id="theme-dark"
name="theme"
onChange={[Function]}
type="radio"
value="dark"
/>
<div>
<div />
</div>
<div
className="mx_StyledRadioButton_content"
>
Dark
</div>
<div
className="mx_StyledRadioButton_spacer"
/>
</label>
</StyledRadioButton>
</StyledRadioGroup>
</div> </div>
</div> </div>
</ThemeChoicePanel> </DocumentFragment>
`; `;

View file

@ -1,11 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<UiFeatureSettingWrapper> renders children when setting is truthy 1`] = ` exports[`<UiFeatureSettingWrapper> renders children when setting is truthy 1`] = `
<UiFeatureSettingWrapper <DocumentFragment>
uiFeature="UIFeature.feedback"
>
<div> <div>
test test
</div> </div>
</UiFeatureSettingWrapper> </DocumentFragment>
`; `;
exports[`<UiFeatureSettingWrapper> returns null when setting is falsy 1`] = `<DocumentFragment />`;
exports[`<UiFeatureSettingWrapper> returns null when setting is truthy but children are undefined 1`] = `<DocumentFragment />`;