Migrate multiple enzyme unit test to testing library (#23237)

This commit is contained in:
Ashish Dhama 2023-05-08 11:00:46 +05:30 committed by GitHub
parent 212ac800a6
commit be771b187b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 178 additions and 258 deletions

View File

@ -1,74 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/post_view/combined_system_message/LastUsers should match snapshot 1`] = `
<span>
<Connect(Markdown)
message="@username2 and "
options={
Object {
"atMentions": true,
"mentionHighlight": false,
"mentionKeys": Array [
Object {
"key": "@username2",
},
Object {
"key": "@username3",
},
Object {
"key": "@username4",
},
],
}
}
/>
<a
onClick={[Function]}
>
2 others
</a>
<Connect(Markdown)
message="were **added to the channel** by user_1."
options={
Object {
"atMentions": true,
"mentionHighlight": false,
"mentionKeys": Array [
Object {
"key": "@username2",
},
Object {
"key": "@username3",
},
Object {
"key": "@username4",
},
],
}
}
/>
</span>
`;
exports[`components/post_view/combined_system_message/LastUsers should match snapshot, expanded 1`] = `
<Connect(Markdown)
message="@username2, @username3 and @username4 **added to the channel** by user_1."
options={
Object {
"atMentions": true,
"mentionHighlight": false,
"mentionKeys": Array [
Object {
"key": "@username2",
},
Object {
"key": "@username3",
},
Object {
"key": "@username4",
},
],
}
}
/>
`;

View File

@ -5,9 +5,11 @@ import React from 'react';
import {Posts} from 'mattermost-redux/constants'; import {Posts} from 'mattermost-redux/constants';
import {shallowWithIntl} from 'tests/helpers/intl-test-helper';
import LastUsers from './last_users'; import LastUsers from './last_users';
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
import {screen} from '@testing-library/react';
import {TestHelper} from 'utils/test_helper';
import userEvent from '@testing-library/user-event';
describe('components/post_view/combined_system_message/LastUsers', () => { describe('components/post_view/combined_system_message/LastUsers', () => {
const formatOptions = { const formatOptions = {
@ -26,31 +28,75 @@ describe('components/post_view/combined_system_message/LastUsers', () => {
usernames: ['@username2', '@username3', '@username4 '], usernames: ['@username2', '@username3', '@username4 '],
}; };
test('should match snapshot', () => { const initialState = {
const wrapper = shallowWithIntl( entities: {
<LastUsers {...baseProps}/>, general: {config: {}},
users: {
currentUserId: 'current_user_id',
profiles: {
user_1: TestHelper.getUserMock({}),
},
},
groups: {groups: {}, myGroups: []},
emojis: {customEmoji: {}},
channels: {},
teams: {
teams: {},
},
preferences: {
myPreferences: {},
},
},
} as any;
test('should match component state', () => {
renderWithIntlAndStore(
<LastUsers {...baseProps}/>, initialState,
); );
expect(wrapper).toMatchSnapshot(); expect(screen.getByText(getMentionKeyAt(0))).toBeInTheDocument();
expect(screen.getByText(getMentionKeyAt(0))).toHaveAttribute('data-mention', 'username2');
expect(screen.getByText('and')).toBeInTheDocument();
//there are 3 mention keys, so the text should read
userEvent.click(screen.getByText(`${formatOptions.mentionKeys.length - 1} others`));
expect(screen.getByText('added to the channel')).toBeInTheDocument();
expect(screen.getByText(`by ${baseProps.actor}`, {exact: false})).toBeInTheDocument();
}); });
test('should match snapshot, expanded', () => { test('should match component state, expanded', () => {
const wrapper = shallowWithIntl( renderWithIntlAndStore(
<LastUsers {...baseProps}/>, <LastUsers {...baseProps}/>, initialState,
); );
wrapper.setState({expand: true}); //first key should be visible
expect(wrapper).toMatchSnapshot(); expect(screen.getByText(getMentionKeyAt(0))).toBeInTheDocument();
expect(screen.getByText(getMentionKeyAt(0))).toHaveAttribute('data-mention', 'username2');
//other keys should be hidden
expect(screen.queryByText(getMentionKeyAt(1))).not.toBeInTheDocument();
expect(screen.queryByText(getMentionKeyAt(2))).not.toBeInTheDocument();
expect(screen.getByText('were', {exact: false})).toBeInTheDocument();
//setting {expand: true} in the state
userEvent.click(screen.getByText(`${formatOptions.mentionKeys.length - 1} others`));
expect(screen.queryByText('were', {exact: false})).not.toBeInTheDocument();
//hidden keys should be visible
expect(screen.getByText(getMentionKeyAt(1))).toBeInTheDocument();
expect(screen.getByText(getMentionKeyAt(1))).toHaveAttribute('data-mention', 'username3');
expect(screen.getByText(getMentionKeyAt(2))).toBeInTheDocument();
expect(screen.getByText(getMentionKeyAt(2))).toHaveAttribute('data-mention', 'username4');
expect(screen.getByText('added to the channel')).toBeInTheDocument();
expect(screen.getByText(`by ${baseProps.actor}`, {exact: false})).toBeInTheDocument();
}); });
test('should match state on handleOnClick', () => { function getMentionKeyAt(index: number) {
const wrapper = shallowWithIntl( return baseProps.formatOptions.mentionKeys[index].key;
<LastUsers {...baseProps}/>, }
);
wrapper.setState({expand: false});
const e = {preventDefault: jest.fn()};
wrapper.find('a').simulate('click', e);
expect(wrapper.state('expand')).toBe(true);
});
}); });

View File

@ -1,24 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/CommentedOnFilesMessage Snapshot when no files 1`] = `""`;
exports[`components/CommentedOnFilesMessage should match snapshot for multiple files 1`] = `
<span>
image_3.png
<MemoizedFormattedMessage
defaultMessage=" plus {count, number} other {count, plural, one {file} other {files}}"
id="post_body.plusMore"
values={
Object {
"count": 2,
}
}
/>
</span>
`;
exports[`components/CommentedOnFilesMessage should match snapshot for single file 1`] = `
<span>
image_1.png
</span>
`;

