Skip to content

Commit b54e8ff

Browse files
authored
test: deprecate react-unit-test-utils part-2 (#428)
1 parent 5a38347 commit b54e8ff

File tree

10 files changed

+151
-225
lines changed

10 files changed

+151
-225
lines changed
Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import React from 'react';
2-
import { shallow } from '@edx/react-unit-test-utils';
3-
1+
import { render, screen } from '@testing-library/react';
42
import ErrorBanner from './ErrorBanner';
5-
63
import messages from '../messages';
74

5+
jest.unmock('@openedx/paragon');
6+
jest.unmock('react');
7+
88
describe('Error Banner component', () => {
99
const children = <p>Abitary Child</p>;
1010

@@ -25,39 +25,29 @@ describe('Error Banner component', () => {
2525
children,
2626
};
2727

28-
let el;
29-
beforeEach(() => {
30-
el = shallow(<ErrorBanner {...props} />);
31-
});
32-
33-
test('snapshot', () => {
34-
expect(el.snapshot).toMatchSnapshot();
35-
});
36-
37-
describe('component', () => {
38-
test('children node', () => {
39-
const childElement = el.instance.children[1];
40-
const child = shallow(children);
41-
42-
expect(childElement.type).toEqual(child.type);
43-
expect(childElement.children[0].el).toEqual(child.children[0].el);
28+
describe('behavior', () => {
29+
it('renders children content', () => {
30+
render(<ErrorBanner {...props} />);
31+
const childText = screen.getByText('Abitary Child');
32+
expect(childText).toBeInTheDocument();
4433
});
4534

46-
test('verify actions', () => {
47-
const { actions } = el.instance.findByType('Alert')[0].props;
48-
expect(actions).toHaveLength(props.actions.length);
35+
it('renders the correct number of action buttons', () => {
36+
render(<ErrorBanner {...props} />);
37+
const buttons = screen.getAllByText('FormattedMessage');
38+
expect(buttons).toHaveLength(3);
39+
});
4940

50-
actions.forEach((action, index) => {
51-
expect(action.type).toEqual('Button');
52-
expect(action.props.onClick).toEqual(props.actions[index].onClick);
53-
// action message
54-
expect(action.props.children.props).toEqual(props.actions[index].message);
55-
});
41+
it('renders error heading with correct message', () => {
42+
render(<ErrorBanner {...props} />);
43+
const heading = screen.getAllByText('FormattedMessage')[0];
44+
expect(heading).toBeInTheDocument();
5645
});
5746

58-
test('verify heading', () => {
59-
const heading = el.instance.findByType('FormattedMessage')[0];
60-
expect(heading.props).toEqual(props.headingMessage);
47+
it('renders with danger variant', () => {
48+
render(<ErrorBanner {...props} />);
49+
const alert = screen.getByRole('alert');
50+
expect(alert).toHaveClass('alert-danger');
6151
});
6252
});
6353
});
Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
1-
import React from 'react';
2-
import { shallow } from '@edx/react-unit-test-utils';
3-
1+
import { render, screen } from '@testing-library/react';
42
import LoadingBanner from './LoadingBanner';
53

4+
jest.unmock('@openedx/paragon');
5+
jest.unmock('react');
6+
67
describe('Loading Banner component', () => {
7-
test('snapshot', () => {
8-
const el = shallow(<LoadingBanner />);
9-
expect(el.snapshot).toMatchSnapshot();
8+
describe('behavior', () => {
9+
it('renders an info alert', () => {
10+
render(<LoadingBanner />);
11+
const alert = screen.getByRole('alert');
12+
expect(alert).toHaveClass('alert-info');
13+
});
14+
15+
it('renders a spinner', () => {
16+
const { container } = render(<LoadingBanner />);
17+
const spinner = container.querySelector('.pgn__spinner');
18+
expect(spinner).toBeInTheDocument();
19+
expect(spinner).toHaveClass('spinner-border');
20+
});
1021
});
1122
});

src/components/FilePreview/Banners/__snapshots__/ErrorBanner.test.jsx.snap

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

src/components/FilePreview/Banners/__snapshots__/LoadingBanner.test.jsx.snap

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,43 @@
11
import React from 'react';
2-
import { shallow } from '@edx/react-unit-test-utils';
2+
import { render, screen } from '@testing-library/react';
33

44
import ImageRenderer from './ImageRenderer';
55

6+
jest.unmock('@openedx/paragon');
7+
jest.unmock('react');
8+
69
describe('Image Renderer Component', () => {
710
const props = {
811
url: 'some_url.jpg',
12+
fileName: 'test-image.jpg',
13+
onError: jest.fn().mockName('this.props.onError'),
14+
onSuccess: jest.fn().mockName('this.props.onSuccess'),
915
};
1016

11-
props.onError = jest.fn().mockName('this.props.onError');
12-
props.onSuccess = jest.fn().mockName('this.props.onSuccess');
17+
it('renders an image with the correct src and alt attributes', () => {
18+
render(<ImageRenderer {...props} />);
19+
const imgElement = screen.getByRole('img');
20+
expect(imgElement).toBeInTheDocument();
21+
expect(imgElement).toHaveAttribute('src', props.url);
22+
expect(imgElement).toHaveAttribute('alt', props.fileName);
23+
expect(imgElement).toHaveClass('image-renderer');
24+
});
25+
26+
it('calls onSuccess when image loads successfully', () => {
27+
render(<ImageRenderer {...props} />);
28+
29+
const imgElement = screen.getByRole('img');
30+
imgElement.dispatchEvent(new Event('load'));
1331

14-
let el;
15-
beforeEach(() => {
16-
el = shallow(<ImageRenderer {...props} />);
32+
expect(props.onSuccess).toHaveBeenCalled();
1733
});
18-
test('snapshot', () => {
19-
expect(el.snapshot).toMatchSnapshot();
34+
35+
it('calls onError when image fails to load', () => {
36+
render(<ImageRenderer {...props} />);
37+
38+
const imgElement = screen.getByRole('img');
39+
imgElement.dispatchEvent(new Event('error'));
40+
41+
expect(props.onError).toHaveBeenCalled();
2042
});
2143
});

src/components/FilePreview/BaseRenderers/__snapshots__/ImageRenderer.test.jsx.snap

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
1-
import React from 'react';
2-
import { shallow } from '@edx/react-unit-test-utils';
3-
4-
import { Popover } from '@openedx/paragon';
1+
import { render, screen, fireEvent } from '@testing-library/react';
52

63
import FileInfo from './FileInfo';
74

8-
describe('File Preview Card component', () => {
5+
jest.unmock('@openedx/paragon');
6+
jest.unmock('react');
7+
8+
describe('FileInfo component', () => {
99
const children = (<h1>some Children</h1>);
1010
const props = { onClick: jest.fn().mockName('this.props.onClick') };
11-
let el;
11+
1212
beforeEach(() => {
13-
el = shallow(<FileInfo {...props}>{children}</FileInfo>);
13+
jest.clearAllMocks();
1414
});
15-
test('snapshot', () => {
16-
expect(el.snapshot).toMatchSnapshot();
17-
});
18-
describe('Component', () => {
19-
test('overlay with passed children', () => {
20-
const { overlay } = el.instance.props;
21-
expect(overlay.type).toEqual(Popover);
22-
expect(overlay.props.children).toEqual(<Popover.Content>{children}</Popover.Content>);
15+
16+
describe('Component rendering', () => {
17+
it('renders the FileInfo button with correct text', () => {
18+
render(<FileInfo {...props}>{children}</FileInfo>);
19+
20+
expect(screen.getByText('FormattedMessage')).toBeInTheDocument();
21+
});
22+
23+
it('calls onClick when button is clicked', () => {
24+
render(<FileInfo {...props}>{children}</FileInfo>);
25+
26+
fireEvent.click(screen.getByText('FormattedMessage'));
27+
expect(props.onClick).toHaveBeenCalledTimes(1);
2328
});
2429
});
2530
});
Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,83 @@
1-
import React from 'react';
2-
import { shallow } from '@edx/react-unit-test-utils';
3-
1+
import { render, screen } from '@testing-library/react';
42
import { formatMessage } from 'testUtils';
53
import { keyStore } from 'utils';
64
import { ErrorStatuses } from 'data/constants/requests';
7-
85
import { FileRenderer } from './FileRenderer';
96
import * as hooks from './hooks';
107

11-
jest.mock('./FileCard', () => 'FileCard');
12-
jest.mock('./Banners', () => ({
13-
ErrorBanner: () => 'ErrorBanner',
14-
LoadingBanner: () => 'LoadingBanner',
15-
}));
8+
jest.unmock('@openedx/paragon');
9+
jest.unmock('react');
1610

1711
const hookKeys = keyStore(hooks);
1812

1913
const props = {
2014
file: {
2115
downloadUrl: 'file download url',
2216
name: 'filename.txt',
17+
description: 'A text file',
2318
},
2419
intl: { formatMessage },
2520
};
2621
describe('FileRenderer', () => {
2722
describe('component', () => {
28-
describe('snapshot', () => {
29-
test('isLoading, no Error', () => {
30-
const hookProps = {
31-
Renderer: () => 'Renderer',
32-
isloading: true,
33-
errorStatus: null,
34-
error: null,
35-
rendererProps: { prop: 'hooks.rendererProps' },
36-
};
37-
jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps);
38-
expect(shallow(<FileRenderer {...props} />).snapshot).toMatchSnapshot();
39-
});
40-
test('is not loading, with error', () => {
41-
const hookProps = {
42-
Renderer: () => 'Renderer',
43-
isloading: false,
44-
errorStatus: ErrorStatuses.serverError,
45-
error: { prop: 'hooks.errorProps' },
46-
rendererProps: { prop: 'hooks.rendererProps' },
47-
};
48-
jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps);
49-
expect(shallow(<FileRenderer {...props} />).snapshot).toMatchSnapshot();
50-
});
23+
it('renders loading banner when isLoading is true', () => {
24+
const hookProps = {
25+
Renderer: () => <div data-testid="mock-renderer">Renderer Component</div>,
26+
isLoading: true,
27+
errorStatus: null,
28+
error: null,
29+
rendererProps: { prop: 'hooks.rendererProps' },
30+
};
31+
jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps);
32+
render(<FileRenderer {...props} />);
33+
34+
expect(screen.getByText('filename.txt')).toBeInTheDocument();
35+
expect(screen.getByTestId('mock-renderer')).toBeInTheDocument();
36+
const spinner = document.querySelector('.spinner-border');
37+
expect(spinner).toBeInTheDocument();
38+
});
39+
it('renders error banner when there is an error status', () => {
40+
const errorProps = {
41+
headingMessage: { id: 'error.heading', defaultMessage: 'Error Heading' },
42+
children: 'Error Message',
43+
actions: [{ id: 'retry', onClick: jest.fn(), message: { id: 'retry', defaultMessage: 'Retry' } }],
44+
};
45+
46+
const hookProps = {
47+
Renderer: () => <div data-testid="mock-renderer">Renderer Component</div>,
48+
isLoading: false,
49+
errorStatus: ErrorStatuses.serverError,
50+
error: errorProps,
51+
rendererProps: { prop: 'hooks.rendererProps' },
52+
};
53+
jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps);
54+
55+
render(<FileRenderer {...props} />);
56+
57+
expect(screen.getByText('filename.txt')).toBeInTheDocument();
58+
expect(screen.getByText('Error Message')).toBeInTheDocument();
59+
expect(document.querySelector('.alert-heading')).toBeInTheDocument();
60+
expect(document.querySelector('.btn.btn-outline-primary')).toBeInTheDocument();
61+
});
62+
63+
it('renders renderer component when not loading and no error', () => {
64+
const hookProps = {
65+
Renderer: () => <div data-testid="mock-renderer">Renderer Component</div>,
66+
isLoading: false,
67+
errorStatus: null,
68+
error: null,
69+
rendererProps: { prop: 'hooks.rendererProps' },
70+
};
71+
jest.spyOn(hooks, hookKeys.renderHooks).mockReturnValueOnce(hookProps);
72+
73+
render(<FileRenderer {...props} />);
74+
75+
expect(screen.getByText('filename.txt')).toBeInTheDocument();
76+
expect(screen.getByTestId('mock-renderer')).toBeInTheDocument();
77+
expect(screen.getByText('Renderer Component')).toBeInTheDocument();
78+
79+
const spinner = document.querySelector('.spinner-border');
80+
expect(spinner).not.toBeInTheDocument();
5181
});
5282
});
5383
});

0 commit comments

Comments
 (0)