diff --git a/app/components/autocomplete/at_mention/at_mention.tsx b/app/components/autocomplete/at_mention/at_mention.tsx
index 9682576db..cbde145ab 100644
--- a/app/components/autocomplete/at_mention/at_mention.tsx
+++ b/app/components/autocomplete/at_mention/at_mention.tsx
@@ -443,7 +443,7 @@ const AtMention = ({
renderSectionHeader={renderSectionHeader}
style={[style.listView, {maxHeight: maxListHeight}]}
sections={sections}
- testID='at_mention_suggestion.list'
+ testID='autocomplete.at_mention.section_list'
/>
);
};
diff --git a/app/components/autocomplete/at_mention_item/index.tsx b/app/components/autocomplete/at_mention_item/index.tsx
index ecc062a5f..a1a7cdf98 100644
--- a/app/components/autocomplete/at_mention_item/index.tsx
+++ b/app/components/autocomplete/at_mention_item/index.tsx
@@ -40,7 +40,7 @@ const AtMentionItem = ({
>
);
diff --git a/app/components/autocomplete/channel_mention/channel_mention.tsx b/app/components/autocomplete/channel_mention/channel_mention.tsx
index da22ba76d..d0d910212 100644
--- a/app/components/autocomplete/channel_mention/channel_mention.tsx
+++ b/app/components/autocomplete/channel_mention/channel_mention.tsx
@@ -349,7 +349,7 @@ const ChannelMention = ({
renderSectionHeader={renderSectionHeader}
style={listStyle}
sections={sections}
- testID='channel_mention_suggestion.list'
+ testID='autocomplete.channel_mention.section_list'
/>
);
};
diff --git a/app/components/channel_actions/info_box/index.tsx b/app/components/channel_actions/info_box/index.tsx
index 347e84470..ec3cad4ab 100644
--- a/app/components/channel_actions/info_box/index.tsx
+++ b/app/components/channel_actions/info_box/index.tsx
@@ -34,7 +34,7 @@ const InfoBox = ({channelId, containerStyle, showAsLabel = false, testID}: Props
leftButtons: [{
id: closeButtonId,
icon: closeButton,
- testID: closeButtonId,
+ testID: 'close.channel_info.button',
}],
},
modal: {swipeToDismiss: false},
diff --git a/app/components/channel_item/__snapshots__/channel_item.test.tsx.snap b/app/components/channel_item/__snapshots__/channel_item.test.tsx.snap
index 8486e0a5c..409c3438e 100644
--- a/app/components/channel_item/__snapshots__/channel_item.test.tsx.snap
+++ b/app/components/channel_item/__snapshots__/channel_item.test.tsx.snap
@@ -34,7 +34,7 @@ exports[`components/channel_list/categories/body/channel_item should match snaps
},
]
}
- testID="channel_list_item.hello.collapsed.true"
+ testID="channel_item.hello"
>
Hello!
@@ -147,7 +147,7 @@ exports[`components/channel_list/categories/body/channel_item should match snaps
},
]
}
- testID="channel_list_item.hello.collapsed.true"
+ testID="channel_item.hello"
>
Hello!
diff --git a/app/components/channel_item/channel_item.test.tsx b/app/components/channel_item/channel_item.test.tsx
index fd0f68205..df5bcd74b 100644
--- a/app/components/channel_item/channel_item.test.tsx
+++ b/app/components/channel_item/channel_item.test.tsx
@@ -37,7 +37,7 @@ describe('components/channel_list/categories/body/channel_item', () => {
membersCount={0}
isMuted={false}
currentUserId={'id'}
- testID='channel_list_item'
+ testID='channel_item'
onPress={() => undefined}
isUnread={myChannel.isUnread}
mentionsCount={myChannel.mentionsCount}
@@ -57,7 +57,7 @@ describe('components/channel_list/categories/body/channel_item', () => {
membersCount={3}
isMuted={false}
currentUserId={'id'}
- testID='channel_list_item'
+ testID='channel_item'
onPress={() => undefined}
isUnread={myChannel.isUnread}
mentionsCount={myChannel.mentionsCount}
diff --git a/app/components/channel_item/channel_item.tsx b/app/components/channel_item/channel_item.tsx
index 751349a39..0bc712f99 100644
--- a/app/components/channel_item/channel_item.tsx
+++ b/app/components/channel_item/channel_item.tsx
@@ -179,7 +179,7 @@ const ChannelListItem = ({
<>
);
};
diff --git a/app/components/emoji_picker/index.tsx b/app/components/emoji_picker/index.tsx
index 10c492cd2..1384ae2da 100644
--- a/app/components/emoji_picker/index.tsx
+++ b/app/components/emoji_picker/index.tsx
@@ -100,11 +100,9 @@ const EmojiPicker = ({customEmojis, customEmojisEnabled, onEmojiPress, recentEmo
-
+
{
scrollViewNativeID={SCROLLVIEW_NATIVE_ID}
normalList={true}
style={styles.container}
+ testID='emoji_picker.emoji_sections.section_bar'
>
diff --git a/app/components/emoji_picker/sections/index.tsx b/app/components/emoji_picker/sections/index.tsx
index ea7309cb3..d195e4293 100644
--- a/app/components/emoji_picker/sections/index.tsx
+++ b/app/components/emoji_picker/sections/index.tsx
@@ -227,6 +227,7 @@ const EmojiSections = ({customEmojis, customEmojisEnabled, onEmojiPress, recentE
sections={sections}
contentContainerStyle={{paddingBottom: 50}}
windowSize={100}
+ testID='emoji_picker.emoji_sections.section_list'
/>
);
diff --git a/app/components/profile_picture/index.tsx b/app/components/profile_picture/index.tsx
index e3a39e3cf..794eb04e5 100644
--- a/app/components/profile_picture/index.tsx
+++ b/app/components/profile_picture/index.tsx
@@ -101,7 +101,7 @@ const ProfilePicture = ({
return (
+
{name}
@@ -143,7 +148,7 @@ const UserItem = ({
{` @${user!.username}`}
@@ -153,6 +158,7 @@ const UserItem = ({
)}
{shared && (
diff --git a/app/screens/channel/channel_post_list/intro/direct_channel/member/member.tsx b/app/screens/channel/channel_post_list/intro/direct_channel/member/member.tsx
index c2486b109..5a0ce2a46 100644
--- a/app/screens/channel/channel_post_list/intro/direct_channel/member/member.tsx
+++ b/app/screens/channel/channel_post_list/intro/direct_channel/member/member.tsx
@@ -53,7 +53,7 @@ const Member = ({channelId, containerStyle, size = 72, showStatus = true, theme,
iconSize={48}
showStatus={showStatus}
statusSize={24}
- testID='channel_intro.profile_picture'
+ testID={`channel_intro.${user.id}.profile_picture`}
/>
);
diff --git a/app/screens/channel/header/header.tsx b/app/screens/channel/header/header.tsx
index 44e2b2d13..6c6fedb8e 100644
--- a/app/screens/channel/header/header.tsx
+++ b/app/screens/channel/header/header.tsx
@@ -111,7 +111,7 @@ const ChannelHeader = ({
leftButtons: [{
id: closeButtonId,
icon: closeButton,
- testID: closeButtonId,
+ testID: 'close.channel_info.button',
}],
},
modal: {swipeToDismiss: false},
diff --git a/app/screens/emoji_picker/index.tsx b/app/screens/emoji_picker/index.tsx
index f60d930d4..cb66e904d 100644
--- a/app/screens/emoji_picker/index.tsx
+++ b/app/screens/emoji_picker/index.tsx
@@ -21,7 +21,7 @@ const EmojiPickerScreen = ({closeButton, componentId, onEmojiPress}: Props) => {
{
icon: closeButton,
id: 'close-add-reaction',
- testID: 'close.add_reaction.button',
+ testID: 'close.emoji_picker.button',
},
],
rightButtons: [],
@@ -50,7 +50,12 @@ const EmojiPickerScreen = ({closeButton, componentId, onEmojiPress}: Props) => {
close();
}, []);
- return ;
+ return (
+
+ );
};
export default EmojiPickerScreen;
diff --git a/app/screens/find_channels/filtered_list/filtered_list.tsx b/app/screens/find_channels/filtered_list/filtered_list.tsx
index e25a18b8b..3e86a40b0 100644
--- a/app/screens/find_channels/filtered_list/filtered_list.tsx
+++ b/app/screens/find_channels/filtered_list/filtered_list.tsx
@@ -45,6 +45,7 @@ type Props = {
term: string;
usersMatch: UserModel[];
usersMatchStart: UserModel[];
+ testID?: string;
}
const style = StyleSheet.create({
@@ -77,7 +78,7 @@ const sortByUserOrChannel = (locale: string, teamm
const FilteredList = ({
archivedChannels, close, channelsMatch, channelsMatchStart, currentTeamId,
keyboardHeight, loading, onLoading, restrictDirectMessage, showTeamName,
- teamIds, teammateDisplayNameSetting, term, usersMatch, usersMatchStart,
+ teamIds, teammateDisplayNameSetting, term, usersMatch, usersMatchStart, testID,
}: Props) => {
const bounce = useRef void>>();
const mounted = useRef(false);
@@ -211,6 +212,7 @@ const FilteredList = ({
isInfo={true}
onPress={onSwitchToChannel}
showTeamName={showTeamName}
+ testID='find_channels.filtered_list.channel_item'
/>
);
} else if ('username' in item) {
@@ -304,6 +306,7 @@ const FilteredList = ({
renderItem={renderItem}
data={data}
showsVerticalScrollIndicator={false}
+ testID={`${testID}.flat_list`}
/>
);
diff --git a/app/screens/find_channels/index.tsx b/app/screens/find_channels/index.tsx
index ad191b6e8..b44297777 100644
--- a/app/screens/find_channels/index.tsx
+++ b/app/screens/find_channels/index.tsx
@@ -83,7 +83,10 @@ const FindChannels = ({closeButtonId, componentId}: Props) => {
}, []);
return (
-
+
{
selectionColor={color}
showLoading={loading}
value={term}
+ testID='find_channels.search_bar'
/>
{term === '' && }
@@ -106,6 +110,7 @@ const FindChannels = ({closeButtonId, componentId}: Props) => {
}
{Boolean(term) &&
@@ -115,6 +120,7 @@ const FindChannels = ({closeButtonId, componentId}: Props) => {
loading={loading}
onLoading={setLoading}
term={term}
+ testID='find_channels.filtered_list'
/>
}
diff --git a/app/screens/find_channels/quick_options/quick_options.tsx b/app/screens/find_channels/quick_options/quick_options.tsx
index 36f891c1a..1811939b2 100644
--- a/app/screens/find_channels/quick_options/quick_options.tsx
+++ b/app/screens/find_channels/quick_options/quick_options.tsx
@@ -76,6 +76,7 @@ const QuickOptions = ({canCreateChannels, canJoinChannels, close}: Props) => {
iconName='globe'
onPress={browseChannels}
text={intl.formatMessage({id: 'find_channels.directory', defaultMessage: 'Directory'})}
+ testID='find_channels.quick_options.directory.option'
/>
>
@@ -84,6 +85,7 @@ const QuickOptions = ({canCreateChannels, canJoinChannels, close}: Props) => {
iconName='account-outline'
onPress={openDirectMessage}
text={intl.formatMessage({id: 'find_channels.open_dm', defaultMessage: 'Open a DM'})}
+ testID='find_channels.quick_options.open_dm.option'
/>
{canCreateChannels &&
<>
@@ -92,6 +94,7 @@ const QuickOptions = ({canCreateChannels, canJoinChannels, close}: Props) => {
iconName='plus'
onPress={createNewChannel}
text={intl.formatMessage({id: 'find_channels.new_channel', defaultMessage: 'New Channel'})}
+ testID='find_channels.quick_options.new_channel.option'
/>
>
}
diff --git a/app/screens/find_channels/unfiltered_list/unfiltered_list.tsx b/app/screens/find_channels/unfiltered_list/unfiltered_list.tsx
index 8ec103763..23073e0f9 100644
--- a/app/screens/find_channels/unfiltered_list/unfiltered_list.tsx
+++ b/app/screens/find_channels/unfiltered_list/unfiltered_list.tsx
@@ -21,6 +21,7 @@ type Props = {
recentChannels: ChannelModel[];
showTeamName: boolean;
unreadChannels: ChannelModel[];
+ testID?: string;
}
const sectionNames = {
@@ -57,7 +58,7 @@ const buildSections = (unreadChannels: ChannelModel[], recentChannels: ChannelMo
return sections;
};
-const UnfilteredList = ({close, keyboardHeight, recentChannels, showTeamName, unreadChannels}: Props) => {
+const UnfilteredList = ({close, keyboardHeight, recentChannels, showTeamName, unreadChannels, testID}: Props) => {
const intl = useIntl();
const serverUrl = useServerUrl();
const [sections, setSections] = useState(buildSections(unreadChannels, recentChannels));
@@ -79,6 +80,7 @@ const UnfilteredList = ({close, keyboardHeight, recentChannels, showTeamName, un
isInfo={true}
onPress={onPress}
showTeamName={showTeamName}
+ testID='find_channels.unfiltered_list.channel_item'
/>
);
}, [onPress, showTeamName]);
@@ -102,6 +104,7 @@ const UnfilteredList = ({close, keyboardHeight, recentChannels, showTeamName, un
sections={sections}
showsVerticalScrollIndicator={false}
stickySectionHeadersEnabled={true}
+ testID={`${testID}.section_list`}
/>
);
diff --git a/app/screens/home/account/components/user_info/index.tsx b/app/screens/home/account/components/user_info/index.tsx
index b9fd270b3..b25a421af 100644
--- a/app/screens/home/account/components/user_info/index.tsx
+++ b/app/screens/home/account/components/user_info/index.tsx
@@ -60,9 +60,9 @@ const AccountUserInfo = ({user, showFullName, theme}: Props) => {
iconSize={28}
showStatus={true}
author={user}
- testID={'account.profile_picture'}
statusStyle={styles.statusStyle}
statusSize={24}
+ testID={`account.${user.id}.profile_picture`}
/>
{showFullName && {title}}
{`${userName}`}
diff --git a/app/screens/home/channel_list/categories_list/__snapshots__/index.test.tsx.snap b/app/screens/home/channel_list/categories_list/__snapshots__/index.test.tsx.snap
index 8ef31d0e3..c7751077d 100644
--- a/app/screens/home/channel_list/categories_list/__snapshots__/index.test.tsx.snap
+++ b/app/screens/home/channel_list/categories_list/__snapshots__/index.test.tsx.snap
@@ -537,6 +537,7 @@ exports[`components/categories_list should render team error 1`] = `
"padding": 8,
}
}
+ testID="channel_list_subheader.search_field.button"
>
);
}, [onChannelSwitch]);
diff --git a/app/screens/home/channel_list/categories_list/categories/header/__snapshots__/header.test.tsx.snap b/app/screens/home/channel_list/categories_list/categories/header/__snapshots__/header.test.tsx.snap
index f320663ba..afaad54d5 100644
--- a/app/screens/home/channel_list/categories_list/categories/header/__snapshots__/header.test.tsx.snap
+++ b/app/screens/home/channel_list/categories_list/categories/header/__snapshots__/header.test.tsx.snap
@@ -17,7 +17,7 @@ exports[`components/channel_list/categories/header should match snapshot 1`] = `
"opacity": 1,
}
}
- testID="category_header.custom.collapsed.false"
+ testID="channel_list.category_header.custom.collapsed.false"
>
Test Category
diff --git a/app/screens/home/channel_list/categories_list/categories/header/header.tsx b/app/screens/home/channel_list/categories_list/categories/header/header.tsx
index 32db634a1..dbcdba6b4 100644
--- a/app/screens/home/channel_list/categories_list/categories/header/header.tsx
+++ b/app/screens/home/channel_list/categories_list/categories/header/header.tsx
@@ -97,7 +97,7 @@ const CategoryHeader = ({category, hasChannels}: Props) => {
return (
{
/>
{displayName}
diff --git a/app/screens/home/channel_list/categories_list/categories/unreads/unreads.tsx b/app/screens/home/channel_list/categories_list/categories/unreads/unreads.tsx
index 956f890eb..ee7f3fa98 100644
--- a/app/screens/home/channel_list/categories_list/categories/unreads/unreads.tsx
+++ b/app/screens/home/channel_list/categories_list/categories/unreads/unreads.tsx
@@ -51,6 +51,7 @@ const UnreadCategories = ({onChannelSwitch, onlyUnreads, unreadChannels, unreadT
);
}, [onChannelSwitch]);
diff --git a/app/screens/home/channel_list/categories_list/subheader/search_field/__snapshots__/index.test.tsx.snap b/app/screens/home/channel_list/categories_list/subheader/search_field/__snapshots__/index.test.tsx.snap
index 8b7d36ac3..e46851dd1 100644
--- a/app/screens/home/channel_list/categories_list/subheader/search_field/__snapshots__/index.test.tsx.snap
+++ b/app/screens/home/channel_list/categories_list/subheader/search_field/__snapshots__/index.test.tsx.snap
@@ -23,6 +23,7 @@ exports[`Search Field should match snapshot 1`] = `
"padding": 8,
}
}
+ testID="channel_list_subheader.search_field.button"
>
{
style={styles.container}
onPress={onPress}
underlayColor={changeOpacity(theme.sidebarText, 0.32)}
+ testID='channel_list_subheader.search_field.button'
>
<>
{
export const bottomSheetModalOptions = (theme: Theme, closeButtonId?: string) => {
if (closeButtonId) {
const closeButton = CompassIcon.getImageSourceSync('close', 24, theme.centerChannelColor);
+ const closeButtonTestId = `${closeButtonId.replace('close-', 'close.').replace(/-/g, '_')}.button`;
return {
modalPresentationStyle: OptionsModalPresentationStyle.formSheet,
modal: {
@@ -90,7 +91,7 @@ export const bottomSheetModalOptions = (theme: Theme, closeButtonId?: string) =>
leftButtons: [{
id: closeButtonId,
icon: closeButton,
- testID: closeButtonId,
+ testID: closeButtonTestId,
}],
leftButtonColor: changeOpacity(theme.centerChannelColor, 0.56),
background: {
@@ -724,7 +725,7 @@ export async function findChannels(title: string, theme: Theme) {
leftButtons: [{
id: closeButtonId,
icon: closeButton,
- testID: closeButtonId,
+ testID: 'close.find_channels.button',
}],
};
diff --git a/app/screens/post_options/reaction_bar/pick_reaction/index.tsx b/app/screens/post_options/reaction_bar/pick_reaction/index.tsx
index ebdc11dea..9ba29ab1a 100644
--- a/app/screens/post_options/reaction_bar/pick_reaction/index.tsx
+++ b/app/screens/post_options/reaction_bar/pick_reaction/index.tsx
@@ -37,7 +37,7 @@ const PickReaction = ({openEmojiPicker, width, height}: PickReactionProps) => {
style={[styles.container, {
width, height,
}]}
- testID='post_options.reaction_bar.pick_reaction'
+ testID='post_options.reaction_bar.pick_reaction.button'
>
{
ellipsizeMode='tail'
numberOfLines={1}
style={style.title}
+ testID={`emoji_aliases.${emoji}`}
>
{aliases}
diff --git a/app/screens/reactions/reactors_list/index.tsx b/app/screens/reactions/reactors_list/index.tsx
index b28af53f3..7c21fe950 100644
--- a/app/screens/reactions/reactors_list/index.tsx
+++ b/app/screens/reactions/reactors_list/index.tsx
@@ -66,6 +66,7 @@ const ReactorsList = ({location, reactions}: Props) => {
scrollEnabled={enabled}
scrollEventThrottle={60}
{...panResponder.panHandlers}
+ testID='reactors_list.flat_list'
/>
);
};
diff --git a/app/screens/reactions/reactors_list/reactor/reactor.tsx b/app/screens/reactions/reactors_list/reactor/reactor.tsx
index 78d15c74d..882fc95a0 100644
--- a/app/screens/reactions/reactors_list/reactor/reactor.tsx
+++ b/app/screens/reactions/reactors_list/reactor/reactor.tsx
@@ -45,6 +45,7 @@ const Reactor = ({channelId, location, user}: Props) => {
);
diff --git a/app/utils/server/index.ts b/app/utils/server/index.ts
index 978cf93f8..bf9687bf8 100644
--- a/app/utils/server/index.ts
+++ b/app/utils/server/index.ts
@@ -235,6 +235,7 @@ function unsupportedServerAlert(intl: IntlShape) {
function buildServerModalOptions(theme: Theme, closeButtonId: string) {
const closeButton = CompassIcon.getImageSourceSync('close', 24, changeOpacity(theme.centerChannelColor, 0.56));
+ const closeButtonTestId = `${closeButtonId.replace('close-', 'close.').replace(/-/g, '_')}.button`;
return {
layout: {
backgroundColor: theme.centerChannelBg,
@@ -251,7 +252,7 @@ function buildServerModalOptions(theme: Theme, closeButtonId: string) {
leftButtons: [{
id: closeButtonId,
icon: closeButton,
- testID: closeButtonId,
+ testID: closeButtonTestId,
}],
leftButtonColor: undefined,
title: {color: theme.sidebarHeaderTextColor},
diff --git a/detox/e2e/support/ui/component/index.ts b/detox/e2e/support/ui/component/index.ts
index 22b870998..e1ba26801 100644
--- a/detox/e2e/support/ui/component/index.ts
+++ b/detox/e2e/support/ui/component/index.ts
@@ -12,6 +12,7 @@ import Post from './post';
import PostDraft from './post_draft';
import PostList from './post_list';
import ProfilePicture from './profile_picture';
+import SearchBar from './search_bar';
import SendButton from './send_button';
import TeamSidebar from './team_sidebar';
@@ -27,6 +28,7 @@ export {
PostDraft,
PostList,
ProfilePicture,
+ SearchBar,
SendButton,
TeamSidebar,
};
diff --git a/detox/e2e/support/ui/component/post.ts b/detox/e2e/support/ui/component/post.ts
index 3402e8a5d..de48c6ddb 100644
--- a/detox/e2e/support/ui/component/post.ts
+++ b/detox/e2e/support/ui/component/post.ts
@@ -5,7 +5,7 @@ import ProfilePicture from './profile_picture';
class Post {
testID = {
- postProfilePicturePrefix: 'post_profile_picture.profile_picture.',
+ postProfilePicturePrefix: 'post_profile_picture.',
blockQuote: 'markdown_block_quote',
editedIndicator: 'edited_indicator',
emoji: 'markdown_emoji',
diff --git a/detox/e2e/support/ui/component/profile_picture.ts b/detox/e2e/support/ui/component/profile_picture.ts
index ef3a05423..510487fa9 100644
--- a/detox/e2e/support/ui/component/profile_picture.ts
+++ b/detox/e2e/support/ui/component/profile_picture.ts
@@ -7,7 +7,7 @@ class ProfilePicture {
};
getProfilePictureItemMatcher = (profilePictureSourcePrefix: string, userId: string) => {
- const profilePictureTestID = `${profilePictureSourcePrefix}${userId}`;
+ const profilePictureTestID = `${profilePictureSourcePrefix}${userId}.profile_picture`;
return by.id(profilePictureTestID);
};
diff --git a/detox/e2e/support/ui/component/search_bar.ts b/detox/e2e/support/ui/component/search_bar.ts
new file mode 100644
index 000000000..f99ca1689
--- /dev/null
+++ b/detox/e2e/support/ui/component/search_bar.ts
@@ -0,0 +1,35 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {isAndroid} from '@support/utils';
+
+class SearchBar {
+ testID = {
+ searchBarSuffix: 'search_bar',
+ searchInputSuffix: 'search_bar.search.input',
+ cancelButtonSuffix: 'search_bar.search.cancel.button',
+ clearButtonSuffix: 'search_bar.search.clear.button',
+ };
+
+ getSearchBar = (screenPrefix: string) => {
+ return element(by.id(`${screenPrefix}${this.testID.searchBarSuffix}`));
+ };
+
+ getSearchInput = (screenPrefix: string) => {
+ return element(by.id(`${screenPrefix}${this.testID.searchInputSuffix}`)).atIndex(0);
+ };
+
+ getCancelButton = (screenPrefix: string) => {
+ if (isAndroid()) {
+ return element(by.id(`${screenPrefix}${this.testID.cancelButtonSuffix}`)).atIndex(0);
+ }
+ return element(by.text('Cancel').withAncestor(by.id(`${screenPrefix}${this.testID.searchBarSuffix}`))).atIndex(0);
+ };
+
+ getClearButton = (screenPrefix: string) => {
+ return element(by.id(`${screenPrefix}${this.testID.clearButtonSuffix}`)).atIndex(0);
+ };
+}
+
+const searchBar = new SearchBar();
+export default searchBar;
diff --git a/detox/e2e/support/ui/screen/channel.ts b/detox/e2e/support/ui/screen/channel.ts
index c875c94ae..b526cdf17 100644
--- a/detox/e2e/support/ui/screen/channel.ts
+++ b/detox/e2e/support/ui/screen/channel.ts
@@ -87,7 +87,7 @@ class ChannelScreen {
open = async (categoryKey: string, channelName: string) => {
// # Open channel screen
- await ChannelListScreen.getChannelListItemDisplayName(categoryKey, channelName).tap();
+ await ChannelListScreen.getChannelItemDisplayName(categoryKey, channelName).tap();
return this.toBeVisible();
};
diff --git a/detox/e2e/support/ui/screen/channel_list.ts b/detox/e2e/support/ui/screen/channel_list.ts
index b7f934c9b..66c165a68 100644
--- a/detox/e2e/support/ui/screen/channel_list.ts
+++ b/detox/e2e/support/ui/screen/channel_list.ts
@@ -16,6 +16,7 @@ class ChannelListScreen {
headerServerDisplayName: 'channel_list_header.server_display_name',
headerChevronButton: 'channel_list_header.chevron.button',
headerPlusButton: 'channel_list_header.plus.button',
+ subheaderSearchFieldButton: 'channel_list_subheader.search_field.button',
findChannelsInput: 'channel_list.search_field.find_channels.input',
threadsButton: 'channel_list.threads.button',
};
@@ -26,6 +27,7 @@ class ChannelListScreen {
headerServerDisplayName = element(by.id(this.testID.headerServerDisplayName));
headerChevronButton = element(by.id(this.testID.headerChevronButton));
headerPlusButton = element(by.id(this.testID.headerPlusButton));
+ subheaderSearchFieldButton = element(by.id(this.testID.subheaderSearchFieldButton));
findChannelsInput = element(by.id(this.testID.findChannelsInput));
threadsButton = element(by.id(this.testID.threadsButton));
@@ -36,19 +38,23 @@ class ChannelListScreen {
openDirectMessageItem = PlusMenu.openDirectMessageItem;
getCategoryCollapsed = (categoryKey: string) => {
- return element(by.id(`category_header.${categoryKey}.collapsed.true`));
+ return element(by.id(`channel_list.category_header.${categoryKey}.collapsed.true`));
};
getCategoryExpanded = (categoryKey: string) => {
- return element(by.id(`category_header.${categoryKey}.collapsed.false`));
+ return element(by.id(`channel_list.category_header.${categoryKey}.collapsed.false`));
};
getCategoryHeaderDisplayName = (categoryKey: string) => {
- return element(by.id(`category_header.${categoryKey}.display_name`));
+ return element(by.id(`channel_list.category_header.${categoryKey}.display_name`));
};
- getChannelListItemDisplayName = (categoryKey: string, channelName: string) => {
- return element(by.id(`category.${categoryKey}.channel_list_item.${channelName}.display_name`));
+ getChannelItem = (categoryKey: string, channelName: string) => {
+ return element(by.id(`channel_list.category.${categoryKey}.channel_item.${channelName}`));
+ };
+
+ getChannelItemDisplayName = (categoryKey: string, channelName: string) => {
+ return element(by.id(`channel_list.category.${categoryKey}.channel_item.${channelName}.display_name`));
};
getTeamItemSelected = (teamId: string) => {
diff --git a/detox/e2e/support/ui/screen/edit_server.ts b/detox/e2e/support/ui/screen/edit_server.ts
index 7c537b60a..ffcb10704 100644
--- a/detox/e2e/support/ui/screen/edit_server.ts
+++ b/detox/e2e/support/ui/screen/edit_server.ts
@@ -2,11 +2,12 @@
// See LICENSE.txt for license information.
import {timeouts} from '@support/utils';
+import {expect} from 'detox';
class EditServerScreen {
testID = {
editServerScreen: 'edit_server.screen',
- closeButton: 'close-server-edit',
+ closeButton: 'close.server_edit.button',
headerTitle: 'edit_server_header.title',
headerDescription: 'edit_server_header.description',
serverDisplayNameInput: 'edit_server_form.server_display_name.input',
@@ -32,6 +33,11 @@ class EditServerScreen {
return this.editServerScreen;
};
+
+ close = async () => {
+ await this.closeButton.tap();
+ await expect(this.editServerScreen).not.toBeVisible();
+ };
}
const editServerScreen = new EditServerScreen();
diff --git a/detox/e2e/support/ui/screen/emoji_picker.ts b/detox/e2e/support/ui/screen/emoji_picker.ts
new file mode 100644
index 000000000..476b41b6c
--- /dev/null
+++ b/detox/e2e/support/ui/screen/emoji_picker.ts
@@ -0,0 +1,44 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {SearchBar} from '@support/ui/component';
+import {PostOptionsScreen} from '@support/ui/screen';
+import {expect} from 'detox';
+
+class EmojiPickerScreen {
+ testID = {
+ emojiPickerScreen: 'emoji_picker.screen',
+ emojiPickerPrefix: 'emoji_picker.',
+ closeButton: 'close.emoji_picker.button',
+ };
+
+ emojiPickerScreen = element(by.id(this.testID.emojiPickerScreen));
+ closeButton = element(by.id(this.testID.closeButton));
+
+ // convenience props
+ searchBar = SearchBar.getSearchBar(this.testID.emojiPickerPrefix);
+ searchInput = SearchBar.getSearchInput(this.testID.emojiPickerPrefix);
+ cancelButton = SearchBar.getCancelButton(this.testID.emojiPickerPrefix);
+ clearButton = SearchBar.getClearButton(this.testID.emojiPickerPrefix);
+
+ toBeVisible = async () => {
+ await expect(this.emojiPickerScreen).toBeVisible();
+
+ return this.emojiPickerScreen;
+ };
+
+ open = async () => {
+ // # Open add reaction screen
+ await PostOptionsScreen.pickReactionButton.tap();
+
+ return this.toBeVisible();
+ };
+
+ close = async () => {
+ await this.closeButton.tap();
+ await expect(this.emojiPickerScreen).not.toBeVisible();
+ };
+}
+
+const emojiPickerScreen = new EmojiPickerScreen();
+export default emojiPickerScreen;
diff --git a/detox/e2e/support/ui/screen/find_channels.ts b/detox/e2e/support/ui/screen/find_channels.ts
new file mode 100644
index 000000000..0154f583a
--- /dev/null
+++ b/detox/e2e/support/ui/screen/find_channels.ts
@@ -0,0 +1,71 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {SearchBar} from '@support/ui/component';
+import {ChannelListScreen} from '@support/ui/screen';
+import {timeouts} from '@support/utils';
+import {expect} from 'detox';
+
+class FindChannelsScreen {
+ testID = {
+ findChannelsScreen: 'find_channels.screen',
+ findChannelsPrefix: 'find_channels.',
+ closeButton: 'close.find_channels.button',
+ directoryQuickOption: 'find_channels.quick_options.directory.option',
+ openDirectMessageQuickOption: 'find_channels.quick_options.open_dm.option',
+ newChannelQuickOption: 'find_channels.quick_options.new_channel.option',
+ sectionUnfilteredChannelList: 'find_channels.unfiltered_list.section_list',
+ flatFilteredChannelList: 'find_channels.filtered_list.flat_list',
+ };
+
+ findChannelsScreen = element(by.id(this.testID.findChannelsScreen));
+ closeButton = element(by.id(this.testID.closeButton));
+ directoryQuickOption = element(by.id(this.testID.directoryQuickOption));
+ openDirectMessageQuickOption = element(by.id(this.testID.openDirectMessageQuickOption));
+ newChannelQuickOption = element(by.id(this.testID.newChannelQuickOption));
+ sectionUnfilteredChannelList = element(by.id(this.testID.sectionUnfilteredChannelList));
+ flatFilteredChannelList = element(by.id(this.testID.flatFilteredChannelList));
+
+ // convenience props
+ searchBar = SearchBar.getSearchBar(this.testID.findChannelsPrefix);
+ searchInput = SearchBar.getSearchInput(this.testID.findChannelsPrefix);
+ cancelButton = SearchBar.getCancelButton(this.testID.findChannelsPrefix);
+ clearButton = SearchBar.getClearButton(this.testID.findChannelsPrefix);
+
+ getUnfilteredChannelItem = (channelName: string) => {
+ return element(by.id(`find_channels.unfiltered_list.channel_item.${channelName}`));
+ };
+
+ getUnfilteredChannelItemDisplayName = (channelName: string) => {
+ return element(by.id(`find_channels.unfiltered_list.channel_item.${channelName}.display_name`));
+ };
+
+ getFilteredChannelItem = (channelName: string) => {
+ return element(by.id(`find_channels.filtered_list.channel_item.${channelName}`));
+ };
+
+ getFilteredChannelItemDisplayName = (channelName: string) => {
+ return element(by.id(`find_channels.filtered_list.channel_item.${channelName}.display_name`));
+ };
+
+ toBeVisible = async () => {
+ await waitFor(this.findChannelsScreen).toExist().withTimeout(timeouts.TEN_SEC);
+
+ return this.findChannelsScreen;
+ };
+
+ open = async () => {
+ // # Open find channels screen
+ await ChannelListScreen.subheaderSearchFieldButton.tap();
+
+ return this.toBeVisible();
+ };
+
+ close = async () => {
+ await this.closeButton.tap();
+ await expect(this.findChannelsScreen).not.toBeVisible();
+ };
+}
+
+const findChannelsScreen = new FindChannelsScreen();
+export default findChannelsScreen;
diff --git a/detox/e2e/support/ui/screen/index.ts b/detox/e2e/support/ui/screen/index.ts
index 71e47d8d6..3f28c9d16 100644
--- a/detox/e2e/support/ui/screen/index.ts
+++ b/detox/e2e/support/ui/screen/index.ts
@@ -10,11 +10,14 @@ import CreateDirectMessageScreen from './create_direct_message';
import CreateOrEditChannelScreen from './create_or_edit_channel';
import EditPostScreen from './edit_post';
import EditServerScreen from './edit_server';
+import EmojiPickerScreen from './emoji_picker';
+import FindChannelsScreen from './find_channels';
import GlobalThreadsScreen from './global_threads';
import HomeScreen from './home';
import LoginScreen from './login';
import PermalinkScreen from './permalink';
import PostOptionsScreen from './post_options';
+import ReactionsScreen from './reactions';
import ServerScreen from './server';
import ServerListScreen from './server_list';
import ThreadScreen from './thread';
@@ -30,11 +33,14 @@ export {
CreateOrEditChannelScreen,
EditPostScreen,
EditServerScreen,
+ EmojiPickerScreen,
+ FindChannelsScreen,
GlobalThreadsScreen,
HomeScreen,
LoginScreen,
PermalinkScreen,
PostOptionsScreen,
+ ReactionsScreen,
ServerScreen,
ServerListScreen,
ThreadScreen,
diff --git a/detox/e2e/support/ui/screen/post_options.ts b/detox/e2e/support/ui/screen/post_options.ts
index fe991557a..c52d7137d 100644
--- a/detox/e2e/support/ui/screen/post_options.ts
+++ b/detox/e2e/support/ui/screen/post_options.ts
@@ -10,7 +10,7 @@ class PostOptionsScreen {
reactionEmojiPrefix: 'post_options.reaction_bar.reaction.',
postOptionsScreen: 'post_options.screen',
postOptionsBackdrop: 'post_options.backdrop',
- pickReaction: 'post_options.reaction_bar.pick_reaction',
+ pickReactionButton: 'post_options.reaction_bar.pick_reaction.button',
replyPostOption: 'post_options.reply_post.option',
followThreadOption: 'post_options.follow_thread.option',
followingThreadOption: 'post_options.following_thread.option',
@@ -27,7 +27,7 @@ class PostOptionsScreen {
postOptionsScreen = element(by.id(this.testID.postOptionsScreen));
postOptionsBackdrop = element(by.id(this.testID.postOptionsBackdrop));
- pickReaction = element(by.id(this.testID.pickReaction));
+ pickReactionButton = element(by.id(this.testID.pickReactionButton));
replyPostOption = element(by.id(this.testID.replyPostOption));
followThreadOption = element(by.id(this.testID.followThreadOption));
followingThreadOption = element(by.id(this.testID.followingThreadOption));
diff --git a/detox/e2e/support/ui/screen/reactions.ts b/detox/e2e/support/ui/screen/reactions.ts
new file mode 100644
index 000000000..4a450092d
--- /dev/null
+++ b/detox/e2e/support/ui/screen/reactions.ts
@@ -0,0 +1,48 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {expect} from 'detox';
+
+class ReactionsScreen {
+ testID = {
+ reactorItemPrefix: 'reactors_list.user_item.',
+ reactionsScreen: 'reactions.screen',
+ reactionsBackdrop: 'reactions.backdrop',
+ flatReactorsList: 'reactors_list.flat_list',
+ };
+
+ reactionsScreen = element(by.id(this.testID.reactionsScreen));
+ reactionsBackdrop = element(by.id(this.testID.reactionsBackdrop));
+ flatReactorsList = element(by.id(this.testID.flatReactorsList));
+
+ toBeVisible = async () => {
+ await expect(this.reactionsScreen).toExist();
+
+ return reactionsScreen;
+ };
+
+ close = async () => {
+ await this.reactionsBackdrop.tap({x: 5, y: 10});
+ await expect(this.reactionsScreen).not.toBeVisible();
+ };
+
+ getReactorItem = (userId: string, emojiName: string) => {
+ const reactorItemEmojiAliasesMatcher = by.id(`emoji_aliases.${emojiName}`);
+ const reactorItemUserTestId = `${this.testID.reactorItemPrefix}${userId}`;
+ const reactorItemUserMatcher = by.id(reactorItemUserTestId);
+ const reactorItemUserProfilePictureMatcher = by.id(`${reactorItemUserTestId}.profile_picture`);
+ const reactorItemUserDisplayNameMatcher = by.id(`${reactorItemUserTestId}.display_name`);
+ const reactorItemUserUsernameMatcher = by.id(`${reactorItemUserTestId}.username`);
+
+ return {
+ reactorItemEmojiAliases: element(reactorItemEmojiAliasesMatcher),
+ reactorItemUser: element(reactorItemUserMatcher),
+ reactorItemUserProfilePicture: element(reactorItemUserProfilePictureMatcher),
+ reactorItemUserDisplayName: element(reactorItemUserDisplayNameMatcher),
+ reactorItemUserUsername: element(reactorItemUserUsernameMatcher),
+ };
+ };
+}
+
+const reactionsScreen = new ReactionsScreen();
+export default reactionsScreen;
diff --git a/detox/e2e/support/ui/screen/server.ts b/detox/e2e/support/ui/screen/server.ts
index fb6b6b6c1..61f5966fb 100644
--- a/detox/e2e/support/ui/screen/server.ts
+++ b/detox/e2e/support/ui/screen/server.ts
@@ -7,7 +7,7 @@ import {expect} from 'detox';
class ServerScreen {
testID = {
serverScreen: 'server.screen',
- closeButton: 'close-server',
+ closeButton: 'close.server.button',
headerTitleAddServer: 'server_header.title.add_server',
headerTitleConnectToServer: 'server_header.title.connect_to_server',
headerWelcome: 'server_header.welcome',
diff --git a/detox/e2e/test/channels/browse_channels.e2e.ts b/detox/e2e/test/channels/browse_channels.e2e.ts
index b74bb6687..4b49f6adf 100644
--- a/detox/e2e/test/channels/browse_channels.e2e.ts
+++ b/detox/e2e/test/channels/browse_channels.e2e.ts
@@ -67,7 +67,7 @@ describe('Channels - Browse Channels', () => {
const {channel} = await Channel.apiCreateChannel(siteOneUrl, {teamId: testTeam.id});
// * Verify new channel does not appear on channel list screen
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, channel.display_name)).not.toExist();
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, channel.display_name)).not.toExist();
// # Open browse channels screen and search for the new channel name to join
await BrowseChannelsScreen.open();
@@ -89,6 +89,20 @@ describe('Channels - Browse Channels', () => {
await ChannelListScreen.toBeVisible();
// * Verify newly joined channel is added to channel list
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, channel.name)).toBeVisible();
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, channel.name)).toBeVisible();
+ });
+
+ it('MM-T4729_3 - should display empty search state for browse channels', async () => {
+ // # Open browse channels screen and search for a non-existent channel
+ const searchTerm = 'blahblahblahblah';
+ await BrowseChannelsScreen.open();
+ await BrowseChannelsScreen.searchInput.replaceText(searchTerm);
+
+ // * Verify empty search state for browse channels
+ await expect(element(by.text(`No results for “${searchTerm}”`))).toBeVisible();
+ await expect(element(by.text('Check the spelling or try another search.'))).toBeVisible();
+
+ // # Go back to channel list screen
+ await BrowseChannelsScreen.close();
});
});
diff --git a/detox/e2e/test/channels/channel_list.e2e.ts b/detox/e2e/test/channels/channel_list.e2e.ts
index 5e426d450..143048cc0 100644
--- a/detox/e2e/test/channels/channel_list.e2e.ts
+++ b/detox/e2e/test/channels/channel_list.e2e.ts
@@ -22,6 +22,7 @@ import {
ChannelListScreen,
CreateDirectMessageScreen,
CreateOrEditChannelScreen,
+ FindChannelsScreen,
GlobalThreadsScreen,
HomeScreen,
LoginScreen,
@@ -75,15 +76,15 @@ describe('Channels - Channel List', () => {
await expect(ChannelListScreen.headerPlusButton).toBeVisible();
await expect(ChannelListScreen.threadsButton).toBeVisible();
await expect(ChannelListScreen.getCategoryHeaderDisplayName(channelsCategory)).toHaveText('CHANNELS');
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, testChannel.name)).toHaveText(testChannel.display_name);
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, offTopicChannelName)).toHaveText('Off-Topic');
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, townSquareChannelName)).toHaveText('Town Square');
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, testChannel.name)).toHaveText(testChannel.display_name);
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, offTopicChannelName)).toHaveText('Off-Topic');
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, townSquareChannelName)).toHaveText('Town Square');
await expect(ChannelListScreen.getCategoryHeaderDisplayName(directMessagesCategory)).toHaveText('DIRECT MESSAGES');
});
it('MM-T4728_2 - should be able to switch between channels', async () => {
// # Tap on a first channel
- await ChannelListScreen.getChannelListItemDisplayName(channelsCategory, testChannel.name).tap();
+ await ChannelListScreen.getChannelItemDisplayName(channelsCategory, testChannel.name).tap();
// * Verify on first channel
await ChannelScreen.toBeVisible();
@@ -93,7 +94,7 @@ describe('Channels - Channel List', () => {
// # Go back to channel list screen and tap on a second channel
await ChannelScreen.back();
await ChannelListScreen.toBeVisible();
- await ChannelListScreen.getChannelListItemDisplayName(channelsCategory, offTopicChannelName).tap();
+ await ChannelListScreen.getChannelItemDisplayName(channelsCategory, offTopicChannelName).tap();
// * Verify on second channel
await ChannelScreen.toBeVisible();
@@ -117,18 +118,18 @@ describe('Channels - Channel List', () => {
// * Verify category is collapsed and channels are not listed
await expect(ChannelListScreen.getCategoryCollapsed(channelsCategory)).toBeVisible();
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, testChannel.name)).not.toBeVisible();
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, offTopicChannelName)).not.toBeVisible();
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, townSquareChannelName)).not.toBeVisible();
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, testChannel.name)).not.toBeVisible();
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, offTopicChannelName)).not.toBeVisible();
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, townSquareChannelName)).not.toBeVisible();
// # Toggle channels category to expand
await ChannelListScreen.getCategoryCollapsed(channelsCategory).tap();
// * Verify category is expanded and all channels are listed
await expect(ChannelListScreen.getCategoryExpanded(channelsCategory)).toBeVisible();
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, testChannel.name)).toBeVisible();
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, offTopicChannelName)).toBeVisible();
- await expect(ChannelListScreen.getChannelListItemDisplayName(channelsCategory, townSquareChannelName)).toBeVisible();
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, testChannel.name)).toBeVisible();
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, offTopicChannelName)).toBeVisible();
+ await expect(ChannelListScreen.getChannelItemDisplayName(channelsCategory, townSquareChannelName)).toBeVisible();
});
it('MM-T4728_4 - should be able to go to browse channels screen', async () => {
@@ -179,8 +180,15 @@ describe('Channels - Channel List', () => {
await GlobalThreadsScreen.back();
});
- xit('MM-T4728_8 - should be able to find channels', async () => {
- // NOT YET IMPLEMENTED
+ it('MM-T4728_8 - should be able to go to find channels screen', async () => {
+ // # Tap on search field button
+ await ChannelListScreen.subheaderSearchFieldButton.tap();
+
+ // * Verify on find channels screen
+ await FindChannelsScreen.toBeVisible();
+
+ // # Go back to channel list screen
+ await FindChannelsScreen.close();
});
it('MM-T4728_9 - should be able to switch between teams', async () => {
diff --git a/detox/e2e/test/channels/create_direct_message.e2e.ts b/detox/e2e/test/channels/create_direct_message.e2e.ts
index 3d0ee5670..eadc5b1b3 100644
--- a/detox/e2e/test/channels/create_direct_message.e2e.ts
+++ b/detox/e2e/test/channels/create_direct_message.e2e.ts
@@ -75,7 +75,7 @@ describe('Channels - Create Direct Message', () => {
// * Verify no direct message channel for the new user appears on channel list screen
const newUserDisplayName = newUser.username;
- await expect(ChannelListScreen.getChannelListItemDisplayName(directMessagesCategory, newUserDisplayName)).not.toBeVisible();
+ await expect(ChannelListScreen.getChannelItemDisplayName(directMessagesCategory, newUserDisplayName)).not.toBeVisible();
// # Open create direct message screen and search for the new user
await CreateDirectMessageScreen.open();
@@ -105,7 +105,7 @@ describe('Channels - Create Direct Message', () => {
// * Verify direct message channel for the new user is added to direct message list
const {channel: directMessageChannel} = await Channel.apiCreateDirectChannel(siteOneUrl, [testUser.id, newUser.id]);
- await expect(ChannelListScreen.getChannelListItemDisplayName(directMessagesCategory, directMessageChannel.name)).toHaveText(newUserDisplayName);
+ await expect(ChannelListScreen.getChannelItemDisplayName(directMessagesCategory, directMessageChannel.name)).toHaveText(newUserDisplayName);
});
it('MM-T4730_3 - should be able to create a group message', async () => {
@@ -152,4 +152,18 @@ describe('Channels - Create Direct Message', () => {
// * Verify group message channel for the other two new users is added to direct message list
await expect(element(by.text(groupDisplayName))).toBeVisible();
});
+
+ it('MM-T4730_4 - should display empty search state for create direct message', async () => {
+ // # Open create direct message screen and search for a non-existent user
+ const searchTerm = 'blahblahblahblah';
+ await CreateDirectMessageScreen.open();
+ await CreateDirectMessageScreen.searchInput.replaceText(searchTerm);
+
+ // * Verify empty search state for create direct message
+ await expect(element(by.text(`No results for “${searchTerm}”`))).toBeVisible();
+ await expect(element(by.text('Check the spelling or try another search.'))).toBeVisible();
+
+ // # Go back to channel list screen
+ await CreateDirectMessageScreen.close();
+ });
});
diff --git a/detox/e2e/test/messaging/emojis_and_reactions.e2e.ts b/detox/e2e/test/messaging/emojis_and_reactions.e2e.ts
new file mode 100644
index 000000000..b3a958909
--- /dev/null
+++ b/detox/e2e/test/messaging/emojis_and_reactions.e2e.ts
@@ -0,0 +1,181 @@
+// 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,
+ EmojiPickerScreen,
+ HomeScreen,
+ LoginScreen,
+ PostOptionsScreen,
+ ReactionsScreen,
+ ServerScreen,
+} from '@support/ui/screen';
+import {getRandomId} from '@support/utils';
+import {expect} from 'detox';
+
+describe('Messaging - Emojis and Reactions', () => {
+ const serverOneDisplayName = 'Server 1';
+ const channelsCategory = 'channels';
+ let testChannel: any;
+ let testUser: any;
+
+ beforeAll(async () => {
+ const {channel, user} = await Setup.apiInit(siteOneUrl);
+ testChannel = channel;
+ testUser = user;
+
+ // # 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-T4862_1 - should be able to view recent reactions and add new reaction via post options', async () => {
+ // # Open a channel screen, post a message, and open post options for message
+ 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);
+
+ // * Verify six default reactions are displayed
+ await expect(PostOptionsScreen.getReactionEmoji('+1')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('smiley')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('white_check_mark')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('heart')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('eyes')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('raised_hands')).toBeVisible();
+
+ // # Open emoji picker screen and add a new reaction
+ await EmojiPickerScreen.open();
+ await EmojiPickerScreen.searchInput.typeText('clown_face');
+ await element(by.text('🤡')).tap();
+
+ // * Verify new reaction is added to the message
+ await expect(element(by.text('🤡').withAncestor(by.id(`channel.post_list.post.${post.id}`)))).toBeVisible();
+
+ // # Open post options for message
+ await ChannelScreen.openPostOptionsFor(post.id, message);
+
+ // * Verify recent reactions are displayed, newest reaction first and then the first five default reactions
+ await expect(PostOptionsScreen.getReactionEmoji('clown_face')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('+1')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('smiley')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('white_check_mark')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('heart')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('eyes')).toBeVisible();
+ await expect(PostOptionsScreen.getReactionEmoji('raised_hands')).not.toBeVisible();
+
+ // # Go back to channel list screen
+ await PostOptionsScreen.close();
+ await ChannelScreen.back();
+ });
+
+ it('MM-T4862_2 - should be able to long press on a reaction to view the list of users who reacted', async () => {
+ // # Open a channel screen, post a message, open post options for message, open emoji picker screen, and add a reaction
+ 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 EmojiPickerScreen.open();
+ await EmojiPickerScreen.searchInput.typeText('fire');
+ await element(by.text('🔥')).tap();
+
+ // * Verify reaction is added to the message
+ const reaction = element(by.text('🔥').withAncestor(by.id(`channel.post_list.post.${post.id}`)));
+ await expect(reaction).toBeVisible();
+
+ // # Long press on the reaction
+ await reaction.longPress();
+
+ // * Verify user who reacted with the emoji
+ await ReactionsScreen.toBeVisible();
+ const {reactorItemEmojiAliases, reactorItemUserProfilePicture, reactorItemUserDisplayName, reactorItemUserUsername} = ReactionsScreen.getReactorItem(testUser.id, 'fire');
+ await expect(reactorItemEmojiAliases).toHaveText(':fire:');
+ await expect(reactorItemUserProfilePicture).toBeVisible();
+ await expect(reactorItemUserDisplayName).toHaveText(`${testUser.first_name} ${testUser.last_name}`);
+ await expect(reactorItemUserUsername).toHaveText(` @${testUser.username}`);
+
+ // # Go back to channel list screen
+ await ReactionsScreen.close();
+ await ChannelScreen.back();
+ });
+
+ it('MM-T4862_3 - should be able to include emojis in a message and be able to find them in emoji bar and recently used section', async () => {
+ // # Open a channel screen and post a message that includes emojis
+ const message = 'The quick brown fox :fox_face: jumps over the lazy dog :dog:';
+ await ChannelScreen.open(channelsCategory, testChannel.name);
+ await ChannelScreen.postMessage(message);
+
+ // * Verify message is posted with emojis
+ const resolvedMessage = 'The quick brown fox 🦊 jumps over the lazy dog 🐶';
+ const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
+ const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, resolvedMessage);
+ await expect(postListPostItem).toBeVisible();
+
+ // # Open post options for message
+ await ChannelScreen.openPostOptionsFor(post.id, resolvedMessage);
+ await PostOptionsScreen.toBeVisible();
+
+ // * Verify emojis exist in emoji bar
+ await expect(element(by.text('🦊'))).toExist();
+ await expect(element(by.text('🐶'))).toExist();
+
+ // # Open emoji picker screen
+ await EmojiPickerScreen.open();
+
+ // * Verify emojis exist in recently used section
+ await expect(element(by.text('Recently Used'))).toExist();
+ await expect(element(by.text('🦊'))).toExist();
+ await expect(element(by.text('🐶'))).toExist();
+
+ // # Go back to channel list screen
+ await EmojiPickerScreen.close();
+ await ChannelScreen.back();
+ });
+
+ it('MM-T4862_4 - should display empty search state for emoji picker', async () => {
+ // # Open a channel screen, post a message, open post options for message, open emoji picker screen, and search for a non-existent emoji
+ const message = `Message ${getRandomId()}`;
+ await ChannelScreen.open(channelsCategory, testChannel.name);
+ await ChannelScreen.postMessage(message);
+ const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
+ const searchTerm = 'blahblahblahblah';
+ await ChannelScreen.openPostOptionsFor(post.id, message);
+ await EmojiPickerScreen.open();
+ await EmojiPickerScreen.searchInput.typeText(searchTerm);
+
+ // * Verify empty search state for emoji picker
+ await expect(element(by.text(`No results for “${searchTerm}”`))).toBeVisible();
+ await expect(element(by.text('Check the spelling or try another search.'))).toBeVisible();
+
+ // # Go back to channel list screen
+ await EmojiPickerScreen.close();
+ await ChannelScreen.back();
+ });
+});
diff --git a/detox/e2e/test/messaging/follow_and_unfollow_messsage.e2e.ts b/detox/e2e/test/messaging/follow_and_unfollow_messsage.e2e.ts
new file mode 100644
index 000000000..f232e3587
--- /dev/null
+++ b/detox/e2e/test/messaging/follow_and_unfollow_messsage.e2e.ts
@@ -0,0 +1,105 @@
+// 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,
+ HomeScreen,
+ LoginScreen,
+ PostOptionsScreen,
+ ServerScreen,
+} from '@support/ui/screen';
+import {getRandomId} from '@support/utils';
+import {expect} from 'detox';
+
+describe('Messaging - Follow and Unfollow Message', () => {
+ const serverOneDisplayName = 'Server 1';
+ const channelsCategory = 'channels';
+ 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-T4863_1 - should be able to follow/unfollow a message via post options', async () => {
+ // # Open a channel screen and post a message
+ const message = `Message ${getRandomId()}`;
+ await ChannelScreen.open(channelsCategory, testChannel.name);
+ await ChannelScreen.postMessage(message);
+
+ // * Verify message is posted
+ const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
+ const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
+ await expect(postListPostItem).toBeVisible();
+
+ // # Open post options for message and tap on follow message option
+ await ChannelScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.followThreadOption.tap();
+
+ // * Verify message is followed by user via post footer
+ const {postListPostItemFooterFollowingButton} = ChannelScreen.getPostListPostItem(post.id, message);
+ await expect(postListPostItemFooterFollowingButton).toBeVisible();
+
+ // # Open post options for message and tap on unfollow message option
+ await ChannelScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.followingThreadOption.tap();
+
+ // * Verify message is not followed by user via post footer
+ await expect(postListPostItemFooterFollowingButton).not.toBeVisible();
+
+ // # Go back to channel list screen
+ await ChannelScreen.back();
+ });
+
+ it('MM-T4863_2 - should be able to unfollow a message via post footer', async () => {
+ // # Open a channel screen, post a message, open post options for message, and tap on follow message 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.followThreadOption.tap();
+
+ // * Verify message is followed by user via post footer
+ const {postListPostItemFooterFollowingButton} = ChannelScreen.getPostListPostItem(post.id, message);
+ await expect(postListPostItemFooterFollowingButton).toBeVisible();
+
+ // # Tap on following button via post footer
+ await postListPostItemFooterFollowingButton.tap();
+
+ // * Verify message is not followed by user via post footer
+ await expect(postListPostItemFooterFollowingButton).not.toBeVisible();
+
+ // # Go back to channel list screen
+ await ChannelScreen.back();
+ });
+});
diff --git a/detox/e2e/test/messaging/message_reply.e2e.ts b/detox/e2e/test/messaging/message_reply.e2e.ts
index 659c17e10..44395bb98 100644
--- a/detox/e2e/test/messaging/message_reply.e2e.ts
+++ b/detox/e2e/test/messaging/message_reply.e2e.ts
@@ -85,7 +85,7 @@ describe('Messaging - Message Reply', () => {
await ChannelScreen.back();
});
- it('MM-T4785_2 - should be able to open reply thread by tapping the post', async () => {
+ it('MM-T4785_2 - should be able to open reply thread by tapping on the post', async () => {
// # Open a channel screen and post a message
const message = `Message ${getRandomId()}`;
await ChannelScreen.open(channelsCategory, testChannel.name);
@@ -96,7 +96,7 @@ describe('Messaging - Message Reply', () => {
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
await expect(postListPostItem).toExist();
- // # Tap the post
+ // # Tap on post to open thread
await postListPostItem.tap();
// * Verify on reply thread screen
diff --git a/detox/e2e/test/messaging/pin_and_unpin_message.e2e.ts b/detox/e2e/test/messaging/pin_and_unpin_message.e2e.ts
new file mode 100644
index 000000000..0e09c856e
--- /dev/null
+++ b/detox/e2e/test/messaging/pin_and_unpin_message.e2e.ts
@@ -0,0 +1,111 @@
+// 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,
+ HomeScreen,
+ LoginScreen,
+ PostOptionsScreen,
+ ServerScreen,
+ ThreadScreen,
+} from '@support/ui/screen';
+import {getRandomId} from '@support/utils';
+import {expect} from 'detox';
+
+describe('Messaging - Pin and Unpin Message', () => {
+ 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-T4865_1 - should be able to pin/unpin a message via post options on channel screen', async () => {
+ // # Open a channel screen and post a message
+ const message = `Message ${getRandomId()}`;
+ await ChannelScreen.open(channelsCategory, testChannel.name);
+ await ChannelScreen.postMessage(message);
+
+ // * Verify message is posted
+ const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
+ const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
+ await expect(postListPostItem).toBeVisible();
+
+ // # Open post options for message and tap on pin to channel option
+ 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 post options for message and tap on unpin from channel option
+ await ChannelScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.unpinPostOption.tap();
+
+ // * Verify pinned text is not displayed on the post pre-header
+ await expect(postListPostItemPreHeaderText).not.toBeVisible();
+
+ // # Go back to channel list screen
+ await ChannelScreen.back();
+ });
+
+ it('MM-T4865_2 - should be able to pin/unpin a message via post options on thread screen', async () => {
+ // # Open a channel screen, post a message, tap on post to open thread, 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);
+ const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
+ await postListPostItem.tap();
+ await ThreadScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.pinPostOption.tap();
+
+ // * Verify pinned text is displayed on the post pre-header
+ const {postListPostItemPreHeaderText} = ThreadScreen.getPostListPostItem(post.id, message);
+ await expect(postListPostItemPreHeaderText).toHaveText(pinnedText);
+
+ // # Open post options for message and tap on unpin from channel option
+ await ThreadScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.unpinPostOption.tap();
+
+ // * Verify pinned text is not displayed on the post pre-header
+ await expect(postListPostItemPreHeaderText).not.toBeVisible();
+
+ // # Go back to channel list screen
+ await ThreadScreen.back();
+ await ChannelScreen.back();
+ });
+});
diff --git a/detox/e2e/test/messaging/save_and_unsave_message.e2e.ts b/detox/e2e/test/messaging/save_and_unsave_message.e2e.ts
new file mode 100644
index 000000000..edaaa1482
--- /dev/null
+++ b/detox/e2e/test/messaging/save_and_unsave_message.e2e.ts
@@ -0,0 +1,111 @@
+// 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,
+ HomeScreen,
+ LoginScreen,
+ PostOptionsScreen,
+ ServerScreen,
+ ThreadScreen,
+} from '@support/ui/screen';
+import {getRandomId} from '@support/utils';
+import {expect} from 'detox';
+
+describe('Messaging - Save and Unsave Message', () => {
+ const serverOneDisplayName = 'Server 1';
+ const channelsCategory = 'channels';
+ const savedText = 'Saved';
+ 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-T4864_1 - should be able to save/unsave a message via post options on channel screen', async () => {
+ // # Open a channel screen and post a message
+ const message = `Message ${getRandomId()}`;
+ await ChannelScreen.open(channelsCategory, testChannel.name);
+ await ChannelScreen.postMessage(message);
+
+ // * Verify message is posted
+ const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
+ const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
+ await expect(postListPostItem).toBeVisible();
+
+ // # Open post options for message and tap on save option
+ await ChannelScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.savePostOption.tap();
+
+ // * Verify saved text is displayed on the post pre-header
+ const {postListPostItemPreHeaderText} = ChannelScreen.getPostListPostItem(post.id, message);
+ await expect(postListPostItemPreHeaderText).toHaveText(savedText);
+
+ // # Open post options for message and tap on unsave option
+ await ChannelScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.unsavePostOption.tap();
+
+ // * Verify saved text is not displayed on the post pre-header
+ await expect(postListPostItemPreHeaderText).not.toBeVisible();
+
+ // # Go back to channel list screen
+ await ChannelScreen.back();
+ });
+
+ it('MM-T4864_2 - should be able to save/unsave a message via post options on thread screen', async () => {
+ // # Open a channel screen, post a message, tap on post to open thread, open post options for message, and tap on save option
+ const message = `Message ${getRandomId()}`;
+ await ChannelScreen.open(channelsCategory, testChannel.name);
+ await ChannelScreen.postMessage(message);
+ const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
+ const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
+ await postListPostItem.tap();
+ await ThreadScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.savePostOption.tap();
+
+ // * Verify saved text is displayed on the post pre-header
+ const {postListPostItemPreHeaderText} = ThreadScreen.getPostListPostItem(post.id, message);
+ await expect(postListPostItemPreHeaderText).toHaveText(savedText);
+
+ // # Open post options for message and tap on unsave option
+ await ThreadScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.unsavePostOption.tap();
+
+ // * Verify saved text is not displayed on the post pre-header
+ await expect(postListPostItemPreHeaderText).not.toBeVisible();
+
+ // # Go back to channel list screen
+ await ThreadScreen.back();
+ await ChannelScreen.back();
+ });
+});
diff --git a/detox/e2e/test/server_login/connect_to_server.e2e.ts b/detox/e2e/test/server_login/connect_to_server.e2e.ts
index 7e0b8efbf..755279b4c 100644
--- a/detox/e2e/test/server_login/connect_to_server.e2e.ts
+++ b/detox/e2e/test/server_login/connect_to_server.e2e.ts
@@ -85,6 +85,7 @@ describe('Server Login - Connect to Server', () => {
await expect(serverUrlInputError).toHaveText(connectionError);
// # Connect with invalid host and valid server display name
+ await device.reloadReactNative();
await serverUrlInput.replaceText('wrong.host.badssl.com');
await serverDisplayNameInput.replaceText('Server 1');
await connectButton.tap();
diff --git a/detox/e2e/test/server_login/server_list.e2e.ts b/detox/e2e/test/server_login/server_list.e2e.ts
index e937185a5..39129d181 100644
--- a/detox/e2e/test/server_login/server_list.e2e.ts
+++ b/detox/e2e/test/server_login/server_list.e2e.ts
@@ -91,6 +91,7 @@ describe('Server Login - Server List', () => {
// * Verify on channel list screen of the second server
await ChannelListScreen.toBeVisible();
+ await device.reloadReactNative();
await expect(ChannelListScreen.headerServerDisplayName).toHaveText(serverTwoDisplayName);
// # Open server list screen
diff --git a/detox/e2e/test/smoke_test/messaging.e2e.ts b/detox/e2e/test/smoke_test/messaging.e2e.ts
index d3e1ec1ba..23365a6d7 100644
--- a/detox/e2e/test/smoke_test/messaging.e2e.ts
+++ b/detox/e2e/test/smoke_test/messaging.e2e.ts
@@ -19,6 +19,7 @@ import {
ChannelScreen,
ChannelListScreen,
EditPostScreen,
+ EmojiPickerScreen,
HomeScreen,
LoginScreen,
PostOptionsScreen,
@@ -31,6 +32,8 @@ import {expect} from 'detox';
describe('Smoke Test - Messaging', () => {
const serverOneDisplayName = 'Server 1';
const channelsCategory = 'channels';
+ const savedText = 'Saved';
+ const pinnedText = 'Pinned';
let testChannel: any;
beforeAll(async () => {
@@ -116,4 +119,83 @@ describe('Smoke Test - Messaging', () => {
await ThreadScreen.back();
await ChannelScreen.back();
});
+
+ it('MM-T4786_3 - should be able to include emojis in a message and add reaction to a message', async () => {
+ // # Open a channel screen and post a message that includes emojis
+ const message = 'The quick brown fox :fox_face: jumps over the lazy dog :dog:';
+ await ChannelScreen.open(channelsCategory, testChannel.name);
+ await ChannelScreen.postMessage(message);
+
+ // * Verify message is posted with emojis
+ const resolvedMessage = 'The quick brown fox 🦊 jumps over the lazy dog 🐶';
+ const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
+ const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, resolvedMessage);
+ await expect(postListPostItem).toBeVisible();
+
+ // # Open post options for message, open emoji picker screen, and add a reaction
+ await ChannelScreen.openPostOptionsFor(post.id, resolvedMessage);
+ await EmojiPickerScreen.open();
+ await EmojiPickerScreen.searchInput.typeText('clown_face');
+ await element(by.text('🤡')).tap();
+
+ // * Verify reaction is added to the message
+ await expect(element(by.text('🤡').withAncestor(by.id(`channel.post_list.post.${post.id}`)))).toBeVisible();
+
+ // # Go back to channel list screen
+ await ChannelScreen.back();
+ });
+
+ it('MM-T4786_4 - should be able to follow/unfollow a message, save/unsave a message, and pin/unpin a message', async () => {
+ // # Open a channel screen, post a message, open post options for message, and tap on follow message 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.followThreadOption.tap();
+
+ // * Verify message is followed by user via post footer
+ const {postListPostItem, postListPostItemFooterFollowingButton} = ChannelScreen.getPostListPostItem(post.id, message);
+ await expect(postListPostItemFooterFollowingButton).toBeVisible();
+
+ // # Tap on following button via post footer
+ await postListPostItemFooterFollowingButton.tap();
+
+ // * Verify message is not followed by user via post footer
+ await expect(postListPostItemFooterFollowingButton).not.toBeVisible();
+
+ // # Open post options for message and tap on save option
+ await ChannelScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.savePostOption.tap();
+
+ // * Verify saved text is displayed on the post pre-header
+ const {postListPostItemPreHeaderText: channelPostListPostItemPreHeaderText} = ChannelScreen.getPostListPostItem(post.id, message);
+ await expect(channelPostListPostItemPreHeaderText).toHaveText(savedText);
+
+ // # Tap on post to open thread and tap on thread overview unsave button
+ await postListPostItem.tap();
+ await ThreadScreen.getThreadOverviewUnsaveButton().tap();
+
+ // * Verify saved text is not displayed on the post pre-header
+ await expect(channelPostListPostItemPreHeaderText).not.toBeVisible();
+
+ // # Open post options for message and tap on pin to channel option
+ await ThreadScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.pinPostOption.tap();
+
+ // * Verify pinned text is displayed on the post pre-header
+ const {postListPostItemPreHeaderText: threadPostListPostItemPreHeaderText} = ThreadScreen.getPostListPostItem(post.id, message);
+ await expect(threadPostListPostItemPreHeaderText).toHaveText(pinnedText);
+
+ // # Go back to channel, open post options for message, and tap on unpin from channel option
+ await ThreadScreen.back();
+ await ChannelScreen.openPostOptionsFor(post.id, message);
+ await PostOptionsScreen.unpinPostOption.tap();
+
+ // * Verify pinned text is not displayed on the post pre-header
+ await expect(channelPostListPostItemPreHeaderText).not.toBeVisible();
+
+ // # Go back to channel list screen
+ await ChannelScreen.back();
+ });
});
diff --git a/detox/e2e/test/smoke_test/server_login.e2e.ts b/detox/e2e/test/smoke_test/server_login.e2e.ts
index 7790cfa68..dbefff3b7 100644
--- a/detox/e2e/test/smoke_test/server_login.e2e.ts
+++ b/detox/e2e/test/smoke_test/server_login.e2e.ts
@@ -72,6 +72,7 @@ describe('Smoke Test - Server Login', () => {
// * Verify on channel list screen of the second server
await ChannelListScreen.toBeVisible();
+ await device.reloadReactNative();
await expect(ChannelListScreen.headerServerDisplayName).toHaveText(serverTwoDisplayName);
// # Go back to first server
diff --git a/detox/e2e/test/smoke_test/threads.e2e.ts b/detox/e2e/test/smoke_test/threads.e2e.ts
index ddd64b621..0f7fd453f 100644
--- a/detox/e2e/test/smoke_test/threads.e2e.ts
+++ b/detox/e2e/test/smoke_test/threads.e2e.ts
@@ -83,6 +83,7 @@ describe('Smoke Test - Threads', () => {
// # Go back to channel list screen, then go to global threads screen, tap on all your threads button, open thread options for thread, tap on mark as unread option, and tap on unread threads button
await ThreadScreen.back();
await ChannelScreen.back();
+ await device.reloadReactNative();
await GlobalThreadsScreen.open();
await GlobalThreadsScreen.headerAllThreadsButton.tap();
await GlobalThreadsScreen.openThreadOptionsFor(parentPost.id);