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

Commit 667ec16

Browse files
authored
Remove Enzyme tests in favour of React testing-library (#10289)
1 parent 303b878 commit 667ec16

File tree

10 files changed

+429
-3160
lines changed

10 files changed

+429
-3160
lines changed

scripts/make-react-component.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,19 @@ const %%ComponentName%%: React.FC<Props> = () => {
3131
export default %%ComponentName%%;
3232
`,
3333
TEST: `
34-
import React from 'react';
35-
import { mount } from 'enzyme';
34+
import React from "react";
35+
import { render } from "@testing-library/react";
3636
3737
import %%ComponentName%% from '%%RelativeComponentPath%%';
3838
39-
describe('<%%ComponentName%% />', () => {
39+
describe("<%%ComponentName%% />", () => {
4040
const defaultProps = {};
4141
const getComponent = (props = {}) =>
42-
mount(<%%ComponentName%% {...defaultProps} {...props} />);
42+
render(<%%ComponentName%% {...defaultProps} {...props} />);
4343
44-
it('renders', () => {
45-
const component = getComponent();
46-
expect(component).toBeTruthy();
44+
it("matches snapshot", () => {
45+
const { asFragment } = getComponent();
46+
expect(asFragment()).toMatchSnapshot()();
4747
});
4848
});
4949
`,

src/components/views/dialogs/ExportDialog.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,14 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
110110
const [displayCancel, setCancelWarning] = useState(false);
111111
const [exportCancelled, setExportCancelled] = useState(false);
112112
const [exportSuccessful, setExportSuccessful] = useState(false);
113-
const [exporter, setExporter] = useStateCallback<Exporter>(null, async (exporter: Exporter): Promise<void> => {
114-
await exporter?.export().then(() => {
115-
if (!exportCancelled) setExportSuccessful(true);
116-
});
117-
});
113+
const [exporter, setExporter] = useStateCallback<Exporter | null>(
114+
null,
115+
async (exporter: Exporter | null): Promise<void> => {
116+
await exporter?.export().then(() => {
117+
if (!exportCancelled) setExportSuccessful(true);
118+
});
119+
},
120+
);
118121

119122
const startExport = async (): Promise<void> => {
120123
const exportOptions = {

test/components/structures/RoomView-test.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import React from "react";
18-
// eslint-disable-next-line deprecate/import
19-
import { mount, ReactWrapper } from "enzyme";
17+
import React, { createRef, RefObject } from "react";
2018
import { mocked, MockedObject } from "jest-mock";
2119
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/client";
2220
import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";
2321
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
2422
import { EventType, RoomStateEvent } from "matrix-js-sdk/src/matrix";
2523
import { MEGOLM_ALGORITHM } from "matrix-js-sdk/src/crypto/olmlib";
26-
import { fireEvent, render, screen } from "@testing-library/react";
24+
import { fireEvent, render, screen, RenderResult } from "@testing-library/react";
2725

2826
import {
2927
stubClient,
@@ -98,7 +96,7 @@ describe("RoomView", () => {
9896
jest.restoreAllMocks();
9997
});
10098

101-
const mountRoomView = async (): Promise<ReactWrapper> => {
99+
const mountRoomView = async (ref?: RefObject<_RoomView>): Promise<RenderResult> => {
102100
if (stores.roomViewStore.getRoomId() !== room.roomId) {
103101
const switchedRoom = new Promise<void>((resolve) => {
104102
const subFn = () => {
@@ -119,14 +117,15 @@ describe("RoomView", () => {
119117
await switchedRoom;
120118
}
121119

122-
const roomView = mount(
120+
const roomView = render(
123121
<SDKContext.Provider value={stores}>
124122
<RoomView
125123
// threepidInvite should be optional on RoomView props
126124
// it is treated as optional in RoomView
127125
threepidInvite={undefined as any}
128126
resizeNotifier={new ResizeNotifier()}
129127
forceTimeline={false}
128+
wrappedRef={ref as any}
130129
/>
131130
</SDKContext.Provider>,
132131
);
@@ -170,8 +169,11 @@ describe("RoomView", () => {
170169
await flushPromises();
171170
return roomView;
172171
};
173-
const getRoomViewInstance = async (): Promise<_RoomView> =>
174-
(await mountRoomView()).find(_RoomView).instance() as _RoomView;
172+
const getRoomViewInstance = async (): Promise<_RoomView> => {
173+
const ref = createRef<_RoomView>();
174+
await mountRoomView(ref);
175+
return ref.current!;
176+
};
175177

176178
it("when there is no room predecessor, getHiddenHighlightCount should return 0", async () => {
177179
const instance = await getRoomViewInstance();

test/components/structures/TimelinePanel-test.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ limitations under the License.
1515
*/
1616

1717
import { render, waitFor, screen } from "@testing-library/react";
18-
// eslint-disable-next-line deprecate/import
19-
import { mount, ReactWrapper } from "enzyme";
2018
import { ReceiptType } from "matrix-js-sdk/src/@types/read_receipts";
2119
import {
2220
EventTimelineSet,
@@ -38,7 +36,7 @@ import {
3836
ThreadEvent,
3937
ThreadFilterType,
4038
} from "matrix-js-sdk/src/models/thread";
41-
import React from "react";
39+
import React, { createRef } from "react";
4240

4341
import TimelinePanel from "../../../src/components/structures/TimelinePanel";
4442
import MatrixClientContext from "../../../src/contexts/MatrixClientContext";
@@ -137,15 +135,17 @@ describe("TimelinePanel", () => {
137135
// Create a TimelinePanel with ev0 already present
138136
const timelineSet = new EventTimelineSet(room, {});
139137
timelineSet.addLiveEvent(ev0);
140-
const component: ReactWrapper<TimelinePanel> = mount(
138+
const ref = createRef<TimelinePanel>();
139+
render(
141140
<TimelinePanel
142141
timelineSet={timelineSet}
143142
manageReadMarkers={true}
144143
manageReadReceipts={true}
145144
eventId={ev0.getId()}
145+
ref={ref}
146146
/>,
147147
);
148-
const timelinePanel = component.instance() as TimelinePanel;
148+
const timelinePanel = ref.current!;
149149

150150
// An event arrived, and we read it
151151
timelineSet.addLiveEvent(ev1);

test/components/views/context_menus/ContextMenu-test.tsx

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ limitations under the License.
1515
*/
1616

1717
import React from "react";
18-
// eslint-disable-next-line deprecate/import
19-
import { mount } from "enzyme";
18+
import { render } from "@testing-library/react";
2019

2120
import ContextMenu, { ChevronFace } from "../../../../src/components/structures/ContextMenu";
2221
import UIStore from "../../../../src/stores/UIStore";
@@ -41,11 +40,11 @@ describe("<ContextMenu />", () => {
4140

4241
const targetChevronOffset = 25;
4342

44-
describe("near top edge of window", () => {
43+
it("near top edge of window", () => {
4544
const targetY = -50;
4645
const onFinished = jest.fn();
4746

48-
const wrapper = mount(
47+
render(
4948
<ContextMenu
5049
bottom={windowSize - targetY - menuSize}
5150
right={menuSize}
@@ -54,25 +53,25 @@ describe("<ContextMenu />", () => {
5453
chevronOffset={targetChevronOffset}
5554
/>,
5655
);
57-
const chevron = wrapper.find(".mx_ContextualMenu_chevron_left");
56+
const chevron = document.querySelector<HTMLElement>(".mx_ContextualMenu_chevron_left")!;
5857

59-
const bottomStyle = parseInt(wrapper.getDOMNode<HTMLElement>().style.getPropertyValue("bottom"));
58+
const bottomStyle = parseInt(
59+
document.querySelector<HTMLElement>(".mx_ContextualMenu_wrapper")!.style.getPropertyValue("bottom"),
60+
);
6061
const actualY = windowSize - bottomStyle - menuSize;
61-
const actualChevronOffset = parseInt(chevron.getDOMNode<HTMLElement>().style.getPropertyValue("top"));
62-
63-
it("stays within the window", () => {
64-
expect(actualY).toBeGreaterThanOrEqual(0);
65-
});
66-
it("positions the chevron correctly", () => {
67-
expect(actualChevronOffset).toEqual(targetChevronOffset + targetY - actualY);
68-
});
62+
const actualChevronOffset = parseInt(chevron.style.getPropertyValue("top"));
63+
64+
// stays within the window
65+
expect(actualY).toBeGreaterThanOrEqual(0);
66+
// positions the chevron correctly
67+
expect(actualChevronOffset).toEqual(targetChevronOffset + targetY - actualY);
6968
});
7069

71-
describe("near right edge of window", () => {
70+
it("near right edge of window", () => {
7271
const targetX = windowSize - menuSize + 50;
7372
const onFinished = jest.fn();
7473

75-
const wrapper = mount(
74+
render(
7675
<ContextMenu
7776
bottom={0}
7877
onFinished={onFinished}
@@ -81,24 +80,24 @@ describe("<ContextMenu />", () => {
8180
chevronOffset={targetChevronOffset}
8281
/>,
8382
);
84-
const chevron = wrapper.find(".mx_ContextualMenu_chevron_top");
83+
const chevron = document.querySelector<HTMLElement>(".mx_ContextualMenu_chevron_top")!;
8584

86-
const actualX = parseInt(wrapper.getDOMNode<HTMLElement>().style.getPropertyValue("left"));
87-
const actualChevronOffset = parseInt(chevron.getDOMNode<HTMLElement>().style.getPropertyValue("left"));
85+
const actualX = parseInt(
86+
document.querySelector<HTMLElement>(".mx_ContextualMenu_wrapper")!.style.getPropertyValue("left"),
87+
);
88+
const actualChevronOffset = parseInt(chevron.style.getPropertyValue("left"));
8889

89-
it("stays within the window", () => {
90-
expect(actualX + menuSize).toBeLessThanOrEqual(windowSize);
91-
});
92-
it("positions the chevron correctly", () => {
93-
expect(actualChevronOffset).toEqual(targetChevronOffset + targetX - actualX);
94-
});
90+
// stays within the window
91+
expect(actualX + menuSize).toBeLessThanOrEqual(windowSize);
92+
// positions the chevron correctly
93+
expect(actualChevronOffset).toEqual(targetChevronOffset + targetX - actualX);
9594
});
9695

97-
describe("near bottom edge of window", () => {
96+
it("near bottom edge of window", () => {
9897
const targetY = windowSize - menuSize + 50;
9998
const onFinished = jest.fn();
10099

101-
const wrapper = mount(
100+
render(
102101
<ContextMenu
103102
top={targetY}
104103
left={0}
@@ -107,24 +106,24 @@ describe("<ContextMenu />", () => {
107106
chevronOffset={targetChevronOffset}
108107
/>,
109108
);
110-
const chevron = wrapper.find(".mx_ContextualMenu_chevron_right");
109+
const chevron = document.querySelector<HTMLElement>(".mx_ContextualMenu_chevron_right")!;
111110

112-
const actualY = parseInt(wrapper.getDOMNode<HTMLElement>().style.getPropertyValue("top"));
113-
const actualChevronOffset = parseInt(chevron.getDOMNode<HTMLElement>().style.getPropertyValue("top"));
111+
const actualY = parseInt(
112+
document.querySelector<HTMLElement>(".mx_ContextualMenu_wrapper")!.style.getPropertyValue("top"),
113+
);
114+
const actualChevronOffset = parseInt(chevron.style.getPropertyValue("top"));
114115

115-
it("stays within the window", () => {
116-
expect(actualY + menuSize).toBeLessThanOrEqual(windowSize);
117-
});
118-
it("positions the chevron correctly", () => {
119-
expect(actualChevronOffset).toEqual(targetChevronOffset + targetY - actualY);
120-
});
116+
// stays within the window
117+
expect(actualY + menuSize).toBeLessThanOrEqual(windowSize);
118+
// positions the chevron correctly
119+
expect(actualChevronOffset).toEqual(targetChevronOffset + targetY - actualY);
121120
});
122121

123-
describe("near left edge of window", () => {
122+
it("near left edge of window", () => {
124123
const targetX = -50;
125124
const onFinished = jest.fn();
126125

127-
const wrapper = mount(
126+
render(
128127
<ContextMenu
129128
top={0}
130129
right={windowSize - targetX - menuSize}
@@ -133,25 +132,25 @@ describe("<ContextMenu />", () => {
133132
chevronOffset={targetChevronOffset}
134133
/>,
135134
);
136-
const chevron = wrapper.find(".mx_ContextualMenu_chevron_bottom");
135+
const chevron = document.querySelector<HTMLElement>(".mx_ContextualMenu_chevron_bottom")!;
137136

138-
const rightStyle = parseInt(wrapper.getDOMNode<HTMLElement>().style.getPropertyValue("right"));
137+
const rightStyle = parseInt(
138+
document.querySelector<HTMLElement>(".mx_ContextualMenu_wrapper")!.style.getPropertyValue("right"),
139+
);
139140
const actualX = windowSize - rightStyle - menuSize;
140-
const actualChevronOffset = parseInt(chevron.getDOMNode<HTMLElement>().style.getPropertyValue("left"));
141-
142-
it("stays within the window", () => {
143-
expect(actualX).toBeGreaterThanOrEqual(0);
144-
});
145-
it("positions the chevron correctly", () => {
146-
expect(actualChevronOffset).toEqual(targetChevronOffset + targetX - actualX);
147-
});
141+
const actualChevronOffset = parseInt(chevron.style.getPropertyValue("left"));
142+
143+
// stays within the window
144+
expect(actualX).toBeGreaterThanOrEqual(0);
145+
// positions the chevron correctly
146+
expect(actualChevronOffset).toEqual(targetChevronOffset + targetX - actualX);
148147
});
149148

150149
it("should automatically close when a modal is opened", () => {
151150
const targetX = -50;
152151
const onFinished = jest.fn();
153152

154-
mount(
153+
render(
155154
<ContextMenu
156155
top={0}
157156
right={windowSize - targetX - menuSize}
@@ -171,7 +170,7 @@ describe("<ContextMenu />", () => {
171170
const onFinished = jest.fn();
172171

173172
Modal.createDialog(BaseDialog);
174-
mount(
173+
render(
175174
<ContextMenu
176175
top={0}
177176
right={windowSize - targetX - menuSize}

0 commit comments

Comments
 (0)