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

Этот коммит содержится в:
Ashish Dhama
2023-05-04 11:17:11 +05:30
коммит произвёл GitHub
родитель 0e371b010e
Коммит 444bbd56f1
10 изменённых файлов: 142 добавлений и 211 удалений

Просмотреть файл

@@ -1,41 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/post_view/FloatingTimestamp should match snapshot 1`] = `
<div
className="post-list__timestamp scrolling toastAdjustment"
data-testid="floatingTimestamp"
>
<div>
<span>
<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,
],
},
]
}
useTime={false}
value={1234}
/>
</span>
</div>
</div>
`;

Просмотреть файл

@@ -2,9 +2,10 @@
// See LICENSE.txt for license information.
import React from 'react';
import {shallow} from 'enzyme';
import FloatingTimestamp from './floating_timestamp';
import {screen} from '@testing-library/react';
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
describe('components/post_view/FloatingTimestamp', () => {
const baseProps = {
@@ -13,10 +14,27 @@ describe('components/post_view/FloatingTimestamp', () => {
toastPresent: true,
isRhsPost: false,
};
const initialState = {
entities: {
general: {
config: {},
},
preferences: {
myPreferences: {},
},
},
};
test('should match snapshot', () => {
const wrapper = shallow(<FloatingTimestamp {...baseProps}/>);
expect(wrapper).toMatchSnapshot();
expect(wrapper.hasClass('toastAdjustment')).toBe(true);
test('should match component state with given props', () => {
renderWithIntlAndStore(<FloatingTimestamp {...baseProps}/>, initialState);
const floatingTimeStamp = screen.getByTestId('floatingTimestamp');
const time = screen.getByText('January 01, 1970');
expect(floatingTimeStamp).toBeInTheDocument();
expect(floatingTimeStamp).toHaveClass('post-list__timestamp scrolling toastAdjustment');
expect(time).toBeInTheDocument();
expect(time).toHaveAttribute('datetime', '1970-01-01T00:00:01.234');
});
});

Просмотреть файл

@@ -1,26 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/post_view/message_attachments/action_button.jsx should match snapshot 1`] = `
<button
data-action-cookie="cookie-contents"
data-action-id="action_id_1"
key="action_id_1"
onClick={[Function]}
>
<LoadingWrapper
loading={true}
text={null}
>
<Connect(Markdown)
message="action_name_1"
options={
Object {
"autolinkedUrlSchemes": Array [],
"markdown": false,
"mentionHighlight": false,
}
}
/>
</LoadingWrapper>
</button>
`;

Просмотреть файл

