Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 3fafa4b

Browse files
author
Kerry
authored
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
1 parent a06163e commit 3fafa4b

16 files changed

+289
-612
lines changed

cypress/e2e/location/location.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe("Location sharing", () => {
2727
};
2828

2929
const submitShareLocation = (): void => {
30-
cy.get('[data-test-id="location-picker-submit-button"]').click();
30+
cy.get('[data-testid="location-picker-submit-button"]').click();
3131
};
3232

3333
beforeEach(() => {

src/components/views/location/EnableLiveShare.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ interface Props {
2929
export const EnableLiveShare: React.FC<Props> = ({ onSubmit }) => {
3030
const [isEnabled, setEnabled] = useState(false);
3131
return (
32-
<div data-test-id="location-picker-enable-live-share" className="mx_EnableLiveShare">
32+
<div data-testid="location-picker-enable-live-share" className="mx_EnableLiveShare">
3333
<StyledLiveBeaconIcon className="mx_EnableLiveShare_icon" />
3434
<Heading className="mx_EnableLiveShare_heading" size="h3">
3535
{_t("Live location sharing")}
@@ -43,13 +43,13 @@ export const EnableLiveShare: React.FC<Props> = ({ onSubmit }) => {
4343
)}
4444
</p>
4545
<LabelledToggleSwitch
46-
data-test-id="enable-live-share-toggle"
46+
data-testid="enable-live-share-toggle"
4747
value={isEnabled}
4848
onChange={setEnabled}
4949
label={_t("Enable live location sharing")}
5050
/>
5151
<AccessibleButton
52-
data-test-id="enable-live-share-submit"
52+
data-testid="enable-live-share-submit"
5353
className="mx_EnableLiveShare_button"
5454
element="button"
5555
kind="primary"

src/components/views/location/LiveDurationDropdown.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const LiveDurationDropdown: React.FC<Props> = ({ timeout, onChange }) => {
6262
return (
6363
<Dropdown
6464
id="live-duration"
65-
data-test-id="live-duration-dropdown"
65+
data-testid="live-duration-dropdown"
6666
label={getLabel(timeout)}
6767
value={timeout.toString()}
6868
onOptionChange={onOptionChange}

src/components/views/location/LocationPicker.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ class LocationPicker extends React.Component<ILocationPickerProps, IState> {
231231
<LiveDurationDropdown onChange={this.onTimeoutChange} timeout={this.state.timeout} />
232232
)}
233233
<AccessibleButton
234-
data-test-id="location-picker-submit-button"
234+
data-testid="location-picker-submit-button"
235235
type="submit"
236236
element="button"
237237
kind="primary"

src/components/views/location/MapError.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export interface MapErrorProps {
3333

3434
export const MapError: React.FC<MapErrorProps> = ({ error, isMinimised, className, onFinished, onClick }) => (
3535
<div
36-
data-test-id="map-rendering-error"
36+
data-testid="map-rendering-error"
3737
className={classNames("mx_MapError", className, { mx_MapError_isMinimised: isMinimised })}
3838
onClick={onClick}
3939
>

src/components/views/location/ShareDialogButtons.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import React from "react";
1919
import AccessibleButton from "../elements/AccessibleButton";
2020
import { Icon as BackIcon } from "../../../../res/img/element-icons/caret-left.svg";
2121
import { Icon as CloseIcon } from "../../../../res/img/element-icons/cancel-rounded.svg";
22+
import { _t } from "../../../languageHandler";
2223

2324
interface Props {
2425
onCancel: () => void;
@@ -32,7 +33,8 @@ const ShareDialogButtons: React.FC<Props> = ({ onBack, onCancel, displayBack })
3233
{displayBack && (
3334
<AccessibleButton
3435
className="mx_ShareDialogButtons_button left"
35-
data-test-id="share-dialog-buttons-back"
36+
data-testid="share-dialog-buttons-back"
37+
aria-label={_t("Back")}
3638
onClick={onBack}
3739
element="button"
3840
>
@@ -41,7 +43,8 @@ const ShareDialogButtons: React.FC<Props> = ({ onBack, onCancel, displayBack })
4143
)}
4244
<AccessibleButton
4345
className="mx_ShareDialogButtons_button right"
44-
data-test-id="share-dialog-buttons-cancel"
46+
data-testid="share-dialog-buttons-cancel"
47+
aria-label={_t("Close")}
4548
onClick={onCancel}
4649
element="button"
4750
>

test/components/views/location/LocationPicker-test.tsx

+50-78
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ limitations under the License.
1515
*/
1616

1717
import React from "react";
18+
import { fireEvent, render, RenderResult } from "@testing-library/react";
1819
import * as maplibregl from "maplibre-gl";
19-
// eslint-disable-next-line deprecate/import
20-
import { mount, ReactWrapper } from "enzyme";
2120
import { act } from "react-dom/test-utils";
2221
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
2322
import { MatrixClient } from "matrix-js-sdk/src/client";
@@ -28,7 +27,7 @@ import LocationPicker from "../../../../src/components/views/location/LocationPi
2827
import { LocationShareType } from "../../../../src/components/views/location/shareLocation";
2928
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
3029
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
31-
import { findById, findByTestId, mockPlatformPeg } from "../../../test-utils";
30+
import { getMockClientWithEventEmitter, mockPlatformPeg } from "../../../test-utils";
3231
import { findMapStyleUrl, LocationShareError } from "../../../../src/utils/location";
3332

3433
jest.mock("../../../../src/utils/location/findMapStyleUrl", () => ({
@@ -49,17 +48,15 @@ describe("LocationPicker", () => {
4948
onChoose: jest.fn(),
5049
onFinished: jest.fn(),
5150
};
52-
const mockClient = {
53-
on: jest.fn(),
54-
removeListener: jest.fn(),
55-
off: jest.fn(),
51+
const mockClient = getMockClientWithEventEmitter({
5652
isGuest: jest.fn(),
5753
getClientWellKnown: jest.fn(),
58-
};
59-
const getComponent = (props = {}) =>
60-
mount(<LocationPicker {...defaultProps} {...props} />, {
61-
wrappingComponent: MatrixClientContext.Provider,
62-
wrappingComponentProps: { value: mockClient },
54+
});
55+
const getComponent = (props = {}): RenderResult =>
56+
render(<LocationPicker {...defaultProps} {...props} />, {
57+
wrapper: ({ children }) => (
58+
<MatrixClientContext.Provider value={mockClient}>{children}</MatrixClientContext.Provider>
59+
),
6360
});
6461

6562
const mapOptions = { container: {} as unknown as HTMLElement, style: "" };
@@ -94,18 +91,20 @@ describe("LocationPicker", () => {
9491
it("displays error when map emits an error", () => {
9592
// suppress expected error log
9693
jest.spyOn(logger, "error").mockImplementation(() => {});
97-
const wrapper = getComponent();
94+
const { getByTestId, getByText } = getComponent();
9895

9996
act(() => {
10097
// @ts-ignore
10198
mocked(mockMap).emit("error", { error: "Something went wrong" });
102-
wrapper.setProps({});
10399
});
104100

105-
expect(findByTestId(wrapper, "map-rendering-error").find("p").text()).toEqual(
106-
"This homeserver is not configured correctly to display maps, " +
107-
"or the configured map server may be unreachable.",
108-
);
101+
expect(getByTestId("map-rendering-error")).toBeInTheDocument();
102+
expect(
103+
getByText(
104+
"This homeserver is not configured correctly to display maps, " +
105+
"or the configured map server may be unreachable.",
106+
),
107+
).toBeInTheDocument();
109108
});
110109

111110
it("displays error when map display is not configured properly", () => {
@@ -115,12 +114,9 @@ describe("LocationPicker", () => {
115114
throw new Error(LocationShareError.MapStyleUrlNotConfigured);
116115
});
117116

118-
const wrapper = getComponent();
119-
wrapper.setProps({});
117+
const { getByText } = getComponent();
120118

121-
expect(findByTestId(wrapper, "map-rendering-error").find("p").text()).toEqual(
122-
"This homeserver is not configured to display maps.",
123-
);
119+
expect(getByText("This homeserver is not configured to display maps.")).toBeInTheDocument();
124120
});
125121

126122
it("displays error when map setup throws", () => {
@@ -132,13 +128,14 @@ describe("LocationPicker", () => {
132128
throw new Error("oups");
133129
});
134130

135-
const wrapper = getComponent();
136-
wrapper.setProps({});
131+
const { getByText } = getComponent();
137132

138-
expect(findByTestId(wrapper, "map-rendering-error").find("p").text()).toEqual(
139-
"This homeserver is not configured correctly to display maps, " +
140-
"or the configured map server may be unreachable.",
141-
);
133+
expect(
134+
getByText(
135+
"This homeserver is not configured correctly to display maps, " +
136+
"or the configured map server may be unreachable.",
137+
),
138+
).toBeInTheDocument();
142139
});
143140

144141
it("initiates map with geolocation", () => {
@@ -174,57 +171,49 @@ describe("LocationPicker", () => {
174171
});
175172

176173
it("sets position on geolocate event", () => {
177-
const wrapper = getComponent({ shareType });
174+
const { container, getByTestId } = getComponent({ shareType });
178175
act(() => {
179176
// @ts-ignore
180177
mocked(mockGeolocate).emit("geolocate", mockGeolocationPosition);
181-
wrapper.setProps({});
182178
});
183179

184180
// marker added
185181
expect(maplibregl.Marker).toHaveBeenCalled();
186182
expect(mockMarker.setLngLat).toHaveBeenCalledWith(new maplibregl.LngLat(12.4, 43.2));
187183
// submit button is enabled when position is truthy
188-
expect(findByTestId(wrapper, "location-picker-submit-button").at(0).props().disabled).toBeFalsy();
189-
expect(wrapper.find("MemberAvatar").length).toBeTruthy();
184+
expect(getByTestId("location-picker-submit-button")).not.toBeDisabled();
185+
expect(container.querySelector(".mx_BaseAvatar")).toBeInTheDocument();
190186
});
191187

192188
it("disables submit button until geolocation completes", () => {
193189
const onChoose = jest.fn();
194-
const wrapper = getComponent({ shareType, onChoose });
190+
const { getByTestId } = getComponent({ shareType, onChoose });
195191

196-
// submit button is enabled when position is truthy
197-
expect(findByTestId(wrapper, "location-picker-submit-button").at(0).props().disabled).toBeTruthy();
198-
act(() => {
199-
findByTestId(wrapper, "location-picker-submit-button").at(0).simulate("click");
200-
});
192+
// button is disabled
193+
expect(getByTestId("location-picker-submit-button")).toBeDisabled();
194+
fireEvent.click(getByTestId("location-picker-submit-button"));
201195
// nothing happens on button click
202196
expect(onChoose).not.toHaveBeenCalled();
203197

204198
act(() => {
205199
// @ts-ignore
206200
mocked(mockGeolocate).emit("geolocate", mockGeolocationPosition);
207-
wrapper.setProps({});
208201
});
209202

210203
// submit button is enabled when position is truthy
211-
expect(findByTestId(wrapper, "location-picker-submit-button").at(0).props().disabled).toBeFalsy();
204+
expect(getByTestId("location-picker-submit-button")).not.toBeDisabled();
212205
});
213206

214207
it("submits location", () => {
215208
const onChoose = jest.fn();
216-
const wrapper = getComponent({ onChoose, shareType });
209+
const { getByTestId } = getComponent({ onChoose, shareType });
217210
act(() => {
218211
// @ts-ignore
219212
mocked(mockGeolocate).emit("geolocate", mockGeolocationPosition);
220213
// make sure button is enabled
221-
wrapper.setProps({});
222-
});
223-
224-
act(() => {
225-
findByTestId(wrapper, "location-picker-submit-button").at(0).simulate("click");
226214
});
227215

216+
fireEvent.click(getByTestId("location-picker-submit-button"));
228217
// content of this call is tested in LocationShareMenu-test
229218
expect(onChoose).toHaveBeenCalled();
230219
});
@@ -239,34 +228,21 @@ describe("LocationPicker", () => {
239228
const shareType = LocationShareType.Live;
240229
testUserLocationShareTypes(shareType);
241230

242-
const getOption = (wrapper: ReactWrapper, timeout: number) =>
243-
findById(wrapper, `live-duration__${timeout}`).at(0);
244-
const getDropdown = (wrapper: ReactWrapper) => findByTestId(wrapper, "live-duration-dropdown");
245-
const getSelectedOption = (wrapper: ReactWrapper) => findById(wrapper, "live-duration_value");
246-
247-
const openDropdown = (wrapper: ReactWrapper) =>
248-
act(() => {
249-
const dropdown = getDropdown(wrapper);
250-
dropdown.find('[role="button"]').at(0).simulate("click");
251-
wrapper.setProps({});
252-
});
253-
254231
it("renders live duration dropdown with default option", () => {
255-
const wrapper = getComponent({ shareType });
256-
expect(getSelectedOption(getDropdown(wrapper)).text()).toEqual("Share for 15m");
232+
const { getByText } = getComponent({ shareType });
233+
expect(getByText("Share for 15m")).toBeInTheDocument();
257234
});
258235

259236
it("updates selected duration", () => {
260-
const wrapper = getComponent({ shareType });
237+
const { getByText, getByLabelText } = getComponent({ shareType });
261238

262-
openDropdown(wrapper);
263-
const dropdown = getDropdown(wrapper);
264-
act(() => {
265-
getOption(dropdown, 3600000).simulate("click");
266-
});
239+
// open dropdown
240+
fireEvent.click(getByLabelText("Share for 15m"));
241+
242+
fireEvent.click(getByText("Share for 1h"));
267243

268244
// value updated
269-
expect(getSelectedOption(getDropdown(wrapper)).text()).toEqual("Share for 1h");
245+
expect(getByText("Share for 1h")).toMatchSnapshot();
270246
});
271247
});
272248

@@ -303,44 +279,40 @@ describe("LocationPicker", () => {
303279

304280
it("does not set position on geolocate event", () => {
305281
mocked(maplibregl.Marker).mockClear();
306-
const wrapper = getComponent({ shareType });
282+
const { container } = getComponent({ shareType });
307283
act(() => {
308284
// @ts-ignore
309285
mocked(mockGeolocate).emit("geolocate", mockGeolocationPosition);
310286
});
311287

312288
// marker not added
313-
expect(wrapper.find("Marker").length).toBeFalsy();
289+
expect(container.querySelector("mx_Marker")).not.toBeInTheDocument();
314290
});
315291

316292
it("sets position on click event", () => {
317-
const wrapper = getComponent({ shareType });
293+
const { container } = getComponent({ shareType });
318294
act(() => {
319295
// @ts-ignore
320296
mocked(mockMap).emit("click", mockClickEvent);
321-
wrapper.setProps({});
322297
});
323298

324299
// marker added
325300
expect(maplibregl.Marker).toHaveBeenCalled();
326301
expect(mockMarker.setLngLat).toHaveBeenCalledWith(new maplibregl.LngLat(12.4, 43.2));
327302

328303
// marker is set, icon not avatar
329-
expect(wrapper.find(".mx_Marker_icon").length).toBeTruthy();
304+
expect(container.querySelector(".mx_Marker_icon")).toBeInTheDocument();
330305
});
331306

332307
it("submits location", () => {
333308
const onChoose = jest.fn();
334-
const wrapper = getComponent({ onChoose, shareType });
309+
const { getByTestId } = getComponent({ onChoose, shareType });
335310
act(() => {
336311
// @ts-ignore
337312
mocked(mockMap).emit("click", mockClickEvent);
338-
wrapper.setProps({});
339313
});
340314

341-
act(() => {
342-
findByTestId(wrapper, "location-picker-submit-button").at(0).simulate("click");
343-
});
315+
fireEvent.click(getByTestId("location-picker-submit-button"));
344316

345317
// content of this call is tested in LocationShareMenu-test
346318
expect(onChoose).toHaveBeenCalled();

0 commit comments

Comments
 (0)