From 62877064525bbb3f8be6c115da1ce8387b694795 Mon Sep 17 00:00:00 2001 From: Malik Date: Mon, 15 Mar 2021 11:25:19 -0400 Subject: [PATCH] Mm 32502 guest identification 2 (#5198) * Add Guest Experience Test Cases * Added testIDs and cleaned up tests * Minor refactor Co-authored-by: Furqan Malik Co-authored-by: Malik Co-authored-by: Furqan Malik Co-authored-by: Joseph Baylon Co-authored-by: Mattermod --- .../channel_mention_item.js | 4 +- app/components/post_header/post_header.js | 1 + app/components/tag.js | 2 + detox/e2e/support/server_api/user.js | 17 ++++ detox/e2e/support/ui/component/post.js | 3 + detox/e2e/support/ui/component/post_list.js | 2 + detox/e2e/support/ui/screen/long_post.js | 2 + .../support/ui/screen/search_result_post.js | 2 + .../guest_account/guest_experience.e2e.js | 90 +++++++++++++++++++ ...ping_channel_url_link_joins_channel.e2e.js | 2 +- 10 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 detox/e2e/test/guest_account/guest_experience.e2e.js diff --git a/app/components/autocomplete/channel_mention_item/channel_mention_item.js b/app/components/autocomplete/channel_mention_item/channel_mention_item.js index 4be107afc..a5065bfed 100644 --- a/app/components/autocomplete/channel_mention_item/channel_mention_item.js +++ b/app/components/autocomplete/channel_mention_item/channel_mention_item.js @@ -78,8 +78,8 @@ const ChannelMentionItem = (props) => { key={channelId} onPress={completeMention} style={[style.row, margins]} - type={'opacity'} testID={testID} + type={'opacity'} > {'@' + displayName} { onPress={completeMention} style={margins} underlayColor={changeOpacity(theme.buttonBg, 0.08)} - type={'native'} testID={testID} + type={'native'} > ); diff --git a/app/components/tag.js b/app/components/tag.js index a975cfce7..784cf8a22 100644 --- a/app/components/tag.js +++ b/app/components/tag.js @@ -42,6 +42,7 @@ export default class Tag extends PureComponent { inTitle: PropTypes.bool, show: PropTypes.bool, style: ViewPropTypes.style, + testID: PropTypes.string, theme: PropTypes.object.isRequired, }; @@ -61,6 +62,7 @@ export default class Tag extends PureComponent { id={this.props.id} defaultMessage={this.props.defaultMessage} style={[style.text, this.props.inTitle ? style.title : null]} + testID={this.props.testID} /> ); diff --git a/detox/e2e/support/server_api/user.js b/detox/e2e/support/server_api/user.js index 9f08053ff..b608eab8f 100644 --- a/detox/e2e/support/server_api/user.js +++ b/detox/e2e/support/server_api/user.js @@ -117,6 +117,22 @@ export const apiGetUserById = async (userId) => { } }; +/** + * Demote a user to a guest. + * See https://api.mattermost.com/#tag/users/paths/~1users~1{user_id}~1demote/post + * @param {string} userId - the user ID + * @return {Object} returns {status} on success or {error, status} on error + */ +export const apiDemoteUserToGuest = async (userId) => { + try { + const response = await client.post(`/api/v4/users/${userId}/demote`); + + return {status: response.status}; + } catch (err) { + return getResponseFromError(err); + } +}; + /** * Get a user by username. * See https://api.mattermost.com/#tag/users/paths/~1users~1username~1{username}/get @@ -177,6 +193,7 @@ function generateRandomUser(prefix) { export const User = { apiAdminLogin, + apiDemoteUserToGuest, apiLogin, apiLogout, apiCreateUser, diff --git a/detox/e2e/support/ui/component/post.js b/detox/e2e/support/ui/component/post.js index 9e987eb08..e16348dc4 100644 --- a/detox/e2e/support/ui/component/post.js +++ b/detox/e2e/support/ui/component/post.js @@ -9,6 +9,7 @@ class Post { message: 'markdown_text', postHeaderDateTime: 'post_header.date_time', postHeaderDisplayName: 'post_header.display_name', + postHeaderGuestTag: 'post_header.guest_tag', postHeaderReply: 'post_header.reply', postPreHeaderText: 'post_pre_header.text', } @@ -30,11 +31,13 @@ class Post { getPostHeader = (postItemMatcher) => { const postItemHeaderDateTimeMatcher = by.id(this.testID.postHeaderDateTime).withAncestor(postItemMatcher); const postItemHeaderDisplayNameMatcher = by.id(this.testID.postHeaderDisplayName).withAncestor(postItemMatcher); + const postItemHeaderGuestTagMatcher = by.id(this.testID.postHeaderGuestTag).withAncestor(postItemMatcher); const postItemHeaderReplyMatcher = by.id(this.testID.postHeaderReply).withAncestor(postItemMatcher); return { postItemHeaderDateTime: element(postItemHeaderDateTimeMatcher), postItemHeaderDisplayName: element(postItemHeaderDisplayNameMatcher), + postItemHeaderGuestTag: element(postItemHeaderGuestTagMatcher), postItemHeaderReply: element(postItemHeaderReplyMatcher), }; } diff --git a/detox/e2e/support/ui/component/post_list.js b/detox/e2e/support/ui/component/post_list.js index fc9d99bc7..afd26fcee 100644 --- a/detox/e2e/support/ui/component/post_list.js +++ b/detox/e2e/support/ui/component/post_list.js @@ -15,6 +15,7 @@ class PostList { postItem, postItemHeaderDateTime, postItemHeaderDisplayName, + postItemHeaderGuestTag, postItemHeaderReply, postItemMessage, postItemPreHeaderText, @@ -26,6 +27,7 @@ class PostList { postListPostItem: postItem, postListPostItemHeaderDateTime: postItemHeaderDateTime, postListPostItemHeaderDisplayName: postItemHeaderDisplayName, + postListPostItemHeaderGuestTag: postItemHeaderGuestTag, postListPostItemHeaderReply: postItemHeaderReply, postListPostItemMessage: postItemMessage, postListPostItemPreHeaderText: postItemPreHeaderText, diff --git a/detox/e2e/support/ui/screen/long_post.js b/detox/e2e/support/ui/screen/long_post.js index 6ef87983d..b37820878 100644 --- a/detox/e2e/support/ui/screen/long_post.js +++ b/detox/e2e/support/ui/screen/long_post.js @@ -13,6 +13,7 @@ class LongPostScreen { postItem, postItemHeaderDateTime, postItemHeaderDisplayName, + postItemHeaderGuestTag, postItemHeaderReply, postItemMessage, postItemProfilePicture, @@ -23,6 +24,7 @@ class LongPostScreen { longPostItem: postItem, longPostItemHeaderDateTime: postItemHeaderDateTime, longPostItemHeaderDisplayName: postItemHeaderDisplayName, + longPostItemHeaderGuestTag: postItemHeaderGuestTag, longPostItemHeaderReply: postItemHeaderReply, longPostItemMessage: postItemMessage, longPostItemProfilePicture: postItemProfilePicture, diff --git a/detox/e2e/support/ui/screen/search_result_post.js b/detox/e2e/support/ui/screen/search_result_post.js index 301ac3979..5614c1bfb 100644 --- a/detox/e2e/support/ui/screen/search_result_post.js +++ b/detox/e2e/support/ui/screen/search_result_post.js @@ -13,6 +13,7 @@ class SearchResultPostScreen { postItem, postItemHeaderDateTime, postItemHeaderDisplayName, + postItemHeaderGuestTag, postItemHeaderReply, postItemMessage, postItemProfilePicture, @@ -23,6 +24,7 @@ class SearchResultPostScreen { searchResultPostItem: postItem, searchResultPostItemHeaderDateTime: postItemHeaderDateTime, searchResultPostItemHeaderDisplayName: postItemHeaderDisplayName, + searchResultPostItemHeaderGuestTag: postItemHeaderGuestTag, searchResultPostItemHeaderReply: postItemHeaderReply, searchResultPostItemMessage: postItemMessage, searchResultPostItemProfilePicture: postItemProfilePicture, diff --git a/detox/e2e/test/guest_account/guest_experience.e2e.js b/detox/e2e/test/guest_account/guest_experience.e2e.js new file mode 100644 index 000000000..209e105b8 --- /dev/null +++ b/detox/e2e/test/guest_account/guest_experience.e2e.js @@ -0,0 +1,90 @@ +// 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 {Autocomplete} from '@support/ui/component'; +import { + ChannelScreen, + SearchScreen, +} from '@support/ui/screen'; +import { + Channel, + Post, + Setup, + User, +} from '@support/server_api'; + +describe('Guest Experience', () => { + let testChannel; + let testTeam; + let testGuestUser; + + beforeAll(async () => { + const {team, user} = await Setup.apiInit(); + testGuestUser = user; + testTeam = team; + + ({channel: testChannel} = await Channel.apiGetChannelByName(testTeam.name, 'town-square')); + + // # Demote user to guest + await User.apiDemoteUserToGuest(testGuestUser.id); + + // # Open channel screen + await ChannelScreen.open(testGuestUser); + }); + + afterAll(async () => { + await ChannelScreen.logout(); + }); + + it('MM-T1404 Guest badge not shown next to system messages', async () => { + // * Verify guest badge is not visible in system message + const systemMessage = 'You and @sysadmin joined the team.'; + const {post} = await Post.apiGetLastPostInChannel(testChannel.id); + const {postListPostItemHeaderGuestTag} = await ChannelScreen.getPostListPostItem(post.id, systemMessage); + await expect(postListPostItemHeaderGuestTag).not.toBeVisible(); + }); + + it('MM-T1397 Guest tag in search in:', async () => { + const { + getSearchResultPostItem, + searchInSection, + searchInput, + } = SearchScreen; + const { + channelMentionSuggestionList, + getChannelMentionItem, + } = Autocomplete; + + // # Post a message as guest user + const testMessage = Date.now().toString(); + await ChannelScreen.postMessage(testMessage); + + // * Verify guest badge is visible in channel + const {post} = await Post.apiGetLastPostInChannel(testChannel.id); + const {postListPostItemHeaderGuestTag} = await ChannelScreen.getPostListPostItem(post.id, testMessage); + await expect(postListPostItemHeaderGuestTag).toBeVisible(); + + // # Search ":in" channel and select channel from autocomplete + await SearchScreen.open(); + await searchInput.clearText(); + await searchInSection.tap(); + await searchInput.typeText(testChannel.name); + await expect(channelMentionSuggestionList).toExist(); + const channelMentionAutocomplete = await getChannelMentionItem(testChannel.id); + await channelMentionAutocomplete.tap(); + await searchInput.tapReturnKey(); + + // * Verify guest badge is visible in search results + const {searchResultPostItemHeaderGuestTag} = await getSearchResultPostItem(post.id, testMessage); + await expect(searchResultPostItemHeaderGuestTag).toBeVisible(); + + // # Go back to channel + await SearchScreen.cancel(); + }); +}); diff --git a/detox/e2e/test/messaging/tapping_channel_url_link_joins_channel.e2e.js b/detox/e2e/test/messaging/tapping_channel_url_link_joins_channel.e2e.js index 48f8602c8..6418b21a1 100644 --- a/detox/e2e/test/messaging/tapping_channel_url_link_joins_channel.e2e.js +++ b/detox/e2e/test/messaging/tapping_channel_url_link_joins_channel.e2e.js @@ -150,7 +150,7 @@ describe('Messaging', () => { }); async function createPrivateChannel(channelName) { - // # Open Mainside bar and press on private channels more button + // # Open create private channel screen await ChannelScreen.openMainSidebar(); await MainSidebar.openCreatePrivateChannelButton.tap();