From 96b537167c72aeb212b6a347b0f84d3e0a4e834e Mon Sep 17 00:00:00 2001 From: Ashish Dhama <16203333+AshishDhama@users.noreply.github.com> Date: Thu, 4 May 2023 11:55:01 +0530 Subject: [PATCH] [WebApp][MM-52125]: Migrate multiple enzyme unit test to testing library (#23245) * Migrate multiple enzyme unit test to testing library --- .../feature_discovery.test.tsx.snap | 137 --- .../feature_discovery.test.tsx | 252 +++-- .../components/post_emoji/post_emoji.test.tsx | 19 +- .../__snapshots__/post_markdown.test.tsx.snap | 301 ------ .../post_markdown/post_markdown.test.tsx | 131 ++- .../post_profile_picture.test.tsx.snap | 43 - .../post_profile_picture.test.tsx | 24 +- .../channel_intro_message.test.tsx.snap | 941 ------------------ .../channel_intro_message.test.tsx | 202 +++- .../widgets/loading/loading_spinner.test.tsx | 68 +- .../widgets/loading/loading_spinner.tsx | 1 + 11 files changed, 489 insertions(+), 1630 deletions(-) delete mode 100644 webapp/channels/src/components/admin_console/feature_discovery/__snapshots__/feature_discovery.test.tsx.snap delete mode 100644 webapp/channels/src/components/post_markdown/__snapshots__/post_markdown.test.tsx.snap delete mode 100644 webapp/channels/src/components/post_profile_picture/__snapshots__/post_profile_picture.test.tsx.snap delete mode 100644 webapp/channels/src/components/post_view/channel_intro_message/__snapshots__/channel_intro_message.test.tsx.snap diff --git a/webapp/channels/src/components/admin_console/feature_discovery/__snapshots__/feature_discovery.test.tsx.snap b/webapp/channels/src/components/admin_console/feature_discovery/__snapshots__/feature_discovery.test.tsx.snap deleted file mode 100644 index 024bb3b9e5..0000000000 --- a/webapp/channels/src/components/admin_console/feature_discovery/__snapshots__/feature_discovery.test.tsx.snap +++ /dev/null @@ -1,137 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`components/feature_discovery FeatureDiscovery should match snapshot 1`] = ` -
-
-
- -
-
- -
- - - - -

- -

-
-
- -
-
-`; - -exports[`components/feature_discovery FeatureDiscovery should match snapshot when is cloud environment 1`] = ` -
-
-
- -
-
- -
- - - - -

- -

-
-
- -
-
-`; - -exports[`components/feature_discovery FeatureDiscovery should match snapshot when is cloud environment and subscription is not loaded yet in redux store 1`] = ` - -`; diff --git a/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.test.tsx b/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.test.tsx index b59e778bd6..e0cd671bb3 100644 --- a/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.test.tsx +++ b/webapp/channels/src/components/admin_console/feature_discovery/feature_discovery.test.tsx @@ -2,103 +2,189 @@ // See LICENSE.txt for license information. import React from 'react'; -import {shallow} from 'enzyme'; import FeatureDiscovery from 'components/admin_console/feature_discovery/feature_discovery'; import {LicenseSkus} from 'utils/constants'; import SamlSVG from './features/images/saml_svg'; +import {renderWithIntl} from 'tests/react_testing_utils'; +import {screen, waitFor} from '@testing-library/react'; +import {Provider as ReduxProvider} from 'react-redux'; +import store from 'stores/redux_store'; +import userEvent from '@testing-library/user-event'; describe('components/feature_discovery', () => { describe('FeatureDiscovery', () => { - test('should match snapshot', () => { - const wrapper = shallow( - } - // eslint-disable-next-line @typescript-eslint/naming-convention - stats={{TOTAL_USERS: 20}} - prevTrialLicense={{IsLicensed: 'false'}} - isCloud={false} - isCloudTrial={false} - hadPrevCloudTrial={false} - isSubscriptionLoaded={true} - isPaidSubscription={false} - cloudFreeDeprecated={false} - actions={{ - getPrevTrialLicense: jest.fn(), - getCloudSubscription: jest.fn(), - openModal: jest.fn(), - }} - />, + test('should match the default state of the component when is not cloud environment', async () => { + const getPrevTrialLicense = jest.fn(); + const getCloudSubscription = jest.fn(); + const openModal = jest.fn(); + + renderWithIntl( + + } + // eslint-disable-next-line @typescript-eslint/naming-convention + stats={{TOTAL_USERS: 20}} + prevTrialLicense={{IsLicensed: 'false'}} + isCloud={false} + isCloudTrial={false} + hadPrevCloudTrial={false} + isSubscriptionLoaded={true} + isPaidSubscription={false} + cloudFreeDeprecated={false} + actions={{ + getPrevTrialLicense, + getCloudSubscription, + openModal, + }} + /> + , ); - expect(wrapper).toMatchSnapshot(); + + expect(screen.queryByText('Bar')).toBeInTheDocument(); + expect(screen.queryByText('Foo')).toBeInTheDocument(); + + expect(screen.getByRole('button', {name: 'Start trial'})).toBeInTheDocument(); + await userEvent.click(screen.getByRole('button', {name: 'Start trial'})); + await userEvent.click(screen.getByText('Mattermost Software and Services License Agreement')); + + //cloud option + expect(screen.queryByRole('button', {name: 'Try free for 30 days'})).not.toBeInTheDocument(); + + const featureLink = screen.getByTestId('featureDiscovery_secondaryCallToAction'); + + expect(featureLink).toBeInTheDocument(); + expect(featureLink).toHaveAttribute('href', 'https://test.mattermost.com/secondary/?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid='); + expect(featureLink).toHaveTextContent('Learn more'); + expect(screen.getByText('Mattermost Software and Services License Agreement')).toHaveAttribute('href', 'https://mattermost.com/pl/software-and-services-license-agreement?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid='); + expect(screen.getByText('Privacy Policy')).toHaveAttribute('href', 'https://mattermost.com/privacy-policy/?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid='); + + expect(getPrevTrialLicense).toHaveBeenCalled(); + expect(getCloudSubscription).not.toHaveBeenCalled(); + expect(openModal).not.toHaveBeenCalled(); }); - test('should match snapshot when is cloud environment', () => { - const wrapper = shallow( - } - // eslint-disable-next-line @typescript-eslint/naming-convention - stats={{TOTAL_USERS: 20}} - prevTrialLicense={{IsLicensed: 'false'}} - isCloud={true} - isCloudTrial={false} - hadPrevCloudTrial={false} - isPaidSubscription={false} - cloudFreeDeprecated={false} - isSubscriptionLoaded={true} - actions={{ - getPrevTrialLicense: jest.fn(), - openModal: jest.fn(), - getCloudSubscription: jest.fn(), - }} - />, - ); - expect(wrapper).toMatchSnapshot(); + test('should match component state when is cloud environment', async () => { + const getPrevTrialLicense = jest.fn(); + const getCloudSubscription = jest.fn(); + const openModal = jest.fn(); + + await waitFor(() => { + renderWithIntl( + + } + // eslint-disable-next-line @typescript-eslint/naming-convention + stats={{TOTAL_USERS: 20}} + prevTrialLicense={{IsLicensed: 'false'}} + isCloud={true} + isCloudTrial={false} + hadPrevCloudTrial={false} + isPaidSubscription={false} + isSubscriptionLoaded={true} + cloudFreeDeprecated={false} + actions={{ + getPrevTrialLicense, + getCloudSubscription, + openModal, + }} + /> + , + ); + }); + + // subscription is loaded, so loadingSpinner should not be visible + expect(screen.queryByTestId('loadingSpinner')).not.toBeInTheDocument(); + + expect(screen.queryByText('Bar')).toBeInTheDocument(); + expect(screen.queryByText('Foo')).toBeInTheDocument(); + + //this option is visible only when it is cloud environment + expect(screen.getByRole('button', {name: 'Try free for 30 days'})).toBeInTheDocument(); + expect(screen.getAllByText('Try free for 30 days')).toHaveLength(2); + + expect(screen.getByTestId('featureDiscovery_secondaryCallToAction')).toHaveAttribute('href', 'https://test.mattermost.com/secondary/?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid='); + + expect(screen.getByText('Privacy Policy')).toHaveAttribute('href', 'https://mattermost.com/privacy-policy/?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid='); + + const featureLink = screen.getByTestId('featureDiscovery_secondaryCallToAction'); + + expect(featureLink).toBeInTheDocument(); + expect(featureLink).toHaveAttribute('href', 'https://test.mattermost.com/secondary/?utm_source=mattermost&utm_medium=in-product&utm_content=feature_discovery&uid=&sid='); + expect(featureLink).toHaveTextContent('Learn more'); + + expect(getPrevTrialLicense).toHaveBeenCalled(); + expect(getCloudSubscription).not.toHaveBeenCalled(); + expect(openModal).not.toHaveBeenCalled(); + + expect(screen.queryByRole('button', {name: 'Start trial'})).not.toBeInTheDocument(); }); - test('should match snapshot when is cloud environment and subscription is not loaded yet in redux store', () => { - const wrapper = shallow( - } - // eslint-disable-next-line @typescript-eslint/naming-convention - stats={{TOTAL_USERS: 20}} - prevTrialLicense={{IsLicensed: 'false'}} - isCloud={true} - isCloudTrial={false} - hadPrevCloudTrial={false} - isSubscriptionLoaded={false} - cloudFreeDeprecated={false} - isPaidSubscription={false} - actions={{ - getPrevTrialLicense: jest.fn(), - openModal: jest.fn(), - getCloudSubscription: jest.fn(), - }} - />, + test('should match component state when is cloud environment and subscription is not loaded yet in redux store', () => { + const getPrevTrialLicense = jest.fn(); + const getCloudSubscription = jest.fn(); + const openModal = jest.fn(); + + renderWithIntl( + + } + // eslint-disable-next-line @typescript-eslint/naming-convention + stats={{TOTAL_USERS: 20}} + prevTrialLicense={{IsLicensed: 'false'}} + isCloud={true} + isCloudTrial={false} + hadPrevCloudTrial={false} + isSubscriptionLoaded={false} + isPaidSubscription={false} + cloudFreeDeprecated={false} + actions={{ + getPrevTrialLicense, + getCloudSubscription, + openModal, + }} + /> + , ); - expect(wrapper).toMatchSnapshot(); + + // when is cloud and subscription is not loaded yet, then only loading spinner is visible + expect(screen.getByTestId('loadingSpinner')).toBeInTheDocument(); + + expect(screen.queryByText('Bar')).not.toBeInTheDocument(); + expect(screen.queryByText('Foo')).not.toBeInTheDocument(); + + //this option is visible only when subscription is loaded and is cloud environment + expect(screen.queryByRole('button', {name: 'Try free for 30 days'})).not.toBeInTheDocument(); + + expect(screen.queryByTestId('featureDiscovery_secondaryCallToAction')).not.toBeInTheDocument(); + + expect(getPrevTrialLicense).toHaveBeenCalled(); + expect(getCloudSubscription).not.toHaveBeenCalled(); + expect(openModal).not.toHaveBeenCalled(); + + expect(screen.queryByRole('button', {name: 'Start trial'})).not.toBeInTheDocument(); }); }); }); diff --git a/webapp/channels/src/components/post_emoji/post_emoji.test.tsx b/webapp/channels/src/components/post_emoji/post_emoji.test.tsx index 5937766d6f..cb4028d693 100644 --- a/webapp/channels/src/components/post_emoji/post_emoji.test.tsx +++ b/webapp/channels/src/components/post_emoji/post_emoji.test.tsx @@ -2,9 +2,9 @@ // See LICENSE.txt for license information. import React from 'react'; -import {shallow} from 'enzyme'; import PostEmoji from './post_emoji'; +import {render, screen} from '@testing-library/react'; describe('PostEmoji', () => { const baseProps = { @@ -13,17 +13,16 @@ describe('PostEmoji', () => { }; test('should render image when imageUrl is provided', () => { - const wrapper = shallow(); + render(); - expect(wrapper.find('span').prop('style')).toMatchObject({ - backgroundImage: `url(${baseProps.imageUrl})`, - }); + expect(screen.getByTitle(':' + baseProps.name + ':')).toBeInTheDocument(); + expect(screen.getByTitle(':' + baseProps.name + ':')).toHaveStyle(`backgroundImage: url(${baseProps.imageUrl})}`); }); test('should render shortcode text within span when imageUrl is provided', () => { - const wrapper = shallow(); + render(); - expect(wrapper.find('span').text()).toBe(`:${baseProps.name}:`); + expect(screen.getByTitle(':' + baseProps.name + ':')).toHaveTextContent(`:${baseProps.name}:`); }); test('should render original text when imageUrl is empty', () => { @@ -32,9 +31,9 @@ describe('PostEmoji', () => { imageUrl: '', }; - const wrapper = shallow(); + render(); - expect(wrapper.find('span')).toHaveLength(0); - expect(wrapper.text()).toBe(`:${props.name}:`); + expect(screen.queryByTitle(':' + baseProps.name + ':')).not.toBeInTheDocument(); + expect(screen.getByText(`:${props.name}:`)).toBeInTheDocument(); }); }); diff --git a/webapp/channels/src/components/post_markdown/__snapshots__/post_markdown.test.tsx.snap b/webapp/channels/src/components/post_markdown/__snapshots__/post_markdown.test.tsx.snap deleted file mode 100644 index d6ee7dfd6a..0000000000 --- a/webapp/channels/src/components/post_markdown/__snapshots__/post_markdown.test.tsx.snap +++ /dev/null @@ -1,301 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`components/PostMarkdown plugin hooks can build upon other hook message updates 1`] = ` - -`; - -exports[`components/PostMarkdown plugin hooks can overwrite other hooks messages 1`] = ` - -`; - -exports[`components/PostMarkdown should correctly pass postId down 1`] = ` - -`; - -exports[`components/PostMarkdown should render header change properly 1`] = ` -
- , - "old": , - "strong": [Function], - "username": , - } - } - /> -
-`; - -exports[`components/PostMarkdown should render properly with a post 1`] = ` - -`; - -exports[`components/PostMarkdown should render properly with an empty post 1`] = ` - -`; - -exports[`components/PostMarkdown should render properly without group highlight on a post 1`] = ` - -`; - -exports[`components/PostMarkdown should render properly without highlight a post 1`] = ` - -`; diff --git a/webapp/channels/src/components/post_markdown/post_markdown.test.tsx b/webapp/channels/src/components/post_markdown/post_markdown.test.tsx index bb30478615..1f938cb71a 100644 --- a/webapp/channels/src/components/post_markdown/post_markdown.test.tsx +++ b/webapp/channels/src/components/post_markdown/post_markdown.test.tsx @@ -2,15 +2,15 @@ // See LICENSE.txt for license information. import React from 'react'; -import {shallow} from 'enzyme'; import {Posts} from 'mattermost-redux/constants'; import PostMarkdown from 'components/post_markdown/post_markdown'; -import Markdown from 'components/markdown'; import {TestHelper} from 'utils/test_helper'; import {Post, PostType} from '@mattermost/types/posts'; +import {screen} from '@testing-library/react'; +import {renderWithIntlAndStore} from 'tests/react_testing_utils'; describe('components/PostMarkdown', () => { const baseProps = { @@ -24,16 +24,51 @@ describe('components/PostMarkdown', () => { currentTeam: TestHelper.getTeamMock(), }; + const state = {entities: { + posts: { + posts: {}, + postsInThread: {}, + }, + channels: {}, + teams: { + teams: { + currentTeamId: {}, + }, + }, + preferences: { + myPreferences: { + }, + }, + groups: { + groups: {}, + myGroups: [], + }, + users: { + currentUserId: '', + profiles: {}, + }, + emojis: {customEmoji: {}}, + general: {config: {}, license: {}}, + }, + }; + test('should not error when rendering without a post', () => { const props = {...baseProps}; - Reflect.deleteProperty(props, 'post'); - shallow(); + Reflect.deleteProperty(props, 'post'); + renderWithIntlAndStore(, state); + + expect(screen.getByText('message')).toBeInTheDocument(); }); test('should render properly with an empty post', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + renderWithIntlAndStore( + , state); + + expect(screen.getByText('message')).toBeInTheDocument(); }); test('should render properly with a post', () => { @@ -45,13 +80,21 @@ describe('components/PostMarkdown', () => { channel_mentions: { test: { display_name: 'Test', + team_name: 'test', }, }, }, }), }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + renderWithIntlAndStore(, state); + + const link = screen.getByRole('link'); + + expect(screen.getByText('See')).toBeInTheDocument(); + expect(link).toHaveAttribute('data-channel-mention', 'test'); + expect(link).toHaveAttribute('data-channel-mention-team', 'test'); + expect(link).toHaveAttribute('href', '/test/channels/test'); + expect(link).toHaveClass('mention-link'); }); test('should render properly without highlight a post', () => { @@ -61,10 +104,21 @@ describe('components/PostMarkdown', () => { options: { mentionHighlight: false, }, - post: TestHelper.getPostMock(), + post: TestHelper.getPostMock({ + props: { + channel_mentions: { + test: { + display_name: 'Test', + team_name: 'test', + }, + }, + }, + }), }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + renderWithIntlAndStore(, state); + expect(screen.getByText('No highlight')).toBeInTheDocument(); + + expect(screen.queryByRole('link')).not.toBeInTheDocument(); }); test('should render properly without group highlight on a post', () => { @@ -78,8 +132,17 @@ describe('components/PostMarkdown', () => { }, }), }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + renderWithIntlAndStore(, state); + + const groupMention = screen.getByText('@group'); + + expect(screen.getByText('No', {exact: false})).toBeInTheDocument(); + expect(groupMention).toBeInTheDocument(); + expect(groupMention).toHaveAttribute('data-mention', 'group'); + + expect(groupMention).not.toHaveClass('mention-link'); + + expect(screen.getByText('highlight', {exact: false})).toBeInTheDocument(); }); test('should correctly pass postId down', () => { @@ -89,9 +152,8 @@ describe('components/PostMarkdown', () => { id: 'post_id', }), }; - const wrapper = shallow(); - expect(wrapper.find(Markdown).prop('postId')).toEqual(props.post.id); - expect(wrapper).toMatchSnapshot(); + renderWithIntlAndStore(, state); + expect(screen.getByText('message')).toBeInTheDocument(); }); test('should render header change properly', () => { @@ -107,13 +169,34 @@ describe('components/PostMarkdown', () => { channel_mentions: { test: { display_name: 'Test', + team_name: 'test', }, }, }, }), }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + + renderWithIntlAndStore(, state); + expect(screen.getByText('@user')).toBeInTheDocument(); + expect(screen.getByText('updated the channel header')).toBeInTheDocument(); + expect(screen.getByText('From:')).toBeInTheDocument(); + expect(screen.getByText('see')).toBeInTheDocument(); + + expect(screen.getByText('To:')).toBeInTheDocument(); + expect(screen.getByText('now')).toBeInTheDocument(); + + const testLink = screen.getAllByRole('link', {name: '~Test'}); + expect(testLink).toHaveLength(2); + + expect(testLink[0]).toHaveAttribute('data-channel-mention', 'test'); + expect(testLink[0]).toHaveAttribute('data-channel-mention-team', 'test'); + expect(testLink[0]).toHaveAttribute('href', '/test/channels/test'); + expect(screen.getAllByRole('link')[0]).toHaveClass('mention-link'); + + expect(testLink[1]).toHaveAttribute('data-channel-mention', 'test'); + expect(testLink[1]).toHaveAttribute('data-channel-mention-team', 'test'); + expect(testLink[1]).toHaveAttribute('href', '/test/channels/test'); + expect(screen.getAllByRole('link')[1]).toHaveClass('mention-link'); }); test('plugin hooks can build upon other hook message updates', () => { @@ -143,8 +226,11 @@ describe('components/PostMarkdown', () => { }, ], }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + renderWithIntlAndStore(, state); + expect(screen.queryByText('world', {exact: true})).not.toBeInTheDocument(); + + // hook message + expect(screen.getByText('hello world!')).toBeInTheDocument(); }); test('plugin hooks can overwrite other hooks messages', () => { @@ -174,7 +260,8 @@ describe('components/PostMarkdown', () => { }, ], }; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + renderWithIntlAndStore(, state); + expect(screen.queryByText('world', {exact: true})).not.toBeInTheDocument(); + expect(screen.queryByText('world!', {exact: true})).toBeInTheDocument(); }); }); diff --git a/webapp/channels/src/components/post_profile_picture/__snapshots__/post_profile_picture.test.tsx.snap b/webapp/channels/src/components/post_profile_picture/__snapshots__/post_profile_picture.test.tsx.snap deleted file mode 100644 index 0b772c4681..0000000000 --- a/webapp/channels/src/components/post_profile_picture/__snapshots__/post_profile_picture.test.tsx.snap +++ /dev/null @@ -1,43 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`components/PostProfilePicture should match snapshot, no status and post icon override specified, default props 1`] = ` - -`; - -exports[`components/PostProfilePicture should match snapshot, status and post icon override specified, default props 1`] = ` - -`; diff --git a/webapp/channels/src/components/post_profile_picture/post_profile_picture.test.tsx b/webapp/channels/src/components/post_profile_picture/post_profile_picture.test.tsx index f967770aee..9101717254 100644 --- a/webapp/channels/src/components/post_profile_picture/post_profile_picture.test.tsx +++ b/webapp/channels/src/components/post_profile_picture/post_profile_picture.test.tsx @@ -2,11 +2,11 @@ // See LICENSE.txt for license information. import React, {ComponentProps} from 'react'; -import {shallow} from 'enzyme'; import {TestHelper} from 'utils/test_helper'; import PostProfilePicture from './post_profile_picture'; +import {render, screen} from '@testing-library/react'; type Props = ComponentProps; @@ -29,25 +29,35 @@ describe('components/PostProfilePicture', () => { isBot: Boolean(user.is_bot), }; - test('should match snapshot, no status and post icon override specified, default props', () => { + test('no status and post icon override specified, default props', () => { const props: Props = baseProps; - const wrapper = shallow( + render( , ); - expect(wrapper).toMatchSnapshot(); + expect(screen.queryByLabelText('Online Icon')).not.toBeInTheDocument(); + + // no status is given, 'Offline Icon' should be in the dom as a fallback + expect(screen.getByLabelText('Offline Icon')).toBeInTheDocument(); }); - test('should match snapshot, status and post icon override specified, default props', () => { + test('status and post icon override specified, default props', () => { const props: Props = { ...baseProps, status: 'away', postIconOverrideURL: 'http://example.com/image.png', }; - const wrapper = shallow( + render( , ); - expect(wrapper).toMatchSnapshot(); + // status is given, 'Away Icon' should be in the dom + expect(screen.getByLabelText('Away Icon')).toBeInTheDocument(); + + expect(screen.queryByLabelText('Online Icon')).not.toBeInTheDocument(); + + expect(screen.queryByLabelText('Offline Icon')).not.toBeInTheDocument(); + + expect(screen.getAllByRole('img')).toHaveLength(2); }); }); diff --git a/webapp/channels/src/components/post_view/channel_intro_message/__snapshots__/channel_intro_message.test.tsx.snap b/webapp/channels/src/components/post_view/channel_intro_message/__snapshots__/channel_intro_message.test.tsx.snap deleted file mode 100644 index 0b3326fc1b..0000000000 --- a/webapp/channels/src/components/post_view/channel_intro_message/__snapshots__/channel_intro_message.test.tsx.snap +++ /dev/null @@ -1,941 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`components/post_view/ChannelIntroMessages test DEFAULT Channel should match snapshot 1`] = ` -
-

