From 77340c7b560ab972ce75247de25785e6c496222b Mon Sep 17 00:00:00 2001 From: Saturnino Abril <5334504+saturninoabril@users.noreply.github.com> Date: Tue, 3 Feb 2026 12:26:52 +0800 Subject: [PATCH] (test): bulk m7-12 enzyme to rtl migration --- .../commercial_support_modal.test.tsx.snap | 165 +- .../commercial_support_modal.test.tsx | 69 +- .../__snapshots__/draft_row.test.tsx.snap | 194 +- .../__snapshots__/action.test.tsx.snap | 32 +- .../delete_draft_modal.test.tsx.snap | 158 +- .../__snapshots__/draft_actions.test.tsx.snap | 109 +- .../send_draft_modal.test.tsx.snap | 154 +- .../drafts/draft_actions/action.test.tsx | 14 +- .../draft_actions/delete_draft_modal.test.tsx | 59 +- .../draft_actions/draft_actions.test.tsx | 25 +- .../draft_actions/send_draft_modal.test.tsx | 59 +- .../src/components/drafts/draft_row.test.tsx | 112 +- .../panel/__snapshots__/panel.test.tsx.snap | 14 +- .../__snapshots__/panel_header.test.tsx.snap | 158 +- .../components/drafts/panel/panel.test.tsx | 7 +- .../drafts/panel/panel_header.test.tsx | 24 +- .../feature_restricted_modal.test.tsx | 65 +- .../__snapshots__/file_preview.test.tsx.snap | 559 +-- .../file_progress_preview.test.tsx.snap | 217 +- .../file_preview/file_preview.test.tsx | 54 +- .../file_progress_preview.test.tsx | 11 +- .../file_preview_modal.test.tsx.snap | 1933 +------- .../__snapshots__/image_preview.test.tsx.snap | 68 +- .../file_preview_modal.test.tsx | 311 +- .../file_preview_modal_footer.test.tsx.snap | 162 +- .../file_preview_modal_footer.test.tsx | 15 +- .../file_preview_modal_header.test.tsx.snap | 232 +- .../file_preview_modal_header.test.tsx | 10 +- .../file_preview_modal_info.test.tsx.snap | 73 +- .../file_preview_modal_info.test.tsx | 10 +- .../file_preview_modal_main_nav.test.tsx.snap | 59 +- .../file_preview_modal_main_nav.test.tsx | 7 +- .../file_preview_modal/image_preview.test.tsx | 24 +- .../__snapshots__/popover_bar.test.tsx.snap | 52 +- .../popover_bar/popover_bar.test.tsx | 7 +- .../post_add_channel_member.test.tsx.snap | 302 +- .../post_add_channel_member.test.tsx | 108 +- .../post_view/post_aria_label_div.test.tsx | 59 +- .../post_flag_icon.test.tsx.snap | 91 +- .../post_flag_icon/post_flag_icon.test.tsx | 25 +- .../post_message_preview.test.tsx.snap | 1339 +++-- .../post_message_preview.test.tsx | 108 +- .../__snapshots__/show_more.test.tsx.snap | 274 +- .../post_view/show_more/show_more.test.tsx | 141 +- .../sidebar_channel.test.tsx.snap | 402 +- .../sidebar_base_channel.test.tsx.snap | 172 +- .../sidebar_base_channel.test.tsx | 77 +- .../sidebar_channel/sidebar_channel.test.tsx | 42 +- .../sidebar_channel_menu.test.tsx.snap | 4308 +++++++++++------ .../sidebar_channel_menu.test.tsx | 110 +- .../__snapshots__/sidebar_list.test.tsx.snap | 106 +- .../sidebar_list/sidebar_list.test.tsx | 162 +- .../unread_channel_indicator.test.tsx.snap | 126 +- .../unread_channel_indicator.test.tsx | 26 +- 54 files changed, 6708 insertions(+), 6492 deletions(-) diff --git a/webapp/channels/src/components/commercial_support_modal/__snapshots__/commercial_support_modal.test.tsx.snap b/webapp/channels/src/components/commercial_support_modal/__snapshots__/commercial_support_modal.test.tsx.snap index 3bb5345c4d7..c9b64ba55cf 100644 --- a/webapp/channels/src/components/commercial_support_modal/__snapshots__/commercial_support_modal.test.tsx.snap +++ b/webapp/channels/src/components/commercial_support_modal/__snapshots__/commercial_support_modal.test.tsx.snap @@ -1,113 +1,64 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/CommercialSupportModal should match snapshot 1`] = ` - - - - - - - -
- -
- - - -
-
- - - - -
-
- - - - +
+
+
+
+ Commercial Support
- - +
+
+ If you're experiencing issues, + + submit a support ticket + + . To help with troubleshooting, it's recommended to download the Support Packet below that includes more details about your Mattermost environment. +
+ + Select your Support Packet contents to download + +
+
+ + +
+ +
+
+
+
`; diff --git a/webapp/channels/src/components/commercial_support_modal/commercial_support_modal.test.tsx b/webapp/channels/src/components/commercial_support_modal/commercial_support_modal.test.tsx index dc0a4e68be8..892c0b5d411 100644 --- a/webapp/channels/src/components/commercial_support_modal/commercial_support_modal.test.tsx +++ b/webapp/channels/src/components/commercial_support_modal/commercial_support_modal.test.tsx @@ -1,15 +1,33 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import {Client4} from 'mattermost-redux/client'; import CommercialSupportModal from 'components/commercial_support_modal/commercial_support_modal'; +import {act, renderWithContext, screen, userEvent, waitFor} from 'tests/react_testing_utils'; import {TestHelper} from 'utils/test_helper'; +jest.mock('react-bootstrap', () => { + const Modal = ({children, show}: {children: React.ReactNode; show: boolean}) => (show ?
{children}
: null); + Modal.Header = ({children}: {children: React.ReactNode}) =>
{children}
; + Modal.Body = ({children}: {children: React.ReactNode}) =>
{children}
; + Modal.Title = ({children}: {children: React.ReactNode}) =>
{children}
; + return {Modal}; +}); + +jest.mock('components/alert_banner', () => (props: {message: React.ReactNode}) => ( +
{props.message}
+)); + +jest.mock('components/external_link', () => ({children, href}: {children: React.ReactNode; href: string}) => ( + {children} +)); + +jest.mock('components/widgets/loading/loading_spinner', () => () =>
{'Loading...'}
); + describe('components/CommercialSupportModal', () => { beforeAll(() => { // Mock getSystemRoute to return a valid URL @@ -37,8 +55,8 @@ describe('components/CommercialSupportModal', () => { }; test('should match snapshot', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); test('should show error message when download fails', async () => { @@ -56,20 +74,17 @@ describe('components/CommercialSupportModal', () => { }), ); - const wrapper = shallow(); + renderWithContext(); - // Trigger download - const instance = wrapper.instance(); - await instance.downloadSupportPacket(); - wrapper.update(); + const user = userEvent.setup(); + const downloadLink = screen.getByText('Download Support Packet').closest('a'); + if (!downloadLink) { + throw new Error('Download Support Packet link not found'); + } + await user.click(downloadLink); // Verify error message is shown - const errorDiv = wrapper.find('.CommercialSupportModal__error'); - expect(errorDiv.exists()).toBe(true); - expect(errorDiv.find('.error-text').text()).toBe(`${errorMessage}: ${detailedError}`); - - // Verify loading state is reset - expect(wrapper.state('loading')).toBe(false); + expect(await screen.findByText(`${errorMessage}: ${detailedError}`)).toBeInTheDocument(); }); test('should clear error when starting new download', async () => { @@ -82,16 +97,30 @@ describe('components/CommercialSupportModal', () => { }), ); - const wrapper = shallow(); + const ref = React.createRef(); + renderWithContext( + , + ); - // Set initial error state - wrapper.setState({error: 'Previous error'}); + act(() => { + ref.current?.setState({error: 'Previous error'}); + }); + expect(screen.getByText('Previous error')).toBeInTheDocument(); // Start download - const instance = wrapper.instance(); - await instance.downloadSupportPacket(); + const user = userEvent.setup(); + const downloadLink = screen.getByText('Download Support Packet').closest('a'); + if (!downloadLink) { + throw new Error('Download Support Packet link not found'); + } + await user.click(downloadLink); // Verify error is cleared - expect(wrapper.state('error')).toBeUndefined(); + await waitFor(() => { + expect(screen.queryByText('Previous error')).not.toBeInTheDocument(); + }); }); }); diff --git a/webapp/channels/src/components/drafts/__snapshots__/draft_row.test.tsx.snap b/webapp/channels/src/components/drafts/__snapshots__/draft_row.test.tsx.snap index f7262f7077a..c7bd8c291da 100644 --- a/webapp/channels/src/components/drafts/__snapshots__/draft_row.test.tsx.snap +++ b/webapp/channels/src/components/drafts/__snapshots__/draft_row.test.tsx.snap @@ -1,80 +1,128 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/drafts/drafts_row should match snapshot for channel draft 1`] = ` - - - +
+
+
+
+
+ Draft Title +
+
+
+
+
+ Draft Actions +
+
+
+
+ 56 years ago +
+
+ + draft + +
+
+
+
+
+ Panel Body +
+
+
`; exports[`components/drafts/drafts_row should match snapshot for thread draft 1`] = ` - - - +
+
+
+
+
+ Draft Title +
+
+
+
+
+ Draft Actions +
+
+
+
+ 56 years ago +
+
+ + + + + Thread not found + +
+
+
+
+
+ Panel Body +
+
+
`; diff --git a/webapp/channels/src/components/drafts/draft_actions/__snapshots__/action.test.tsx.snap b/webapp/channels/src/components/drafts/draft_actions/__snapshots__/action.test.tsx.snap index 9d9f7d9812e..5ddfe76a8ba 100644 --- a/webapp/channels/src/components/drafts/draft_actions/__snapshots__/action.test.tsx.snap +++ b/webapp/channels/src/components/drafts/draft_actions/__snapshots__/action.test.tsx.snap @@ -1,23 +1,23 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/drafts/draft_actions/action should match snapshot 1`] = ` -
- +
- - + +
+
`; diff --git a/webapp/channels/src/components/drafts/draft_actions/__snapshots__/delete_draft_modal.test.tsx.snap b/webapp/channels/src/components/drafts/draft_actions/__snapshots__/delete_draft_modal.test.tsx.snap index 99981dbbd9b..7262849e1c0 100644 --- a/webapp/channels/src/components/drafts/draft_actions/__snapshots__/delete_draft_modal.test.tsx.snap +++ b/webapp/channels/src/components/drafts/draft_actions/__snapshots__/delete_draft_modal.test.tsx.snap @@ -1,108 +1,70 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/drafts/draft_actions/delete_draft_modal should have called onConfirm 1`] = ` - - - +
+
+

+ Delete draft +

+
+ Are you sure you want to delete this draft to + + display_name + + ? +
+ + +
+
`; exports[`components/drafts/draft_actions/delete_draft_modal should have called onExited 1`] = ` - - - +
+
+

+ Delete draft +

+
+ Are you sure you want to delete this draft to + + display_name + + ? +
+ + +
+
`; exports[`components/drafts/draft_actions/delete_draft_modal should match snapshot 1`] = ` - - - +
+
+

+ Delete draft +

+
+ Are you sure you want to delete this draft to + + display_name + + ? +
+ + +
+
`; diff --git a/webapp/channels/src/components/drafts/draft_actions/__snapshots__/draft_actions.test.tsx.snap b/webapp/channels/src/components/drafts/draft_actions/__snapshots__/draft_actions.test.tsx.snap index 17f253a8c77..f3f33833497 100644 --- a/webapp/channels/src/components/drafts/draft_actions/__snapshots__/draft_actions.test.tsx.snap +++ b/webapp/channels/src/components/drafts/draft_actions/__snapshots__/draft_actions.test.tsx.snap @@ -1,43 +1,74 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/drafts/draft_actions should match snapshot 1`] = ` - - - +
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
`; diff --git a/webapp/channels/src/components/drafts/draft_actions/__snapshots__/send_draft_modal.test.tsx.snap b/webapp/channels/src/components/drafts/draft_actions/__snapshots__/send_draft_modal.test.tsx.snap index 9a581b37823..c1a831dc005 100644 --- a/webapp/channels/src/components/drafts/draft_actions/__snapshots__/send_draft_modal.test.tsx.snap +++ b/webapp/channels/src/components/drafts/draft_actions/__snapshots__/send_draft_modal.test.tsx.snap @@ -1,104 +1,70 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/drafts/draft_actions/send_draft_modal should have called onConfirm 1`] = ` - - - +
+
+

+ Send message now +

+
+ Are you sure you want to send this message to + + display_name + + ? +
+ + +
+
`; exports[`components/drafts/draft_actions/send_draft_modal should have called onExited 1`] = ` - - - +
+
+

+ Send message now +

+
+ Are you sure you want to send this message to + + display_name + + ? +
+ + +
+
`; exports[`components/drafts/draft_actions/send_draft_modal should match snapshot 1`] = ` - - - +
+
+

+ Send message now +

+
+ Are you sure you want to send this message to + + display_name + + ? +
+ + +
+
`; diff --git a/webapp/channels/src/components/drafts/draft_actions/action.test.tsx b/webapp/channels/src/components/drafts/draft_actions/action.test.tsx index db9a21b3f42..da62b84b051 100644 --- a/webapp/channels/src/components/drafts/draft_actions/action.test.tsx +++ b/webapp/channels/src/components/drafts/draft_actions/action.test.tsx @@ -1,11 +1,19 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; +import {render} from 'tests/react_testing_utils'; + import Action from './action'; +jest.mock('components/with_tooltip', () => ({ + __esModule: true, + default: ({children}: {children: React.ReactNode}) => ( +
{children}
+ ), +})); + describe('components/drafts/draft_actions/action', () => { const baseProps = { icon: 'some-icon', @@ -16,11 +24,11 @@ describe('components/drafts/draft_actions/action', () => { }; it('should match snapshot', () => { - const wrapper = shallow( + const {container} = render( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/drafts/draft_actions/delete_draft_modal.test.tsx b/webapp/channels/src/components/drafts/draft_actions/delete_draft_modal.test.tsx index f21fe2debb5..8670147c962 100644 --- a/webapp/channels/src/components/drafts/draft_actions/delete_draft_modal.test.tsx +++ b/webapp/channels/src/components/drafts/draft_actions/delete_draft_modal.test.tsx @@ -1,13 +1,32 @@ // 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 {GenericModal} from '@mattermost/components'; +import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; -import mockStore from 'tests/test_store'; +jest.mock('@mattermost/components', () => ({ + GenericModal: ({ + children, + handleConfirm, + onExited, + confirmButtonText, + modalHeaderText, + }: { + children: React.ReactNode; + handleConfirm?: () => void; + onExited?: () => void; + confirmButtonText?: string; + modalHeaderText?: string; + }) => ( +
+

{modalHeaderText}

+
{children}
+ + +
+ ), +})); import DeleteDraftModal from './delete_draft_modal'; @@ -19,35 +38,33 @@ describe('components/drafts/draft_actions/delete_draft_modal', () => { }; it('should match snapshot', () => { - const store = mockStore(); - - const wrapper = shallow( - - - , + const {container} = renderWithContext( + , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); - it('should have called onConfirm', () => { - const wrapper = shallow( + it('should have called onConfirm', async () => { + const {container} = renderWithContext( , ); - wrapper.find(GenericModal).first().props().handleConfirm!(); + const user = userEvent.setup(); + await user.click(screen.getByRole('button', {name: /yes, delete/i})); expect(baseProps.onConfirm).toHaveBeenCalledTimes(1); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); - it('should have called onExited', () => { - const wrapper = shallow( + it('should have called onExited', async () => { + const {container} = renderWithContext( , ); - wrapper.find(GenericModal).first().props().onExited?.(); + const user = userEvent.setup(); + await user.click(screen.getByRole('button', {name: 'onExited'})); expect(baseProps.onExited).toHaveBeenCalledTimes(1); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/drafts/draft_actions/draft_actions.test.tsx b/webapp/channels/src/components/drafts/draft_actions/draft_actions.test.tsx index eabe850e066..51e673fad2a 100644 --- a/webapp/channels/src/components/drafts/draft_actions/draft_actions.test.tsx +++ b/webapp/channels/src/components/drafts/draft_actions/draft_actions.test.tsx @@ -1,14 +1,19 @@ // 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 {renderWithContext} from 'tests/react_testing_utils'; import DraftActions from './draft_actions'; +jest.mock('components/with_tooltip', () => ({ + __esModule: true, + default: ({children}: {children: React.ReactNode}) => ( +
{children}
+ ), +})); + describe('components/drafts/draft_actions', () => { const baseProps = { displayName: '', @@ -24,15 +29,11 @@ describe('components/drafts/draft_actions', () => { }; it('should match snapshot', () => { - const store = mockStore(); - - const wrapper = shallow( - - - , + const {container} = renderWithContext( + , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/drafts/draft_actions/send_draft_modal.test.tsx b/webapp/channels/src/components/drafts/draft_actions/send_draft_modal.test.tsx index 6c770abb613..8a7e864d089 100644 --- a/webapp/channels/src/components/drafts/draft_actions/send_draft_modal.test.tsx +++ b/webapp/channels/src/components/drafts/draft_actions/send_draft_modal.test.tsx @@ -1,13 +1,32 @@ // 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 {GenericModal} from '@mattermost/components'; +import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; -import mockStore from 'tests/test_store'; +jest.mock('@mattermost/components', () => ({ + GenericModal: ({ + children, + handleConfirm, + onExited, + confirmButtonText, + modalHeaderText, + }: { + children: React.ReactNode; + handleConfirm?: () => void; + onExited?: () => void; + confirmButtonText?: string; + modalHeaderText?: string; + }) => ( +
+

{modalHeaderText}

+
{children}
+ + +
+ ), +})); import SendDraftModal from './send_draft_modal'; @@ -19,35 +38,33 @@ describe('components/drafts/draft_actions/send_draft_modal', () => { }; it('should match snapshot', () => { - const store = mockStore(); - - const wrapper = shallow( - - - , + const {container} = renderWithContext( + , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); - it('should have called onConfirm', () => { - const wrapper = shallow( + it('should have called onConfirm', async () => { + const {container} = renderWithContext( , ); - wrapper.find(GenericModal).first().props().handleConfirm!(); + const user = userEvent.setup(); + await user.click(screen.getByRole('button', {name: /yes, send now/i})); expect(baseProps.onConfirm).toHaveBeenCalledTimes(1); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); - it('should have called onExited', () => { - const wrapper = shallow( + it('should have called onExited', async () => { + const {container} = renderWithContext( , ); - wrapper.find(GenericModal).first().props().onExited?.(); + const user = userEvent.setup(); + await user.click(screen.getByRole('button', {name: 'onExited'})); expect(baseProps.onExited).toHaveBeenCalledTimes(1); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/drafts/draft_row.test.tsx b/webapp/channels/src/components/drafts/draft_row.test.tsx index db65869a90d..1b1908e4e3e 100644 --- a/webapp/channels/src/components/drafts/draft_row.test.tsx +++ b/webapp/channels/src/components/drafts/draft_row.test.tsx @@ -1,57 +1,119 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import type {ComponentProps} from 'react'; import React from 'react'; -import {Provider} from 'react-redux'; +import type {ChannelType} from '@mattermost/types/channels'; +import type {PostType} from '@mattermost/types/posts'; import type {UserProfile, UserStatus} from '@mattermost/types/users'; -import mockStore from 'tests/test_store'; +import {renderWithContext} from 'tests/react_testing_utils'; import type {PostDraft} from 'types/store/draft'; import DraftRow from './draft_row'; +jest.mock('components/advanced_text_editor/use_priority', () => () => ({onSubmitCheck: jest.fn()})); +jest.mock('components/advanced_text_editor/use_submit', () => () => [jest.fn()]); +jest.mock('components/drafts/draft_actions', () => () =>
{'Draft Actions'}
); +jest.mock('components/drafts/draft_title', () => () =>
{'Draft Title'}
); +jest.mock('components/drafts/panel/panel_body', () => () =>
{'Panel Body'}
); +jest.mock('components/drafts/draft_actions/schedule_post_actions/scheduled_post_actions', () => () => ( +
{'Scheduled Post Actions'}
+)); +jest.mock('components/edit_scheduled_post', () => () =>
{'Edit Scheduled Post'}
); +jest.mock('components/drafts/placeholder_scheduled_post_title/placeholder_scheduled_posts_title', () => () => ( +
{'Placeholder Scheduled Post Title'}
+)); +jest.mock('mattermost-redux/actions/posts', () => ({ + getPost: () => jest.fn(), +})); +jest.mock('mattermost-redux/actions/scheduled_posts', () => ({ + deleteScheduledPost: () => jest.fn(), + updateScheduledPost: () => jest.fn(), +})); +jest.mock('mattermost-redux/selectors/entities/roles', () => ({ + haveIChannelPermission: () => true, +})); +jest.mock('mattermost-redux/selectors/entities/channels', () => ({ + ...jest.requireActual('mattermost-redux/selectors/entities/channels'), + isDeactivatedDirectChannel: () => false, +})); + describe('components/drafts/drafts_row', () => { + const channelId = 'channel_id'; + const teamId = 'team_id'; + const channel = { + id: channelId, + team_id: teamId, + name: 'channel-name', + display_name: 'Channel Name', + type: 'O' as ChannelType, + delete_at: 0, + }; + const initialState = { + entities: { + channels: {channels: {[channelId]: channel}}, + teams: { + currentTeamId: teamId, + teams: {[teamId]: {id: teamId, name: 'team-name'}}, + }, + general: { + config: { + MaxPostSize: '16383', + BurnOnReadDurationSeconds: '600', + }, + license: {}, + }, + posts: {posts: {}}, + }, + websocket: {connectionId: 'connection_id'}, + }; + const baseProps: ComponentProps = { - item: {} as PostDraft, - user: {} as UserProfile, - status: {} as UserStatus['status'], + item: { + message: 'draft message', + updateAt: 1234, + createAt: 1234, + fileInfos: [], + uploadsInProgress: [], + channelId, + rootId: '', + type: 'standard' as PostType, + } as PostDraft, + user: {id: 'user_id', username: 'username'} as UserProfile, + status: 'online' as UserStatus['status'], displayName: 'test', isRemote: false, }; it('should match snapshot for channel draft', () => { - const store = mockStore(); - - const wrapper = shallow( - - - , + const {container} = renderWithContext( + , + initialState, ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); it('should match snapshot for thread draft', () => { - const store = mockStore(); - const props = { ...baseProps, - draft: {rootId: 'some_id'} as PostDraft, + item: { + ...baseProps.item, + rootId: 'some_id', + } as PostDraft, }; - const wrapper = shallow( - - - , + const {container} = renderWithContext( + , + initialState, ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/drafts/panel/__snapshots__/panel.test.tsx.snap b/webapp/channels/src/components/drafts/panel/__snapshots__/panel.test.tsx.snap index 04d33efc70d..884b91513c9 100644 --- a/webapp/channels/src/components/drafts/panel/__snapshots__/panel.test.tsx.snap +++ b/webapp/channels/src/components/drafts/panel/__snapshots__/panel.test.tsx.snap @@ -1,13 +1,11 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/drafts/panel/ should match snapshot 1`] = ` -
- +
+
`; diff --git a/webapp/channels/src/components/drafts/panel/__snapshots__/panel_header.test.tsx.snap b/webapp/channels/src/components/drafts/panel/__snapshots__/panel_header.test.tsx.snap index 02e319e4d67..fb512172e4f 100644 --- a/webapp/channels/src/components/drafts/panel/__snapshots__/panel_header.test.tsx.snap +++ b/webapp/channels/src/components/drafts/panel/__snapshots__/panel_header.test.tsx.snap @@ -1,126 +1,110 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/drafts/panel/panel_header should match snapshot 1`] = ` -
+
-
- title -
-
-
- actions + title
- +
+ actions +
+
+
+
+ 56 years ago +
+
+ + draft + +
-
`; exports[`components/drafts/panel/panel_header should show sync icon when draft is from server 1`] = ` -
+
-
- title -
-
-
- actions + title
- - } - > - - +
+ actions +
- +
+
+ + + +
+
+
+ 56 years ago +
+
+ + draft + +
-
diff --git a/webapp/channels/src/components/drafts/panel/panel.test.tsx b/webapp/channels/src/components/drafts/panel/panel.test.tsx index de8414e0ff5..32408cb3117 100644 --- a/webapp/channels/src/components/drafts/panel/panel.test.tsx +++ b/webapp/channels/src/components/drafts/panel/panel.test.tsx @@ -1,9 +1,10 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; +import {render} from 'tests/react_testing_utils'; + import Panel from './panel'; describe('components/drafts/panel/', () => { @@ -17,12 +18,12 @@ describe('components/drafts/panel/', () => { }; it('should match snapshot', () => { - const wrapper = shallow( + const {container} = render( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/drafts/panel/panel_header.test.tsx b/webapp/channels/src/components/drafts/panel/panel_header.test.tsx index 363ac18060d..703d53137d7 100644 --- a/webapp/channels/src/components/drafts/panel/panel_header.test.tsx +++ b/webapp/channels/src/components/drafts/panel/panel_header.test.tsx @@ -1,13 +1,19 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; -import WithTooltip from 'components/with_tooltip'; +import {renderWithContext, screen} from 'tests/react_testing_utils'; import PanelHeader from './panel_header'; +jest.mock('components/with_tooltip', () => ({ + __esModule: true, + default: ({children}: {children: React.ReactNode}) => ( +
{children}
+ ), +})); + describe('components/drafts/panel/panel_header', () => { const baseProps: React.ComponentProps = { kind: 'draft' as const, @@ -19,15 +25,15 @@ describe('components/drafts/panel/panel_header', () => { }; it('should match snapshot', () => { - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper.find('div.PanelHeader__actions').hasClass('PanelHeader__actions show')).toBe(false); - expect(wrapper.find(WithTooltip).exists()).toBe(false); - expect(wrapper).toMatchSnapshot(); + expect(screen.queryByTestId('with-tooltip')).not.toBeInTheDocument(); + expect(screen.getByText('actions').closest('.PanelHeader__actions')).not.toHaveClass('show'); + expect(container).toMatchSnapshot(); }); it('should show sync icon when draft is from server', () => { @@ -36,13 +42,13 @@ describe('components/drafts/panel/panel_header', () => { remote: true, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper.find(WithTooltip).exists()).toBe(true); - expect(wrapper).toMatchSnapshot(); + expect(screen.getByTestId('with-tooltip')).toBeInTheDocument(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/feature_restricted_modal/feature_restricted_modal.test.tsx b/webapp/channels/src/components/feature_restricted_modal/feature_restricted_modal.test.tsx index cd8b105ffcb..9fd4d4ad229 100644 --- a/webapp/channels/src/components/feature_restricted_modal/feature_restricted_modal.test.tsx +++ b/webapp/channels/src/components/feature_restricted_modal/feature_restricted_modal.test.tsx @@ -1,9 +1,9 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; +import {renderWithContext, screen} from 'tests/react_testing_utils'; import {ModalIdentifiers} from 'utils/constants'; import FeatureRestrictedModal from './feature_restricted_modal'; @@ -17,6 +17,31 @@ jest.mock('react-redux', () => ({ useDispatch: () => mockDispatch, })); +jest.mock('components/common/hooks/useOpenPricingModal', () => () => ({ + openPricingModal: jest.fn(), + isAirGapped: false, +})); + +jest.mock('components/notify_admin_cta/notify_admin_cta', () => ({ + useNotifyAdmin: () => { + const {NotifyStatus} = require('components/common/hooks/useGetNotifyAdmin'); + return ['Notify admin', jest.fn(), NotifyStatus.None]; + }, +})); + +jest.mock('components/learn_more_trial_modal/start_trial_btn', () => (props: {onClick: () => void}) => ( + +)); + +jest.mock('@mattermost/components', () => ({ + GenericModal: ({children, modalHeaderText}: {children: React.ReactNode; modalHeaderText?: string}) => ( +
+

{modalHeaderText}

+ {children} +
+ ), +})); + describe('components/global/product_switcher_menu', () => { const defaultProps = { titleAdminPreTrial: 'Title admin pre trial', @@ -78,36 +103,34 @@ describe('components/global/product_switcher_menu', () => { }); test('should show with end user pre trial', () => { - const wrapper = shallow(); + const {container} = renderWithContext(); - expect(wrapper.find('.FeatureRestrictedModal__description').text()).toEqual(defaultProps.messageEndUser); - expect(wrapper.find('.FeatureRestrictedModal__terms').length).toEqual(0); - expect(wrapper.find('.FeatureRestrictedModal__buttons').hasClass('single')).toEqual(true); - expect(wrapper.find('.button-plans').length).toEqual(1); - expect(wrapper.find('CloudStartTrialButton').length).toEqual(0); - expect(wrapper.find('StartTrialBtn').length).toEqual(0); + expect(screen.getByText(defaultProps.messageEndUser)).toBeInTheDocument(); + expect(container.querySelector('.FeatureRestrictedModal__terms')).not.toBeInTheDocument(); + expect(container.querySelector('.FeatureRestrictedModal__buttons')).toHaveClass('single'); + expect(screen.getByRole('button', {name: /notify admin/i})).toBeInTheDocument(); + expect(screen.queryByRole('button', {name: /try free/i})).not.toBeInTheDocument(); }); test('should show with end user post trial', () => { - const wrapper = shallow(); + const {container} = renderWithContext(); - expect(wrapper.find('.FeatureRestrictedModal__description').text()).toEqual(defaultProps.messageEndUser); - expect(wrapper.find('.FeatureRestrictedModal__terms').length).toEqual(0); - expect(wrapper.find('.FeatureRestrictedModal__buttons').hasClass('single')).toEqual(true); - expect(wrapper.find('.button-plans').length).toEqual(1); - expect(wrapper.find('CloudStartTrialButton').length).toEqual(0); - expect(wrapper.find('StartTrialBtn').length).toEqual(0); + expect(screen.getByText(defaultProps.messageEndUser)).toBeInTheDocument(); + expect(container.querySelector('.FeatureRestrictedModal__terms')).not.toBeInTheDocument(); + expect(container.querySelector('.FeatureRestrictedModal__buttons')).toHaveClass('single'); + expect(screen.getByRole('button', {name: /notify admin/i})).toBeInTheDocument(); + expect(screen.queryByRole('button', {name: /try free/i})).not.toBeInTheDocument(); }); test('should show with system admin pre trial for self hosted', () => { mockState.entities.users.profiles.user1.roles = 'system_admin'; - const wrapper = shallow(); + const {container} = renderWithContext(); - expect(wrapper.find('.FeatureRestrictedModal__description').text()).toEqual(defaultProps.messageAdminPreTrial); - expect(wrapper.find('.FeatureRestrictedModal__terms').length).toEqual(1); - expect(wrapper.find('.FeatureRestrictedModal__buttons').hasClass('single')).toEqual(false); - expect(wrapper.find('.button-plans').length).toEqual(1); - expect(wrapper.find('StartTrialBtn').length).toEqual(1); + expect(screen.getByText(defaultProps.messageAdminPreTrial)).toBeInTheDocument(); + expect(container.querySelector('.FeatureRestrictedModal__terms')).toBeInTheDocument(); + expect(container.querySelector('.FeatureRestrictedModal__buttons')).not.toHaveClass('single'); + expect(screen.getByRole('button', {name: /view plans/i})).toBeInTheDocument(); + expect(screen.getByRole('button', {name: /try free/i})).toBeInTheDocument(); }); }); diff --git a/webapp/channels/src/components/file_preview/__snapshots__/file_preview.test.tsx.snap b/webapp/channels/src/components/file_preview/__snapshots__/file_preview.test.tsx.snap index d6fdc92e885..7a6a4f7afd5 100644 --- a/webapp/channels/src/components/file_preview/__snapshots__/file_preview.test.tsx.snap +++ b/webapp/channels/src/components/file_preview/__snapshots__/file_preview.test.tsx.snap @@ -1,355 +1,334 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`FilePreview should match snapshot 1`] = ` -
+
-
-
-
+
+
+
- - - PNG - - + test_filename + + + PNG + + + 100B + +
+
+
- `; exports[`FilePreview should match snapshot when props are changed 1`] = ` -
+
-
-
-
+
+
+
- - - PNG - - + test_filename + + + PNG + + + 100B + +
+
+
- `; exports[`FilePreview should match snapshot when props are changed 2`] = ` -
+
-
-
-
- - - PNG - - - 100B - -
+ class="post-image normal" + style="background-image: url(\\"/api/v4/files/file_id_1/thumbnail\\"); background-size: cover;" + />
-
- - - -
-
-
-
-
-
-
-
- - - JPG - - + test_filename + + + PNG + + + 100B + +
+
+
-
- +
+
+
+
+
+
- - +
+ + file_two.jpg + + + JPG + + + 120B + +
+
+
+ + + +
diff --git a/webapp/channels/src/components/file_preview/__snapshots__/file_progress_preview.test.tsx.snap b/webapp/channels/src/components/file_preview/__snapshots__/file_progress_preview.test.tsx.snap index 7d1c4e74a7a..d69b960d7e4 100644 --- a/webapp/channels/src/components/file_preview/__snapshots__/file_progress_preview.test.tsx.snap +++ b/webapp/channels/src/components/file_preview/__snapshots__/file_progress_preview.test.tsx.snap @@ -1,159 +1,114 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`component/file_preview/file_progress_preview should match snapshot 1`] = ` -
+
-
-
-
+
+
+
- - - - - (50%) + + test_filename - + + Uploading... + + (50%) + + +
+
+
+ + + +
+
+
-
- - - -
-
`; exports[`component/file_preview/file_progress_preview snapshot for percent value undefined 1`] = ` -
+
-
-
-
- - - - - (0%) - - -
+ class="file-icon image" + />
-
- +
- - +
+ + test_filename + + + Uploading... + + (0%) + + +
+
+
+ + + +
diff --git a/webapp/channels/src/components/file_preview/file_preview.test.tsx b/webapp/channels/src/components/file_preview/file_preview.test.tsx index 404477d1f20..c1bca3d1687 100644 --- a/webapp/channels/src/components/file_preview/file_preview.test.tsx +++ b/webapp/channels/src/components/file_preview/file_preview.test.tsx @@ -1,11 +1,12 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import {getFileUrl} from 'mattermost-redux/utils/file_utils'; +import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; + import FilePreview from './file_preview'; describe('FilePreview', () => { @@ -62,45 +63,53 @@ describe('FilePreview', () => { }; test('should match snapshot', () => { - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot when props are changed', () => { - const wrapper = shallow( + const {container, rerender} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); const fileInfo2 = { + ...baseProps.fileInfos[0], id: 'file_id_2', - create_at: '2', - width: 100, - height: 100, + create_at: 2, extension: 'jpg', + name: 'file_two.jpg', + size: 120, }; const newFileInfos = [...fileInfos, fileInfo2]; - wrapper.setProps({ - fileInfos: newFileInfos, - uploadsInProgress: [], - }); - expect(wrapper).toMatchSnapshot(); + rerender( + , + ); + expect(container).toMatchSnapshot(); }); - test('should call handleRemove when file removed', () => { + test('should call handleRemove when file removed', async () => { const newOnRemove = jest.fn(); const props = {...baseProps, onRemove: newOnRemove}; - const wrapper = shallow( + const {container} = renderWithContext( , ); - wrapper.instance().handleRemove(''); + const user = userEvent.setup(); + const removeLink = container.querySelector('a.file-preview__remove'); + if (!removeLink) { + throw new Error('Remove link not found'); + } + await user.click(removeLink); expect(newOnRemove).toHaveBeenCalled(); }); test('should not render an SVG when SVGs are disabled', () => { - const fileId = 'file_id_1'; const props = { ...baseProps, fileInfos: [ @@ -112,12 +121,12 @@ describe('FilePreview', () => { ], }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper.find('img').find({src: getFileUrl(fileId)}).exists()).toBe(false); - expect(wrapper.find('div').find('.file-icon.generic').exists()).toBe(true); + expect(screen.queryByAltText('file preview')).not.toBeInTheDocument(); + expect(container.querySelector('.file-icon.generic')).toBeInTheDocument(); }); test('should render an SVG when SVGs are enabled', () => { @@ -134,11 +143,10 @@ describe('FilePreview', () => { ], }; - const wrapper = shallow( + renderWithContext( , ); - expect(wrapper.find('img').find({src: getFileUrl(fileId)}).exists()).toBe(true); - expect(wrapper.find('div').find('.file-icon.generic').exists()).toBe(false); + expect(screen.getByAltText('file preview')).toHaveAttribute('src', getFileUrl(fileId)); }); }); diff --git a/webapp/channels/src/components/file_preview/file_progress_preview.test.tsx b/webapp/channels/src/components/file_preview/file_progress_preview.test.tsx index 4ab7c82a7c5..c077ed443db 100644 --- a/webapp/channels/src/components/file_preview/file_progress_preview.test.tsx +++ b/webapp/channels/src/components/file_preview/file_progress_preview.test.tsx @@ -1,9 +1,10 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; +import {renderWithContext} from 'tests/react_testing_utils'; + import FileProgressPreview from './file_progress_preview'; describe('component/file_preview/file_progress_preview', () => { @@ -36,10 +37,10 @@ describe('component/file_preview/file_progress_preview', () => { }; test('should match snapshot', () => { - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('snapshot for percent value undefined', () => { @@ -51,9 +52,9 @@ describe('component/file_preview/file_progress_preview', () => { }, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/file_preview_modal/__snapshots__/file_preview_modal.test.tsx.snap b/webapp/channels/src/components/file_preview_modal/__snapshots__/file_preview_modal.test.tsx.snap index 1bd07db74c4..8127eba41ec 100644 --- a/webapp/channels/src/components/file_preview_modal/__snapshots__/file_preview_modal.test.tsx.snap +++ b/webapp/channels/src/components/file_preview_modal/__snapshots__/file_preview_modal.test.tsx.snap @@ -1,1826 +1,349 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/FilePreviewModal should fall back to default preview if plugin does not need to override preview component 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot for external file 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot when plugin overrides the preview component 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot, loaded 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot, loaded and showing footer 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot, loaded with .js file 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot, loaded with .m4a file 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot, loaded with .mov file 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot, loaded with footer 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot, loaded with image 1`] = ` - - -
+
+
+
- - +
+
`; exports[`components/FilePreviewModal should match snapshot, loaded with other file 1`] = ` - - -
+
+
+
- - +
+
`; diff --git a/webapp/channels/src/components/file_preview_modal/__snapshots__/image_preview.test.tsx.snap b/webapp/channels/src/components/file_preview_modal/__snapshots__/image_preview.test.tsx.snap index c0557630000..22ba8ec936d 100644 --- a/webapp/channels/src/components/file_preview_modal/__snapshots__/image_preview.test.tsx.snap +++ b/webapp/channels/src/components/file_preview_modal/__snapshots__/image_preview.test.tsx.snap @@ -1,43 +1,51 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/view_image/ImagePreview should match snapshot, with preview 1`] = ` - - preview url image - + `; exports[`components/view_image/ImagePreview should match snapshot, with preview, cannot download 1`] = ` - +
+ +
`; exports[`components/view_image/ImagePreview should match snapshot, without preview 1`] = ` - - preview url image - + `; exports[`components/view_image/ImagePreview should match snapshot, without preview, cannot download 1`] = ` - +
+ +
`; diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal.test.tsx b/webapp/channels/src/components/file_preview_modal/file_preview_modal.test.tsx index e6c46d6178c..785a019dbc1 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal.test.tsx +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal.test.tsx @@ -1,16 +1,46 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import FilePreviewModal from 'components/file_preview_modal/file_preview_modal'; +import {act, render} from 'tests/react_testing_utils'; import Constants from 'utils/constants'; import {TestHelper} from 'utils/test_helper'; import * as Utils from 'utils/utils'; import {generateId} from 'utils/utils'; +jest.mock('react-bootstrap', () => { + const Modal = ({children, show}: {children: React.ReactNode; show: boolean}) => (show ?
{children}
: null); + Modal.Header = ({children}: {children: React.ReactNode}) =>
{children}
; + Modal.Body = ({children}: {children: React.ReactNode}) =>
{children}
; + Modal.Title = ({children}: {children: React.ReactNode}) =>
{children}
; + return {Modal}; +}); + +jest.mock('components/archived_preview', () => () =>
{'Archived Preview'}
); +jest.mock('components/audio_video_preview', () => () =>
{'Audio Video Preview'}
); +jest.mock('components/code_preview', () => ({ + __esModule: true, + default: () =>
{'Code Preview'}
, + hasSupportedLanguage: () => true, +})); +jest.mock('components/file_info_preview', () => () =>
{'File Info Preview'}
); +jest.mock('components/loading_image_preview', () => () =>
{'Loading Image Preview'}
); +jest.mock('components/pdf_preview', () => ({ + __esModule: true, + default: () =>
{'PDF Preview'}
, +})); +jest.mock('components/file_preview_modal/file_preview_modal_footer/file_preview_modal_footer', () => () => ( +
{'File Preview Modal Footer'}
+)); +jest.mock('components/file_preview_modal/file_preview_modal_header/file_preview_modal_header', () => () => ( +
{'File Preview Modal Header'}
+)); +jest.mock('components/file_preview_modal/image_preview', () => () =>
{'Image Preview'}
); +jest.mock('components/file_preview_modal/popover_bar', () => () =>
{'Popover Bar'}
); + describe('components/FilePreviewModal', () => { const baseProps = { fileInfos: [TestHelper.getFileInfoMock({id: 'file_id', extension: 'jpg'})], @@ -22,53 +52,68 @@ describe('components/FilePreviewModal', () => { onExited: jest.fn(), }; - test('should match snapshot', () => { - const wrapper = shallow(); + const renderModal = (props = baseProps) => { + const ref = React.createRef(); + const utils = render( + , + ); + return {ref, ...utils}; + }; - expect(wrapper).toMatchSnapshot(); + test('should match snapshot', () => { + const {container} = renderModal(); + expect(container).toMatchSnapshot(); }); test('should match snapshot, loaded with image', () => { - const wrapper = shallow(); - - wrapper.setState({loaded: [true]}); - expect(wrapper).toMatchSnapshot(); + const {container, ref} = renderModal(); + act(() => { + ref.current?.setState({loaded: [true] as any}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, loaded with .mov file', () => { const fileInfos = [TestHelper.getFileInfoMock({id: 'file_id', extension: 'mov'})]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); - - wrapper.setState({loaded: [true]}); - expect(wrapper).toMatchSnapshot(); + const {container, ref} = renderModal(props); + act(() => { + ref.current?.setState({loaded: [true] as any}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, loaded with .m4a file', () => { const fileInfos = [TestHelper.getFileInfoMock({id: 'file_id', extension: 'm4a'})]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); - - wrapper.setState({loaded: [true]}); - expect(wrapper).toMatchSnapshot(); + const {container, ref} = renderModal(props); + act(() => { + ref.current?.setState({loaded: [true] as any}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, loaded with .js file', () => { const fileInfos = [TestHelper.getFileInfoMock({id: 'file_id', extension: 'js'})]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); - - wrapper.setState({loaded: [true]}); - expect(wrapper).toMatchSnapshot(); + const {container, ref} = renderModal(props); + act(() => { + ref.current?.setState({loaded: [true] as any}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, loaded with other file', () => { const fileInfos = [TestHelper.getFileInfoMock({id: 'file_id', extension: 'other'})]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); - - wrapper.setState({loaded: [true]}); - expect(wrapper).toMatchSnapshot(); + const {container, ref} = renderModal(props); + act(() => { + ref.current?.setState({loaded: [true] as any}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, loaded with footer', () => { @@ -78,24 +123,27 @@ describe('components/FilePreviewModal', () => { TestHelper.getFileInfoMock({id: 'file_id_3', extension: 'mp4'}), ]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); - - wrapper.setState({loaded: [true, true, true]}); - expect(wrapper).toMatchSnapshot(); + const {container, ref} = renderModal(props); + act(() => { + ref.current?.setState({loaded: [true, true, true] as any}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, loaded', () => { - const wrapper = shallow(); - - wrapper.setState({loaded: [true]}); - expect(wrapper).toMatchSnapshot(); + const {container, ref} = renderModal(); + act(() => { + ref.current?.setState({loaded: [true] as any}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, loaded and showing footer', () => { - const wrapper = shallow(); - - wrapper.setState({loaded: [true]}); - expect(wrapper).toMatchSnapshot(); + const {container, ref} = renderModal(); + act(() => { + ref.current?.setState({loaded: [true] as any}); + }); + expect(container).toMatchSnapshot(); }); test('should go to next or previous upon key press of right or left, respectively', () => { @@ -105,43 +153,59 @@ describe('components/FilePreviewModal', () => { TestHelper.getFileInfoMock({id: 'file_id_3', extension: 'mp4'}), ]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); - - wrapper.setState({loaded: [true, true, true]}); + const {ref} = renderModal(props); + act(() => { + ref.current?.setState({loaded: [true, true, true] as any}); + }); let evt = {key: Constants.KeyCodes.RIGHT[0]} as KeyboardEvent; - - wrapper.instance().handleKeyPress(evt); - expect(wrapper.state('imageIndex')).toBe(1); - wrapper.instance().handleKeyPress(evt); - expect(wrapper.state('imageIndex')).toBe(2); + act(() => { + ref.current?.handleKeyPress(evt); + }); + expect(ref.current?.state.imageIndex).toBe(1); + act(() => { + ref.current?.handleKeyPress(evt); + }); + expect(ref.current?.state.imageIndex).toBe(2); evt = {key: Constants.KeyCodes.LEFT[0]} as KeyboardEvent; - wrapper.instance().handleKeyPress(evt); - expect(wrapper.state('imageIndex')).toBe(1); - wrapper.instance().handleKeyPress(evt); - expect(wrapper.state('imageIndex')).toBe(0); + act(() => { + ref.current?.handleKeyPress(evt); + }); + expect(ref.current?.state.imageIndex).toBe(1); + act(() => { + ref.current?.handleKeyPress(evt); + }); + expect(ref.current?.state.imageIndex).toBe(0); }); test('should handle onMouseEnter and onMouseLeave', () => { - const wrapper = shallow(); - wrapper.setState({loaded: [true]}); + const {ref} = renderModal(); + act(() => { + ref.current?.setState({loaded: [true] as any}); + }); - wrapper.instance().onMouseEnterImage(); - expect(wrapper.state('showCloseBtn')).toBe(true); + act(() => { + ref.current?.onMouseEnterImage(); + }); + expect(ref.current?.state.showCloseBtn).toBe(true); - wrapper.instance().onMouseLeaveImage(); - expect(wrapper.state('showCloseBtn')).toBe(false); + act(() => { + ref.current?.onMouseLeaveImage(); + }); + expect(ref.current?.state.showCloseBtn).toBe(false); }); test('should handle on modal close', () => { - const wrapper = shallow(); - wrapper.setState({ - loaded: [true], + const {ref} = renderModal(); + act(() => { + ref.current?.setState({loaded: [true] as any}); }); - wrapper.instance().handleModalClose(); - expect(wrapper.state('show')).toBe(false); + act(() => { + ref.current?.handleModalClose(); + }); + expect(ref.current?.state.show).toBe(false); }); test('should match snapshot for external file', () => { @@ -149,24 +213,24 @@ describe('components/FilePreviewModal', () => { TestHelper.getFileInfoMock({extension: 'png'}), ]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderModal(props); + expect(container).toMatchSnapshot(); }); test('should correctly identify image URLs with isImageUrl method', () => { - const wrapper = shallow(); + const {ref} = renderModal(); // Test proxied image URLs - expect(wrapper.instance().isImageUrl('http://localhost:8065/api/v4/image?url=https%3A%2F%2Fexample.com%2Fimage.jpg')).toBe(true); + expect(ref.current?.isImageUrl('http://localhost:8065/api/v4/image?url=https%3A%2F%2Fexample.com%2Fimage.jpg')).toBe(true); // Test URLs with image extensions - expect(wrapper.instance().isImageUrl('https://example.com/image.jpg')).toBe(true); - expect(wrapper.instance().isImageUrl('https://example.com/image.png')).toBe(true); - expect(wrapper.instance().isImageUrl('https://example.com/image.gif')).toBe(true); + expect(ref.current?.isImageUrl('https://example.com/image.jpg')).toBe(true); + expect(ref.current?.isImageUrl('https://example.com/image.png')).toBe(true); + expect(ref.current?.isImageUrl('https://example.com/image.gif')).toBe(true); // Test non-image URLs - expect(wrapper.instance().isImageUrl('https://example.com/document.pdf')).toBe(false); - expect(wrapper.instance().isImageUrl('https://example.com/file.txt')).toBe(false); + expect(ref.current?.isImageUrl('https://example.com/document.pdf')).toBe(false); + expect(ref.current?.isImageUrl('https://example.com/file.txt')).toBe(false); }); test('should handle external image URLs correctly', () => { @@ -183,21 +247,24 @@ describe('components/FilePreviewModal', () => { // Create a LinkInfo object for an external image URL const externalImageUrl = 'http://localhost:8065/api/v4/image?url=https%3A%2F%2Fexample.com%2Fimage.jpg'; - const fileInfos = [{ - has_preview_image: false, - link: externalImageUrl, - extension: '', - name: 'External Image', - }]; + const fileInfos = [ + TestHelper.getFileInfoMock({ + id: '', + has_preview_image: false, + link: externalImageUrl, + extension: '', + name: 'External Image', + }), + ]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); + const {ref} = renderModal(props); - // Spy on handleImageLoaded - const handleImageLoadedSpy = jest.spyOn(wrapper.instance(), 'handleImageLoaded'); + const handleImageLoadedSpy = jest.spyOn(ref.current as FilePreviewModal, 'handleImageLoaded'); - // Call loadImage with the external image URL - wrapper.instance().loadImage(0); + act(() => { + ref.current?.loadImage(0); + }); // Verify that Utils.loadImage was called with the correct URL expect(loadImageSpy).toHaveBeenCalledWith( @@ -220,17 +287,21 @@ describe('components/FilePreviewModal', () => { TestHelper.getFileInfoMock({id: 'file_id_3', extension: 'mp4'}), ]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); + const {ref} = renderModal(props); let index = 1; - wrapper.setState({loaded: [true, false, false]}); - wrapper.instance().loadImage(index); + act(() => { + ref.current?.setState({loaded: [true, false, false] as any}); + ref.current?.loadImage(index); + }); - expect(wrapper.state('loaded')[index]).toBe(true); + expect(ref.current?.state.loaded[index]).toBe(true); index = 2; - wrapper.instance().loadImage(index); - expect(wrapper.state('loaded')[index]).toBe(true); + act(() => { + ref.current?.loadImage(index); + }); + expect(ref.current?.state.loaded[index]).toBe(true); }); test('should handle handleImageLoaded', () => { @@ -240,17 +311,21 @@ describe('components/FilePreviewModal', () => { TestHelper.getFileInfoMock({id: 'file_id_3', extension: 'mp4'}), ]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); + const {ref} = renderModal(props); let index = 1; - wrapper.setState({loaded: [true, false, false]}); - wrapper.instance().handleImageLoaded(index); + act(() => { + ref.current?.setState({loaded: [true, false, false] as any}); + ref.current?.handleImageLoaded(index); + }); - expect(wrapper.state('loaded')[index]).toBe(true); + expect(ref.current?.state.loaded[index]).toBe(true); index = 2; - wrapper.instance().handleImageLoaded(index); - expect(wrapper.state('loaded')[index]).toBe(true); + act(() => { + ref.current?.handleImageLoaded(index); + }); + expect(ref.current?.state.loaded[index]).toBe(true); }); test('should handle handleImageProgress', () => { @@ -260,36 +335,46 @@ describe('components/FilePreviewModal', () => { TestHelper.getFileInfoMock({id: 'file_id_3', extension: 'mp4'}), ]; const props = {...baseProps, fileInfos}; - const wrapper = shallow(); + const {ref} = renderModal(props); const index = 1; let completedPercentage = 30; - wrapper.setState({loaded: [true, false, false]}); - wrapper.instance().handleImageProgress(index, completedPercentage); + act(() => { + ref.current?.setState({loaded: [true, false, false] as any}); + ref.current?.handleImageProgress(index, completedPercentage); + }); - expect(wrapper.state('progress')[index]).toBe(completedPercentage); + expect(ref.current?.state.progress[index]).toBe(completedPercentage); completedPercentage = 70; - wrapper.instance().handleImageProgress(index, completedPercentage); + act(() => { + ref.current?.handleImageProgress(index, completedPercentage); + }); - expect(wrapper.state('progress')[index]).toBe(completedPercentage); + expect(ref.current?.state.progress[index]).toBe(completedPercentage); }); test('should pass componentWillReceiveProps', () => { - const wrapper = shallow(); + const {ref, rerender} = renderModal(); - expect(Object.keys(wrapper.state('loaded')).length).toBe(1); - expect(Object.keys(wrapper.state('progress')).length).toBe(1); + expect(Object.keys(ref.current?.state.loaded || {})).toHaveLength(1); + expect(Object.keys(ref.current?.state.progress || {})).toHaveLength(1); - wrapper.setProps({ - fileInfos: [ - TestHelper.getFileInfoMock({id: 'file_id_1', extension: 'gif'}), - TestHelper.getFileInfoMock({id: 'file_id_2', extension: 'wma'}), - TestHelper.getFileInfoMock({id: 'file_id_3', extension: 'mp4'}), - ], + act(() => { + rerender( + , + ); }); - expect(Object.keys(wrapper.state('loaded')).length).toBe(3); - expect(Object.keys(wrapper.state('progress')).length).toBe(3); + expect(Object.keys(ref.current?.state.loaded || {})).toHaveLength(3); + expect(Object.keys(ref.current?.state.progress || {})).toHaveLength(3); }); test('should match snapshot when plugin overrides the preview component', () => { @@ -300,9 +385,8 @@ describe('components/FilePreviewModal', () => { component: () =>
{'Preview'}
, }]; const props = {...baseProps, pluginFilePreviewComponents}; - const wrapper = shallow(); - - expect(wrapper).toMatchSnapshot(); + const {container} = renderModal(props); + expect(container).toMatchSnapshot(); }); test('should fall back to default preview if plugin does not need to override preview component', () => { @@ -313,8 +397,7 @@ describe('components/FilePreviewModal', () => { component: () =>
{'Preview'}
, }]; const props = {...baseProps, pluginFilePreviewComponents}; - const wrapper = shallow(); - - expect(wrapper).toMatchSnapshot(); + const {container} = renderModal(props); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal_footer/__snapshots__/file_preview_modal_footer.test.tsx.snap b/webapp/channels/src/components/file_preview_modal/file_preview_modal_footer/__snapshots__/file_preview_modal_footer.test.tsx.snap index 1c8723edac4..bc5da04e566 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal_footer/__snapshots__/file_preview_modal_footer.test.tsx.snap +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal_footer/__snapshots__/file_preview_modal_footer.test.tsx.snap @@ -1,149 +1,31 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/file_preview_modal/file_preview_modal_footer/FilePreviewModalFooter should match snapshot the desktop view 1`] = ` -
- - +
+
`; exports[`components/file_preview_modal/file_preview_modal_footer/FilePreviewModalFooter should match snapshot the mobile view 1`] = ` -
- - +
+
`; diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal_footer/file_preview_modal_footer.test.tsx b/webapp/channels/src/components/file_preview_modal/file_preview_modal_footer/file_preview_modal_footer.test.tsx index a6a5988fefa..d42a9092bbe 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal_footer/file_preview_modal_footer.test.tsx +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal_footer/file_preview_modal_footer.test.tsx @@ -1,13 +1,18 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; +import {renderWithContext} from 'tests/react_testing_utils'; import {TestHelper} from 'utils/test_helper'; import FilePreviewModalFooter from './file_preview_modal_footer'; +jest.mock('../file_preview_modal_info/file_preview_modal_info', () => () =>
{'FilePreviewModalInfo'}
); +jest.mock('../file_preview_modal_main_actions/file_preview_modal_main_actions', () => () => ( +
{'FilePreviewModalMainActions'}
+)); + describe('components/file_preview_modal/file_preview_modal_footer/FilePreviewModalFooter', () => { const defaultProps = { enablePublicLink: false, @@ -32,8 +37,8 @@ describe('components/file_preview_modal/file_preview_modal_footer/FilePreviewMod ...defaultProps, }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); test('should match snapshot the mobile view', () => { @@ -42,7 +47,7 @@ describe('components/file_preview_modal/file_preview_modal_footer/FilePreviewMod isMobile: true, }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal_header/__snapshots__/file_preview_modal_header.test.tsx.snap b/webapp/channels/src/components/file_preview_modal/file_preview_modal_header/__snapshots__/file_preview_modal_header.test.tsx.snap index 8e44ae4bf28..f0d6001d43f 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal_header/__snapshots__/file_preview_modal_header.test.tsx.snap +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal_header/__snapshots__/file_preview_modal_header.test.tsx.snap @@ -1,102 +1,148 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/file_preview_modal/file_preview_modal_header/FilePreviewModalHeader should match snapshot the desktop view 1`] = ` -
- - - +
+
+
+
+
+ img.png +
+ + + Someone + + + +
+
+
+ + + 2 of 3 + + +
+
+ + + + + + + +
+
`; exports[`components/file_preview_modal/file_preview_modal_header/FilePreviewModalHeader should match snapshot the mobile view 1`] = ` -
- - +
+
+
+ +
+
+ + + 2 of 3 + + +
+
`; diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal_header/file_preview_modal_header.test.tsx b/webapp/channels/src/components/file_preview_modal/file_preview_modal_header/file_preview_modal_header.test.tsx index 831ee043ad4..ecf20ccee02 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal_header/file_preview_modal_header.test.tsx +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal_header/file_preview_modal_header.test.tsx @@ -1,11 +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 type {Post} from '@mattermost/types/posts'; +import {renderWithContext} from 'tests/react_testing_utils'; import {TestHelper} from 'utils/test_helper'; import FilePreviewModalHeader from './file_preview_modal_header'; @@ -36,8 +36,8 @@ describe('components/file_preview_modal/file_preview_modal_header/FilePreviewMod ...defaultProps, }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); test('should match snapshot the mobile view', () => { @@ -46,7 +46,7 @@ describe('components/file_preview_modal/file_preview_modal_header/FilePreviewMod isMobileView: true, }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal_info/__snapshots__/file_preview_modal_info.test.tsx.snap b/webapp/channels/src/components/file_preview_modal/file_preview_modal_info/__snapshots__/file_preview_modal_info.test.tsx.snap index c8fafbd7054..36408f6356d 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal_info/__snapshots__/file_preview_modal_info.test.tsx.snap +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal_info/__snapshots__/file_preview_modal_info.test.tsx.snap @@ -1,56 +1,51 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/FilePreviewModalInfo should match snapshot 1`] = ` -
- +
-
+
- some-user -
- - - +
+ some-user +
+ + Shared in ~name + +
`; exports[`components/FilePreviewModalInfo should match snapshot where post is missing and avoid crash 1`] = ` -
+
-
- Someone -
- +
+ Someone +
+ +
`; diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal_info/file_preview_modal_info.test.tsx b/webapp/channels/src/components/file_preview_modal/file_preview_modal_info/file_preview_modal_info.test.tsx index d169f09215a..33491226b4f 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal_info/file_preview_modal_info.test.tsx +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal_info/file_preview_modal_info.test.tsx @@ -1,10 +1,10 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import type {ComponentProps} from 'react'; +import {renderWithContext} from 'tests/react_testing_utils'; import {TestHelper} from 'utils/test_helper'; import type {GlobalState} from 'types/store'; @@ -45,23 +45,23 @@ describe('components/FilePreviewModalInfo', () => { test('should match snapshot', () => { mockState.entities.users.profiles = {user_id: mockedUser}; mockState.entities.channels.channels = {channel_id: mockedChannel}; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot where post is missing and avoid crash', () => { mockState.entities.users.profiles = {user_id: mockedUser}; mockState.entities.channels.channels = {channel_id: mockedChannel}; baseProps.post = undefined; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/__snapshots__/file_preview_modal_main_nav.test.tsx.snap b/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/__snapshots__/file_preview_modal_main_nav.test.tsx.snap index f993052ada8..26a7ec47b09 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/__snapshots__/file_preview_modal_main_nav.test.tsx.snap +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/__snapshots__/file_preview_modal_main_nav.test.tsx.snap @@ -1,64 +1,35 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/file_preview_modal/file_preview_modal_main_nav/FilePreviewModalMainNav should match snapshot with multiple files 1`] = ` -
- - } +
+
- - - - - - } - > + + 2 of 2 + - +
`; diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/file_preview_modal_main_nav.test.tsx b/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/file_preview_modal_main_nav.test.tsx index 0a4347fa92d..009214c5e79 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/file_preview_modal_main_nav.test.tsx +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/file_preview_modal_main_nav.test.tsx @@ -1,9 +1,10 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; +import {renderWithContext} from 'tests/react_testing_utils'; + import FilePreviewModalMainNav from './file_preview_modal_main_nav'; describe('components/file_preview_modal/file_preview_modal_main_nav/FilePreviewModalMainNav', () => { @@ -20,7 +21,7 @@ describe('components/file_preview_modal/file_preview_modal_main_nav/FilePreviewM enablePublicLink: false, }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/file_preview_modal/image_preview.test.tsx b/webapp/channels/src/components/file_preview_modal/image_preview.test.tsx index a63818c3db4..31aac4156ea 100644 --- a/webapp/channels/src/components/file_preview_modal/image_preview.test.tsx +++ b/webapp/channels/src/components/file_preview_modal/image_preview.test.tsx @@ -1,11 +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 ImagePreview from 'components/file_preview_modal/image_preview'; +import {render, screen} from 'tests/react_testing_utils'; import {TestHelper} from 'utils/test_helper'; describe('components/view_image/ImagePreview', () => { @@ -16,11 +16,11 @@ describe('components/view_image/ImagePreview', () => { }; test('should match snapshot, without preview', () => { - const wrapper = shallow( + const {container} = render( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot, with preview', () => { @@ -33,11 +33,11 @@ describe('components/view_image/ImagePreview', () => { }, }; - const wrapper = shallow( + const {container} = render( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot, without preview, cannot download', () => { @@ -46,11 +46,11 @@ describe('components/view_image/ImagePreview', () => { canDownloadFiles: false, }; - const wrapper = shallow( + const {container} = render( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot, with preview, cannot download', () => { @@ -64,11 +64,11 @@ describe('components/view_image/ImagePreview', () => { }, }; - const wrapper = shallow( + const {container} = render( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should not download link for external file', () => { @@ -82,11 +82,11 @@ describe('components/view_image/ImagePreview', () => { }, }; - const wrapper = shallow( + render( , ); - expect(wrapper.find('a').prop('href')).toBe('#'); - expect(wrapper.find('img').prop('src')).toBe(props.fileInfo.link); + expect(screen.getByRole('link')).toHaveAttribute('href', '#'); + expect(screen.getByTestId('imagePreview')).toHaveAttribute('src', props.fileInfo.link); }); }); diff --git a/webapp/channels/src/components/file_preview_modal/popover_bar/__snapshots__/popover_bar.test.tsx.snap b/webapp/channels/src/components/file_preview_modal/popover_bar/__snapshots__/popover_bar.test.tsx.snap index 72fd42defad..32fda6df987 100644 --- a/webapp/channels/src/components/file_preview_modal/popover_bar/__snapshots__/popover_bar.test.tsx.snap +++ b/webapp/channels/src/components/file_preview_modal/popover_bar/__snapshots__/popover_bar.test.tsx.snap @@ -1,64 +1,36 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/file_preview_modal/popover_bar/PopoverBar should match snapshot with zoom controls enabled 1`] = ` -
+
`; diff --git a/webapp/channels/src/components/file_preview_modal/popover_bar/popover_bar.test.tsx b/webapp/channels/src/components/file_preview_modal/popover_bar/popover_bar.test.tsx index f46d356eb25..d5a584cada2 100644 --- a/webapp/channels/src/components/file_preview_modal/popover_bar/popover_bar.test.tsx +++ b/webapp/channels/src/components/file_preview_modal/popover_bar/popover_bar.test.tsx @@ -1,11 +1,12 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import PopoverBar from 'components/file_preview_modal/popover_bar/popover_bar'; +import {render} from 'tests/react_testing_utils'; + describe('components/file_preview_modal/popover_bar/PopoverBar', () => { const defaultProps = { showZoomControls: false, @@ -17,7 +18,7 @@ describe('components/file_preview_modal/popover_bar/PopoverBar', () => { showZoomControls: true, }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = render(); + expect(container).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/post_view/post_add_channel_member/__snapshots__/post_add_channel_member.test.tsx.snap b/webapp/channels/src/components/post_view/post_add_channel_member/__snapshots__/post_add_channel_member.test.tsx.snap index 5ccc5ffddf7..fd1c50fce2f 100644 --- a/webapp/channels/src/components/post_view/post_add_channel_member/__snapshots__/post_add_channel_member.test.tsx.snap +++ b/webapp/channels/src/components/post_view/post_add_channel_member/__snapshots__/post_add_channel_member.test.tsx.snap @@ -1,272 +1,150 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing -exports[`components/post_view/PostAddChannelMember should match snapshot, empty channelType 1`] = `""`; +exports[`components/post_view/PostAddChannelMember should match snapshot, empty channelType 1`] = `
`; -exports[`components/post_view/PostAddChannelMember should match snapshot, empty postId 1`] = `""`; +exports[`components/post_view/PostAddChannelMember should match snapshot, empty postId 1`] = `
`; exports[`components/post_view/PostAddChannelMember should match snapshot, more than 3 users 1`] = ` - -

+

+

- - - , + + @username_1 - + 2 others - - + + @username_4 + - + did not get notified by this mention because they are not in the channel. Would you like to - + add them to the channel - + ? They will have access to all message history.

- +
`; exports[`components/post_view/PostAddChannelMember should match snapshot, more than 3 users 2`] = ` - -

+

+

- - - , + + @username_1 - - - , + 2 others + + + @username_4 - - - - + did not get notified by this mention because they are not in the channel. Would you like to - + add them to the channel - + ? They will have access to all message history.

- +
`; exports[`components/post_view/PostAddChannelMember should match snapshot, private channel 1`] = ` - -

- +

+

+ + + @username_1 + + - + did not get notified by this mention because they are not in the channel. Would you like to - + add them to this private channel - + ? They will have access to all message history.

- +
`; exports[`components/post_view/PostAddChannelMember should match snapshot, public channel 1`] = ` - -

- +

+

+ + + @username_1 + + - + did not get notified by this mention because they are not in the channel. Would you like to - + add them to the channel - + ? They will have access to all message history.

- +
`; exports[`components/post_view/PostAddChannelMember should match snapshot, with ABAC policy enforced 1`] = ` -

- - - - , +

+

+ + + @username_1 + + + @username_2 + + + @username_3 + - - - - - - did not get notified by this mention because they are not in the channel. -

+ + did not get notified by this mention because they are not in the channel. +

+
`; exports[`components/post_view/PostAddChannelMember should match snapshot, with no-groups usernames 1`] = ` - -

- +

+

+ + + @username_1 + + - + did not get notified by this mention because they are not in the channel. Would you like to - + add them to the channel - + ? They will have access to all message history.

-

- +

+ + + @user_id_2 + + - + did not get notified by this mention because they are not in the channel. They cannot be added to the channel because they are not a member of the linked groups. To add them to this channel, they must be added to the linked groups.

- +
`; diff --git a/webapp/channels/src/components/post_view/post_add_channel_member/post_add_channel_member.test.tsx b/webapp/channels/src/components/post_view/post_add_channel_member/post_add_channel_member.test.tsx index 37fd4740546..47b0df170f6 100644 --- a/webapp/channels/src/components/post_view/post_add_channel_member/post_add_channel_member.test.tsx +++ b/webapp/channels/src/components/post_view/post_add_channel_member/post_add_channel_member.test.tsx @@ -1,7 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import type {Post} from '@mattermost/types/posts'; @@ -12,6 +11,7 @@ import {sendAddToChannelEphemeralPost} from 'actions/global_actions'; import PostAddChannelMember from 'components/post_view/post_add_channel_member/post_add_channel_member'; import type {Props} from 'components/post_view/post_add_channel_member/post_add_channel_member'; +import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; import {TestHelper} from 'utils/test_helper'; jest.mock('actions/global_actions', () => { @@ -20,7 +20,12 @@ jest.mock('actions/global_actions', () => { }; }); +jest.mock('components/at_mention', () => ({mentionName}: {mentionName: string}) => ( + {`@${mentionName}`} +)); + describe('components/post_view/PostAddChannelMember', () => { + let generateMentionsSpy: jest.SpyInstance; const post: Post = TestHelper.getPostMock({ id: 'post_id_1', root_id: 'root_id', @@ -46,13 +51,40 @@ describe('components/post_view/PostAddChannelMember', () => { isPolicyEnforced: false, }; + beforeEach(() => { + generateMentionsSpy = jest.spyOn(PostAddChannelMember.prototype, 'generateAtMentions').mockImplementation((usernames = []) => { + if (usernames.length > 3) { + const otherUsersCount = usernames.length - 2; + return ( + + {`@${usernames[0]}`} + {`${otherUsersCount} others`} + {`@${usernames[usernames.length - 1]}`} + + ); + } + + return ( + + {usernames.map((username) => ( + {`@${username}`} + ))} + + ); + }); + }); + + afterEach(() => { + generateMentionsSpy.mockRestore(); + }); + test('should match snapshot, empty postId', () => { const props: Props = { ...requiredProps, postId: '', }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); test('should match snapshot, empty channelType', () => { @@ -60,13 +92,13 @@ describe('components/post_view/PostAddChannelMember', () => { ...requiredProps, channelType: '', }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); test('should match snapshot, public channel', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); test('should match snapshot, private channel', () => { @@ -75,11 +107,11 @@ describe('components/post_view/PostAddChannelMember', () => { channelType: 'P', }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); - test('should match snapshot, more than 3 users', () => { + test('should match snapshot, more than 3 users', async () => { const userIds = ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4']; const usernames = ['username_1', 'username_2', 'username_3', 'username_4']; const props: Props = { @@ -88,26 +120,34 @@ describe('components/post_view/PostAddChannelMember', () => { usernames, }; - const wrapper = shallow(); - expect(wrapper.state('expanded')).toEqual(false); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); - wrapper.find('.PostBody_otherUsersLink').simulate('click'); - expect(wrapper.state('expanded')).toEqual(true); - expect(wrapper).toMatchSnapshot(); + const user = userEvent.setup(); + const otherUsersLink = screen.getByText(/others/i).closest('a'); + if (!otherUsersLink) { + throw new Error('Other users link not found'); + } + await user.click(otherUsersLink); + expect(container).toMatchSnapshot(); }); - test('actions should have been called', () => { + test('actions should have been called', async () => { const actions = { removePost: jest.fn(), addChannelMember: jest.fn(), }; const props: Props = {...requiredProps, actions}; - const wrapper = shallow( + renderWithContext( , ); - wrapper.find('.PostBody_addChannelMemberLink').simulate('click'); + const user = userEvent.setup(); + const addToChannelLink = screen.getByText(/add them to the channel/i).closest('a'); + if (!addToChannelLink) { + throw new Error('Add to channel link not found'); + } + await user.click(addToChannelLink); expect(actions.addChannelMember).toHaveBeenCalledTimes(1); expect(actions.addChannelMember).toHaveBeenCalledWith(post.channel_id, requiredProps.userIds[0], post.root_id); @@ -117,7 +157,7 @@ describe('components/post_view/PostAddChannelMember', () => { expect(actions.removePost).toHaveBeenCalledWith(post); }); - test('addChannelMember should have been called multiple times', () => { + test('addChannelMember should have been called multiple times', async () => { const userIds = ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4']; const usernames = ['username_1', 'username_2', 'username_3', 'username_4']; const actions = { @@ -125,11 +165,16 @@ describe('components/post_view/PostAddChannelMember', () => { addChannelMember: jest.fn(), }; const props: Props = {...requiredProps, userIds, usernames, actions}; - const wrapper = shallow( + renderWithContext( , ); - wrapper.find('.PostBody_addChannelMemberLink').simulate('click'); + const user = userEvent.setup(); + const addToChannelLink = screen.getByText(/add them to the channel/i).closest('a'); + if (!addToChannelLink) { + throw new Error('Add to channel link not found'); + } + await user.click(addToChannelLink); expect(actions.addChannelMember).toHaveBeenCalledTimes(4); }); @@ -138,8 +183,8 @@ describe('components/post_view/PostAddChannelMember', () => { ...requiredProps, noGroupsUsernames: ['user_id_2'], }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); test('should match snapshot, with ABAC policy enforced', () => { @@ -148,8 +193,8 @@ describe('components/post_view/PostAddChannelMember', () => { usernames: ['username_1', 'username_2', 'username_3'], isPolicyEnforced: true, }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(); + expect(container).toMatchSnapshot(); }); test('should never show invite links when policy is enforced (ABAC channels)', () => { @@ -159,8 +204,8 @@ describe('components/post_view/PostAddChannelMember', () => { noGroupsUsernames: [], isPolicyEnforced: true, }; - const wrapper = shallow(); - expect(wrapper.find('.PostBody_addChannelMemberLink')).toHaveLength(0); + renderWithContext(); + expect(screen.queryByRole('link', {name: /add them/i})).not.toBeInTheDocument(); }); test('should show single consolidated message for ABAC channels regardless of user types', () => { @@ -170,10 +215,9 @@ describe('components/post_view/PostAddChannelMember', () => { noGroupsUsernames: ['user3'], isPolicyEnforced: true, }; - const wrapper = shallow(); + renderWithContext(); - // Should render only one consolidated message with no invite links - expect(wrapper.find('p')).toHaveLength(1); - expect(wrapper.find('.PostBody_addChannelMemberLink')).toHaveLength(0); + expect(screen.getByText('did not get notified by this mention because they are not in the channel.')).toBeInTheDocument(); + expect(screen.queryByRole('link', {name: /add them/i})).not.toBeInTheDocument(); }); }); diff --git a/webapp/channels/src/components/post_view/post_aria_label_div.test.tsx b/webapp/channels/src/components/post_view/post_aria_label_div.test.tsx index d8ac50cae4e..5cbfb14f1b8 100644 --- a/webapp/channels/src/components/post_view/post_aria_label_div.test.tsx +++ b/webapp/channels/src/components/post_view/post_aria_label_div.test.tsx @@ -1,13 +1,12 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {mount} from 'enzyme'; import React from 'react'; import * as reactIntl from 'react-intl'; import enMessages from 'i18n/en.json'; import esMessages from 'i18n/es.json'; -import {mockStore} from 'tests/test_store'; +import {renderWithContext, screen} from 'tests/react_testing_utils'; import {TestHelper} from 'utils/test_helper'; import PostAriaLabelDiv from './post_aria_label_div'; @@ -49,42 +48,48 @@ describe('PostAriaLabelDiv', () => { post: TestHelper.getPostMock({ user_id: author.id, message: 'This is a test.', + create_at: new Date('2020-01-15T12:00:00Z').getTime(), }), } as Omit; test('should render aria-label in the given locale', () => { - const {mountOptions} = mockStore(baseState); - (reactIntl.useIntl as jest.Mock).mockImplementation(() => reactIntl.createIntl({locale: 'en', messages: enMessages, defaultLocale: 'en'})); - let wrapper = mount(, mountOptions); - let div = wrapper.childAt(0); + let renderResult = renderWithContext(, baseState, { + locale: 'en', + intlMessages: enMessages, + }); - expect(div.prop('aria-label')).toContain(author.username); - expect(div.prop('aria-label')).toContain('January'); + let div = renderResult.container.firstChild as HTMLElement; + expect(div.getAttribute('aria-label')).toContain(author.username); + expect(div.getAttribute('aria-label')).toContain('January'); (reactIntl.useIntl as jest.Mock).mockImplementation(() => reactIntl.createIntl({locale: 'es', messages: esMessages, defaultLocale: 'es'})); - wrapper = mount(, mountOptions); - div = wrapper.childAt(0); + renderResult = renderWithContext(, baseState, { + locale: 'es', + intlMessages: esMessages, + }); + div = renderResult.container.firstChild as HTMLElement; - expect(div.prop('aria-label')).toContain(author.username); - expect(div.prop('aria-label')).toContain('enero'); + expect(div.getAttribute('aria-label')).toContain(author.username); + expect(div.getAttribute('aria-label')).toContain('enero'); }); test('should pass other props through to the rendered div', () => { - const {mountOptions} = mockStore(baseState); - (reactIntl.useIntl as jest.Mock).mockImplementation(() => reactIntl.createIntl({locale: 'en', messages: enMessages, defaultLocale: 'en'})); let props = baseProps; - let wrapper = mount(, mountOptions); - let div = wrapper.childAt(0); + let renderResult = renderWithContext(, baseState, { + locale: 'en', + intlMessages: enMessages, + }); + let div = renderResult.container.firstChild as HTMLElement; - expect(div.prop('className')).toBeUndefined(); - expect(div.prop('data-something')).toBeUndefined(); - expect(div.children()).toHaveLength(0); + expect(div.className).toBe(''); + expect(div.getAttribute('data-something')).toBeNull(); + expect(div.childNodes.length).toBe(0); props = { ...props, @@ -92,16 +97,20 @@ describe('PostAriaLabelDiv', () => { 'data-something': 'something', } as Props; - wrapper = mount( + renderResult = renderWithContext(

{'This is a paragraph.'}

, - mountOptions, + baseState, + { + locale: 'en', + intlMessages: enMessages, + }, ); - div = wrapper.childAt(0); + div = renderResult.container.firstChild as HTMLElement; - expect(div.prop('className')).toBe('some-class'); - expect(div.prop('data-something')).toBe('something'); - expect(div.children()).toHaveLength(1); + expect(div.className).toBe('some-class'); + expect(div.getAttribute('data-something')).toBe('something'); + expect(screen.getByText('This is a paragraph.')).toBeInTheDocument(); }); }); diff --git a/webapp/channels/src/components/post_view/post_flag_icon/__snapshots__/post_flag_icon.test.tsx.snap b/webapp/channels/src/components/post_view/post_flag_icon/__snapshots__/post_flag_icon.test.tsx.snap index 4d1a7a67c55..5ed5bae128a 100644 --- a/webapp/channels/src/components/post_view/post_flag_icon/__snapshots__/post_flag_icon.test.tsx.snap +++ b/webapp/channels/src/components/post_view/post_flag_icon/__snapshots__/post_flag_icon.test.tsx.snap @@ -1,47 +1,78 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/post_view/PostFlagIcon should match snapshot 1`] = ` - - } -> +
- +
`; exports[`components/post_view/PostFlagIcon should match snapshot 2`] = ` - - } -> +
- +
`; diff --git a/webapp/channels/src/components/post_view/post_flag_icon/post_flag_icon.test.tsx b/webapp/channels/src/components/post_view/post_flag_icon/post_flag_icon.test.tsx index a61f690d8ab..abb5ca163fa 100644 --- a/webapp/channels/src/components/post_view/post_flag_icon/post_flag_icon.test.tsx +++ b/webapp/channels/src/components/post_view/post_flag_icon/post_flag_icon.test.tsx @@ -1,11 +1,12 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import PostFlagIcon from 'components/post_view/post_flag_icon/post_flag_icon'; +import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils'; + describe('components/post_view/PostFlagIcon', () => { const baseProps = { postId: 'post_id', @@ -16,22 +17,26 @@ describe('components/post_view/PostFlagIcon', () => { }, }; - test('should match snapshot', () => { - const wrapper = shallow(); + test('should match snapshot', async () => { + const {container, rerender} = renderWithContext(); // for unflagged icon - expect(wrapper).toMatchSnapshot(); - expect(wrapper.find('button').hasClass('post-menu__item')).toBe(true); - wrapper.find('button').simulate('click', {preventDefault: jest.fn}); + expect(container).toMatchSnapshot(); + const user = userEvent.setup(); + await user.click(screen.getByRole('button', {name: /save message/i})); expect(baseProps.actions.flagPost).toHaveBeenCalledTimes(1); expect(baseProps.actions.flagPost).toHaveBeenCalledWith('post_id'); expect(baseProps.actions.unflagPost).not.toHaveBeenCalled(); // for flagged icon - wrapper.setProps({isFlagged: true}); - expect(wrapper).toMatchSnapshot(); - expect(wrapper.find('button').hasClass('post-menu__item')).toBe(true); - wrapper.find('button').simulate('click', {preventDefault: jest.fn}); + rerender( + , + ); + expect(container).toMatchSnapshot(); + await user.click(screen.getByRole('button', {name: /remove from saved/i})); expect(baseProps.actions.flagPost).toHaveBeenCalledTimes(1); expect(baseProps.actions.unflagPost).toHaveBeenCalledTimes(1); expect(baseProps.actions.unflagPost).toHaveBeenCalledWith('post_id'); diff --git a/webapp/channels/src/components/post_view/post_message_preview/__snapshots__/post_message_preview.test.tsx.snap b/webapp/channels/src/components/post_view/post_message_preview/__snapshots__/post_message_preview.test.tsx.snap index 3f1346186fc..ea1563bbf8c 100644 --- a/webapp/channels/src/components/post_view/post_message_preview/__snapshots__/post_message_preview.test.tsx.snap +++ b/webapp/channels/src/components/post_view/post_message_preview/__snapshots__/post_message_preview.test.tsx.snap @@ -1,860 +1,741 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`PostMessagePreview direct and group messages should render preview for D message 1`] = ` - +
- -
-

- -

-
+
`; exports[`PostMessagePreview direct and group messages should render preview for G message 1`] = ` - +
- -
-

- -

-
+
`; exports[`PostMessagePreview nested previews should render file preview 1`] = ` - +
- - -
-

- -

-
+
`; exports[`PostMessagePreview nested previews should render opengraph preview 1`] = ` - +
- - -
-

- -

-
+
`; exports[`PostMessagePreview should not render bot icon 1`] = ` - +
- -
-

- -

-
+
`; exports[`PostMessagePreview should render bot icon 1`] = ` - +
- -
-

- -

-
+
`; exports[`PostMessagePreview should render correctly 1`] = ` - +
- -
-

- -

-
+
`; -exports[`PostMessagePreview should render without preview 1`] = `""`; +exports[`PostMessagePreview should render without preview 1`] = `
`; exports[`PostMessagePreview show render without preview when preview posts becomes undefined after being defined 1`] = ` - +
- -
-

- -

-
+
`; -exports[`PostMessagePreview show render without preview when preview posts becomes undefined after being defined 2`] = `""`; +exports[`PostMessagePreview show render without preview when preview posts becomes undefined after being defined 2`] = `
`; diff --git a/webapp/channels/src/components/post_view/post_message_preview/post_message_preview.test.tsx b/webapp/channels/src/components/post_view/post_message_preview/post_message_preview.test.tsx index 06ef0371218..c0469d92f94 100644 --- a/webapp/channels/src/components/post_view/post_message_preview/post_message_preview.test.tsx +++ b/webapp/channels/src/components/post_view/post_message_preview/post_message_preview.test.tsx @@ -1,7 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import type {ChannelType} from '@mattermost/types/channels'; @@ -10,6 +9,8 @@ import type {UserProfile} from '@mattermost/types/users'; import {General} from 'mattermost-redux/constants'; +import {renderWithContext} from 'tests/react_testing_utils'; + import PostMessagePreview from './post_message_preview'; import type {Props} from './post_message_preview'; @@ -22,11 +23,14 @@ describe('PostMessagePreview', () => { id: 'post_id', message: 'post message', metadata: {}, + channel_id: 'channel_id', + create_at: new Date('2020-01-15T12:00:00Z').getTime(), } as Post; const user = { id: 'user_1', username: 'username1', + roles: 'system_admin', } as UserProfile; const baseProps: Props = { @@ -52,47 +56,98 @@ describe('PostMessagePreview', () => { isPostPriorityEnabled: false, }; - test('should render correctly', () => { - const wrapper = shallow(); + const baseState = { + entities: { + users: { + currentUserId: user.id, + profiles: { + [user.id]: user, + }, + }, + teams: { + currentTeamId: 'team_id', + teams: { + team_id: { + id: 'team_id', + name: 'team1', + }, + }, + }, + channels: { + channels: { + channel_id: { + id: 'channel_id', + team_id: 'team_id', + type: 'O' as ChannelType, + name: 'channel-name', + display_name: 'Channel Name', + }, + }, + }, + posts: { + posts: { + [previewPost.id]: previewPost, + }, + }, + preferences: { + myPreferences: {}, + }, + general: { + config: {}, + }, + roles: { + roles: { + system_admin: { + permissions: [], + }, + }, + }, + }, + }; - expect(wrapper).toMatchSnapshot(); + test('should render correctly', () => { + const {container} = renderWithContext(, baseState); + expect(container).toMatchSnapshot(); }); test('should render without preview', () => { - const wrapper = shallow( + const {container} = renderWithContext( , + baseState, ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('show render without preview when preview posts becomes undefined after being defined', () => { const props = {...baseProps}; - let wrapper = shallow( + let renderResult = renderWithContext( , + baseState, ); - expect(wrapper).toMatchSnapshot(); - let permalink = wrapper.find('.permalink'); - expect(permalink.length).toBe(1); + expect(renderResult.container).toMatchSnapshot(); + let permalink = renderResult.container.querySelector('.attachment--permalink'); + expect(permalink).toBeInTheDocument(); // now we'll set the preview post to undefined. This happens when the // previewed post is deleted. props.previewPost = undefined; - wrapper = shallow( + renderResult = renderWithContext( , + baseState, ); - expect(wrapper).toMatchSnapshot(); - permalink = wrapper.find('.permalink'); - expect(permalink.length).toBe(0); + expect(renderResult.container).toMatchSnapshot(); + permalink = renderResult.container.querySelector('.attachment--permalink'); + expect(permalink).not.toBeInTheDocument(); }); test('should not render bot icon', () => { @@ -111,13 +166,14 @@ describe('PostMessagePreview', () => { ...baseProps, previewPost: postPreview, }; - const wrapper = shallow( + const {container} = renderWithContext( , + baseState, ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should render bot icon', () => { @@ -137,13 +193,14 @@ describe('PostMessagePreview', () => { previewPost: postPreview, enablePostIconOverride: true, }; - const wrapper = shallow( + const {container} = renderWithContext( , + baseState, ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); describe('nested previews', () => { @@ -172,9 +229,8 @@ describe('PostMessagePreview', () => { previewPost: postPreview, }; - const wrapper = shallow(); - - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(, baseState); + expect(container).toMatchSnapshot(); }); test('should render file preview', () => { @@ -188,9 +244,8 @@ describe('PostMessagePreview', () => { previewPost: postPreview, }; - const wrapper = shallow(); - - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext(, baseState); + expect(container).toMatchSnapshot(); }); }); @@ -210,13 +265,14 @@ describe('PostMessagePreview', () => { metadata, }; - const wrapper = shallow( + const {container} = renderWithContext( , + baseState, ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); }); diff --git a/webapp/channels/src/components/post_view/show_more/__snapshots__/show_more.test.tsx.snap b/webapp/channels/src/components/post_view/show_more/__snapshots__/show_more.test.tsx.snap index 1e291e6521c..ad77aa4d8c8 100644 --- a/webapp/channels/src/components/post_view/show_more/__snapshots__/show_more.test.tsx.snap +++ b/webapp/channels/src/components/post_view/show_more/__snapshots__/show_more.test.tsx.snap @@ -1,231 +1,199 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/post_view/ShowMore should match snapshot 1`] = ` -
+
-
-

- text -

+
+
+

+ text +

+
`; exports[`components/post_view/ShowMore should match snapshot, PostAttachment on collapsed view 1`] = ` -
+
-
+
- +
- -
+
`; exports[`components/post_view/ShowMore should match snapshot, PostAttachment on expanded view 1`] = ` -
+
-
+
- +
- -
+
`; exports[`components/post_view/ShowMore should match snapshot, PostMessageView on collapsed view 1`] = ` -
+
-
+
- +
- -
+
`; exports[`components/post_view/ShowMore should match snapshot, PostMessageView on expanded view 1`] = ` -
+
-
+
- +
- -
+
`; exports[`components/post_view/ShowMore should match snapshot, PostMessageView on expanded view with compactDisplay 1`] = ` -
+
-
+
- +
- -
+
diff --git a/webapp/channels/src/components/post_view/show_more/show_more.test.tsx b/webapp/channels/src/components/post_view/show_more/show_more.test.tsx index 978008f800b..aaaad38e920 100644 --- a/webapp/channels/src/components/post_view/show_more/show_more.test.tsx +++ b/webapp/channels/src/components/post_view/show_more/show_more.test.tsx @@ -1,11 +1,12 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import ShowMore from 'components/post_view/show_more/show_more'; +import {act, renderWithContext} from 'tests/react_testing_utils'; + describe('components/post_view/ShowMore', () => { const children = (

{'text'}

); const baseProps = { @@ -19,84 +20,166 @@ describe('components/post_view/ShowMore', () => { }; test('should match snapshot', () => { - const wrapper = shallow({children}); - expect(wrapper).toMatchSnapshot(); + const {container} = renderWithContext({children}); + expect(container).toMatchSnapshot(); }); test('should match snapshot, PostMessageView on collapsed view', () => { - const wrapper = shallow(); - wrapper.setState({isOverflow: true, isCollapsed: true}); - expect(wrapper).toMatchSnapshot(); + const ref = React.createRef(); + const {container} = renderWithContext( + , + ); + act(() => { + ref.current?.setState({isOverflow: true, isCollapsed: true}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, PostMessageView on expanded view', () => { - const wrapper = shallow(); - wrapper.setState({isOverflow: true, isCollapsed: false}); - expect(wrapper).toMatchSnapshot(); + const ref = React.createRef(); + const {container} = renderWithContext( + , + ); + act(() => { + ref.current?.setState({isOverflow: true, isCollapsed: false}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, PostAttachment on collapsed view', () => { - const wrapper = shallow( + const ref = React.createRef(); + const {container} = renderWithContext( , ); - wrapper.setState({isOverflow: true, isCollapsed: true}); - expect(wrapper).toMatchSnapshot(); + act(() => { + ref.current?.setState({isOverflow: true, isCollapsed: true}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, PostAttachment on expanded view', () => { - const wrapper = shallow( + const ref = React.createRef(); + const {container} = renderWithContext( , ); - wrapper.setState({isOverflow: true, isCollapsed: false}); - expect(wrapper).toMatchSnapshot(); + act(() => { + ref.current?.setState({isOverflow: true, isCollapsed: false}); + }); + expect(container).toMatchSnapshot(); }); test('should match snapshot, PostMessageView on expanded view with compactDisplay', () => { - const wrapper = shallow( + const ref = React.createRef(); + const {container} = renderWithContext( , ); - wrapper.setState({isOverflow: true, isCollapsed: false}); - expect(wrapper).toMatchSnapshot(); + act(() => { + ref.current?.setState({isOverflow: true, isCollapsed: false}); + }); + expect(container).toMatchSnapshot(); }); test('should call checkTextOverflow', () => { - const wrapper = shallow(); - const instance = wrapper.instance() as ShowMore; - instance.checkTextOverflow = jest.fn(); + const ref = React.createRef(); + const {rerender} = renderWithContext( + , + ); + const instance = ref.current as ShowMore; + jest.spyOn(instance, 'checkTextOverflow'); expect(instance.checkTextOverflow).not.toHaveBeenCalled(); - wrapper.setProps({isRHSExpanded: true}); + rerender( + , + ); expect(instance.checkTextOverflow).toHaveBeenCalledTimes(1); - wrapper.setProps({isRHSExpanded: false}); + rerender( + , + ); expect(instance.checkTextOverflow).toHaveBeenCalledTimes(2); - wrapper.setProps({isRHSOpen: true}); + rerender( + , + ); expect(instance.checkTextOverflow).toHaveBeenCalledTimes(3); - wrapper.setProps({isRHSOpen: false}); + rerender( + , + ); expect(instance.checkTextOverflow).toHaveBeenCalledTimes(4); - wrapper.setProps({text: 'text change'}); + rerender( + , + ); expect(instance.checkTextOverflow).toHaveBeenCalledTimes(5); - wrapper.setProps({text: 'text another change'}); + rerender( + , + ); expect(instance.checkTextOverflow).toHaveBeenCalledTimes(6); - wrapper.setProps({checkOverflow: 1}); + rerender( + , + ); expect(instance.checkTextOverflow).toHaveBeenCalledTimes(7); - wrapper.setProps({checkOverflow: 1}); + rerender( + , + ); expect(instance.checkTextOverflow).toHaveBeenCalledTimes(7); }); }); diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/__snapshots__/sidebar_channel.test.tsx.snap b/webapp/channels/src/components/sidebar/sidebar_channel/__snapshots__/sidebar_channel.test.tsx.snap index 2e3cf92d36a..5dfcd16ca92 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/__snapshots__/sidebar_channel.test.tsx.snap +++ b/webapp/channels/src/components/sidebar/sidebar_channel/__snapshots__/sidebar_channel.test.tsx.snap @@ -1,193 +1,247 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/sidebar/sidebar_channel should match snapshot 1`] = ` -
  • - -
  • + `; exports[`components/sidebar/sidebar_channel should match snapshot when DM channel 1`] = ` -
  • - -
  • +
    +
  • +
    + Direct Channel +
    +
  • +
    `; exports[`components/sidebar/sidebar_channel should match snapshot when GM channel 1`] = ` -
  • - -
  • +
    +
  • +
    + Group Channel +
    +
  • +
    `; exports[`components/sidebar/sidebar_channel should match snapshot when active 1`] = ` -
  • - -
  • + `; exports[`components/sidebar/sidebar_channel should match snapshot when collapsed 1`] = ` -
  • - -
  • + `; exports[`components/sidebar/sidebar_channel should match snapshot when unread 1`] = ` -
  • - -
  • + `; diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_base_channel/__snapshots__/sidebar_base_channel.test.tsx.snap b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_base_channel/__snapshots__/sidebar_base_channel.test.tsx.snap index 003e02302d1..b58439e224c 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_base_channel/__snapshots__/sidebar_base_channel.test.tsx.snap +++ b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_base_channel/__snapshots__/sidebar_base_channel.test.tsx.snap @@ -1,137 +1,61 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/sidebar/sidebar_channel/sidebar_base_channel should match snapshot 1`] = ` - - } - label="channel_display_name" - link="/team_name/channels/" -/> +
    +
    + +
    + channel_display_name +
    +
    +
    `; exports[`components/sidebar/sidebar_channel/sidebar_base_channel should match snapshot when private channel 1`] = ` - - } - label="channel_display_name" - link="/team_name/channels/" -/> +
    +
    + +
    + channel_display_name +
    +
    +
    `; exports[`components/sidebar/sidebar_channel/sidebar_base_channel should match snapshot when shared channel 1`] = ` - - } - isSharedChannel={true} - label="channel_display_name" - link="/team_name/channels/" -/> +
    +
    + +
    + channel_display_name +
    +
    +
    `; exports[`components/sidebar/sidebar_channel/sidebar_base_channel should match snapshot when shared private channel 1`] = ` - - } - isSharedChannel={true} - label="channel_display_name" - link="/team_name/channels/" -/> +
    +
    + +
    + channel_display_name +
    +
    +
    `; diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_base_channel/sidebar_base_channel.test.tsx b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_base_channel/sidebar_base_channel.test.tsx index 85bc744a1ed..b20959aadab 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_base_channel/sidebar_base_channel.test.tsx +++ b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_base_channel/sidebar_base_channel.test.tsx @@ -1,15 +1,50 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {screen, waitFor} from '@testing-library/react'; -import {shallow} from 'enzyme'; import React from 'react'; import type {ChannelType} from '@mattermost/types/channels'; import SidebarBaseChannel from 'components/sidebar/sidebar_channel/sidebar_base_channel/sidebar_base_channel'; -import {renderWithContext, userEvent} from 'tests/react_testing_utils'; +import {renderWithContext, screen, userEvent, waitFor} from 'tests/react_testing_utils'; + +jest.mock('components/tours/onboarding_tour', () => ({ + ChannelsAndDirectMessagesTour: () => null, +})); + +jest.mock('components/sidebar/sidebar_channel/sidebar_channel_link', () => { + const React = require('react'); + + return ({label, channelLeaveHandler}: {label: string; channelLeaveHandler?: (callback: () => void) => void}) => { + const [isOpen, setIsOpen] = React.useState(false); + + return ( +
    + + {isOpen && ( +
    + +
    + )} +
    {label}
    +
    + ); + }; +}); describe('components/sidebar/sidebar_channel/sidebar_base_channel', () => { const baseProps = { @@ -38,11 +73,11 @@ describe('components/sidebar/sidebar_channel/sidebar_base_channel', () => { }; test('should match snapshot', () => { - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot when shared channel', () => { @@ -54,11 +89,11 @@ describe('components/sidebar/sidebar_channel/sidebar_base_channel', () => { }, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot when private channel', () => { @@ -70,11 +105,11 @@ describe('components/sidebar/sidebar_channel/sidebar_base_channel', () => { }, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot when shared private channel', () => { @@ -87,11 +122,11 @@ describe('components/sidebar/sidebar_channel/sidebar_base_channel', () => { }, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('expect leaveChannel to be called when leave public channel ', async () => { @@ -112,14 +147,12 @@ describe('components/sidebar/sidebar_channel/sidebar_base_channel', () => { }; renderWithContext(); + const user = userEvent.setup(); - const optionsBtn = screen.getByRole('button'); - expect(optionsBtn.classList).toContain('SidebarMenu_menuButton'); + const optionsBtn = screen.getByRole('button', {name: /channel options/i}); - await userEvent.click(optionsBtn); // open options - const leaveOption: HTMLElement = screen.getByText('Leave Channel').parentElement!; - - await userEvent.click(leaveOption); + await user.click(optionsBtn); // open options + await user.click(screen.getByRole('menuitem', {name: 'Leave Channel'})); await waitFor(() => { expect(mockfn).toHaveBeenCalledTimes(1); }); @@ -142,14 +175,12 @@ describe('components/sidebar/sidebar_channel/sidebar_base_channel', () => { }; renderWithContext(); + const user = userEvent.setup(); - const optionsBtn = screen.getByRole('button'); - expect(optionsBtn.classList).toContain('SidebarMenu_menuButton'); + const optionsBtn = screen.getByRole('button', {name: /channel options/i}); - await userEvent.click(optionsBtn); // open options - const leaveOption: HTMLElement = screen.getByText('Leave Channel').parentElement!; - - await userEvent.click(leaveOption); + await user.click(optionsBtn); // open options + await user.click(screen.getByRole('menuitem', {name: 'Leave Channel'})); await waitFor(() => { expect(mockfn).toHaveBeenCalledTimes(1); }); diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel.test.tsx b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel.test.tsx index 7c8805c4991..6f031028d7a 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel.test.tsx +++ b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel.test.tsx @@ -1,13 +1,21 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {shallow} from 'enzyme'; import React from 'react'; import type {ChannelType} from '@mattermost/types/channels'; import SidebarChannel from 'components/sidebar/sidebar_channel/sidebar_channel'; +import {renderWithContext, screen} from 'tests/react_testing_utils'; + +jest.mock('components/tours/onboarding_tour', () => ({ + ChannelsAndDirectMessagesTour: () => null, +})); + +jest.mock('components/sidebar/sidebar_channel/sidebar_direct_channel', () => () =>
    {'Direct Channel'}
    ); +jest.mock('components/sidebar/sidebar_channel/sidebar_group_channel', () => () =>
    {'Group Channel'}
    ); + describe('components/sidebar/sidebar_channel', () => { const baseProps = { channel: { @@ -46,11 +54,11 @@ describe('components/sidebar/sidebar_channel', () => { }; test('should match snapshot', () => { - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot when collapsed', () => { @@ -59,11 +67,11 @@ describe('components/sidebar/sidebar_channel', () => { isCategoryCollapsed: true, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot when unread', () => { @@ -73,11 +81,11 @@ describe('components/sidebar/sidebar_channel', () => { unreadMentions: 1, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot when active', () => { @@ -86,11 +94,11 @@ describe('components/sidebar/sidebar_channel', () => { isCurrentChannel: true, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot when DM channel', () => { @@ -102,11 +110,11 @@ describe('components/sidebar/sidebar_channel', () => { }, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should match snapshot when GM channel', () => { @@ -118,11 +126,11 @@ describe('components/sidebar/sidebar_channel', () => { }, }; - const wrapper = shallow( + const {container} = renderWithContext( , ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); test('should not be collapsed when there are unread messages', () => { @@ -132,11 +140,11 @@ describe('components/sidebar/sidebar_channel', () => { isUnread: true, }; - const wrapper = shallow( + renderWithContext( , ); - expect(wrapper.find('.expanded')).toHaveLength(1); + expect(screen.getByRole('listitem')).toHaveClass('expanded'); }); test('should not be collapsed if channel is current channel', () => { @@ -146,10 +154,10 @@ describe('components/sidebar/sidebar_channel', () => { isCurrentChannel: true, }; - const wrapper = shallow( + renderWithContext( , ); - expect(wrapper.find('.expanded')).toHaveLength(1); + expect(screen.getByRole('listitem')).toHaveClass('expanded'); }); }); diff --git a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_menu/__snapshots__/sidebar_channel_menu.test.tsx.snap b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_menu/__snapshots__/sidebar_channel_menu.test.tsx.snap index e700981c48b..8ffcc66432d 100644 --- a/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_menu/__snapshots__/sidebar_channel_menu.test.tsx.snap +++ b/webapp/channels/src/components/sidebar/sidebar_channel/sidebar_channel_menu/__snapshots__/sidebar_channel_menu.test.tsx.snap @@ -1,1402 +1,2988 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`components/sidebar/sidebar_channel/sidebar_channel_menu should match snapshot and contain correct buttons 1`] = ` -, - "class": "SidebarMenu_menuButton", - "id": "SidebarChannelMenu-Button-channel_id", - } - } - menuButtonTooltip={ - Object { - "class": "hidden-xs", - "text": "Channel options", - } - } + - - } - leadingElement={ - - } - onClick={[Function]} - /> - - } - leadingElement={ - - } - onClick={[Function]} - /> - - } - leadingElement={ - - } - onClick={[Function]} - /> - - - - - } - leadingElement={ - - } - onClick={[Function]} - /> - - } - leadingElement={ - - } - onClick={[Function]} - /> - - - } - leadingElement={ - - } - onClick={[Function]} - /> - + + +