Skip to content

Commit f8a8f74

Browse files
authored
test: deprecate react-unit-test-utils 4/14 (#340)
* test: deprecate react-unit-test-utils 4/14 * fix: change AppContainer queries to follow RTL query priorities * test: address feedback * test: address feedback
1 parent c25782b commit f8a8f74

File tree

10 files changed

+364
-268
lines changed

10 files changed

+364
-268
lines changed

src/components/AppContainer/__snapshots__/index.test.jsx.snap

Lines changed: 0 additions & 47 deletions
This file was deleted.
Lines changed: 229 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,32 @@
1-
import { shallow } from '@edx/react-unit-test-utils';
1+
import { render, screen } from '@testing-library/react';
2+
import '@testing-library/jest-dom';
3+
import { IntlProvider } from '@edx/frontend-platform/i18n';
4+
25
import {
36
useIsPageDataLoaded,
47
useIsORAConfigLoaded,
58
usePageDataError,
69
useORAConfigDataError,
710
} from 'hooks/app';
11+
812
import AppContainer from '.';
913

14+
jest.unmock('@openedx/paragon');
15+
jest.unmock('react');
16+
jest.unmock('@edx/frontend-platform/i18n');
17+
18+
jest.mock('@edx/frontend-platform/i18n', () => ({
19+
...jest.requireActual('@edx/frontend-platform/i18n'),
20+
getLocale: jest.fn().mockReturnValue('en'),
21+
configure: jest.fn(),
22+
}));
23+
24+
jest.mock('@edx/frontend-platform/react', () => ({
25+
...jest.requireActual('@edx/frontend-platform/react'),
26+
// eslint-disable-next-line react/prop-types
27+
ErrorPage: ({ message }) => <div role="alert">{message}</div>,
28+
}));
29+
1030
jest.mock('hooks/app', () => ({
1131
useIsPageDataLoaded: jest.fn().mockReturnValue(true),
1232
useIsORAConfigLoaded: jest.fn().mockReturnValue(true),
@@ -16,44 +36,215 @@ jest.mock('hooks/app', () => ({
1636

1737
describe('<AppContainer />', () => {
1838
const props = {
19-
children: <div>children</div>,
39+
children: <div>Test children content</div>,
2040
};
2141

22-
it('render default', () => {
23-
const wrapper = shallow(<AppContainer {...props} />);
24-
expect(wrapper.snapshot).toMatchSnapshot();
25-
expect(wrapper.instance.findByType('Spinner')).toHaveLength(0);
26-
});
27-
28-
describe('render error', () => {
29-
it('pageDataError', () => {
30-
usePageDataError.mockReturnValueOnce({ response: { data: { error: { errorCode: 'error' } } } });
31-
const wrapper = shallow(<AppContainer {...props} />);
32-
expect(wrapper.snapshot).toMatchSnapshot();
33-
expect(wrapper.instance.findByType('ErrorPage')).toHaveLength(1);
34-
});
35-
36-
it('oraConfigDataError', () => {
37-
useORAConfigDataError.mockReturnValueOnce({ response: { data: { error: { errorCode: 'error' } } } });
38-
const wrapper = shallow(<AppContainer {...props} />);
39-
expect(wrapper.snapshot).toMatchSnapshot();
40-
expect(wrapper.instance.findByType('ErrorPage')).toHaveLength(1);
41-
});
42-
});
43-
44-
describe('render loading', () => {
45-
it('isPageDataLoaded', () => {
46-
useIsPageDataLoaded.mockReturnValueOnce(false);
47-
const wrapper = shallow(<AppContainer {...props} />);
48-
expect(wrapper.snapshot).toMatchSnapshot();
49-
expect(wrapper.instance.findByType('Spinner')).toHaveLength(1);
50-
});
51-
52-
it('isORAConfigLoaded', () => {
53-
useIsORAConfigLoaded.mockReturnValueOnce(false);
54-
const wrapper = shallow(<AppContainer {...props} />);
55-
expect(wrapper.snapshot).toMatchSnapshot();
56-
expect(wrapper.instance.findByType('Spinner')).toHaveLength(1);
57-
});
42+
const renderWithIntl = (component) => render(<IntlProvider locale="en">{component}</IntlProvider>);
43+
44+
beforeEach(() => {
45+
useIsPageDataLoaded.mockReturnValue(true);
46+
useIsORAConfigLoaded.mockReturnValue(true);
47+
usePageDataError.mockReturnValue(null);
48+
useORAConfigDataError.mockReturnValue(null);
49+
});
50+
51+
afterEach(() => {
52+
jest.clearAllMocks();
53+
});
54+
55+
it('renders children when data is loaded and no errors', () => {
56+
renderWithIntl(<AppContainer {...props} />);
57+
58+
expect(screen.getByText('Test children content')).toBeInTheDocument();
59+
expect(screen.queryByRole('status')).not.toBeInTheDocument(); // No spinner
60+
});
61+
62+
it('renders spinner when page data is not loaded', () => {
63+
useIsPageDataLoaded.mockReturnValue(false);
64+
65+
renderWithIntl(<AppContainer {...props} />);
66+
67+
expect(screen.getByRole('status')).toBeInTheDocument();
68+
expect(screen.getByText('loading')).toBeInTheDocument();
69+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
70+
});
71+
72+
it('renders spinner when ORA config is not loaded', () => {
73+
useIsORAConfigLoaded.mockReturnValue(false);
74+
75+
renderWithIntl(<AppContainer {...props} />);
76+
77+
expect(screen.getByRole('status')).toBeInTheDocument();
78+
expect(screen.getByText('loading')).toBeInTheDocument();
79+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
80+
});
81+
82+
it('renders with correct container styling', () => {
83+
const { container } = renderWithIntl(<AppContainer {...props} />);
84+
85+
const containerDiv = container.querySelector('.w-100.h-100');
86+
expect(containerDiv).toBeInTheDocument();
87+
});
88+
89+
it('renders spinner with correct classes when loading', () => {
90+
useIsPageDataLoaded.mockReturnValue(false);
91+
92+
const { container } = renderWithIntl(<AppContainer {...props} />);
93+
94+
const spinner = container.querySelector('.app-loading');
95+
expect(spinner).toBeInTheDocument();
96+
expect(spinner).toHaveClass('spinner-border');
97+
});
98+
99+
it('renders error page when page data error occurs', () => {
100+
const mockError = {
101+
response: {
102+
data: {
103+
error: {
104+
errorCode: 'ERR_INVALID_STATE_FOR_ASSESSMENT',
105+
},
106+
},
107+
},
108+
};
109+
usePageDataError.mockReturnValue(mockError);
110+
111+
renderWithIntl(<AppContainer {...props} />);
112+
113+
const errorMessage = 'This step is not available. Unable to retrieve the assessment.';
114+
expect(screen.getByRole('alert')).toBeInTheDocument();
115+
expect(screen.getByText(errorMessage)).toBeInTheDocument();
116+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
117+
expect(screen.queryByRole('status')).not.toBeInTheDocument();
118+
});
119+
120+
it('renders error page when ORA config error occurs', () => {
121+
const mockError = {
122+
response: {
123+
data: {
124+
error: {
125+
errorCode: 'ERR_INVALID_STATE_FOR_ASSESSMENT',
126+
},
127+
},
128+
},
129+
};
130+
useORAConfigDataError.mockReturnValue(mockError);
131+
132+
renderWithIntl(<AppContainer {...props} />);
133+
134+
const errorMessage = 'This step is not available. Unable to retrieve the assessment.';
135+
expect(screen.getByRole('alert')).toBeInTheDocument();
136+
expect(screen.getByText(errorMessage)).toBeInTheDocument();
137+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
138+
expect(screen.queryByRole('status')).not.toBeInTheDocument();
139+
});
140+
141+
it('renders unknown error message when error has unknown error code', () => {
142+
const mockError = {
143+
response: {
144+
data: {
145+
error: {
146+
errorCode: 'UNKNOWN_ERROR_CODE',
147+
},
148+
},
149+
},
150+
};
151+
usePageDataError.mockReturnValue(mockError);
152+
153+
renderWithIntl(<AppContainer {...props} />);
154+
155+
const errorMessage = 'An unknown error occurred. Please try again.';
156+
expect(screen.getByRole('alert')).toBeInTheDocument();
157+
expect(screen.getByText(errorMessage)).toBeInTheDocument();
158+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
159+
expect(screen.queryByRole('status')).not.toBeInTheDocument();
160+
});
161+
162+
it('renders unknown error message when error has no error code', () => {
163+
const mockError = {
164+
response: {
165+
data: {
166+
error: {},
167+
},
168+
},
169+
};
170+
usePageDataError.mockReturnValue(mockError);
171+
172+
renderWithIntl(<AppContainer {...props} />);
173+
174+
const errorMessage = 'An unknown error occurred. Please try again.';
175+
expect(screen.getByRole('alert')).toBeInTheDocument();
176+
expect(screen.getByText(errorMessage)).toBeInTheDocument();
177+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
178+
expect(screen.queryByRole('status')).not.toBeInTheDocument();
179+
});
180+
181+
it('renders unknown error message when error has no response data', () => {
182+
const mockError = {
183+
response: {},
184+
};
185+
usePageDataError.mockReturnValue(mockError);
186+
187+
renderWithIntl(<AppContainer {...props} />);
188+
189+
const errorMessage = 'An unknown error occurred. Please try again.';
190+
expect(screen.getByRole('alert')).toBeInTheDocument();
191+
expect(screen.getByText(errorMessage)).toBeInTheDocument();
192+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
193+
expect(screen.queryByRole('status')).not.toBeInTheDocument();
194+
});
195+
196+
it('renders unknown error message when error has no response', () => {
197+
const mockError = {};
198+
usePageDataError.mockReturnValue(mockError);
199+
200+
renderWithIntl(<AppContainer {...props} />);
201+
202+
const errorMessage = 'An unknown error occurred. Please try again.';
203+
expect(screen.getByRole('alert')).toBeInTheDocument();
204+
expect(screen.getByText(errorMessage)).toBeInTheDocument();
205+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
206+
expect(screen.queryByRole('status')).not.toBeInTheDocument();
207+
});
208+
209+
it('prioritizes page data error over ORA config error when both exist', () => {
210+
const pageDataError = {
211+
response: {
212+
data: {
213+
error: {
214+
errorCode: 'ERR_INVALID_STATE_FOR_ASSESSMENT',
215+
},
216+
},
217+
},
218+
};
219+
const oraConfigError = {
220+
response: {
221+
data: {
222+
error: {
223+
errorCode: 'DIFFERENT_ERROR',
224+
},
225+
},
226+
},
227+
};
228+
usePageDataError.mockReturnValue(pageDataError);
229+
useORAConfigDataError.mockReturnValue(oraConfigError);
230+
231+
renderWithIntl(<AppContainer {...props} />);
232+
233+
const errorMessage = 'This step is not available. Unable to retrieve the assessment.';
234+
expect(screen.getByRole('alert')).toBeInTheDocument();
235+
expect(screen.getByText(errorMessage)).toBeInTheDocument();
236+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
237+
expect(screen.queryByRole('status')).not.toBeInTheDocument();
238+
});
239+
240+
it('renders spinner when both config and page data are not loaded', () => {
241+
useIsPageDataLoaded.mockReturnValue(false);
242+
useIsORAConfigLoaded.mockReturnValue(false);
243+
244+
renderWithIntl(<AppContainer {...props} />);
245+
246+
expect(screen.getByRole('status')).toBeInTheDocument();
247+
expect(screen.getByText('loading')).toBeInTheDocument();
248+
expect(screen.queryByText('Test children content')).not.toBeInTheDocument();
58249
});
59250
});

0 commit comments

Comments
 (0)