diff --git a/app/components/draft/__snapshots__/draft.test.tsx.snap b/app/components/draft/__snapshots__/draft.test.tsx.snap new file mode 100644 index 0000000000..46ae0cc841 --- /dev/null +++ b/app/components/draft/__snapshots__/draft.test.tsx.snap @@ -0,0 +1,1102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Draft should match the file count 1`] = ` + + + + + + + + + + + Direct Message Channel + + + + + + + + + + + + Hello, World! + + + + + + + + + + + + + + + + + + + file1.txt + + + + + 64 B + + + + + + + + + + + + + + + + + + file2.pdf + + + + + 64 B + + + + + + + + + + + +`; + +exports[`Draft should render the draft with channel info and draft message 1`] = ` + + + + + + + + + + + Direct Message Channel + + + + + + + + + + + + Hello, World! + + + + + + + + + + +`; + +exports[`Draft should render the draft with channel info and draft message for a thread 1`] = ` + + + + + + + + + + + Direct Message Channel + + + + + + + + + + + + Hello, World! + + + + + + + + + + +`; + +exports[`Draft should render the draft with post priority 1`] = ` + + + + + + + + + + + Direct Message Channel + + + + + + + + IMPORTANT + + + + + + + + + + + + + Hello, World! + + + + + + + + + + +`; diff --git a/app/components/draft/draft.test.tsx b/app/components/draft/draft.test.tsx new file mode 100644 index 0000000000..42b579d883 --- /dev/null +++ b/app/components/draft/draft.test.tsx @@ -0,0 +1,190 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import CompassIcon from '@components/compass_icon'; +import FormattedText from '@components/formatted_text'; +import {General} from '@constants'; +import {renderWithEverything} from '@test/intl-test-helper'; +import TestHelper from '@test/test_helper'; + +import Draft from './draft'; + +import type {Database} from '@nozbe/watermelondb'; +import type ChannelModel from '@typings/database/models/servers/channel'; +import type DraftModel from '@typings/database/models/servers/draft'; + +jest.mock('@components/formatted_text', () => jest.fn(() => null)); +jest.mock('@components/formatted_time', () => jest.fn(() => null)); +jest.mock('@components/compass_icon', () => jest.fn(() => null)); + +describe('Draft', () => { + let database: Database; + + beforeAll(async () => { + const server = await TestHelper.setupServerDatabase(); + database = server.database; + }); + it('should render the draft with channel info and draft message', () => { + const props = { + channel: {type: General.OPEN_CHANNEL, displayName: 'Direct Message Channel'} as ChannelModel, + location: 'channel', + draft: { + updateAt: 1633024800000, + message: 'Hello, World!', + channelId: 'channel_id', + rootId: '', + files: [], + metadata: {}, + } as unknown as DraftModel, + layoutWidth: 100, + isPostPriorityEnabled: false, + }; + const wrapper = renderWithEverything( + + , {database}, + ); + + const {getByText} = wrapper; + + expect(FormattedText).toHaveBeenCalledWith( + expect.objectContaining({ + id: 'channel_info.draft_in_channel', + defaultMessage: 'In:', + }), + expect.anything(), + ); + expect(CompassIcon).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'globe', + }), + expect.anything(), + ); + expect(getByText('Hello, World!')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('should match the file count', () => { + const props = { + channel: {type: General.OPEN_CHANNEL, displayName: 'Direct Message Channel'} as ChannelModel, + location: 'channel', + draft: { + updateAt: 1633024800000, + message: 'Hello, World!', + channelId: 'channel_id', + rootId: '', + files: [{ + has_preview_image: false, + height: 0, + name: 'file1.txt', + extension: 'txt', + size: 64, + }, { + has_preview_image: false, + height: 0, + name: 'file2.pdf', + extension: 'txt', + size: 64, + }], + metadata: {}, + } as unknown as DraftModel, + layoutWidth: 100, + isPostPriorityEnabled: false, + }; + const wrapper = renderWithEverything( + + , {database}, + ); + const {getAllByTestId} = wrapper; + expect(getAllByTestId('file_attachment')).toHaveLength(2); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('should render the draft with channel info and draft message for a thread', () => { + const props = { + channel: {type: General.OPEN_CHANNEL, displayName: 'Direct Message Channel'} as ChannelModel, + location: 'thread', + draft: { + updateAt: 1633024800000, + message: 'Hello, World!', + channelId: 'channel_id', + rootId: 'root_id', + files: [], + metadata: {}, + } as unknown as DraftModel, + layoutWidth: 100, + isPostPriorityEnabled: false, + }; + const wrapper = renderWithEverything( + + , {database}, + ); + + const {getByText} = wrapper; + expect(FormattedText).toHaveBeenCalledWith( + expect.objectContaining({ + id: 'channel_info.thread_in', + defaultMessage: 'Thread in:', + }), + expect.anything(), + ); + + expect(CompassIcon).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'globe', + }), + expect.anything(), + ); + expect(getByText('Hello, World!')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('should render the draft with post priority', () => { + const props = { + channel: {type: General.OPEN_CHANNEL, displayName: 'Direct Message Channel'} as ChannelModel, + location: 'thread', + draft: { + updateAt: 1633024800000, + message: 'Hello, World!', + channelId: 'channel_id', + rootId: 'root_id', + files: [], + metadata: {priority: {priority: 'important', requested_ack: false}}, + } as unknown as DraftModel, + layoutWidth: 100, + isPostPriorityEnabled: true, + }; + const wrapper = renderWithEverything( + + , {database}, + ); + const {getByText} = wrapper; + expect(getByText('IMPORTANT')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/components/draft/draft_post/__snapshots__/draft_message.test.tsx.snap b/app/components/draft/draft_post/__snapshots__/draft_message.test.tsx.snap new file mode 100644 index 0000000000..bb98c07a3d --- /dev/null +++ b/app/components/draft/draft_post/__snapshots__/draft_message.test.tsx.snap @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Draft Message should match snapshot 1`] = ` + + + + + + + + Hello, World! + + + + + + + +`; diff --git a/app/components/draft/draft_post/__snapshots__/draft_post.test.tsx.snap b/app/components/draft/draft_post/__snapshots__/draft_post.test.tsx.snap new file mode 100644 index 0000000000..6b951f3879 --- /dev/null +++ b/app/components/draft/draft_post/__snapshots__/draft_post.test.tsx.snap @@ -0,0 +1,72 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Draft Post should match the snapshot 1`] = ` + + + + + + + + + Hello, World! + + + + + + + + +`; diff --git a/app/components/draft/draft_post/draft_message.test.tsx b/app/components/draft/draft_post/draft_message.test.tsx new file mode 100644 index 0000000000..445d2c13e4 --- /dev/null +++ b/app/components/draft/draft_post/draft_message.test.tsx @@ -0,0 +1,59 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {renderWithEverything} from '@test/intl-test-helper'; +import TestHelper from '@test/test_helper'; + +import DraftMessage from './draft_message'; + +import type {Database} from '@nozbe/watermelondb'; +import type DraftModel from '@typings/database/models/servers/draft'; + +describe('Draft Message', () => { + let database: Database; + + beforeAll(async () => { + const server = await TestHelper.setupServerDatabase(); + database = server.database; + }); + it('should render the message', () => { + const props = { + draft: { + updateAt: 1633024800000, + message: 'Hello, World!', + channelId: 'channel_id', + rootId: '', + files: [], + metadata: {}, + } as unknown as DraftModel, + layoutWidth: 100, + location: 'draft', + }; + const {getByText} = renderWithEverything( + , {database}, + ); + expect(getByText('Hello, World!')).toBeTruthy(); + }); + + it('should match snapshot', () => { + const props = { + draft: { + updateAt: 1633024800000, + message: 'Hello, World!', + channelId: 'channel_id', + rootId: '', + files: [], + metadata: {}, + } as unknown as DraftModel, + layoutWidth: 100, + location: 'draft', + }; + const wrapper = renderWithEverything( + , {database}, + ); + + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/components/draft/draft_post/draft_post.test.tsx b/app/components/draft/draft_post/draft_post.test.tsx new file mode 100644 index 0000000000..0151e62912 --- /dev/null +++ b/app/components/draft/draft_post/draft_post.test.tsx @@ -0,0 +1,40 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {renderWithEverything} from '@test/intl-test-helper'; +import TestHelper from '@test/test_helper'; + +import DraftPost from '.'; + +import type {Database} from '@nozbe/watermelondb'; +import type DraftModel from '@typings/database/models/servers/draft'; + +describe('Draft Post', () => { + let database: Database; + + beforeAll(async () => { + const server = await TestHelper.setupServerDatabase(); + database = server.database; + }); + it('should match the snapshot', () => { + const props = { + draft: { + updateAt: 1633024800000, + message: 'Hello, World!', + channelId: 'channel_id', + rootId: '', + files: [], + metadata: {}, + } as unknown as DraftModel, + layoutWidth: 100, + location: 'draft', + }; + const wrapper = renderWithEverything( + , {database}, + ); + + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/components/draft_post_header/__snapshots__/channel_info.test.tsx.snap b/app/components/draft_post_header/__snapshots__/channel_info.test.tsx.snap new file mode 100644 index 0000000000..d7e92523bf --- /dev/null +++ b/app/components/draft_post_header/__snapshots__/channel_info.test.tsx.snap @@ -0,0 +1,324 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DraftPostHeader Component renders CompassIcon when draftReceiverUser is not provided 1`] = ` + + + + + + + + + Direct Message Channel + + + +`; + +exports[`DraftPostHeader Component renders correctly for a DM channel 1`] = ` + + + + + + + + + Direct Message Channel + + + +`; + +exports[`DraftPostHeader Component renders correctly for a public channel 1`] = ` + + + + + + + + + Public Channel + + + +`; + +exports[`DraftPostHeader Component renders correctly for a thread 1`] = ` + + + + + + + + + Direct Message Channel + + + +`; + +exports[`DraftPostHeader Component renders the Avatar when draftReceiverUser is provided 1`] = ` + + + + + + + Direct Message Channel + + + +`; diff --git a/app/components/draft_post_header/__snapshots__/profile_avatar.test.tsx.snap b/app/components/draft_post_header/__snapshots__/profile_avatar.test.tsx.snap new file mode 100644 index 0000000000..706c7472ec --- /dev/null +++ b/app/components/draft_post_header/__snapshots__/profile_avatar.test.tsx.snap @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ProfileAvatar Component renders the avatar image when URI is available 1`] = ` + + + +`; + +exports[`ProfileAvatar Component renders the fallback icon when URI is not available 1`] = ` + + + +`; + +exports[`ProfileAvatar Component renders the fallback icon when author is not provided 1`] = ` + + + +`; diff --git a/app/components/draft_post_header/channel_info.test.tsx b/app/components/draft_post_header/channel_info.test.tsx new file mode 100644 index 0000000000..2c1dab5d57 --- /dev/null +++ b/app/components/draft_post_header/channel_info.test.tsx @@ -0,0 +1,164 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {render} from '@testing-library/react-native'; +import React from 'react'; + +import CompassIcon from '@components/compass_icon'; +import FormattedText from '@components/formatted_text'; +import FormattedTime from '@components/formatted_time'; +import {General} from '@constants'; +import {useTheme} from '@context/theme'; +import {getUserTimezone} from '@utils/user'; + +import DraftPostHeader from './draft_post_header'; +import ProfileAvatar from './profile_avatar'; + +import type ChannelModel from '@typings/database/models/servers/channel'; +import type UserModel from '@typings/database/models/servers/user'; + +jest.mock('@context/theme', () => ({ + useTheme: jest.fn(), +})); + +jest.mock('@components/formatted_text', () => jest.fn(() => null)); +jest.mock('@components/formatted_time', () => jest.fn(() => null)); +jest.mock('./profile_avatar', () => jest.fn(() => null)); +jest.mock('@components/compass_icon', () => jest.fn(() => null)); +jest.mock('@utils/user', () => ({ + getUserTimezone: jest.fn(), +})); + +describe('DraftPostHeader Component', () => { + const mockTheme = { + centerChannelColor: '#000000', + }; + + beforeEach(() => { + jest.clearAllMocks(); + (useTheme as jest.Mock).mockReturnValue(mockTheme); + (getUserTimezone as jest.Mock).mockReturnValue('UTC'); + }); + + it('renders correctly for a DM channel', () => { + const baseProps = { + channel: {type: General.DM_CHANNEL, displayName: 'Direct Message Channel'} as ChannelModel, + draftReceiverUser: undefined, + updateAt: 1633024800000, + rootId: undefined, + testID: 'channel-info', + currentUser: {timezone: 'UTC'} as unknown as UserModel, + isMilitaryTime: true, + }; + + const wrapper = render(); + expect(CompassIcon).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'globe', + }), + expect.anything(), + ); + expect(FormattedTime).toHaveBeenCalledWith( + expect.objectContaining({ + timezone: 'UTC', + isMilitaryTime: true, + value: 1633024800000, + }), + expect.anything(), + ); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('renders correctly for a public channel', () => { + const baseProps = { + channel: {type: General.OPEN_CHANNEL, displayName: 'Public Channel', createAt: 0, creatorId: '', deleteAt: 0, updateAt: 0} as ChannelModel, + draftReceiverUser: undefined, + updateAt: 1633024800000, + rootId: undefined, + testID: 'channel-info', + currentUser: {timezone: 'UTC'} as unknown as UserModel, + isMilitaryTime: true, + }; + const wrapper = render(); + expect(FormattedText).toHaveBeenCalledWith( + expect.objectContaining({ + id: 'channel_info.draft_in_channel', + defaultMessage: 'In:', + }), + expect.anything(), + ); + expect(CompassIcon).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'globe', + }), + expect.anything(), + ); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('renders correctly for a thread', () => { + const baseProps = { + channel: {type: General.DM_CHANNEL, displayName: 'Direct Message Channel'} as ChannelModel, + draftReceiverUser: undefined, + updateAt: 1633024800000, + rootId: 'root-post-id', + testID: 'channel-info', + currentUser: {timezone: 'UTC'} as unknown as UserModel, + isMilitaryTime: true, + }; + const wrapper = render(); + const {getByTestId} = wrapper; + + expect(useTheme).toHaveBeenCalled(); + expect(getByTestId('channel-info')).toBeTruthy(); + expect(FormattedText).toHaveBeenCalledWith( + expect.objectContaining({ + id: 'channel_info.thread_in', + defaultMessage: 'Thread in:', + }), + expect.anything(), + ); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('renders the Avatar when draftReceiverUser is provided', () => { + const baseProps = { + channel: {type: General.DM_CHANNEL, displayName: 'Direct Message Channel'} as ChannelModel, + draftReceiverUser: {id: 'user-id', username: 'JohnDoe'} as UserModel, + updateAt: 1633024800000, + rootId: undefined, + testID: 'channel-info', + currentUser: {timezone: 'UTC'} as unknown as UserModel, + isMilitaryTime: true, + }; + const wrapper = render(); + + expect(ProfileAvatar).toHaveBeenCalledWith( + expect.objectContaining({ + author: baseProps.draftReceiverUser, + }), + expect.anything(), + ); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('renders CompassIcon when draftReceiverUser is not provided', () => { + const baseProps = { + channel: {type: General.DM_CHANNEL, displayName: 'Direct Message Channel'} as ChannelModel, + draftReceiverUser: undefined, + updateAt: 1633024800000, + rootId: undefined, + testID: 'channel-info', + currentUser: {timezone: 'UTC'} as unknown as UserModel, + isMilitaryTime: true, + }; + const wrapper = render(); + expect(CompassIcon).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'globe', + }), + expect.anything(), + ); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/components/draft_post_header/profile_avatar.test.tsx b/app/components/draft_post_header/profile_avatar.test.tsx new file mode 100644 index 0000000000..d33e3d6e5d --- /dev/null +++ b/app/components/draft_post_header/profile_avatar.test.tsx @@ -0,0 +1,86 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +import {render} from '@testing-library/react-native'; +import React from 'react'; + +import ProfileAvatar from './profile_avatar'; + +import type UserModel from '@typings/database/models/servers/user'; + +jest.mock('@actions/remote/user', () => ({ + buildProfileImageUrlFromUser: jest.fn(), +})); + +jest.mock('@actions/remote/file', () => ({ + buildAbsoluteUrl: jest.fn(), +})); + +jest.mock('@context/server', () => ({ + useServerUrl: jest.fn(), +})); + +const mockBuildAbsoluteUrl = require('@actions/remote/file').buildAbsoluteUrl; +const mockBuildProfileImageUrlFromUser = require('@actions/remote/user').buildProfileImageUrlFromUser; +const mockUseServerUrl = require('@context/server').useServerUrl; + +describe('ProfileAvatar Component', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders the avatar image when URI is available', () => { + const mockServerUrl = 'base.url.com'; + const mockUri = '/api/v4/users/mock-user-id/image'; + const mockAuthor = {id: 'mock-user-id'} as UserModel; + + mockUseServerUrl.mockReturnValue(mockServerUrl); + mockBuildProfileImageUrlFromUser.mockImplementation((_: string, author: UserModel) => { + return author ? mockUri : ''; + }); + mockBuildAbsoluteUrl.mockImplementation((serverUrl: string, uri: string) => `${serverUrl}${uri}`); + + const wrapper = render(); + const {queryByTestId} = wrapper; + + expect(mockBuildProfileImageUrlFromUser).toHaveBeenCalledWith(mockServerUrl, mockAuthor); + expect(mockBuildAbsoluteUrl).toHaveBeenCalledWith(mockServerUrl, mockUri); + + expect(queryByTestId('avatar-icon')).toBeNull(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('renders the fallback icon when URI is not available', () => { + const mockServerUrl = 'base.url.com'; + const mockAuthor = {id: 'mock-user-id'} as UserModel; + + mockUseServerUrl.mockReturnValue(mockServerUrl); + mockBuildProfileImageUrlFromUser.mockReturnValue(''); + mockBuildAbsoluteUrl.mockReturnValue(''); + const wrapper = render(); + const {getByTestId, queryByTestId} = wrapper; + + expect(mockBuildProfileImageUrlFromUser).toHaveBeenCalledWith(mockServerUrl, mockAuthor); + expect(mockBuildAbsoluteUrl).not.toHaveBeenCalled(); + + const icon = getByTestId('avatar-icon'); + expect(icon.props.name).toBe('account-outline'); + expect(queryByTestId('avatar-image')).toBeNull(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('renders the fallback icon when author is not provided', () => { + const mockServerUrl = 'base.url.com'; + + mockUseServerUrl.mockReturnValue(mockServerUrl); + const wrapper = render(); + const {getByTestId, queryByTestId} = wrapper; + + expect(mockBuildProfileImageUrlFromUser).toHaveBeenCalled(); + expect(mockBuildAbsoluteUrl).not.toHaveBeenCalled(); + + const icon = getByTestId('avatar-icon'); + expect(icon.props.name).toBe('account-outline'); + expect(queryByTestId('avatar-image')).toBeNull(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/components/draft_post_header/profile_avatar.tsx b/app/components/draft_post_header/profile_avatar.tsx index db36bad66b..f1513ac1fc 100644 --- a/app/components/draft_post_header/profile_avatar.tsx +++ b/app/components/draft_post_header/profile_avatar.tsx @@ -43,6 +43,7 @@ const ProfileAvatar = ({ if (uri) { picture = ( @@ -50,6 +51,7 @@ const ProfileAvatar = ({ } else { picture = ( + + + + Drafts + + + + + 5 + + + + +`; + +exports[`Drafts Button should render the drafts button component 1`] = ` + + + + + Drafts + + + + + 1 + + + + +`; + +exports[`Drafts Button should render the drafts button component with drafts count 1`] = ` + + + + + Drafts + + + + + 23 + + + + +`; diff --git a/app/components/drafts_buttton/drafts_button.test.tsx b/app/components/drafts_buttton/drafts_button.test.tsx new file mode 100644 index 0000000000..e6c38f9bdd --- /dev/null +++ b/app/components/drafts_buttton/drafts_button.test.tsx @@ -0,0 +1,52 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {fireEvent} from '@testing-library/react-native'; +import React from 'react'; + +import {switchToGlobalDrafts} from '@actions/local/draft'; +import {renderWithIntl} from '@test/intl-test-helper'; + +import DraftsButton from './drafts_button'; + +jest.mock('@actions/local/draft', () => ({ + switchToGlobalDrafts: jest.fn(), +})); +describe('Drafts Button', () => { + it('should render the drafts button component', () => { + const wrapper = renderWithIntl( + , + ); + + const {getByText} = wrapper; + expect(getByText('Drafts')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('should render the drafts button component with drafts count', () => { + const wrapper = renderWithIntl( + , + ); + + const {getByText} = wrapper; + expect(getByText('Drafts')).toBeTruthy(); + expect(getByText('23')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('calls switchToGlobalDrafts when pressed', () => { + const wrapper = renderWithIntl( + , + ); + const {getByTestId} = wrapper; + fireEvent.press(getByTestId('channel_list.drafts.button')); + expect(switchToGlobalDrafts).toHaveBeenCalledTimes(1); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/components/files/files.tsx b/app/components/files/files.tsx index 1006393637..ffdece6f1e 100644 --- a/app/components/files/files.tsx +++ b/app/components/files/files.tsx @@ -92,6 +92,7 @@ const Files = ({canDownloadFiles, failed, filesInfo, isReplyPost, layoutWidth, l + + + Delete draft + + +`; + +exports[`DeleteDraft should render the component 1`] = ` + + + + Delete draft + + +`; diff --git a/app/screens/draft_options/__snapshots__/draft_options.test.tsx.snap b/app/screens/draft_options/__snapshots__/draft_options.test.tsx.snap new file mode 100644 index 0000000000..090ab7cb76 --- /dev/null +++ b/app/screens/draft_options/__snapshots__/draft_options.test.tsx.snap @@ -0,0 +1,793 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Draft Options should render the draft options 1`] = ` +[ + , + + + + + + + + + Draft actions + + + + + Edit draft + + + + + + Send draft + + + + + + Delete draft + + + + + + + + + + + + + , +] +`; + +exports[`Draft Options should render the draft options component 1`] = ` +[ + , + + + + + + + + + Draft actions + + + + + Edit draft + + + + + + Send draft + + + + + + Delete draft + + + + + + + + + + + + + , +] +`; diff --git a/app/screens/draft_options/__snapshots__/edit_draft.test.tsx.snap b/app/screens/draft_options/__snapshots__/edit_draft.test.tsx.snap new file mode 100644 index 0000000000..1fb97ef14c --- /dev/null +++ b/app/screens/draft_options/__snapshots__/edit_draft.test.tsx.snap @@ -0,0 +1,127 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Edit Draft Should call editHandler when pressed 1`] = ` + + + + Edit draft + + +`; + +exports[`Edit Draft Should render the Edit draft component 1`] = ` + + + + Edit draft + + +`; diff --git a/app/screens/draft_options/__snapshots__/send_draft.test.tsx.snap b/app/screens/draft_options/__snapshots__/send_draft.test.tsx.snap new file mode 100644 index 0000000000..ca3528993a --- /dev/null +++ b/app/screens/draft_options/__snapshots__/send_draft.test.tsx.snap @@ -0,0 +1,125 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Send Draft should call dismissBottmSheet after sending the draft 1`] = ` + + + + Send draft + + +`; + +exports[`Send Draft should render the component 1`] = ` + + + + Send draft + + +`; diff --git a/app/screens/draft_options/delete_draft.test.tsx b/app/screens/draft_options/delete_draft.test.tsx new file mode 100644 index 0000000000..d892a99070 --- /dev/null +++ b/app/screens/draft_options/delete_draft.test.tsx @@ -0,0 +1,44 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {Screens} from '@constants'; +import {dismissBottomSheet} from '@screens/navigation'; +import {fireEvent, renderWithIntlAndTheme} from '@test/intl-test-helper'; + +import DeleteDraft from './delete_draft'; + +jest.mock('@screens/navigation', () => ({ + dismissBottomSheet: jest.fn(), +})); + +describe('DeleteDraft', () => { + it('should render the component', () => { + const wrapper = renderWithIntlAndTheme( + , + ); + const {getByText, getByTestId} = wrapper; + expect(getByText('Delete draft')).toBeTruthy(); + expect(getByTestId('trash-can-outline-icon')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('calls draftDeleteHandler when pressed', () => { + const wrapper = renderWithIntlAndTheme( + , + ); + const {getByTestId} = wrapper; + fireEvent.press(getByTestId('trash-can-outline-icon')); + expect(dismissBottomSheet).toHaveBeenCalledTimes(1); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/screens/draft_options/delete_draft.tsx b/app/screens/draft_options/delete_draft.tsx index 3b1bdfd0a7..f7a4ca27ad 100644 --- a/app/screens/draft_options/delete_draft.tsx +++ b/app/screens/draft_options/delete_draft.tsx @@ -66,6 +66,7 @@ const DeleteDraft: React.FC = ({ > diff --git a/app/screens/draft_options/draft_options.test.tsx b/app/screens/draft_options/draft_options.test.tsx new file mode 100644 index 0000000000..2f7a43bdc8 --- /dev/null +++ b/app/screens/draft_options/draft_options.test.tsx @@ -0,0 +1,71 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {renderWithEverything} from '@test/intl-test-helper'; +import TestHelper from '@test/test_helper'; + +import DraftOptions from '.'; + +import type {Database} from '@nozbe/watermelondb'; +import type ChannelModel from '@typings/database/models/servers/channel'; +import type DraftModel from '@typings/database/models/servers/draft'; +describe('Draft Options', () => { + let database: Database; + + beforeAll(async () => { + const server = await TestHelper.setupServerDatabase(); + database = server.database; + }); + it('should render the draft options component', () => { + const props = { + channel: { + id: 'channel_id', + teamId: 'team_id', + } as unknown as ChannelModel, + rootId: '', + draft: { + updateAt: 1633024800000, + message: 'Hello, World!', + channelId: 'channel_id', + rootId: '', + files: [], + metadata: {}, + } as unknown as DraftModel, + draftReceiverUserName: undefined, + }; + const wrapper = renderWithEverything( + , {database}, + ); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('should render the draft options', () => { + const props = { + channel: { + id: 'channel_id', + teamId: 'team_id', + } as unknown as ChannelModel, + rootId: '', + draft: { + updateAt: 1633024800000, + message: 'Hello, World!', + channelId: 'channel_id', + rootId: '', + files: [], + metadata: {}, + } as unknown as DraftModel, + draftReceiverUserName: 'username', + }; + const wrapper = renderWithEverything( + , {database}, + ); + const {getByText} = wrapper; + expect(getByText('Draft actions')).toBeTruthy(); + expect(getByText('Edit draft')).toBeTruthy(); + expect(getByText('Send draft')).toBeTruthy(); + expect(getByText('Delete draft')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/screens/draft_options/edit_draft.test.tsx b/app/screens/draft_options/edit_draft.test.tsx new file mode 100644 index 0000000000..15d4d09ae9 --- /dev/null +++ b/app/screens/draft_options/edit_draft.test.tsx @@ -0,0 +1,54 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {Screens} from '@constants'; +import {dismissBottomSheet} from '@screens/navigation'; +import {fireEvent, renderWithIntlAndTheme} from '@test/intl-test-helper'; + +import EditDraft from './edit_draft'; + +import type ChannelModel from '@typings/database/models/servers/channel'; + +jest.mock('@screens/navigation', () => ({ + dismissBottomSheet: jest.fn(), +})); + +describe('Edit Draft', () => { + it('Should render the Edit draft component', () => { + const props = { + bottomSheetId: Screens.DRAFT_OPTIONS, + channel: { + id: 'channel_id', + teamId: 'team_id', + } as ChannelModel, + rootId: 'root_id', + }; + const wrapper = renderWithIntlAndTheme( + , + ); + const {getByTestId, getByText} = wrapper; + expect(getByTestId('pencil-outline-icon')).toBeTruthy(); + expect(getByText('Edit draft')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('Should call editHandler when pressed', () => { + const props = { + bottomSheetId: Screens.DRAFT_OPTIONS, + channel: { + id: 'channel_id', + teamId: 'team_id', + } as ChannelModel, + rootId: 'root_id', + }; + const wrapper = renderWithIntlAndTheme( + , + ); + const {getByTestId} = wrapper; + fireEvent.press(getByTestId('pencil-outline-icon')); + expect(dismissBottomSheet).toHaveBeenCalledTimes(1); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/screens/draft_options/edit_draft.tsx b/app/screens/draft_options/edit_draft.tsx index 7062b85fa5..0ead831a23 100644 --- a/app/screens/draft_options/edit_draft.tsx +++ b/app/screens/draft_options/edit_draft.tsx @@ -65,6 +65,7 @@ const EditDraft: React.FC = ({ > diff --git a/app/screens/draft_options/send_draft.test.tsx b/app/screens/draft_options/send_draft.test.tsx new file mode 100644 index 0000000000..ccf94cba55 --- /dev/null +++ b/app/screens/draft_options/send_draft.test.tsx @@ -0,0 +1,75 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {General, Screens} from '@constants'; +import {dismissBottomSheet} from '@screens/navigation'; +import {fireEvent, renderWithIntlAndTheme} from '@test/intl-test-helper'; + +import SendDraft from './send_draft'; + +jest.mock('@screens/navigation', () => ({ + dismissBottomSheet: jest.fn(), +})); + +describe('Send Draft', () => { + it('should render the component', () => { + const props = { + channelId: 'channel_id', + channelName: 'channel_name', + rootId: '', + channelType: General.OPEN_CHANNEL, + bottomSheetId: Screens.DRAFT_OPTIONS, + currentUserId: 'current_user_id', + maxMessageLength: 4000, + useChannelMentions: true, + userIsOutOfOffice: false, + customEmojis: [], + value: 'value', + files: [], + postPriority: '' as unknown as PostPriority, + persistentNotificationInterval: 0, + persistentNotificationMaxRecipients: 0, + draftReceiverUserName: undefined, + }; + const wrapper = renderWithIntlAndTheme( + , + ); + const {getByText} = wrapper; + expect(getByText('Send draft')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('should call dismissBottmSheet after sending the draft', () => { + const props = { + channelId: 'channel_id', + channelName: 'channel_name', + rootId: '', + channelType: General.OPEN_CHANNEL, + bottomSheetId: Screens.DRAFT_OPTIONS, + currentUserId: 'current_user_id', + maxMessageLength: 4000, + useChannelMentions: true, + userIsOutOfOffice: false, + customEmojis: [], + value: 'value', + files: [], + postPriority: '' as unknown as PostPriority, + persistentNotificationInterval: 0, + persistentNotificationMaxRecipients: 0, + draftReceiverUserName: undefined, + }; + const wrapper = renderWithIntlAndTheme( + , + ); + const {getByTestId} = wrapper; + fireEvent.press(getByTestId('send_draft_button')); + expect(dismissBottomSheet).toHaveBeenCalledTimes(1); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +}); diff --git a/app/screens/global_drafts/components/__snapshots__/draft_empty_component.test.tsx.snap b/app/screens/global_drafts/components/__snapshots__/draft_empty_component.test.tsx.snap new file mode 100644 index 0000000000..7f816ebca4 --- /dev/null +++ b/app/screens/global_drafts/components/__snapshots__/draft_empty_component.test.tsx.snap @@ -0,0 +1,143 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Draft Empty Component should match the snapshot 1`] = ` + + + + No drafts at the moment + + + Any message you have started will show here. + + +`; + +exports[`Draft Empty Component should render empty draft message 1`] = ` + + + + No drafts at the moment + + + Any message you have started will show here. + + +`; diff --git a/app/screens/global_drafts/components/draft_empty_component.test.tsx b/app/screens/global_drafts/components/draft_empty_component.test.tsx new file mode 100644 index 0000000000..6f0c1b600d --- /dev/null +++ b/app/screens/global_drafts/components/draft_empty_component.test.tsx @@ -0,0 +1,26 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {renderWithIntlAndTheme} from '@test/intl-test-helper'; + +import DraftEmptyComponent from './draft_empty_component'; + +describe('Draft Empty Component', () => { + it('should match the snapshot', () => { + const wrapper = renderWithIntlAndTheme( + , + ); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); + + it('should render empty draft message', () => { + const wrapper = renderWithIntlAndTheme( + , + ); + expect(wrapper.getByText('No drafts at the moment')).toBeTruthy(); + expect(wrapper.getByText('Any message you have started will show here.')).toBeTruthy(); + expect(wrapper.toJSON()).toMatchSnapshot(); + }); +});