Skip to content

Commit 0ce0b75

Browse files
feat: upgrade to react 18 (#1766)
1 parent 3685dbd commit 0ce0b75

File tree

59 files changed

+5588
-2187
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+5588
-2187
lines changed

package-lock.json

Lines changed: 5210 additions & 1853 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"@edx/browserslist-config": "1.2.0",
5252
"@edx/frontend-component-footer": "^14.3.0",
5353
"@edx/frontend-component-header": "^6.2.0",
54-
"@edx/frontend-enterprise-hotjar": "^2.0.0",
54+
"@edx/frontend-enterprise-hotjar": "^7.2.0",
5555
"@edx/frontend-platform": "^8.3.1",
5656
"@edx/openedx-atlas": "^0.6.0",
5757
"@openedx-plugins/course-app-calculator": "file:plugins/course-apps/calculator",
@@ -85,9 +85,9 @@
8585
"moment-shortformat": "^2.1.0",
8686
"npm": "^10.8.1",
8787
"prop-types": "^15.8.1",
88-
"react": "17.0.2",
88+
"react": "^18.3.1",
8989
"react-datepicker": "^4.13.0",
90-
"react-dom": "17.0.2",
90+
"react-dom": "^18.3.1",
9191
"react-error-boundary": "^4.0.13",
9292
"react-helmet": "^6.1.0",
9393
"react-onclickoutside": "^6.13.0",
@@ -110,12 +110,11 @@
110110
"yup": "0.31.1"
111111
},
112112
"devDependencies": {
113-
"@edx/react-unit-test-utils": "3.0.0",
113+
"@edx/react-unit-test-utils": "^4.0.0",
114114
"@edx/stylelint-config-edx": "2.3.3",
115115
"@edx/typescript-config": "^1.0.1",
116-
"@testing-library/jest-dom": "5.17.0",
117-
"@testing-library/react": "12.1.5",
118-
"@testing-library/react-hooks": "^8.0.1",
116+
"@testing-library/jest-dom": "^6.6.3",
117+
"@testing-library/react": "^16.2.0",
119118
"@testing-library/user-event": "^13.2.1",
120119
"@types/lodash": "^4.17.7",
121120
"axios-mock-adapter": "1.22.0",
@@ -124,7 +123,7 @@
124123
"husky": "7.0.4",
125124
"jest-canvas-mock": "^2.5.2",
126125
"jest-expect-message": "^1.1.3",
127-
"react-test-renderer": "17.0.2",
126+
"react-test-renderer": "^18.3.1",
128127
"redux-mock-store": "^1.5.4"
129128
}
130129
}