- -

-

- -

- - - - - - - -
-
-`; - -exports[`components/post_view/ChannelIntroMessages test DEFAULT Channel should match snapshot, readonly 1`] = ` -
-

- -

-

- -

-
-
-`; - -exports[`components/post_view/ChannelIntroMessages test DEFAULT Channel should match snapshot, with enable, group constrained 1`] = ` -
-

- -

-

- -

- - - - - - - - - - - - - - - -
-
-`; - -exports[`components/post_view/ChannelIntroMessages test DEFAULT Channel should match snapshot, with enableUserCreation 1`] = ` -
-

- -

-

- -

- - - - } - setHeader={ - - - - - - - } - usersLimit={10} - /> - - -
-
-`; - -exports[`components/post_view/ChannelIntroMessages test DIRECT Channel should match snapshot, with teammate 1`] = ` -
-
- -
-
- -
-

- -

- - - - - -
-`; - -exports[`components/post_view/ChannelIntroMessages test DIRECT Channel should match snapshot, without teammate 1`] = ` -
-

- -

-
-`; - -exports[`components/post_view/ChannelIntroMessages test Group Channel should match snapshot, no profiles 1`] = ` -
-

- -

-
-`; - -exports[`components/post_view/ChannelIntroMessages test Group Channel should match snapshot, with profiles 1`] = ` -
-
- - -
-

