Skip to content

Commit 7a4549f

Browse files
committed
test: deprecate react-unit-test-utils 7/14
1 parent baaf4e6 commit 7a4549f

File tree

11 files changed

+424
-479
lines changed

11 files changed

+424
-479
lines changed

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

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/components/FilePreview/components/FileRenderer/__snapshots__/index.test.jsx.snap

Lines changed: 0 additions & 47 deletions
This file was deleted.

src/components/FilePreview/components/FileRenderer/hooks.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { mockUseKeyedState } from '@edx/react-unit-test-utils';
22

33
import { useRenderData, stateKeys } from './hooks';
4+
import { errorStatuses, errorMessages } from '../constants';
45

56
const state = mockUseKeyedState(stateKeys);
67

@@ -43,4 +44,27 @@ describe('useRenderData', () => {
4344
state.expectSetStateCalledWith(stateKeys.errorStatus, null);
4445
state.expectSetStateCalledWith(stateKeys.isLoading, true);
4546
});
47+
48+
it('returns correct error message for different error statuses', () => {
49+
// Test notFound error message
50+
state.mockVal(stateKeys.errorStatus, errorStatuses.notFound);
51+
let out = useRenderData(props);
52+
expect(out.error.headerMessage).toBe(errorMessages[errorStatuses.notFound]);
53+
54+
// Test fallback to serverError message for unknown error status
55+
state.mockVal(stateKeys.errorStatus, errorStatuses.badRequest);
56+
out = useRenderData(props);
57+
expect(out.error.headerMessage).toBe(
58+
errorMessages[errorStatuses.serverError],
59+
);
60+
});
61+
62+
it('handles unknown file types', () => {
63+
const propsWithUnknownFile = {
64+
...props,
65+
file: { fileName: 'file.unknown', fileUrl: 'http://example.com' },
66+
};
67+
const out = useRenderData(propsWithUnknownFile);
68+
expect(out.Renderer).toBeUndefined();
69+
});
4670
});
Lines changed: 116 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,45 @@
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';
24

35
import { useRenderData } from './hooks';
46
import { FileRenderer } from './index';
57

6-
jest.mock('./Banners', () => ({
7-
ErrorBanner: () => 'ErrorBanner',
8-
LoadingBanner: () => 'LoadingBanner',
9-
}));
8+
jest.unmock('@openedx/paragon');
9+
jest.unmock('react');
10+
jest.unmock('@edx/frontend-platform/i18n');
11+
12+
/* eslint-disable react/prop-types */
1013

1114
jest.mock('./hooks', () => ({
1215
useRenderData: jest.fn(),
1316
}));
1417