View File

@ -2,37 +2,38 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {shallow} from 'enzyme';
import CommentedOnFilesMessage from './commented_on_files_message'; import CommentedOnFilesMessage from './commented_on_files_message';
import {render, screen} from '@testing-library/react';
import {renderWithIntl} from 'tests/react_testing_utils';
describe('components/CommentedOnFilesMessage', () => { describe('components/CommentedOnFilesMessage', () => {
const baseProps = { const baseProps = {
parentPostId: 'parentPostId', parentPostId: 'parentPostId',
}; };
test('Snapshot when no files', () => { test('component state when no files', () => {
const wrapper = shallow( render(
<CommentedOnFilesMessage {...baseProps}/>, <CommentedOnFilesMessage {...baseProps}/>,
); );
expect(wrapper).toMatchSnapshot(); //no file is given in props
expect(screen.queryByTestId('fileInfo')).not.toBeInTheDocument();
}); });
test('should match snapshot for single file', () => { test('should match component state for single file', () => {
const props = { const props = {
...baseProps, ...baseProps,
fileInfos: [{id: 'file_id_1', name: 'image_1.png', extension: 'png', create_at: 1}], fileInfos: [{id: 'file_id_1', name: 'image_1.png', extension: 'png', create_at: 1}],
}; };
const wrapper = shallow( render(
<CommentedOnFilesMessage {...props}/>, <CommentedOnFilesMessage {...props}/>,
); );
expect(screen.getByTestId('fileInfo')).toHaveTextContent('image_1.png');
expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot for multiple files', () => { test('should match component state for multiple files', () => {
const fileInfos = [ const fileInfos = [
{id: 'file_id_3', name: 'image_3.png', extension: 'png', create_at: 3}, {id: 'file_id_3', name: 'image_3.png', extension: 'png', create_at: 3},
{id: 'file_id_2', name: 'image_2.png', extension: 'png', create_at: 2}, {id: 'file_id_2', name: 'image_2.png', extension: 'png', create_at: 2},
@ -44,10 +45,11 @@ describe('components/CommentedOnFilesMessage', () => {
fileInfos, fileInfos,
}; };
const wrapper = shallow( renderWithIntl(
<CommentedOnFilesMessage {...props}/>, <CommentedOnFilesMessage {...props}/>,
); );
expect(wrapper).toMatchSnapshot(); // total files = 3
expect(screen.getByTestId('fileInfo')).toHaveTextContent('image_3.png plus 2 other files');
}); });
}); });

View File

@ -37,7 +37,7 @@ export default class CommentedOnFilesMessage extends React.PureComponent<Props>
} }
return ( return (
<span> <span data-testid='fileInfo'>
{this.props.fileInfos[0].name} {this.props.fileInfos[0].name}
{plusMore} {plusMore}
</span> </span>

View File

@ -1,35 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/post_view/DateSeparator should render Timestamp inside of a BasicSeparator and pass date/value to it 1`] = `
<BasicSeparator>
<Connect(injectIntl(Timestamp))
ranges={
Array [
Object {
"display": <Memo(MemoizedFormattedMessage)
defaultMessage="Today"
id="date_separator.today"
/>,
"equals": Array [
"day",
0,
],
},
Object {
"display": <Memo(MemoizedFormattedMessage)
defaultMessage="Yesterday"
id="date_separator.yesterday"
/>,
"equals": Array [
"day",
-1,
],
},
]
}
useSemanticOutput={false}
useTime={false}
value={2018-01-12T08:15:13.000Z}
/>
</BasicSeparator>
`;

View File

@ -3,24 +3,31 @@
import React from 'react'; import React from 'react';
import {shallow} from 'enzyme';
import BasicSeparator from 'components/widgets/separator/basic-separator';
import DateSeparator from 'components/post_view/date_separator/date_separator'; import DateSeparator from 'components/post_view/date_separator/date_separator';
import Timestamp from 'components/timestamp'; import {screen} from '@testing-library/react';
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
describe('components/post_view/DateSeparator', () => { describe('components/post_view/DateSeparator', () => {
const initialState = {
entities: {
general: {
config: {},
},
preferences: {
myPreferences: {},
},
},
} as any;
test('should render Timestamp inside of a BasicSeparator and pass date/value to it', () => { test('should render Timestamp inside of a BasicSeparator and pass date/value to it', () => {
const value = new Date('Fri Jan 12 2018 20:15:13 GMT+1200 (+12)'); const value = new Date('Fri Jan 12 2018 20:15:13 GMT+1200 (+12)');
const wrapper = shallow( renderWithIntlAndStore(
<DateSeparator <DateSeparator
date={value} date={value}
/>, />, initialState,
); );
expect(wrapper).toMatchSnapshot();
expect(wrapper.find(BasicSeparator).exists()); expect(screen.getByTestId('basicSeparator')).toBeInTheDocument();
expect(wrapper.find(Timestamp).prop('value')).toBe(value); expect(screen.getByText('January 12, 2018')).toBeInTheDocument();
}); });
}); });

View File

@ -1,23 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/post_view/embedded_bindings/button_binding/ should match snapshot 1`] = `
<button
onClick={[Function]}
>
<LoadingWrapper
loading={false}
text={null}
>
<Connect(Markdown)
message="some_label"
options={
Object {
"autolinkedUrlSchemes": Array [],
"markdown": false,
"mentionHighlight": false,
}
}
/>
</LoadingWrapper>
</button>
`;

View File

@ -2,16 +2,15 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {shallow} from 'enzyme';
import {AppBinding, AppCallResponse} from '@mattermost/types/apps'; import {AppBinding, AppCallResponse} from '@mattermost/types/apps';
import {Post} from '@mattermost/types/posts'; import {Post} from '@mattermost/types/posts';
import {shallowWithIntl} from 'tests/helpers/intl-test-helper';
import ButtonBinding, {ButtonBinding as ButtonBindingUnwrapped} from './button_binding'; import ButtonBinding, {ButtonBinding as ButtonBindingUnwrapped} from './button_binding';
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
import {screen, waitFor} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('components/post_view/embedded_bindings/button_binding/', () => { describe('components/post_view/embedded_bindings/button_binding/', () => {
const post = { const post = {
id: 'some_post_id', id: 'some_post_id',
@ -58,15 +57,35 @@ describe('components/post_view/embedded_bindings/button_binding/', () => {
}, },
}; };
const initialState = {
entities: {
general: {config: {}},
users: {
profiles: {
},
},
groups: {myGroups: []},
emojis: {},
channels: {},
teams: {
teams: {},
},
preferences: {
myPreferences: {},
},
},
};
const intl = { const intl = {
formatMessage: (message: {id: string; defaultMessage: string}) => { formatMessage: (message: {id: string; defaultMessage: string}) => {
return message.defaultMessage; return message.defaultMessage;
}, },
} as any; } as any;
test('should match snapshot', () => { test('should match default component state', () => {
const wrapper = shallowWithIntl(<ButtonBinding {...baseProps}/>); renderWithIntlAndStore(<ButtonBinding {...baseProps}/>, initialState);
expect(wrapper).toMatchSnapshot();
screen.getByText('some_label');
}); });
test('should call doAppSubmit on click', async () => { test('should call doAppSubmit on click', async () => {
@ -75,18 +94,24 @@ describe('components/post_view/embedded_bindings/button_binding/', () => {
intl, intl,
}; };
const wrapper = shallow<ButtonBindingUnwrapped>(<ButtonBindingUnwrapped {...props}/>); renderWithIntlAndStore(<ButtonBindingUnwrapped {...props}/>, initialState);
await wrapper.instance().handleClick();
screen.getByText('some_label');
const submitButton = screen.getByRole('button');
userEvent.click(submitButton);
expect(baseProps.actions.getChannel).toHaveBeenCalledWith('some_channel_id'); expect(baseProps.actions.getChannel).toHaveBeenCalledWith('some_channel_id');
expect(baseProps.actions.handleBindingClick).toHaveBeenCalledWith(binding, { await waitFor(() => {
app_id: 'some_app_id', expect(baseProps.actions.handleBindingClick).toHaveBeenCalledWith(binding, {
channel_id: 'some_channel_id', app_id: 'some_app_id',
location: '/in_post/some_location', channel_id: 'some_channel_id',
post_id: 'some_post_id', location: '/in_post/some_location',
root_id: 'some_root_id', post_id: 'some_post_id',
team_id: 'some_team_id', root_id: 'some_root_id',
}, expect.anything()); team_id: 'some_team_id',
}, expect.anything());
});
expect(baseProps.actions.postEphemeralCallResponseForPost).toHaveBeenCalledWith(callResponse, 'Nice job!', post); expect(baseProps.actions.postEphemeralCallResponseForPost).toHaveBeenCalledWith(callResponse, 'Nice job!', post);
}); });
@ -118,9 +143,15 @@ describe('components/post_view/embedded_bindings/button_binding/', () => {
intl, intl,
}; };
const wrapper = shallow<ButtonBindingUnwrapped>(<ButtonBindingUnwrapped {...props}/>); renderWithIntlAndStore(<ButtonBindingUnwrapped {...props}/>, initialState);
await wrapper.instance().handleClick();
expect(props.actions.postEphemeralCallResponseForPost).toHaveBeenCalledWith(errorCallResponse, 'The error', post); screen.getByText('some_label');
const submitButton = screen.getByRole('button');
userEvent.click(submitButton);
await waitFor(() => {
expect(props.actions.postEphemeralCallResponseForPost).toHaveBeenCalledWith(errorCallResponse, 'The error', post);
});
}); });
}); });