@@ -2,13 +2,14 @@
// See LICENSE.txt for license information.
import React from 'react';
import {shallow} from 'enzyme';
import {Theme} from 'mattermost-redux/selectors/entities/preferences';
import {changeOpacity} from 'mattermost-redux/utils/theme_utils';
import {Preferences} from 'mattermost-redux/constants';
import ActionButton from 'components/post_view/message_attachments/action_button/action_button';
import {render, screen} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('components/post_view/message_attachments/action_button.jsx', () => {
const baseProps = {
@@ -17,15 +18,23 @@ describe('components/post_view/message_attachments/action_button.jsx', () => {
theme: Preferences.THEMES.denim as unknown as Theme,
};
test('should match snapshot', () => {
const wrapper = shallow(<ActionButton {...baseProps}/>);
expect(wrapper).toMatchSnapshot();
test('should match default component state with given props', () => {
render(<ActionButton {...baseProps}/>);
const button = screen.getByRole('button');
expect(button).toHaveAttribute('data-action-cookie', 'cookie-contents');
expect(button).toHaveAttribute('data-action-id', 'action_id_1');
const loadingIcon = screen.getByTitle('Loading Icon');
expect(loadingIcon).toHaveClass('fa fa-spinner fa-fw fa-pulse spinner');
});
test('should call handleAction on click', () => {
const wrapper = shallow(<ActionButton {...baseProps}/>);
render(<ActionButton {...baseProps}/>);
wrapper.find('button').simulate('click');
const button = screen.getByRole('button');
userEvent.click(button);
expect(baseProps.handleAction).toHaveBeenCalledTimes(1);
});
@@ -36,12 +45,13 @@ describe('components/post_view/message_attachments/action_button.jsx', () => {
action: {...baseProps.action, style: 'onlineIndicator'},
};
const wrapper = shallow(<ActionButton {...props}/>);
const buttonStyles = wrapper.find('button').prop('style');
render(<ActionButton {...props}/>);
expect(buttonStyles).toHaveProperty('borderColor', changeOpacity(Preferences.THEMES.denim.onlineIndicator, 0.25));
expect(buttonStyles).toHaveProperty('borderWidth', 2);
expect(buttonStyles).toHaveProperty('color', Preferences.THEMES.denim.onlineIndicator);
const button = screen.getByRole('button');
expect(button).toHaveStyle(`borderColor: ${changeOpacity(Preferences.THEMES.denim.onlineIndicator, 0.25)}`);
expect(button).toHaveStyle('borderWidth: 2');
expect(button).toHaveStyle(`color: ${Preferences.THEMES.denim.onlineIndicator}`);
});
test('should have correct styles when provided color from not default theme', () => {
@@ -51,12 +61,13 @@ describe('components/post_view/message_attachments/action_button.jsx', () => {
action: {...baseProps.action, style: 'danger'},
};
const wrapper = shallow(<ActionButton {...props}/>);
const buttonStyles = wrapper.find('button').prop('style');
render(<ActionButton {...props}/>);
expect(buttonStyles).toHaveProperty('borderColor', changeOpacity(Preferences.THEMES.indigo.errorTextColor, 0.25));
expect(buttonStyles).toHaveProperty('borderWidth', 2);
expect(buttonStyles).toHaveProperty('color', Preferences.THEMES.indigo.errorTextColor);
const button = screen.getByRole('button');
expect(button).toHaveStyle(`borderColor: ${changeOpacity(Preferences.THEMES.indigo.errorTextColor, 0.25)}`);
expect(button).toHaveStyle('borderWidth: 2');
expect(button).toHaveStyle(`color: ${Preferences.THEMES.indigo.errorTextColor}`);
});
test('should have correct styles when provided status color', () => {
@@ -65,12 +76,12 @@ describe('components/post_view/message_attachments/action_button.jsx', () => {
action: {...baseProps.action, style: 'success'},
};
const wrapper = shallow(<ActionButton {...props}/>);
const buttonStyles = wrapper.find('button').prop('style');
render(<ActionButton {...props}/>);
const button = screen.getByRole('button');
expect(buttonStyles).toHaveProperty('borderColor', changeOpacity(Preferences.THEMES.denim.onlineIndicator, 0.25));
expect(buttonStyles).toHaveProperty('borderWidth', 2);
expect(buttonStyles).toHaveProperty('color', Preferences.THEMES.denim.onlineIndicator);
expect(button).toHaveStyle(`borderColor: ${changeOpacity(Preferences.THEMES.denim.onlineIndicator, 0.25)}`);
expect(button).toHaveStyle('borderWidth: 2');
expect(button).toHaveStyle(`color: ${Preferences.THEMES.denim.onlineIndicator}`);
});
test('should have correct styles when provided hex color', () => {
@@ -79,12 +90,12 @@ describe('components/post_view/message_attachments/action_button.jsx', () => {
action: {...baseProps.action, style: '#28a745'},
};
const wrapper = shallow(<ActionButton {...props}/>);
const buttonStyles = wrapper.find('button').prop('style');
render(<ActionButton {...props}/>);
const button = screen.getByRole('button');
expect(buttonStyles).toHaveProperty('borderColor', changeOpacity(props.action.style, 0.25));
expect(buttonStyles).toHaveProperty('borderWidth', 2);
expect(buttonStyles).toHaveProperty('color', props.action.style);
expect(button).toHaveStyle(`borderColor: ${changeOpacity(props.action.style, 0.25)}`);
expect(button).toHaveStyle('borderWidth: 2');
expect(button).toHaveStyle(`color: ${props.action.style}`);
});
test('should have no styles when provided invalid hex color', () => {
@@ -93,10 +104,10 @@ describe('components/post_view/message_attachments/action_button.jsx', () => {
action: {...baseProps.action, style: '#wrong'},
};
const wrapper = shallow(<ActionButton {...props}/>);
const buttonStyles = wrapper.find('button').prop('style');
render(<ActionButton {...props}/>);
const button = screen.getByRole('button');
expect(buttonStyles).toBeUndefined();
expect(button.style.length).toBe(0);
});
test('should have no styles when provided undefined', () => {
@@ -105,9 +116,9 @@ describe('components/post_view/message_attachments/action_button.jsx', () => {
action: {...baseProps.action, style: undefined},
};
const wrapper = shallow(<ActionButton {...props}/>);
const buttonStyles = wrapper.find('button').prop('style');
render(<ActionButton {...props}/>);
const button = screen.getByRole('button');
expect(buttonStyles).toBeUndefined();
expect(button.style.length).toBe(0);
});
});

Просмотреть файл

@@ -1,10 +1,11 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {shallow} from 'enzyme';
import React from 'react';
import ActionMenu from './action_menu';
import {screen} from '@testing-library/react';
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
describe('components/post_view/message_attachments/ActionMenu', () => {
const baseProps = {
@@ -30,13 +31,20 @@ describe('components/post_view/message_attachments/ActionMenu', () => {
selectAttachmentMenuAction: jest.fn(),
};
test('should start with nothing selected', () => {
const wrapper = shallow(<ActionMenu {...baseProps}/>);
test('should start with nothing selected', async () => {
renderWithIntlAndStore(<ActionMenu {...baseProps}/>, {});
expect(wrapper.state()).toMatchObject({
selected: undefined,
value: '',
});
const autoCompleteSelector = screen.getByTestId('autoCompleteSelector');
const input = screen.getByPlaceholderText('action');
expect(autoCompleteSelector).toBeInTheDocument();
expect(autoCompleteSelector).toHaveClass('form-group');
//if nothing is selected or selected is undefined, baseProps.selectAttachmentMenuAction should not be called
expect(baseProps.selectAttachmentMenuAction).not.toHaveBeenCalled();
expect(input).toHaveClass('form-control');
expect(input).toHaveAttribute('value', '');
});
test('should set selected based on default option', () => {
@@ -47,14 +55,11 @@ describe('components/post_view/message_attachments/ActionMenu', () => {
default_option: '2',
},
};
const wrapper = shallow(<ActionMenu {...props}/>);
renderWithIntlAndStore(<ActionMenu {...props}/>, {});
expect(wrapper.state()).toMatchObject({
selected: {
text: 'Two',
value: '2',
},
value: 'Two',
});
const input = screen.getByPlaceholderText('action');
//default_option is given in props
expect(input).toHaveAttribute('value', 'Two');
});
});

Просмотреть файл

@@ -1,16 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/post_view/new_message_separator should render new_message_separator 1`] = `
<div
className="new-separator"
>
<NotificationSeparator
id="1234"
>
<MemoizedFormattedMessage
defaultMessage="New Messages"
id="posts_view.newMsg"
/>
</NotificationSeparator>
</div>
`;

Просмотреть файл

@@ -1,16 +1,25 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {shallow} from 'enzyme';
import React from 'react';
import NewMessageSeparator from './new_message_separator';
import {screen} from '@testing-library/react';
import {renderWithIntl} from 'tests/react_testing_utils';
describe('components/post_view/new_message_separator', () => {
test('should render new_message_separator', () => {
const wrapper = shallow(
renderWithIntl(
<NewMessageSeparator separatorId='1234'/>,
);
expect(wrapper).toMatchSnapshot();
const newMessage = screen.getByText('New Messages');
const separator = screen.getByTestId('NotificationSeparator');
expect(newMessage).toBeInTheDocument();
expect(newMessage).toHaveClass('separator__text');
expect(separator).toBeInTheDocument();
expect(separator).toHaveClass('Separator NotificationSeparator');
});
});

Просмотреть файл

@@ -1,44 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PostAttachmentContainer should render correctly 1`] = `
<ContextProvider
value={
Object {
"store": Object {
"clearActions": [Function],
"dispatch": [Function],
"getActions": [Function],
"getState": [Function],
"replaceReducer": [Function],
"subscribe": [Function],
},
"subscription": Subscription {
"handleChangeWrapper": [Function],
"listeners": Object {
"notify": [Function],
},
"onStateChange": [Function],
"parentSub": undefined,
"store": Object {
"clearActions": [Function],
"dispatch": [Function],
"getActions": [Function],
"getState": [Function],
"replaceReducer": [Function],
"subscribe": [Function],
},
"unsubscribe": null,
},
}
}
>
<PostAttachmentContainer
className="permalink"
link="/test/pl/1"
>
<p>
some children
</p>
</PostAttachmentContainer>
</ContextProvider>
`;

Просмотреть файл

@@ -1,14 +1,13 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {shallow} from 'enzyme';
import React from 'react';
import {Provider} from 'react-redux';
import {mockStore} from 'tests/test_store';
import PostAttachmentContainer, {Props} from './post_attachment_container';
import {screen} from '@testing-library/react';
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
import {DeepPartial} from '@mattermost/types/utilities';
import {GlobalState} from '@mattermost/types/store';
describe('PostAttachmentContainer', () => {
const baseProps: Props = {
@@ -17,24 +16,34 @@ describe('PostAttachmentContainer', () => {
link: '/test/pl/1',
};
const initialState = {
const initialState: DeepPartial<GlobalState> = {
entities: {
general: {config: {}},
users: {
currentUserId: 'user1',
profiles: {},
},
teams: {
currentTeamId: 'current_team_id',
teams: {},
},
posts: {posts: {}},
preferences: {myPreferences: {}},
},
};
test('should render correctly', async () => {
const store = await mockStore(initialState);
const wrapper = shallow(
<Provider store={store.store}>
<PostAttachmentContainer {...baseProps}/>
</Provider>,
test('should render correctly', () => {
renderWithIntlAndStore(
<PostAttachmentContainer {...baseProps}/>, initialState,
);
expect(wrapper).toMatchSnapshot();
const button = screen.getByRole('button');
expect(button).toBeInTheDocument();
expect(button).toHaveClass('attachment attachment--permalink');
expect(button.children[0]).toHaveClass('attachment__content attachment__content--permalink');
expect(screen.getByText('some children')).toBeInTheDocument();
});
});

Просмотреть файл

@@ -1,7 +1,6 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {mount} from 'enzyme';
import React from 'react';
import {createIntl, useIntl} from 'react-intl';
@@ -13,6 +12,9 @@ import {mockStore} from 'tests/test_store';
import {TestHelper} from 'utils/test_helper';
import LatestPostReader from './latest_post_reader';
import {render, screen} from '@testing-library/react';
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
import {Provider} from 'react-redux';
jest.mock('react-intl', () => ({
...jest.requireActual('react-intl'),
@@ -59,36 +61,40 @@ describe('LatestPostReader', () => {
};
test('should render aria-label as a child in the given locale', () => {
const {mountOptions} = mockStore(baseState);
const store = mockStore(baseState);
(useIntl as jest.Mock).mockImplementation(() => createIntl({locale: 'en', messages: enMessages, defaultLocale: 'en'}));
let wrapper = mount(<LatestPostReader {...baseProps}/>, mountOptions);
let span = wrapper.childAt(0);
const {rerender} = render(
<Provider store={store.store}>
<LatestPostReader {...baseProps}/>
</Provider>,
);
expect(span.prop('children')).toContain(author.username);
expect(span.prop('children')).toContain('January');
const prevMessage = screen.getByText(`January 1, ${author.username} wrote, This is a test`, {exact: false});
expect(prevMessage).toBeInTheDocument();
expect(prevMessage).toHaveClass('sr-only');
(useIntl as jest.Mock).mockImplementation(() => createIntl({locale: 'es', messages: esMessages, defaultLocale: 'es'}));
wrapper = mount(<LatestPostReader {...baseProps}/>, mountOptions);
span = wrapper.childAt(0);
rerender(<Provider store={store.store}> <LatestPostReader {...baseProps}/></Provider>);
const januaryInSpanish = 'enero';
const message = screen.getByText(`${januaryInSpanish}, ${author.username} wrote, This is a test`, {exact: false});
expect(span.prop('children')).toContain(author.username);
expect(span.prop('children')).toContain('enero');
expect(message).toBeInTheDocument();
expect(message).toHaveClass('sr-only');
});
test('should be able to handle an empty post array', () => {
const {mountOptions} = mockStore(baseState);
const props = {
...baseProps,
postIds: [],
};
const wrapper = mount(<LatestPostReader {...props}/>, mountOptions);
const span = wrapper.childAt(0);
renderWithIntlAndStore(<LatestPostReader {...props}/>, baseState);
expect(span.prop('children')).toEqual('');
// body should be empty
const message = screen.queryByText('This is a test');
expect(message).not.toBeInTheDocument();
});
});