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();