View File

@ -1,29 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/post_view/FailedPostOptions should match snapshot 1`] = `
<span
className="pending-post-actions"
>
<a
className="post-retry"
href="#"
onClick={[Function]}
>
<MemoizedFormattedMessage
defaultMessage="Retry"
id="pending_post_actions.retry"
/>
</a>
-
<a
className="post-cancel"
href="#"
onClick={[Function]}
>
<MemoizedFormattedMessage
defaultMessage="Cancel"
id="pending_post_actions.cancel"
/>
</a>
</span>
`;

View File

@ -2,11 +2,13 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import {shallow} from 'enzyme';
import {TestHelper} from 'utils/test_helper'; import {TestHelper} from 'utils/test_helper';
import FailedPostOptions from 'components/post_view/failed_post_options/failed_post_options'; import FailedPostOptions from 'components/post_view/failed_post_options/failed_post_options';
import {renderWithIntl} from 'tests/react_testing_utils';
import {screen} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('components/post_view/FailedPostOptions', () => { describe('components/post_view/FailedPostOptions', () => {
const baseProps = { const baseProps = {
@ -17,9 +19,21 @@ describe('components/post_view/FailedPostOptions', () => {
}, },
}; };
test('should match snapshot', () => { test('should match default component state', () => {
const wrapper = shallow(<FailedPostOptions {...baseProps}/>); renderWithIntl(<FailedPostOptions {...baseProps}/>);
expect(wrapper).toMatchSnapshot();
const retryLink = screen.getByText('Retry');
const cancelLink = screen.getByText('Cancel');
expect(retryLink).toBeInTheDocument();
expect(retryLink).toHaveClass('post-retry');
expect(retryLink).toHaveAttribute('href', '#');
expect(cancelLink).toBeInTheDocument();
expect(cancelLink).toHaveClass('post-cancel');
expect(cancelLink).toHaveAttribute('href', '#');
expect(screen.getAllByRole('link')).toHaveLength(2);
}); });
test('should create post on retry', () => { test('should create post on retry', () => {
@ -31,13 +45,16 @@ describe('components/post_view/FailedPostOptions', () => {
}, },
}; };
const wrapper = shallow(<FailedPostOptions {...props}/>); renderWithIntl(<FailedPostOptions {...props}/>);
const e = {preventDefault: jest.fn()};
const retryLink = screen.getByText('Retry');
userEvent.click(retryLink);
wrapper.find('.post-retry').simulate('click', e);
expect(props.actions.createPost.mock.calls.length).toBe(1); expect(props.actions.createPost.mock.calls.length).toBe(1);
wrapper.find('.post-retry').simulate('click', e); userEvent.click(retryLink);
expect(props.actions.createPost.mock.calls.length).toBe(2); expect(props.actions.createPost.mock.calls.length).toBe(2);
}); });
@ -50,10 +67,12 @@ describe('components/post_view/FailedPostOptions', () => {
}, },
}; };
const wrapper = shallow(<FailedPostOptions {...props}/>); renderWithIntl(<FailedPostOptions {...props}/>);
const e = {preventDefault: jest.fn()};
const cancelLink = screen.getByText('Cancel');
userEvent.click(cancelLink);
wrapper.find('.post-cancel').simulate('click', e);
expect(props.actions.removePost.mock.calls.length).toBe(1); expect(props.actions.removePost.mock.calls.length).toBe(1);
}); });
}); });