plugins/course-apps/proctoring/Settings.test.jsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -544,12 +544,9 @@ describe('ProctoredExamSettings', () => {
544544

545545
describe('Connection states', () => {
546546
it('Shows the spinner before the connection is complete', async () => {
547-
await act(async () => {
548-
render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />));
549-
// This expectation is _inside_ the `act` intentionally, so that it executes immediately.
550-
const spinner = await screen.findByRole('status');
551-
expect(spinner.textContent).toEqual('Loading...');
552-
});
547+
render(intlWrapper(<IntlProctoredExamSettings {...defaultProps} />));
548+
const spinner = await screen.findByRole('status');
549+
expect(spinner.textContent).toEqual('Loading...');
553550
});
554551

555552
it('Show connection error message when we suffer studio server side error', async () => {

plugins/course-apps/xpert_unit_summary/Settings.test.jsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
88
import { AppProvider, PageWrap } from '@edx/frontend-platform/react';
99
import {
10-
queryByTestId, render, waitFor, getByText, fireEvent,
10+
findByTestId, queryByTestId, render, waitFor, getByText, fireEvent,
1111
} from '@testing-library/react';
1212
import MockAdapter from 'axios-mock-adapter';
1313
import PagesAndResourcesProvider from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
@@ -106,8 +106,9 @@ describe('XpertUnitSummarySettings', () => {
106106
});
107107

108108
test('Shows switch on if enabled from backend', async () => {
109+
const enableBadge = await findByTestId(container, 'enable-badge');
109110
expect(container.querySelector('#enable-xpert-unit-summary-toggle').checked).toBeTruthy();
110-
expect(queryByTestId(container, 'enable-badge')).toBeTruthy();
111+
expect(enableBadge).toBeTruthy();
111112
});
112113

113114
test('Shows switch on if disabled from backend', async () => {

src/content-tags-drawer/ContentTagsCollapsible.test.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ describe('<ContentTagsCollapsible />', () => {
699699
const xButtonAppliedTag = within(appliedTag).getByRole('button', {
700700
name: /delete/i,
701701
});
702-
xButtonAppliedTag.click();
702+
await userEvent.click(xButtonAppliedTag);
703703

704704
// Check that the applied tag has been removed
705705
expect(appliedTag).not.toBeInTheDocument();

src/content-tags-drawer/ContentTagsDrawer.test.jsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {
2-
act,
32
fireEvent,
43
initializeMocks,
54
render,
@@ -94,15 +93,12 @@ describe('<ContentTagsDrawer />', () => {
9493
});
9594

9695
it('shows the taxonomies data including tag numbers after the query is complete', async () => {
97-
await act(async () => {
98-
const { container } = renderDrawer(largeTagsId);
99-
await waitFor(() => { expect(screen.getByText('Taxonomy 1')).toBeInTheDocument(); });
100-
expect(screen.getByText('Taxonomy 1')).toBeInTheDocument();
101-
expect(screen.getByText('Taxonomy 2')).toBeInTheDocument();
102-
const tagCountBadges = container.getElementsByClassName('taxonomy-tags-count-chip');
103-
expect(tagCountBadges[0].textContent).toBe('3');
104-
expect(tagCountBadges[1].textContent).toBe('2');
105-
});
96+
const { container } = renderDrawer(largeTagsId);
97+
await screen.findByText('Taxonomy 1');
98+
await screen.findByText('Taxonomy 2');
99+
const tagCountBadges = container.getElementsByClassName('taxonomy-tags-count-chip');
100+
expect(tagCountBadges[0].textContent).toBe('3');
101+
expect(tagCountBadges[1].textContent).toBe('2');
106102
});
107103

108104
it('should be read only on first render on drawer variant', async () => {

src/content-tags-drawer/ContentTagsDropDownSelector.test.jsx

Lines changed: 96 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React from 'react';
22
import { IntlProvider } from '@edx/frontend-platform/i18n';
33
import {
4-
act,
54
render,
65
waitFor,
76
fireEvent,
@@ -74,11 +73,9 @@ describe('<ContentTagsDropDownSelector />', () => {
7473
}
7574

7675
it('should render taxonomy tags drop down selector loading with spinner', async () => {
77-
await act(async () => {
78-
const { getByRole } = await getComponent();
79-
const spinner = getByRole('status');
80-
expect(spinner.textContent).toEqual('Loading tags'); // Uses <Spinner />
81-
});
76+
const { getByRole } = await getComponent();
77+
const spinner = getByRole('status');
78+
expect(spinner.textContent).toEqual('Loading tags'); // Uses <Spinner />
8279
});
8380

8481
it('should render taxonomy tags drop down selector with no sub tags', async () => {
@@ -99,13 +96,11 @@ describe('<ContentTagsDropDownSelector />', () => {
9996
},
10097
});
10198

102-
await act(async () => {
103-
const { container, getByText } = await getComponent();
99+
const { container, getByText } = await getComponent();
104100

105-
await waitFor(() => {
106-
expect(getByText('Tag 1')).toBeInTheDocument();
107-
expect(container.getElementsByClassName('taxonomy-tags-arrow-drop-down').length).toBe(0);
108-
});
101+
await waitFor(() => {
102+
expect(getByText('Tag 1')).toBeInTheDocument();
103+
expect(container.getElementsByClassName('taxonomy-tags-arrow-drop-down').length).toBe(0);
109104
});
110105
});
111106

@@ -127,13 +122,11 @@ describe('<ContentTagsDropDownSelector />', () => {
127122
},
128123
});
129124

130-
await act(async () => {
131-
const { container, getByText } = await getComponent();
125+
const { container, getByText } = await getComponent();
132126

133-
await waitFor(() => {
134-
expect(getByText('Tag 2')).toBeInTheDocument();
135-
expect(container.getElementsByClassName('taxonomy-tags-arrow-drop-down').length).toBe(1);
136-
});
127+
await waitFor(() => {
128+
expect(getByText('Tag 2')).toBeInTheDocument();
129+
expect(container.getElementsByClassName('taxonomy-tags-arrow-drop-down').length).toBe(1);
137130
});
138131
});
139132

@@ -155,47 +148,45 @@ describe('<ContentTagsDropDownSelector />', () => {
155148
},
156149
});
157150

158-
await act(async () => {
159-
const dataWithTagsTree = {
160-
...data,
161-
tagsTree: {
162-
'Tag 3': {
163-
explicit: false,
164-
children: {},
165-
},
166-
},
167-
};
168-
const { container, getByText } = await getComponent(dataWithTagsTree);
169-
await waitFor(() => {
170-
expect(getByText('Tag 2')).toBeInTheDocument();
171-
expect(container.getElementsByClassName('taxonomy-tags-arrow-drop-down').length).toBe(1);
172-
});
173-
174-
// Mock useTaxonomyTagsData again since it gets called in the recursive call
175-
useTaxonomyTagsData.mockReturnValueOnce({
176-
hasMorePages: false,
177-
tagPages: {
178-
isLoading: false,
179-
isError: false,
180-
data: [{
181-
value: 'Tag 3',
182-
externalId: null,
183-
childCount: 0,
184-
depth: 1,
185-
parentValue: 'Tag 2',
186-
id: 12346,
187-
subTagsUrl: null,
188-
}],
151+
const dataWithTagsTree = {
152+
...data,
153+
tagsTree: {
154+
'Tag 3': {
155+
explicit: false,
156+
children: {},
189157
},
190-
});
158+
},
159+
};
160+
const { container, getByText } = await getComponent(dataWithTagsTree);
161+
await waitFor(() => {
162+
expect(getByText('Tag 2')).toBeInTheDocument();
163+
expect(container.getElementsByClassName('taxonomy-tags-arrow-drop-down').length).toBe(1);
164+
});
165+
166+
// Mock useTaxonomyTagsData again since it gets called in the recursive call
167+
useTaxonomyTagsData.mockReturnValueOnce({
168+
hasMorePages: false,
169+
tagPages: {
170+
isLoading: false,
171+
isError: false,
172+
data: [{
173+
value: 'Tag 3',
174+
externalId: null,
175+
childCount: 0,
176+
depth: 1,
177+
parentValue: 'Tag 2',
178+
id: 12346,
179+
subTagsUrl: null,
180+
}],
181+
},
182+
});
191183

192-
// Expand the dropdown to see the subtags selectors
193-
const expandToggle = container.querySelector('.taxonomy-tags-arrow-drop-down span');
194-
fireEvent.click(expandToggle);
184+
// Expand the dropdown to see the subtags selectors
185+
const expandToggle = container.querySelector('.taxonomy-tags-arrow-drop-down span');
186+
fireEvent.click(expandToggle);
195187

196-
await waitFor(() => {
197-
expect(getByText('Tag 3')).toBeInTheDocument();
198-
});
188+
await waitFor(() => {
189+
expect(getByText('Tag 3')).toBeInTheDocument();
199190
});
200191
});
201192

@@ -219,48 +210,46 @@ describe('<ContentTagsDropDownSelector />', () => {
219210
});
220211

221212
const initalSearchTerm = 'test 1';
222-
await act(async () => {
223-
const { rerender } = await getComponent({ ...data, searchTerm: initalSearchTerm });
224-
225-
await waitFor(() => {
226-
expect(useTaxonomyTagsData).toBeCalledWith(data.taxonomyId, null, 1, initalSearchTerm);
227-
});
228-
229-
const updatedSearchTerm = 'test 2';
230-
rerender(<ContentTagsDropDownSelectorComponent
231-
key={`selector-${data.taxonomyId}`}
232-
taxonomyId={data.taxonomyId}
233-
level={data.level}
234-
tagsTree={data.tagsTree}
235-
searchTerm={updatedSearchTerm}
236-
appliedContentTagsTree={{}}
237-
stagedContentTagsTree={{}}
238-
/>);
239-
240-
await waitFor(() => {
241-
expect(useTaxonomyTagsData).toBeCalledWith(data.taxonomyId, null, 1, updatedSearchTerm);
242-
});
243-
244-
// Clean search term
245-
const cleanSearchTerm = '';
246-
rerender(<ContentTagsDropDownSelectorComponent
247-
key={`selector-${data.taxonomyId}`}
248-
taxonomyId={data.taxonomyId}
249-
level={data.level}
250-
tagsTree={data.tagsTree}
251-
searchTerm={cleanSearchTerm}
252-
appliedContentTagsTree={{}}
253-
stagedContentTagsTree={{}}
254-
/>);
255-
256-
await waitFor(() => {
257-
expect(useTaxonomyTagsData).toBeCalledWith(data.taxonomyId, null, 1, cleanSearchTerm);
258-
});
213+
const { rerender } = await getComponent({ ...data, searchTerm: initalSearchTerm });
214+
215+
await waitFor(() => {
216+
expect(useTaxonomyTagsData).toHaveBeenCalledWith(data.taxonomyId, null, 1, initalSearchTerm);
217+
});
218+
219+
const updatedSearchTerm = 'test 2';
220+
rerender(<ContentTagsDropDownSelectorComponent
221+
key={`selector-${data.taxonomyId}`}
222+
taxonomyId={data.taxonomyId}
223+
level={data.level}
224+
tagsTree={data.tagsTree}
225+
searchTerm={updatedSearchTerm}
226+
appliedContentTagsTree={{}}
227+
stagedContentTagsTree={{}}
228+
/>);
229+
230+
await waitFor(() => {
231+
expect(useTaxonomyTagsData).toHaveBeenCalledWith(data.taxonomyId, null, 1, updatedSearchTerm);
232+
});
233+
234+
// Clean search term
235+
const cleanSearchTerm = '';
236+
rerender(<ContentTagsDropDownSelectorComponent
237+
key={`selector-${data.taxonomyId}`}
238+
taxonomyId={data.taxonomyId}
239+
level={data.level}
240+
tagsTree={data.tagsTree}
241+
searchTerm={cleanSearchTerm}
242+
appliedContentTagsTree={{}}
243+
stagedContentTagsTree={{}}
244+
/>);
245+
246+
await waitFor(() => {
247+
expect(useTaxonomyTagsData).toHaveBeenCalledWith(data.taxonomyId, null, 1, cleanSearchTerm);
259248
});
260249
});
261250

262251
it('should render "noTag" message if search doesnt return taxonomies', async () => {
263-
useTaxonomyTagsData.mockReturnValueOnce({
252+
useTaxonomyTagsData.mockReturnValue({
264253
hasMorePages: false,
265254
tagPages: {
266255
isLoading: false,
@@ -271,20 +260,18 @@ describe('<ContentTagsDropDownSelector />', () => {
271260
});
272261

273262
const searchTerm = 'uncommon search term';
274-
await act(async () => {
275-
const { getByText } = await getComponent({ ...data, searchTerm });
276-
277-
await waitFor(() => {
278-
expect(useTaxonomyTagsData).toBeCalledWith(data.taxonomyId, null, 1, searchTerm);
279-
});
263+
const { getByText } = await getComponent({ ...data, searchTerm });
280264

281-
const message = `No tags found with the search term "${searchTerm}"`;
282-
expect(getByText(message)).toBeInTheDocument();
265+
await waitFor(() => {
266+
expect(useTaxonomyTagsData).toHaveBeenCalledWith(data.taxonomyId, null, 1, searchTerm);
283267
});
268+
269+
const message = `No tags found with the search term "${searchTerm}"`;
270+
expect(getByText(message)).toBeInTheDocument();
284271
});
285272

286273
it('should render "noTagsInTaxonomy" message if taxonomy is empty', async () => {
287-
useTaxonomyTagsData.mockReturnValueOnce({
274+
useTaxonomyTagsData.mockReturnValue({
288275
hasMorePages: false,
289276
tagPages: {
290277
isLoading: false,
@@ -295,15 +282,13 @@ describe('<ContentTagsDropDownSelector />', () => {
295282
});
296283

297284
const searchTerm = '';
298-
await act(async () => {
299-
const { getByText } = await getComponent({ ...data, searchTerm });
300-
301-
await waitFor(() => {
302-
expect(useTaxonomyTagsData).toBeCalledWith(data.taxonomyId, null, 1, searchTerm);
303-
});
285+
const { getByText } = await getComponent({ ...data, searchTerm });
304286

305-
const message = 'No tags in this taxonomy yet';
306-
expect(getByText(message)).toBeInTheDocument();
287+
await waitFor(() => {
288+
expect(useTaxonomyTagsData).toHaveBeenCalledWith(data.taxonomyId, null, 1, searchTerm);
307289
});
290+
291+
const message = 'No tags in this taxonomy yet';
292+
expect(getByText(message)).toBeInTheDocument();
308293
});
309294
});

0 commit comments

Comments
 (0)