18+
jest.mock('./Banners', () => ({
19+
ErrorBanner: ({ message, headerMessage, actions }) => (
20+
<div data-testid="error-banner">
21+
<div data-testid="error-header">{headerMessage}</div>
22+
<div data-testid="error-message">{message}</div>
23+
{actions?.map((action) => (
24+
<span data-testid={`error-action-${action.id}`}>{action.message}</span>
25+
))}
26+
</div>
27+
),
28+
LoadingBanner: () => <div data-testid="loading-banner">Loading...</div>,
29+
}));
30+
31+
jest.mock('./FileCard', () => ({ children, file, defaultOpen }) => (
32+
<div data-testid="file-card">
33+
<div>
34+
{file.fileName} - {defaultOpen ? 'open' : 'closed'}
35+
</div>
36+
{children}
37+
</div>
38+
));
39+
1540
describe('FileRenderer Component', () => {
41+
const renderWithIntl = (component) => render(<IntlProvider locale="en">{component}</IntlProvider>);
42+
1643
const props = {
1744
file: {
1845
fileName: 'some_file',
@@ -22,7 +49,7 @@ describe('FileRenderer Component', () => {
2249
};
2350

2451
const defaultRenderData = {
25-
Renderer: () => 'Renderer',
52+
Renderer: () => <div data-testid="renderer">Renderer content</div>,
2653
isLoading: false,
2754
errorStatus: false,
2855
error: null,
@@ -31,32 +58,97 @@ describe('FileRenderer Component', () => {
3158
},
3259
};
3360

34-
it('render default', () => {
61+
beforeEach(() => {
62+
jest.clearAllMocks();
63+
});
64+
65+
it('renders default renderer', () => {
3566
useRenderData.mockReturnValue(defaultRenderData);
36-
const wrapper = shallow(<FileRenderer {...props} />);
37-
expect(wrapper.snapshot).toMatchSnapshot();
67+
renderWithIntl(<FileRenderer {...props} />);
3868

39-
expect(wrapper.instance.findByType('Renderer')).toHaveLength(1);
40-
expect(wrapper.instance.findByType('LoadingBanner')).toHaveLength(0);
41-
expect(wrapper.instance.findByType('ErrorBanner')).toHaveLength(0);
69+
expect(screen.getByTestId('file-card')).toBeInTheDocument();
70+
expect(screen.getByText('some_file - open')).toBeInTheDocument();
71+
expect(screen.getByTestId('renderer')).toBeInTheDocument();
72+
expect(screen.getByText('Renderer content')).toBeInTheDocument();
73+
expect(screen.queryByTestId('loading-banner')).not.toBeInTheDocument();
74+
expect(screen.queryByTestId('error-banner')).not.toBeInTheDocument();
4275
});
4376

44-
it('render loading banner', () => {
77+
it('renders loading banner', () => {
4578
useRenderData.mockReturnValue({ ...defaultRenderData, isLoading: true });
46-
const wrapper = shallow(<FileRenderer {...props} />);
47-
expect(wrapper.snapshot).toMatchSnapshot();
79+
renderWithIntl(<FileRenderer {...props} />);
80+
81+
expect(screen.getByTestId('loading-banner')).toBeInTheDocument();
82+
expect(screen.getByText('Loading...')).toBeInTheDocument();
83+
expect(screen.queryByTestId('error-banner')).not.toBeInTheDocument();
84+
expect(screen.queryByTestId('renderer')).not.toBeInTheDocument();
85+
});
4886

49-
expect(wrapper.instance.findByType('LoadingBanner')).toHaveLength(1);
50-
expect(wrapper.instance.findByType('ErrorBanner')).toHaveLength(0);
51-
expect(wrapper.instance.findByType('Renderer')).toHaveLength(0);
87+
it('renders error banner', () => {
88+
useRenderData.mockReturnValue({
89+
errorStatus: true,
90+
error: { message: 'some_error' },
91+
});
92+
renderWithIntl(<FileRenderer {...props} />);
93+
94+
expect(screen.getByTestId('error-banner')).toBeInTheDocument();
95+
expect(screen.getByText('some_error')).toBeInTheDocument();
96+
expect(screen.queryByTestId('loading-banner')).not.toBeInTheDocument();
97+
expect(screen.queryByTestId('renderer')).not.toBeInTheDocument();
98+
});
99+
100+
it('passes defaultOpen prop correctly', () => {
101+
useRenderData.mockReturnValue(defaultRenderData);
102+
renderWithIntl(<FileRenderer {...props} defaultOpen={false} />);
103+
104+
expect(screen.getByText('some_file - closed')).toBeInTheDocument();
105+
});
106+
107+
it('passes rendererProps to Renderer component', () => {
108+
const CustomRenderer = jest.fn(() => <div>Custom Renderer</div>);
109+
const customRendererProps = {
110+
prop1: 'value1',
111+
prop2: 'value2',
112+
};
113+
useRenderData.mockReturnValue({
114+
...defaultRenderData,
115+
Renderer: CustomRenderer,
116+
rendererProps: customRendererProps,
117+
});
118+
119+
renderWithIntl(<FileRenderer {...props} />);
120+
expect(CustomRenderer).toHaveBeenCalledWith(customRendererProps, {});
121+
});
122+
123+
it('passes all error properties to ErrorBanner', () => {
124+
const errorData = {
125+
headerMessage: 'Error Header',
126+
message: 'Error Message',
127+
actions: [{ id: 'retry', message: 'Retry', onClick: jest.fn() }],
128+
};
129+
useRenderData.mockReturnValue({
130+
errorStatus: true,
131+
error: errorData,
132+
});
133+
134+
renderWithIntl(<FileRenderer {...props} />);
135+
expect(screen.getByTestId('error-header')).toHaveTextContent(
136+
'Error Header',
137+
);
138+
expect(screen.getByTestId('error-message')).toHaveTextContent(
139+
'Error Message',
140+
);
141+
expect(screen.getByTestId('error-action-retry')).toHaveTextContent('Retry');
52142
});
53143

54-
it('render error banner', () => {
55-
useRenderData.mockReturnValue({ errorStatus: true, error: { message: 'some_error' } });
56-
const wrapper = shallow(<FileRenderer {...props} />);
57-
expect(wrapper.snapshot).toMatchSnapshot();
144+
it('handles missing optional file properties', () => {
145+
const minimalProps = {
146+
file: { fileName: 'minimal_file' },
147+
defaultOpen: true,
148+
};
149+
useRenderData.mockReturnValue(defaultRenderData);
58150

59-
expect(wrapper.instance.findByType('ErrorBanner')).toHaveLength(1);
60-
expect(wrapper.instance.findByType('LoadingBanner')).toHaveLength(0);
151+
renderWithIntl(<FileRenderer {...minimalProps} />);
152+
expect(screen.getByText('minimal_file - open')).toBeInTheDocument();
61153
});
62154
});
Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,86 @@
1-
import { shallow } from '@edx/react-unit-test-utils';
1+
import { render, screen } from '@testing-library/react';
2+
import '@testing-library/jest-dom';
23

34
import { useResponse } from 'hooks/app';
45
import { isSupported } from './components';
56

67
import FilePreview from './index';
78

9+
jest.unmock('@openedx/paragon');
10+
jest.unmock('react');
11+
jest.unmock('@edx/frontend-platform/i18n');
12+
813
jest.mock('hooks/app', () => ({
914
useResponse: jest.fn(),
1015
}));
1116

1217
jest.mock('./components', () => ({
13-
FileRenderer: () => 'FileRenderer',
18+
// eslint-disable-next-line react/prop-types
19+
FileRenderer: ({ file, defaultOpen }) => (
20+
<div data-testid="file-renderer">
21+
{/* eslint-disable-next-line react/prop-types */}
22+
{file.fileName} - {defaultOpen ? 'open' : 'closed'}
23+
</div>
24+
),
1425
isSupported: jest.fn(),
1526
}));
1627

1728
describe('<FilePreview />', () => {
1829
const props = {
1930
defaultCollapsePreview: false,
2031
};
32+
33+
beforeEach(() => {
34+
jest.clearAllMocks();
35+
});
36+
2137
it('renders nothing when no files are uploaded', () => {
22-
useResponse.mockReturnValueOnce({ uploadedFiles: null });
23-
const wrapper = shallow(<FilePreview {...props} />);
24-
expect(wrapper.snapshot).toMatchSnapshot();
25-
expect(wrapper.isEmptyRender()).toBe(true);
38+
useResponse.mockReturnValue({ uploadedFiles: null });
39+
const { container } = render(<FilePreview {...props} />);
40+
expect(container.firstChild).toBeNull();
2641
});
2742

28-
it('renders only div when no supported files are uploaded', () => {
29-
useResponse.mockReturnValueOnce({
43+
it('renders empty div when no supported files are uploaded', () => {
44+
useResponse.mockReturnValue({
3045
uploadedFiles: [{ fileName: 'file1.txt' }],
3146
});
32-
isSupported.mockReturnValueOnce(false);
33-
const wrapper = shallow(<FilePreview {...props} />);
34-
expect(wrapper.snapshot).toMatchSnapshot();
47+
isSupported.mockReturnValue(false);
48+
const { container } = render(<FilePreview {...props} />);
3549

36-
expect(wrapper.instance.findByType('FileRenderer')).toHaveLength(0);
50+
expect(container.firstChild).toBeInTheDocument();
51+
expect(container.firstChild.tagName).toBe('DIV');
52+
expect(screen.queryByTestId('file-renderer')).not.toBeInTheDocument();
3753
});
3854

39-
it('render only supported files', () => {
55+
it('renders only supported files', () => {
4056
isSupported
4157
.mockReturnValueOnce(false)
4258
.mockReturnValueOnce(true)
4359
.mockReturnValueOnce(true);
4460

45-
useResponse.mockReturnValueOnce({
61+
useResponse.mockReturnValue({
4662
uploadedFiles: [
4763
{ fileName: 'file1.txt' },
4864
{ fileName: 'file2.pdf' },
4965
{ fileName: 'file3.jpg' },
5066
],
5167
});
52-
const wrapper = shallow(<FilePreview {...props} />);
53-
expect(wrapper.snapshot).toMatchSnapshot();
68+
render(<FilePreview {...props} />);
69+
70+
const fileRenderers = screen.getAllByTestId('file-renderer');
71+
expect(fileRenderers).toHaveLength(2);
72+
expect(screen.getByText('file2.pdf - open')).toBeInTheDocument();
73+
expect(screen.getByText('file3.jpg - open')).toBeInTheDocument();
74+
expect(screen.queryByText('file1.txt - open')).not.toBeInTheDocument();
75+
});
76+
77+
it('passes defaultCollapsePreview prop correctly', () => {
78+
isSupported.mockReturnValue(true);
79+
useResponse.mockReturnValue({
80+
uploadedFiles: [{ fileName: 'file1.pdf' }],
81+
});
82+
render(<FilePreview defaultCollapsePreview />);
5483

55-
expect(wrapper.instance.findByType('FileRenderer')).toHaveLength(2);
84+
expect(screen.getByText('file1.pdf - closed')).toBeInTheDocument();
5685
});
5786
});

0 commit comments

Comments
 (0)