- -

- - - - - -
-`; - -exports[`components/post_view/ChannelIntroMessages test OFFTOPIC Channel should match snapshot 1`] = ` -
-

- -

-

- -

- - } - setHeader={ - - - - - - - } - usersLimit={10} - /> -
-`; - -exports[`components/post_view/ChannelIntroMessages test Open Channel should match snapshot, without boards 1`] = ` -
-

- -

-

- - , - "name": "test channel", - } - } - /> - - - - - -
-

- - } - setHeader={ - - - - - - - } - usersLimit={10} - /> -
-`; diff --git a/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.test.tsx b/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.test.tsx index c961fe10ee..23778fc4d1 100644 --- a/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.test.tsx +++ b/webapp/channels/src/components/post_view/channel_intro_message/channel_intro_message.test.tsx @@ -2,7 +2,6 @@ // See LICENSE.txt for license information. import React from 'react'; -import {shallow} from 'enzyme'; import {Constants} from 'utils/constants'; import {UserProfile} from '@mattermost/types/users'; @@ -10,6 +9,9 @@ import {UserProfile} from '@mattermost/types/users'; import {Channel, ChannelType} from '@mattermost/types/channels'; import ChannelIntroMessage from './channel_intro_message'; +import {screen} from '@testing-library/react'; +import {renderWithIntlAndStore} from 'tests/react_testing_utils'; +import {TestHelper} from 'utils/test_helper'; describe('components/post_view/ChannelIntroMessages', () => { const channel = { @@ -49,12 +51,51 @@ describe('components/post_view/ChannelIntroMessages', () => { }, }; + const initialState = { + entities: { + general: {config: {}}, + users: { + profiles: { + user1: TestHelper.getUserMock({ + id: 'user1', + username: 'my teammate', + }), + }, + }, + + roles: { + roles: {}, + }, + channels: {roles: {channel_id: ['system_user']}, + currentChannelId: 'channel_id', + myMembers: {}, + }, + teams: { + teams: {}, + }, + preferences: { + myPreferences: {}, + }, + }, + + plugins: { + components: {}, + }, + } as any; + describe('test Open Channel', () => { - test('should match snapshot, without boards', () => { - const wrapper = shallow( - , + test('should match component state, without boards', () => { + renderWithIntlAndStore( + , initialState, ); - expect(wrapper).toMatchSnapshot(); + + const beginningHeading = screen.getByText('Beginning of test channel'); + + expect(beginningHeading).toBeInTheDocument(); + expect(beginningHeading).toHaveClass('channel-intro__title'); + + expect(screen.getByText(`This is the start of the test channel channel, created by ${baseProps.creatorName} on October 17, 2017.`)); + expect(screen.getByText('Any member can join and read this channel.')).toBeInTheDocument(); }); }); @@ -68,23 +109,51 @@ describe('components/post_view/ChannelIntroMessages', () => { channel: groupChannel, }; - test('should match snapshot, no profiles', () => { - const wrapper = shallow( + test('should match component state, no profiles', () => { + renderWithIntlAndStore( , + />, initialState, ); - expect(wrapper).toMatchSnapshot(); + + expect(screen.queryByText('Beginning of test channel')).not.toBeInTheDocument(); + expect(screen.queryByText('Any member can join and read this channel.')).not.toBeInTheDocument(); + + // there are no profiles in the dom, channel type is GM_CHANNEL, teammate text should be displayed + expect(screen.getByText('This is the start of your group message history with these teammates. Messages and files shared here are not shown to people outside this area.')).toBeInTheDocument(); + + expect(screen.getByText('This is the start of your', {exact: false})).toHaveClass('channel-intro-text'); }); - test('should match snapshot, with profiles', () => { - const wrapper = shallow( + test('should match component state, with profiles', () => { + renderWithIntlAndStore( , + />, initialState, ); - expect(wrapper).toMatchSnapshot(); + + expect(screen.getByText('This is the start of your group message history with test channel', {exact: false})).toBeInTheDocument(); + + const headerDialog = screen.getByLabelText('Set a Header dialog'); + expect(headerDialog).toBeInTheDocument(); + expect(headerDialog).toHaveTextContent('Set a Header'); + expect(headerDialog).toHaveClass('style--none intro-links color--link channelIntroButton'); + + // one for user1 and one for guest + + const image = screen.getAllByAltText('user profile image'); + expect(image).toHaveLength(2); + expect(image[0]).toHaveAttribute('src', '/api/v4/users/user1/image?_=0'); + expect(image[0]).toHaveAttribute('loading', 'lazy'); + + expect(image[1]).toHaveAttribute('src', '/api/v4/users/guest1/image?_=0'); + expect(image[1]).toHaveAttribute('loading', 'lazy'); + + const editIcon = screen.getByTitle('Edit Icon'); + + expect(editIcon).toBeInTheDocument(); + expect(editIcon).toHaveClass('icon-pencil-outline'); }); }); @@ -98,24 +167,50 @@ describe('components/post_view/ChannelIntroMessages', () => { channel: directChannel, }; - test('should match snapshot, without teammate', () => { - const wrapper = shallow( + test('should match component state, without teammate', () => { + renderWithIntlAndStore( , + />, initialState, ); - expect(wrapper).toMatchSnapshot(); + + const message = screen.getByText('This is the start of your direct message history with this teammate', {exact: false}); + expect(message).toBeInTheDocument(); + expect(message).toHaveClass('channel-intro-text'); }); - test('should match snapshot, with teammate', () => { - const wrapper = shallow( + test('should match component state, with teammate', () => { + renderWithIntlAndStore( , + />, initialState, ); - expect(wrapper).toMatchSnapshot(); + expect(screen.getByText('This is the start of your direct message history with my teammate', {exact: false})).toBeInTheDocument(); + + const teammate = screen.getByLabelText('my teammate'); + + expect(teammate).toBeInTheDocument(); + expect(teammate).toHaveTextContent('my teammate'); + expect(teammate).toHaveClass('user-popover style--none'); + + const image = screen.getByRole('img'); + + expect(image).toBeInTheDocument(); + expect(image).toHaveAttribute('src', '/api/v4/users/user1/image?_=0'); + expect(image).toHaveAttribute('loading', 'lazy'); + + const headerDialog = screen.getByLabelText('Set a Header dialog'); + + expect(headerDialog).toBeInTheDocument(); + expect(headerDialog).toHaveTextContent('Set a Header'); + expect(headerDialog).toHaveClass('style--none intro-links color--link channelIntroButton'); + + const editIcon = screen.getByTitle('Edit Icon'); + + expect(editIcon).toBeInTheDocument(); + expect(editIcon).toHaveClass('icon-pencil-outline'); }); }); @@ -130,66 +225,67 @@ describe('components/post_view/ChannelIntroMessages', () => { channel: directChannel, }; - test('should match snapshot, readonly', () => { - const wrapper = shallow( + test('should match component state, readonly', () => { + renderWithIntlAndStore( , + />, initialState, ); - expect(wrapper).toMatchSnapshot(); + + const beginningHeading = screen.getByText('Beginning of test channel'); + + expect(beginningHeading).toBeInTheDocument(); + expect(beginningHeading).toHaveClass('channel-intro__title'); + + expect(screen.getByText('Welcome to test channel!')).toBeInTheDocument(); + expect(screen.getByText('Messages can only be posted by system admins. Everyone automatically becomes a permanent member of this channel when they join the team.', {exact: false})).toBeInTheDocument(); }); - test('should match snapshot', () => { - const wrapper = shallow( + test('should match component state without any permission', () => { + renderWithIntlAndStore( , + />, initialState, ); - expect(wrapper).toMatchSnapshot(); - }); - test('should match snapshot, with enableUserCreation', () => { - const wrapper = shallow( - , - ); - expect(wrapper).toMatchSnapshot(); - }); + //no permission is given, invite link should not be in the dom + expect(screen.queryByText('Add other groups to this team')).not.toBeInTheDocument(); - test('should match snapshot, with enable, group constrained', () => { - const wrapper = shallow( - , - ); - expect(wrapper).toMatchSnapshot(); + const beginningHeading = screen.getByText('Beginning of test channel'); + + expect(beginningHeading).toBeInTheDocument(); + expect(beginningHeading).toHaveClass('channel-intro__title'); + expect(screen.getByText('Welcome to test channel!')).toBeInTheDocument(); + expect(screen.getByText('Post messages here that you want everyone to see. Everyone automatically becomes a permanent member of this channel when they join the team.', {exact: false})).toBeInTheDocument(); }); }); - describe('test OFFTOPIC Channel', () => { + describe('test OFF TOPIC Channel', () => { const directChannel = { ...channel, type: Constants.OPEN_CHANNEL as ChannelType, name: Constants.OFFTOPIC_CHANNEL, + display_name: Constants.OFFTOPIC_CHANNEL, }; const props = { ...baseProps, channel: directChannel, }; - test('should match snapshot', () => { - const wrapper = shallow( + test('should match component state', () => { + renderWithIntlAndStore( , + />, initialState, ); - expect(wrapper).toMatchSnapshot(); + expect(screen.getByText('Beginning of off-topic')).toBeInTheDocument(); + screen.getByText('This is the start of off-topic, a channel for non-work-related conversations.'); + expect(screen.getByText('This is the start of off-topic, a channel for non-work-related conversations.')).toHaveClass('channel-intro__content'); + + // stats.total_users_count is not specified, loading icon should be in the dom + screen.getByTitle('Loading Icon'); }); }); }); diff --git a/webapp/channels/src/components/widgets/loading/loading_spinner.test.tsx b/webapp/channels/src/components/widgets/loading/loading_spinner.test.tsx index 3fe761cd5c..e0f6213a2b 100644 --- a/webapp/channels/src/components/widgets/loading/loading_spinner.test.tsx +++ b/webapp/channels/src/components/widgets/loading/loading_spinner.test.tsx @@ -10,42 +10,44 @@ describe('components/widgets/loadingLoadingSpinner', () => { test('showing spinner with text', () => { const wrapper = shallow(); expect(wrapper).toMatchInlineSnapshot(` - - - test - -`); + + + test + + `); }); test('showing spinner without text', () => { const wrapper = shallow(); expect(wrapper).toMatchInlineSnapshot(` - - - -`); + + + + `); }); }); diff --git a/webapp/channels/src/components/widgets/loading/loading_spinner.tsx b/webapp/channels/src/components/widgets/loading/loading_spinner.tsx index 8280fb7dda..f9089f8fa4 100644 --- a/webapp/channels/src/components/widgets/loading/loading_spinner.tsx +++ b/webapp/channels/src/components/widgets/loading/loading_spinner.tsx @@ -23,6 +23,7 @@ export default class LoadingSpinner extends React.PureComponent { id='loadingSpinner' className={'LoadingSpinner' + (this.props.text ? ' with-text' : '')} style={this.props.style} + data-testid='loadingSpinner' >