diff --git a/app/screens/pinned_messages/pinned_messages.tsx b/app/screens/pinned_messages/pinned_messages.tsx index eed9b5b14..a1a64fb3d 100644 --- a/app/screens/pinned_messages/pinned_messages.tsx +++ b/app/screens/pinned_messages/pinned_messages.tsx @@ -140,6 +140,7 @@ function SavedMessages({ shouldRenderReplyButton={false} skipSavedHeader={true} skipPinnedHeader={true} + testID='pinned_messages.post_list.post' /> ); }, [currentTimezone, isTimezoneEnabled, theme]); @@ -148,6 +149,7 @@ function SavedMessages({ ); diff --git a/detox/e2e/support/ui/screen/index.ts b/detox/e2e/support/ui/screen/index.ts index b16ca0524..574d48e63 100644 --- a/detox/e2e/support/ui/screen/index.ts +++ b/detox/e2e/support/ui/screen/index.ts @@ -17,6 +17,7 @@ import GlobalThreadsScreen from './global_threads'; import HomeScreen from './home'; import LoginScreen from './login'; import PermalinkScreen from './permalink'; +import PinnedMessagesScreen from './pinned_messages'; import PostOptionsScreen from './post_options'; import ReactionsScreen from './reactions'; import RecentMentionsScreen from './recent_mentions'; @@ -45,6 +46,7 @@ export { HomeScreen, LoginScreen, PermalinkScreen, + PinnedMessagesScreen, PostOptionsScreen, ReactionsScreen, RecentMentionsScreen, diff --git a/detox/e2e/support/ui/screen/pinned_messages.ts b/detox/e2e/support/ui/screen/pinned_messages.ts new file mode 100644 index 000000000..f9ccd3008 --- /dev/null +++ b/detox/e2e/support/ui/screen/pinned_messages.ts @@ -0,0 +1,81 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {PostList} from '@support/ui/component'; +import { + ChannelInfoScreen, + PostOptionsScreen, +} from '@support/ui/screen'; +import {timeouts, wait} from '@support/utils'; +import {expect} from 'detox'; + +class PinnedMessagesScreen { + testID = { + pinnedMessagesScreenPrefix: 'pinned_messages.', + pinnedMessagesScreen: 'pinned_messages.screen', + backButton: 'screen.back.button', + emptyTitle: 'pinned_messages.empty.title', + emptyParagraph: 'pinned_messages.empty.paragraph', + }; + + pinnedMessagesScreen = element(by.id(this.testID.pinnedMessagesScreen)); + backButton = element(by.id(this.testID.backButton)); + emptyTitle = element(by.id(this.testID.emptyTitle)); + emptyParagraph = element(by.id(this.testID.emptyParagraph)); + + postList = new PostList(this.testID.pinnedMessagesScreenPrefix); + + getFlatPostList = () => { + return this.postList.getFlatList(); + }; + + getPostListPostItem = (postId: string, text = '', postProfileOptions: any = {}) => { + return this.postList.getPost(postId, text, postProfileOptions); + }; + + getPostMessageAtIndex = (index: number) => { + return this.postList.getPostMessageAtIndex(index); + }; + + toBeVisible = async () => { + await waitFor(this.pinnedMessagesScreen).toExist().withTimeout(timeouts.TEN_SEC); + + return this.pinnedMessagesScreen; + }; + + open = async () => { + // # Open pinned messages screen + await ChannelInfoScreen.pinnedMessagesOption.tap(); + + return this.toBeVisible(); + }; + + back = async () => { + await this.backButton.tap(); + await expect(this.pinnedMessagesScreen).not.toBeVisible(); + }; + + openPostOptionsFor = async (postId: string, text: string) => { + const {postListPostItem} = this.getPostListPostItem(postId, text); + await expect(postListPostItem).toBeVisible(); + + // # Open post options + await postListPostItem.longPress(); + await PostOptionsScreen.toBeVisible(); + await wait(timeouts.TWO_SEC); + }; + + hasPostMessage = async (postId: string, postMessage: string) => { + const {postListPostItem} = this.getPostListPostItem(postId, postMessage); + await expect(postListPostItem).toBeVisible(); + }; + + hasPostMessageAtIndex = async (index: number, postMessage: string) => { + await expect( + this.getPostMessageAtIndex(index), + ).toHaveText(postMessage); + }; +} + +const pinnedMessagesScreen = new PinnedMessagesScreen(); +export default pinnedMessagesScreen; diff --git a/detox/e2e/support/ui/screen/recent_mentions.ts b/detox/e2e/support/ui/screen/recent_mentions.ts index b1adb49f2..5989de2ae 100644 --- a/detox/e2e/support/ui/screen/recent_mentions.ts +++ b/detox/e2e/support/ui/screen/recent_mentions.ts @@ -24,7 +24,7 @@ class RecentMentionsScreen { emptyTitle = element(by.id(this.testID.emptyTitle)); emptyParagraph = element(by.id(this.testID.emptyParagraph)); - // convenience propers + // convenience props largeHeaderTitle = NavigationHeader.largeHeaderTitle; largeHeaderSubtitle = NavigationHeader.largeHeaderSubtitle; diff --git a/detox/e2e/support/ui/screen/saved_messages.ts b/detox/e2e/support/ui/screen/saved_messages.ts index df8b979fd..ceea5b851 100644 --- a/detox/e2e/support/ui/screen/saved_messages.ts +++ b/detox/e2e/support/ui/screen/saved_messages.ts @@ -24,7 +24,7 @@ class SavedMessagesScreen { emptyTitle = element(by.id(this.testID.emptyTitle)); emptyParagraph = element(by.id(this.testID.emptyParagraph)); - // convenience propers + // convenience props largeHeaderTitle = NavigationHeader.largeHeaderTitle; largeHeaderSubtitle = NavigationHeader.largeHeaderSubtitle; diff --git a/detox/e2e/test/search/pinned_messages.e2e.ts b/detox/e2e/test/search/pinned_messages.e2e.ts new file mode 100644 index 000000000..16f1b3610 --- /dev/null +++ b/detox/e2e/test/search/pinned_messages.e2e.ts @@ -0,0 +1,251 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ******************************************************************* +// - [#] indicates a test step (e.g. # Go to a screen) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element testID when selecting an element. Create one if none. +// ******************************************************************* + +import { + Post, + Setup, +} from '@support/server_api'; +import { + serverOneUrl, + siteOneUrl, +} from '@support/test_config'; +import { + ChannelListScreen, + ChannelScreen, + EditPostScreen, + HomeScreen, + LoginScreen, + PermalinkScreen, + PostOptionsScreen, + PinnedMessagesScreen, + SavedMessagesScreen, + ServerScreen, + ThreadScreen, + ChannelInfoScreen, +} from '@support/ui/screen'; +import {getRandomId} from '@support/utils'; +import {expect} from 'detox'; + +describe('Search - Pinned Messages', () => { + const serverOneDisplayName = 'Server 1'; + const channelsCategory = 'channels'; + const pinnedText = 'Pinned'; + let testChannel: any; + + beforeAll(async () => { + const {channel, user} = await Setup.apiInit(siteOneUrl); + testChannel = channel; + + // # Log in to server + await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName); + await LoginScreen.login(user); + }); + + beforeEach(async () => { + // * Verify on channel list screen + await ChannelListScreen.toBeVisible(); + }); + + afterAll(async () => { + // # Log out + await HomeScreen.logout(); + }); + + it('MM-T4918_1 - should match elements on pinned messages screen', async () => { + // # Open a channel screen, open channel info screen, and open pinned messages screen + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify basic elements on pinned messages screen + await expect(PinnedMessagesScreen.emptyTitle).toHaveText('No pinned messages yet'); + await expect(PinnedMessagesScreen.emptyParagraph).toHaveText('To pin important messages, long-press on a message and choose Pin To Channel. Pinned messages will be visible to everyone in this channel.'); + + // # Go back to channel list screen + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); + + it('MM-T4918_2 - should be able to display a pinned message in pinned messages screen and navigate to message channel', async () => { + // # Open a channel screen, post a message, open post options for message, and tap on pin to channel option + const message = `Message ${getRandomId()}`; + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelScreen.postMessage(message); + const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); + await ChannelScreen.openPostOptionsFor(post.id, message); + await PostOptionsScreen.pinPostOption.tap(); + + // * Verify pinned text is displayed on the post pre-header + const {postListPostItemPreHeaderText} = ChannelScreen.getPostListPostItem(post.id, message); + await expect(postListPostItemPreHeaderText).toHaveText(pinnedText); + + // # Open channel info screen and open pinned messages screen + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify on pinned messages screen and pinned message is displayed + await PinnedMessagesScreen.toBeVisible(); + const {postListPostItem: pinnedMessagesPostListPostItem} = PinnedMessagesScreen.getPostListPostItem(post.id, message); + await expect(pinnedMessagesPostListPostItem).toBeVisible(); + + // # Tap on post and jump to recent messages + await pinnedMessagesPostListPostItem.tap(); + await PermalinkScreen.jumpToRecentMessages(); + + // * Verify on channel screen and pinned message is displayed + await ChannelScreen.toBeVisible(); + const {postListPostItem: channelPostListPostItem} = ChannelScreen.getPostListPostItem(post.id, message); + await expect(channelPostListPostItem).toBeVisible(); + + // # Go back to channel list screen + await ChannelScreen.back(); + }); + + it('MM-T4918_3 - should be able to edit, reply to, and delete a pinned message from pinned messages screen', async () => { + // # Open a channel screen, post a message, open post options for message, tap on pin to channel option, open channel info screen, and open pinned messages screen + const message = `Message ${getRandomId()}`; + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelScreen.postMessage(message); + const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); + await ChannelScreen.openPostOptionsFor(pinnedPost.id, message); + await PostOptionsScreen.pinPostOption.tap(); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify on pinned messages screen + await PinnedMessagesScreen.toBeVisible(); + + // # Open post options for pinned message and tap on edit option + await PinnedMessagesScreen.openPostOptionsFor(pinnedPost.id, message); + await PostOptionsScreen.editPostOption.tap(); + + // * Verify on edit post screen + await EditPostScreen.toBeVisible(); + + // # Edit post message and tap save button + const updatedMessage = `${message} edit`; + await EditPostScreen.messageInput.replaceText(updatedMessage); + await EditPostScreen.saveButton.tap(); + + // * Verify post message is updated and displays edited indicator '(edited)' + const {postListPostItem: updatedPostListPostItem, postListPostItemEditedIndicator} = PinnedMessagesScreen.getPostListPostItem(pinnedPost.id, updatedMessage); + await expect(updatedPostListPostItem).toBeVisible(); + await expect(postListPostItemEditedIndicator).toHaveText('(edited)'); + + // # Open post options for updated pinned message and tap on reply option + await PinnedMessagesScreen.openPostOptionsFor(pinnedPost.id, updatedMessage); + await PostOptionsScreen.replyPostOption.tap(); + + // * Verify on thread screen + await ThreadScreen.toBeVisible(); + + // # Post a reply + const replyMessage = `${updatedMessage} reply`; + await ThreadScreen.postMessage(replyMessage); + + // * Verify reply is posted + const {post: replyPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); + const {postListPostItem: replyPostListPostItem} = ThreadScreen.getPostListPostItem(replyPost.id, replyMessage); + await expect(replyPostListPostItem).toBeVisible(); + + // # Go back to pinned messages screen + await ThreadScreen.back(); + + // * Verify reply count and following button + const {postListPostItem, postListPostItemFooterReplyCount, postListPostItemFooterFollowingButton} = PinnedMessagesScreen.getPostListPostItem(pinnedPost.id, updatedMessage); + await expect(postListPostItemFooterReplyCount).toHaveText('1 reply'); + await expect(postListPostItemFooterFollowingButton).toBeVisible(); + + // # Open post options for updated pinned message and delete post + await PinnedMessagesScreen.openPostOptionsFor(pinnedPost.id, updatedMessage); + await PostOptionsScreen.deletePost({confirm: true}); + + // * Verify updated pinned message is deleted + await expect(postListPostItem).not.toExist(); + + // # Go back to channel list screen + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); + + it('MM-T4918_4 - should be able to unpin a message from pinned messages screen', async () => { + // # Open a channel screen, post a message, open post options for message, tap on pin to channel option, open channel info screen, and open pinned messages screen + const message = `Message ${getRandomId()}`; + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelScreen.postMessage(message); + const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); + await ChannelScreen.openPostOptionsFor(pinnedPost.id, message); + await PostOptionsScreen.pinPostOption.tap(); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify on pinned messages screen + await PinnedMessagesScreen.toBeVisible(); + + // # Open post options for pinned message and tap on unpin from channel option + await PinnedMessagesScreen.openPostOptionsFor(pinnedPost.id, message); + await PostOptionsScreen.unpinPostOption.tap(); + + // * Verify pinned message is not displayed anymore + const {postListPostItem} = PinnedMessagesScreen.getPostListPostItem(pinnedPost.id, message); + await expect(postListPostItem).not.toExist(); + + // # Go back to channel list screen + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); + + it('MM-T4918_5 - should be able to save/unsave a pinned message from pinned messages screen', async () => { + // # Open a channel screen, post a message, open post options for message, tap on pin to channel option, open channel info screen, and open pinned messages screen + const message = `Message ${getRandomId()}`; + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelScreen.postMessage(message); + const {post: pinnedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); + await ChannelScreen.openPostOptionsFor(pinnedPost.id, message); + await PostOptionsScreen.pinPostOption.tap(); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify on pinned messages screen + await PinnedMessagesScreen.toBeVisible(); + + // # Open post options for pinned message, tap on save option, go back to channel list screen, and open saved messages screen + await PinnedMessagesScreen.openPostOptionsFor(pinnedPost.id, message); + await PostOptionsScreen.savePostOption.tap(); + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + await SavedMessagesScreen.open(); + + // * Verify pinned message is displayed on saved messages screen + const {postListPostItem} = SavedMessagesScreen.getPostListPostItem(pinnedPost.id, message); + await expect(postListPostItem).toBeVisible(); + + // # Go back to pinned messages screen, open post options for pinned message, tap on usave option, go back to channel list screen, and open saved messages screen + await ChannelListScreen.open(); + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + await PinnedMessagesScreen.openPostOptionsFor(pinnedPost.id, message); + await PostOptionsScreen.unsavePostOption.tap(); + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + await SavedMessagesScreen.open(); + + // * Verify pinned message is not displayed anymore on saved messages screen + await expect(postListPostItem).not.toExist(); + + // # Go back to channel list screen + await ChannelListScreen.open(); + }); +}); diff --git a/detox/e2e/test/search/recent_mentions.e2e.ts b/detox/e2e/test/search/recent_mentions.e2e.ts index 75d7cd643..1b9dfdd88 100644 --- a/detox/e2e/test/search/recent_mentions.e2e.ts +++ b/detox/e2e/test/search/recent_mentions.e2e.ts @@ -16,12 +16,14 @@ import { siteOneUrl, } from '@support/test_config'; import { + ChannelInfoScreen, ChannelListScreen, ChannelScreen, EditPostScreen, HomeScreen, LoginScreen, PermalinkScreen, + PinnedMessagesScreen, PostOptionsScreen, RecentMentionsScreen, SavedMessagesScreen, @@ -205,4 +207,49 @@ describe('Search - Recent Mentions', () => { // # Go back to channel list screen await ChannelListScreen.open(); }); + + it('MM-T4909_5 - should be able to pin/unpin a recent mention from recent mentions screen', async () => { + // # Open a channel screen, post a message with at-mention to current user, go back to channel list screen, and open recent mentions screen + const message = `@${testUser.username}`; + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelScreen.postMessage(message); + await ChannelScreen.back(); + await RecentMentionsScreen.open(); + + // * Verify on recent mentions screen + await RecentMentionsScreen.toBeVisible(); + + // # Open post options for recent mention, tap on pin to channel option, go back to channel list screen, open the channel screen where recent mention is posted, open channel info screen, and open pinned messages screen + const {post: mentionPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); + await RecentMentionsScreen.openPostOptionsFor(mentionPost.id, message); + await PostOptionsScreen.pinPostOption.tap(); + await ChannelListScreen.open(); + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify recent mention is displayed on pinned messages screen + const {postListPostItem} = PinnedMessagesScreen.getPostListPostItem(mentionPost.id, message); + await expect(postListPostItem).toBeVisible(); + + // # Go back to recent mentions screen, open post options for recent mention, tap on unpin from channel option, go back to channel list screen, open the channel screen where recent mention is posted, open channel info screen, and open pinned messages screen + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + await RecentMentionsScreen.open(); + await RecentMentionsScreen.openPostOptionsFor(mentionPost.id, message); + await PostOptionsScreen.unpinPostOption.tap(); + await ChannelListScreen.open(); + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify recent mention is not displayed anymore on pinned messages screen + await expect(postListPostItem).not.toExist(); + + // # Go back to channel list screen + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); }); diff --git a/detox/e2e/test/search/saved_messages.e2e.ts b/detox/e2e/test/search/saved_messages.e2e.ts index 043f5bea8..c2fd25db9 100644 --- a/detox/e2e/test/search/saved_messages.e2e.ts +++ b/detox/e2e/test/search/saved_messages.e2e.ts @@ -16,12 +16,14 @@ import { siteOneUrl, } from '@support/test_config'; import { + ChannelInfoScreen, ChannelListScreen, ChannelScreen, EditPostScreen, HomeScreen, LoginScreen, PermalinkScreen, + PinnedMessagesScreen, PostOptionsScreen, SavedMessagesScreen, ServerScreen, @@ -200,4 +202,51 @@ describe('Search - Saved Messages', () => { // # Go back to channel list screen await ChannelListScreen.open(); }); + + it('MM-T4910_5 - should be able to pin/unpin a saved message from saved messages screen', async () => { + // # Open a channel screen, post a message, open post options for message, tap on save option, go back to channel list screen, and open saved messages screen + const message = `Message ${getRandomId()}`; + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelScreen.postMessage(message); + const {post: savedPost} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); + await ChannelScreen.openPostOptionsFor(savedPost.id, message); + await PostOptionsScreen.savePostOption.tap(); + await ChannelScreen.back(); + await SavedMessagesScreen.open(); + + // * Verify on saved messages screen + await SavedMessagesScreen.toBeVisible(); + + // # Open post options for saved message, tap on pin to channel option, go back to channel list screen, open the channel screen where saved message is posted, open channel info screen, and open pinned messages screen + await SavedMessagesScreen.openPostOptionsFor(savedPost.id, message); + await PostOptionsScreen.pinPostOption.tap(); + await ChannelListScreen.open(); + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify saved message is displayed on pinned messages screen + const {postListPostItem} = PinnedMessagesScreen.getPostListPostItem(savedPost.id, message); + await expect(postListPostItem).toBeVisible(); + + // # Go back to saved messages screen, open post options for saved message, tap on unpin from channel option, go back to channel list screen, open the channel screen where saved message is posted, open channel info screen, and open pinned messages screen + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + await SavedMessagesScreen.open(); + await SavedMessagesScreen.openPostOptionsFor(savedPost.id, message); + await PostOptionsScreen.unpinPostOption.tap(); + await ChannelListScreen.open(); + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify saved message is not displayed anymore on pinned messages screen + await expect(postListPostItem).not.toExist(); + + // # Go back to channel list screen + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); }); diff --git a/detox/e2e/test/smoke_test/search.e2e.ts b/detox/e2e/test/smoke_test/search.e2e.ts index 7a92d0b88..e4681d762 100644 --- a/detox/e2e/test/smoke_test/search.e2e.ts +++ b/detox/e2e/test/smoke_test/search.e2e.ts @@ -16,10 +16,12 @@ import { siteOneUrl, } from '@support/test_config'; import { + ChannelInfoScreen, ChannelListScreen, ChannelScreen, HomeScreen, LoginScreen, + PinnedMessagesScreen, PostOptionsScreen, RecentMentionsScreen, SavedMessagesScreen, @@ -91,4 +93,26 @@ describe('Smoke Test - Search', () => { // # Go back to channel list screen await ChannelListScreen.open(); }); + + it('MM-T4911_3 - should be able to display a pinned message on pinned messages screen', async () => { + // # Open a channel screen, post a message, open post options for message, tap on pin to channel option, open channel info screen, and open pinned messages screen + const message = `Message ${getRandomId()}`; + await ChannelScreen.open(channelsCategory, testChannel.name); + await ChannelScreen.postMessage(message); + const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id); + await ChannelScreen.openPostOptionsFor(post.id, message); + await PostOptionsScreen.pinPostOption.tap(); + await ChannelInfoScreen.open(); + await PinnedMessagesScreen.open(); + + // * Verify on pinned messages screen and pinned message is displayed + await PinnedMessagesScreen.toBeVisible(); + const {postListPostItem} = PinnedMessagesScreen.getPostListPostItem(post.id, message); + await expect(postListPostItem).toBeVisible(); + + // # Go back to channel list screen + await PinnedMessagesScreen.back(); + await ChannelInfoScreen.close(); + await ChannelScreen.back(); + }); });