diff --git a/app/components/edit_channel_info/__snapshots__/edit_channel_info.test.js.snap b/app/components/edit_channel_info/__snapshots__/edit_channel_info.test.js.snap
index 0f00e9804..729536436 100644
--- a/app/components/edit_channel_info/__snapshots__/edit_channel_info.test.js.snap
+++ b/app/components/edit_channel_info/__snapshots__/edit_channel_info.test.js.snap
@@ -30,6 +30,7 @@ exports[`EditChannelInfo should match snapshot 1`] = `
"flex": 1,
}
}
+ testID="edit_channel_info"
>
@@ -161,7 +162,7 @@ exports[`EditChannelInfo should match snapshot 1`] = `
},
]
}
- testID="edit_channel.purpose.input"
+ testID="edit_channel_info.purpose.input"
textAlignVertical="top"
underlineColorAndroid="transparent"
value="purpose"
@@ -251,7 +252,7 @@ exports[`EditChannelInfo should match snapshot 1`] = `
},
]
}
- testID="edit_channel.header.input"
+ testID="edit_channel_info.header.input"
textAlignVertical="top"
underlineColorAndroid="transparent"
value="header"
diff --git a/app/components/edit_channel_info/edit_channel_info.test.js b/app/components/edit_channel_info/edit_channel_info.test.js
index c20dd81af..696d99575 100644
--- a/app/components/edit_channel_info/edit_channel_info.test.js
+++ b/app/components/edit_channel_info/edit_channel_info.test.js
@@ -11,6 +11,7 @@ import EditChannelInfo from './index';
describe('EditChannelInfo', () => {
const baseProps = {
+ testID: 'edit_channel_info',
theme: Preferences.THEMES.default,
deviceWidth: 400,
deviceHeight: 600,
diff --git a/app/components/edit_channel_info/index.js b/app/components/edit_channel_info/index.js
index 391be69dd..b0ff25f05 100644
--- a/app/components/edit_channel_info/index.js
+++ b/app/components/edit_channel_info/index.js
@@ -228,7 +228,10 @@ export default class EditChannelInfo extends PureComponent {
style={style.errorContainer}
>
-
+
);
@@ -263,7 +266,7 @@ export default class EditChannelInfo extends PureComponent {
-
+
-
+
{
const fuse = new Fuse(emojis, options);
const baseProps = {
+ testID: 'emoji_picker',
actions: {
getCustomEmojis: jest.fn(),
incrementEmojiPickerPage: jest.fn(),
diff --git a/app/components/emoji_picker/emoji_picker_base.js b/app/components/emoji_picker/emoji_picker_base.js
index c265ddbbe..ca8cceae0 100644
--- a/app/components/emoji_picker/emoji_picker_base.js
+++ b/app/components/emoji_picker/emoji_picker_base.js
@@ -41,6 +41,7 @@ export function filterEmojiSearchInput(searchText) {
export default class EmojiPicker extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
customEmojisEnabled: PropTypes.bool.isRequired,
customEmojiPage: PropTypes.number.isRequired,
deviceWidth: PropTypes.number.isRequired,
diff --git a/app/components/error_text/error_text.js b/app/components/error_text/error_text.js
index 72f88c408..2e3f751c7 100644
--- a/app/components/error_text/error_text.js
+++ b/app/components/error_text/error_text.js
@@ -12,13 +12,14 @@ import {makeStyleSheetFromTheme} from 'app/utils/theme';
export default class ErrorText extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
error: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
textStyle: CustomPropTypes.Style,
theme: PropTypes.object.isRequired,
};
render() {
- const {error, textStyle, theme} = this.props;
+ const {testID, error, textStyle, theme} = this.props;
if (!error) {
return null;
}
@@ -29,7 +30,7 @@ export default class ErrorText extends PureComponent {
if (intl) {
return (
{error.message || error}
diff --git a/app/components/error_text/error_text.test.js b/app/components/error_text/error_text.test.js
index ddcb88fcf..75fc44017 100644
--- a/app/components/error_text/error_text.test.js
+++ b/app/components/error_text/error_text.test.js
@@ -9,6 +9,7 @@ import ErrorText from './error_text.js';
describe('ErrorText', () => {
const baseProps = {
+ testID: 'error.text',
textStyle: {
fontSize: 14,
marginHorizontal: 15,
diff --git a/app/components/post_draft/__snapshots__/post_draft.test.js.snap b/app/components/post_draft/__snapshots__/post_draft.test.js.snap
index 7e1a89465..210172a93 100644
--- a/app/components/post_draft/__snapshots__/post_draft.test.js.snap
+++ b/app/components/post_draft/__snapshots__/post_draft.test.js.snap
@@ -384,6 +384,7 @@ exports[`PostDraft Should render the DraftInput 1`] = `
"height": 44,
}
}
+ testID="post_draft.quick_actions"
>
+`;
diff --git a/app/components/post_draft/archived/archived.js b/app/components/post_draft/archived/archived.js
index e2f3184f8..323ebd5b0 100644
--- a/app/components/post_draft/archived/archived.js
+++ b/app/components/post_draft/archived/archived.js
@@ -14,6 +14,7 @@ import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
export default class Archived extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
deactivated: PropTypes.bool,
rootId: PropTypes.string,
selectPenultimateChannel: PropTypes.func.isRequired,
@@ -46,12 +47,12 @@ export default class Archived extends PureComponent {
};
render() {
- const {theme} = this.props;
+ const {testID, theme} = this.props;
const style = getStyleSheet(theme);
return (
{
+ const baseProps = {
+ selectPenultimateChannel: jest.fn(),
+ testID: 'post_draft.archived',
+ deactivated: false,
+ rootId: 'root-id',
+ teamId: 'team-id',
+ theme: Preferences.THEMES.default,
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallowWithIntl();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
diff --git a/app/components/post_draft/draft_input/draft_input.js b/app/components/post_draft/draft_input/draft_input.js
index e7375aa24..f56b7591c 100644
--- a/app/components/post_draft/draft_input/draft_input.js
+++ b/app/components/post_draft/draft_input/draft_input.js
@@ -409,6 +409,9 @@ export default class DraftInput extends PureComponent {
rootId,
theme,
} = this.props;
+ const postInputTestID = `${testID}.post.input`;
+ const quickActionsTestID = `${testID}.quick_actions`;
+ const sendActionTestID = `${testID}.send_action`;
const style = getStyleSheet(theme);
return (
@@ -435,6 +438,7 @@ export default class DraftInput extends PureComponent {
disableScrollViewPanResponder={true}
>
{
const {
+ testID,
accessoriesContainerID,
canPost,
channelId,
@@ -71,8 +73,11 @@ export default class PostDraft extends PureComponent {
} = this.props;
if (channelIsArchived || deactivatedChannel) {
+ const archivedTestID = `${testID}.archived`;
+
return (
+
);
}
const draftInput = (
{
const baseProps = {
+ testID: 'post_draft',
canPost: true,
channelId: 'channel-id',
channelIsArchived: false,
diff --git a/app/components/post_draft/post_input/post_input.js b/app/components/post_draft/post_input/post_input.js
index a337a32f6..84d8c3f44 100644
--- a/app/components/post_draft/post_input/post_input.js
+++ b/app/components/post_draft/post_input/post_input.js
@@ -27,6 +27,7 @@ export default class PostInput extends PureComponent {
};
static propTypes = {
+ testID: PropTypes.string,
channelDisplayName: PropTypes.string,
channelId: PropTypes.string.isRequired,
cursorPositionEvent: PropTypes.string,
@@ -267,7 +268,7 @@ export default class PostInput extends PureComponent {
render() {
const {formatMessage} = this.context.intl;
- const {channelDisplayName, isLandscape, theme} = this.props;
+ const {testID, channelDisplayName, isLandscape, theme} = this.props;
const style = getStyleSheet(theme);
const placeholder = this.getPlaceHolder();
let maxHeight = 150;
@@ -278,7 +279,7 @@ export default class PostInput extends PureComponent {
return (
{
const baseProps = {
+ testID: 'post_draft.post.input',
channelDisplayName: 'Test Channel',
channelId: 'channel-id',
cursorPositionEvent: '',
diff --git a/app/components/post_draft/quick_actions/__snapshots__/quick_actions.test.js.snap b/app/components/post_draft/quick_actions/__snapshots__/quick_actions.test.js.snap
new file mode 100644
index 000000000..f85fd79f2
--- /dev/null
+++ b/app/components/post_draft/quick_actions/__snapshots__/quick_actions.test.js.snap
@@ -0,0 +1,195 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`QuickActions should match snapshot 1`] = `
+
+
+
+
+
+
+
+`;
diff --git a/app/components/post_draft/quick_actions/camera_quick_action/__snapshots__/camera_quick_action.test.js.snap b/app/components/post_draft/quick_actions/camera_quick_action/__snapshots__/camera_quick_action.test.js.snap
index 0087b8123..aa0ff1db0 100644
--- a/app/components/post_draft/quick_actions/camera_quick_action/__snapshots__/camera_quick_action.test.js.snap
+++ b/app/components/post_draft/quick_actions/camera_quick_action/__snapshots__/camera_quick_action.test.js.snap
@@ -10,7 +10,7 @@ exports[`CameraButton should match snapshot 1`] = `
"padding": 10,
}
}
- testID="post_draft.camera_quick_action"
+ testID="post_draft.quick_actions.camera_action"
type="opacity"
>
({
describe('CameraButton', () => {
const formatMessage = jest.fn();
const baseProps = {
+ testID: 'post_draft.quick_actions.camera_action',
fileCount: 0,
maxFileCount: 5,
onShowFileMaxWarning: jest.fn(),
diff --git a/app/components/post_draft/quick_actions/camera_quick_action/index.js b/app/components/post_draft/quick_actions/camera_quick_action/index.js
index 92b21f3df..07184bfbd 100644
--- a/app/components/post_draft/quick_actions/camera_quick_action/index.js
+++ b/app/components/post_draft/quick_actions/camera_quick_action/index.js
@@ -22,6 +22,7 @@ import {changeOpacity} from '@utils/theme';
export default class CameraQuickAction extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
disabled: PropTypes.bool,
fileCount: PropTypes.number,
maxFileCount: PropTypes.number,
@@ -147,17 +148,17 @@ export default class CameraQuickAction extends PureComponent {
};
render() {
- const {disabled, theme} = this.props;
- const testID = disabled ?
- 'post_draft.camera_quick_action.disabled' :
- 'post_draft.camera_quick_action';
+ const {testID, disabled, theme} = this.props;
+ const actionTestID = disabled ?
+ `${testID}.disabled` :
+ testID;
const color = disabled ?
changeOpacity(theme.centerChannelColor, 0.16) :
changeOpacity(theme.centerChannelColor, 0.64);
return (
{
const formatMessage = jest.fn();
const baseProps = {
+ testID: 'post_draft.quick_actions.file_action',
fileCount: 0,
maxFileCount: 5,
onShowFileMaxWarning: jest.fn(),
diff --git a/app/components/post_draft/quick_actions/file_quick_action/index.js b/app/components/post_draft/quick_actions/file_quick_action/index.js
index e504b5b5e..9187e0340 100644
--- a/app/components/post_draft/quick_actions/file_quick_action/index.js
+++ b/app/components/post_draft/quick_actions/file_quick_action/index.js
@@ -20,6 +20,7 @@ const ShareExtension = NativeModules.MattermostShare;
export default class FileQuickAction extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
disabled: PropTypes.bool,
fileCount: PropTypes.number,
maxFileCount: PropTypes.number,
@@ -139,17 +140,17 @@ export default class FileQuickAction extends PureComponent {
};
render() {
- const {disabled, theme} = this.props;
- const testID = disabled ?
- 'post_draft.file_quick_action.disabled' :
- 'post_draft.file_quick_action';
+ const {testID, disabled, theme} = this.props;
+ const actionTestID = disabled ?
+ `${testID}.disabled` :
+ testID;
const color = disabled ?
changeOpacity(theme.centerChannelColor, 0.16) :
changeOpacity(theme.centerChannelColor, 0.64);
return (
({
describe('ImageQuickAction', () => {
const formatMessage = jest.fn();
const baseProps = {
+ testID: 'post_draft.quick_actions.image_action',
fileCount: 0,
maxFileCount: 5,
onShowFileMaxWarning: jest.fn(),
diff --git a/app/components/post_draft/quick_actions/image_quick_action/index.js b/app/components/post_draft/quick_actions/image_quick_action/index.js
index ac7067ccf..e0ab98829 100644
--- a/app/components/post_draft/quick_actions/image_quick_action/index.js
+++ b/app/components/post_draft/quick_actions/image_quick_action/index.js
@@ -17,6 +17,7 @@ import {changeOpacity} from '@utils/theme';
export default class ImageQuickAction extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
disabled: PropTypes.bool,
fileCount: PropTypes.number,
maxFileCount: PropTypes.number,
@@ -154,17 +155,17 @@ export default class ImageQuickAction extends PureComponent {
};
render() {
- const {disabled, theme} = this.props;
- const testID = disabled ?
- 'post_draft.image_quick_action.disabled' :
- 'post_draft.image_quick_action';
+ const {testID, disabled, theme} = this.props;
+ const actionTestID = disabled ?
+ `${testID}.disabled` :
+ testID;
const color = disabled ?
changeOpacity(theme.centerChannelColor, 0.16) :
changeOpacity(theme.centerChannelColor, 0.64);
return (
+
+
+`;
diff --git a/app/components/post_draft/quick_actions/input_quick_action/index.js b/app/components/post_draft/quick_actions/input_quick_action/index.js
index 5eb0f2ca5..31857d324 100644
--- a/app/components/post_draft/quick_actions/input_quick_action/index.js
+++ b/app/components/post_draft/quick_actions/input_quick_action/index.js
@@ -11,6 +11,7 @@ import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
export default class InputQuickAction extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
disabled: PropTypes.bool,
inputType: PropTypes.oneOf(['at', 'slash']).isRequired,
onTextChange: PropTypes.func.isRequired,
@@ -56,11 +57,15 @@ export default class InputQuickAction extends PureComponent {
}
render() {
- const {disabled, theme} = this.props;
+ const {testID, disabled, theme} = this.props;
+ const actionTestID = disabled ?
+ `${testID}.disabled` :
+ testID;
const style = getStyleSheet(theme);
return (
{
+ const baseProps = {
+ onTextChange: jest.fn(),
+ testID: 'post_draft.quick_actions.input_action',
+ disabled: false,
+ inputType: 'at',
+ theme: Preferences.THEMES.default,
+ value: 'value',
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallow();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
diff --git a/app/components/post_draft/quick_actions/quick_actions.js b/app/components/post_draft/quick_actions/quick_actions.js
index 5bb0404f6..03ed712cb 100644
--- a/app/components/post_draft/quick_actions/quick_actions.js
+++ b/app/components/post_draft/quick_actions/quick_actions.js
@@ -15,6 +15,7 @@ import InputAction from './input_quick_action';
export default class QuickActions extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
canUploadFiles: PropTypes.bool,
fileCount: PropTypes.number,
inputEventType: PropTypes.string.isRequired,
@@ -64,10 +65,16 @@ export default class QuickActions extends PureComponent {
render() {
const {
+ testID,
canUploadFiles,
fileCount,
theme,
} = this.props;
+ const atInputActionTestID = `${testID}.at_input_action`;
+ const slashInputActionTestID = `${testID}.slash_input_action`;
+ const fileActionTestID = `${testID}.file_action`;
+ const imageActionTestID = `${testID}.image_action`;
+ const cameraActionTestID = `${testID}.camera_action`;
const uploadProps = {
disabled: !canUploadFiles,
fileCount,
@@ -77,8 +84,12 @@ export default class QuickActions extends PureComponent {
};
return (
-
+
-
-
-
+
+
+
);
}
diff --git a/app/components/post_draft/quick_actions/quick_actions.test.js b/app/components/post_draft/quick_actions/quick_actions.test.js
new file mode 100644
index 000000000..ea39be784
--- /dev/null
+++ b/app/components/post_draft/quick_actions/quick_actions.test.js
@@ -0,0 +1,27 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {shallow} from 'enzyme';
+
+import Preferences from '@mm-redux/constants/preferences';
+
+import QuickActions from './quick_actions';
+
+describe('QuickActions', () => {
+ const baseProps = {
+ onTextChange: jest.fn(),
+ testID: 'post_draft.quick_actions',
+ canUploadFiles: true,
+ fileCount: 1,
+ inputEventType: 'input-event-type',
+ maxFileSize: 10,
+ theme: Preferences.THEMES.default,
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallow();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
\ No newline at end of file
diff --git a/app/components/post_draft/read_only/__snapshots__/read_only.test.js.snap b/app/components/post_draft/read_only/__snapshots__/read_only.test.js.snap
index 026c1fbe6..ab58ec7b0 100644
--- a/app/components/post_draft/read_only/__snapshots__/read_only.test.js.snap
+++ b/app/components/post_draft/read_only/__snapshots__/read_only.test.js.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`PostDraft ReadOnly Should match snapshot 1`] = `
+exports[`PostDraft ReadOnly should match snapshot 1`] = `
{
+const ReadOnlyChannnel = ({testID, theme}: ReadOnlyProps): ReactNode => {
const style = getStyle(theme);
return (
{
style={style.background}
>
{
- test('Should match snapshot', () => {
- const wrapper = shallowWithIntl(
- ,
- );
+ const baseProps = {
+ testID: 'post_draft.read_only',
+ theme: Preferences.THEMES.default,
+ };
- expect(wrapper).toMatchSnapshot();
+ test('should match snapshot', () => {
+ const wrapper = shallowWithIntl();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
});
});
diff --git a/app/components/post_draft/send_action/__snapshots__/send.test.js.snap b/app/components/post_draft/send_action/__snapshots__/send.test.js.snap
index 3824b8b99..eb284b1a4 100644
--- a/app/components/post_draft/send_action/__snapshots__/send.test.js.snap
+++ b/app/components/post_draft/send_action/__snapshots__/send.test.js.snap
@@ -8,7 +8,7 @@ exports[`SendAction should change theme backgroundColor to 0.3 opacity 1`] = `
"paddingRight": 8,
}
}
- testID="post_draft.send.button.disabled"
+ testID="post_draft.send_action.send.button.disabled"
>
@@ -32,7 +34,7 @@ function SendButton(props) {
return (
{
const baseProps = {
+ testID: 'post_draft.send_action',
theme: Preferences.THEMES.default,
handleSendMessage: jest.fn(),
disabled: false,
diff --git a/app/components/post_header/__snapshots__/post_header.test.js.snap b/app/components/post_header/__snapshots__/post_header.test.js.snap
index a6afb9dd0..0fa554399 100644
--- a/app/components/post_header/__snapshots__/post_header.test.js.snap
+++ b/app/components/post_header/__snapshots__/post_header.test.js.snap
@@ -515,6 +515,7 @@ exports[`PostHeader should match snapshot when post isBot and shouldRenderReplyB
"justifyContent": "flex-end",
}
}
+ testID="post_header.reply"
>
+
{
const {
+ testID,
highlightPinnedOrFlagged,
highlightPostId,
isSearchResult,
@@ -360,6 +362,7 @@ export default class PostList extends PureComponent {
const postId = item;
return (
+
+
+ }
+ containerStyle={
+ Object {
+ "backgroundColor": "#ffffff",
+ "flex": 1,
+ "paddingBottom": 0,
+ "paddingTop": 0,
+ }
+ }
+ disableFullscreenUI={true}
+ editable={true}
+ enablesReturnKeyAutomatically={true}
+ inputContainerStyle={
+ Object {
+ "backgroundColor": undefined,
+ "borderRadius": 2,
+ "height": 10,
+ }
+ }
+ inputStyle={
+ Object {
+ "backgroundColor": "transparent",
+ "color": "#fff",
+ "fontSize": 14,
+ "height": 10,
+ "marginLeft": 4,
+ "marginTop": 0,
+ "paddingTop": 0,
+ }
+ }
+ keyboardAppearance="keyboard-appearance"
+ keyboardType="keyboard-type"
+ leftIconContainerStyle={
+ Object {
+ "marginLeft": 4,
+ "width": 30,
+ }
+ }
+ onBlur={[Function]}
+ onCancel={[Function]}
+ onChangeText={[Function]}
+ onClear={[Function]}
+ onFocus={[Function]}
+ onSelectionChange={[Function]}
+ onSubmitEditing={[Function]}
+ placeholder="placeholder"
+ placeholderTextColor="#000000"
+ platform="ios"
+ returnKeyType="return-key-type"
+ searchIcon={
+
+ }
+ selectionColor="#dddddd"
+ showCancel={true}
+ testID="search_bar.search.input"
+ underlineColorAndroid="transparent"
+ value="value"
+ />
+
+
+`;
diff --git a/app/components/search_bar/index.js b/app/components/search_bar/index.js
index 7198e4ea6..590b29a3c 100644
--- a/app/components/search_bar/index.js
+++ b/app/components/search_bar/index.js
@@ -25,6 +25,7 @@ const LEFT_COMPONENT_INITIAL_POSITION = Platform.OS === 'ios' ? 7 : 0;
export default class Search extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
onBlur: PropTypes.func,
onFocus: PropTypes.func,
onSearchButtonPress: PropTypes.func,
@@ -214,7 +215,10 @@ export default class Search extends PureComponent {
}
render() {
- const {backgroundColor, inputHeight, inputStyle, placeholderTextColor, tintColorSearch, cancelButtonStyle, tintColorDelete, titleCancelColor, searchBarRightMargin, containerHeight} = this.props;
+ const {testID, backgroundColor, inputHeight, inputStyle, placeholderTextColor, tintColorSearch, cancelButtonStyle, tintColorDelete, titleCancelColor, searchBarRightMargin, containerHeight} = this.props;
+ const searchClearButtonTestID = `${testID}.search.clear.button`;
+ const searchBackButtonTestID = `${testID}.search.back.button`;
+ const searchInputTestID = `${testID}.search.input`;
const searchBarStyle = getSearchBarStyle(
backgroundColor,
cancelButtonStyle,
@@ -236,6 +240,7 @@ export default class Search extends PureComponent {
if (Platform.OS === 'ios') {
clearIcon = (
+
{((this.props.leftComponent) ?
{
+ const baseProps = {
+ onBlur: jest.fn,
+ onFocus: jest.fn,
+ onSearchButtonPress: jest.fn,
+ onChangeText: jest.fn,
+ onCancelButtonPress: jest.fn,
+ onSelectionChange: jest.fn,
+ testID: 'search_bar',
+ backgroundColor: '#ffffff',
+ placeholderTextColor: '#000000',
+ titleCancelColor: '#aaaaaa',
+ tintColorSearch: '#bbbbbb',
+ tintColorDelete: '#cccccc',
+ selectionColor: '#dddddd',
+ inputStyle: {},
+ containerStyle: {},
+ cancelButtonStyle: {},
+ autoFocus: true,
+ placeholder: 'placeholder',
+ cancelTitle: 'cancel title',
+ returnKeyType: 'return-key-type',
+ keyboardType: 'keyboard-type',
+ autoCapitalize: 'auto-capitalize',
+ inputHeight: 10,
+ editable: true,
+ blurOnSubmit: true,
+ keyboardShouldPersist: true,
+ value: 'value',
+ keyboardAppearance: 'keyboard-appearance',
+ showArrow: true,
+ searchBarRightMargin: 5,
+ searchIconSize: 1,
+ backArrowSize: 1,
+ deleteIconSize: 1,
+ showCancel: true,
+ containerHeight: 20,
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallowWithIntl();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
diff --git a/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap b/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap
index 77f57baf1..bcbe95d59 100644
--- a/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap
+++ b/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap
@@ -16,6 +16,7 @@ exports[`ChannelItem should match snapshot 1`] = `
undefined,
]
}
+ testID="main.sidebar.channels_list.list.channel_item"
>
display_name
@@ -118,6 +119,7 @@ exports[`ChannelItem should match snapshot for current user i.e currentUser (you
undefined,
]
}
+ testID="main.sidebar.channels_list.list.channel_item"
>
{displayname} (you)
@@ -230,6 +232,7 @@ exports[`ChannelItem should match snapshot for current user i.e currentUser (you
undefined,
]
}
+ testID="main.sidebar.channels_list.list.channel_item"
>
{displayname} (you)
@@ -342,6 +345,7 @@ exports[`ChannelItem should match snapshot for deactivated user and is currentCh
undefined,
]
}
+ testID="main.sidebar.channels_list.list.channel_item"
>
display_name
@@ -454,6 +458,7 @@ exports[`ChannelItem should match snapshot for deactivated user and is searchRes
undefined,
]
}
+ testID="main.sidebar.channels_list.list.channel_item"
>
display_name
@@ -556,6 +561,7 @@ exports[`ChannelItem should match snapshot for deactivated user and not searchRe
undefined,
]
}
+ testID="main.sidebar.channels_list.list.channel_item"
>
display_name
@@ -658,6 +664,7 @@ exports[`ChannelItem should match snapshot for isManualUnread 1`] = `
undefined,
]
}
+ testID="main.sidebar.channels_list.list.channel_item"
>
display_name
@@ -764,6 +771,7 @@ exports[`ChannelItem should match snapshot with draft 1`] = `
undefined,
]
}
+ testID="main.sidebar.channels_list.list.channel_item"
>
display_name
@@ -868,6 +876,7 @@ exports[`ChannelItem should match snapshot with mentions and muted 1`] = `
},
]
}
+ testID="main.sidebar.channels_list.list.channel_item"
>
display_name
diff --git a/app/components/sidebars/main/channels_list/channel_item/channel_item.js b/app/components/sidebars/main/channels_list/channel_item/channel_item.js
index fd530390a..a2dd6621a 100644
--- a/app/components/sidebars/main/channels_list/channel_item/channel_item.js
+++ b/app/components/sidebars/main/channels_list/channel_item/channel_item.js
@@ -18,6 +18,7 @@ import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
export default class ChannelItem extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
channelId: PropTypes.string.isRequired,
channel: PropTypes.object,
currentChannelId: PropTypes.string.isRequired,
@@ -61,6 +62,7 @@ export default class ChannelItem extends PureComponent {
render() {
const {
+ testID,
channelId,
currentChannelId,
displayName,
@@ -165,12 +167,17 @@ export default class ChannelItem extends PureComponent {
/>
);
+ const displayNameTestID = `${testID}.display_name`;
+
return (
-
+
{extraBorder}
{icon}
@@ -178,7 +185,7 @@ export default class ChannelItem extends PureComponent {
style={[style.text, extraTextStyle]}
ellipsizeMode='tail'
numberOfLines={1}
- testID='channel_item.display_name'
+ testID={displayNameTestID}
>
{channelDisplayName}
diff --git a/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js b/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
index 7a9ba72c3..55233e017 100644
--- a/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
+++ b/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
@@ -7,7 +7,7 @@ import {TouchableHighlight} from 'react-native';
import Preferences from '@mm-redux/constants/preferences';
-import ChannelItem from './channel_item.js';
+import ChannelItem from './channel_item';
jest.useFakeTimers();
jest.mock('react-intl');
@@ -22,6 +22,7 @@ describe('ChannelItem', () => {
};
const baseProps = {
+ testID: 'main.sidebar.channels_list.list.channel_item',
channelId: 'channel_id',
channel,
currentChannelId: 'current_channel_id',
diff --git a/app/components/sidebars/main/channels_list/channels_list.js b/app/components/sidebars/main/channels_list/channels_list.js
index e12bb70fb..15b7c24d8 100644
--- a/app/components/sidebars/main/channels_list/channels_list.js
+++ b/app/components/sidebars/main/channels_list/channels_list.js
@@ -27,6 +27,7 @@ let FilteredList = null;
export default class ChannelsList extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
onJoinChannel: PropTypes.func.isRequired,
onSearchEnds: PropTypes.func.isRequired,
onSearchStart: PropTypes.func.isRequired,
@@ -92,15 +93,18 @@ export default class ChannelsList extends PureComponent {
render() {
const {intl} = this.context;
- const {onShowTeams, theme} = this.props;
-
+ const {testID, onShowTeams, theme} = this.props;
const {searching, term} = this.state;
const styles = getStyleSheet(theme);
+ const filteredListTestID = `${testID}.filtered_list`;
+ const listTestID = `${testID}.list`;
+ const searchBarTestID = `${testID}.search_bar`;
let list;
if (searching) {
list = (
@@ -128,6 +133,7 @@ export default class ChannelsList extends PureComponent {
style={styles.searchContainer}
>
{title}
diff --git a/app/components/sidebars/main/channels_list/filtered_list/__snapshots__/filtered_list.test.js.snap b/app/components/sidebars/main/channels_list/filtered_list/__snapshots__/filtered_list.test.js.snap
new file mode 100644
index 000000000..694e31876
--- /dev/null
+++ b/app/components/sidebars/main/channels_list/filtered_list/__snapshots__/filtered_list.test.js.snap
@@ -0,0 +1,89 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ChannelsList FilteredList should match snapshot 1`] = `
+
+`;
diff --git a/app/components/sidebars/main/channels_list/filtered_list/filtered_list.js b/app/components/sidebars/main/channels_list/filtered_list/filtered_list.js
index afcf9237f..0430e11ac 100644
--- a/app/components/sidebars/main/channels_list/filtered_list/filtered_list.js
+++ b/app/components/sidebars/main/channels_list/filtered_list/filtered_list.js
@@ -24,6 +24,7 @@ const VIEWABILITY_CONFIG = ListTypes.VISIBILITY_CONFIG_DEFAULTS;
class FilteredList extends Component {
static propTypes = {
+ testID: PropTypes.string,
actions: PropTypes.shape({
getProfilesInTeam: PropTypes.func.isRequired,
makeGroupMessageVisibleIfNecessary: PropTypes.func.isRequired,
@@ -339,8 +340,12 @@ class FilteredList extends Component {
keyExtractor = (item) => item.id || item;
renderItem = ({item}) => {
+ const {testID} = this.props;
+ const channelItemTestID = `${testID}.channel_item`;
+
return (
{
+ const baseProps = {
+ actions: {
+ getProfilesInTeam: jest.fn(),
+ makeGroupMessageVisibleIfNecessary: jest.fn(),
+ searchChannels: jest.fn(),
+ searchProfiles: jest.fn(),
+ },
+ onSelectChannel: jest.fn(),
+ testID: 'main.sidebar.channels_list.filtered_list',
+ channels: {},
+ currentTeam: {},
+ currentUserId: 'current-user-id',
+ currentChannel: {},
+ groupChannelMemberDetails: {},
+ teammateNameDisplay: 'teammate-name-display',
+ otherChannels: [],
+ archivedChannels: [],
+ profiles: {},
+ teamProfiles: {},
+ searchOrder: [],
+ pastDirectMessages: [],
+ restrictDms: false,
+ statuses: {},
+ styles: {},
+ term: 'term',
+ theme: Preferences.THEMES.default,
+ isLandscape: false,
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallowWithIntl();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
diff --git a/app/components/sidebars/main/channels_list/list/__snapshots__/list.test.js.snap b/app/components/sidebars/main/channels_list/list/__snapshots__/list.test.js.snap
new file mode 100644
index 000000000..d0f3f5a3c
--- /dev/null
+++ b/app/components/sidebars/main/channels_list/list/__snapshots__/list.test.js.snap
@@ -0,0 +1,40 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ChannelsList List should match snapshot 1`] = `
+
+
+
+`;
diff --git a/app/components/sidebars/main/channels_list/list/list.js b/app/components/sidebars/main/channels_list/list/list.js
index a4cb9d478..e20ffb533 100644
--- a/app/components/sidebars/main/channels_list/list/list.js
+++ b/app/components/sidebars/main/channels_list/list/list.js
@@ -38,6 +38,7 @@ let UnreadIndicator = null;
export default class List extends PureComponent {
static propTypes = {
+ testID: PropTypes.string,
canJoinPublicChannels: PropTypes.bool.isRequired,
canCreatePrivateChannels: PropTypes.bool.isRequired,
canCreatePublicChannels: PropTypes.bool.isRequired,
@@ -311,10 +312,12 @@ export default class List extends PureComponent {
};
renderItem = ({item}) => {
- const {favoriteChannelIds, unreadChannelIds} = this.props;
+ const {testID, favoriteChannelIds, unreadChannelIds} = this.props;
+ const channelItemTestID = `${testID}.channel_item`;
return (
diff --git a/app/components/sidebars/main/channels_list/list/list.test.js b/app/components/sidebars/main/channels_list/list/list.test.js
new file mode 100644
index 000000000..55e510311
--- /dev/null
+++ b/app/components/sidebars/main/channels_list/list/list.test.js
@@ -0,0 +1,31 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {shallow} from 'enzyme';
+
+import Preferences from '@mm-redux/constants/preferences';
+
+import List from './list';
+
+describe('ChannelsList List', () => {
+ const baseProps = {
+ onSelectChannel: jest.fn(),
+ testID: 'main.sidebar.channels_list.list',
+ canJoinPublicChannels: true,
+ canCreatePrivateChannels: true,
+ canCreatePublicChannels: true,
+ favoriteChannelIds: [],
+ unreadChannelIds: [],
+ styles: {},
+ theme: Preferences.THEMES.default,
+ orderedChannelIds: [],
+ isLandscape: false,
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallow(
);
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
diff --git a/app/components/sidebars/main/main_sidebar_base.js b/app/components/sidebars/main/main_sidebar_base.js
index e2aeeb6c9..2488bbc38 100644
--- a/app/components/sidebars/main/main_sidebar_base.js
+++ b/app/components/sidebars/main/main_sidebar_base.js
@@ -230,6 +230,7 @@ export default class MainSidebarBase extends Component {
style={style.swiperContent}
>
+
+
+`;
diff --git a/app/screens/add_reaction/add_reaction.test.js b/app/screens/add_reaction/add_reaction.test.js
new file mode 100644
index 000000000..937571867
--- /dev/null
+++ b/app/screens/add_reaction/add_reaction.test.js
@@ -0,0 +1,21 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {shallowWithIntl} from 'test/intl-test-helper';
+
+import AddReaction from './index';
+
+describe('AddReaction', () => {
+ const baseProps = {
+ onEmojiPress: jest.fn(),
+ componentId: 'component-id',
+ closeButton: {},
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallowWithIntl();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
diff --git a/app/screens/channel/channel.android.js b/app/screens/channel/channel.android.js
index 3ad15c658..7c0c0494c 100644
--- a/app/screens/channel/channel.android.js
+++ b/app/screens/channel/channel.android.js
@@ -74,6 +74,7 @@ export default class ChannelAndroid extends ChannelBase {
diff --git a/app/screens/channel/channel_post_list/channel_post_list.js b/app/screens/channel/channel_post_list/channel_post_list.js
index 9c6c0abb8..4d7aef47d 100644
--- a/app/screens/channel/channel_post_list/channel_post_list.js
+++ b/app/screens/channel/channel_post_list/channel_post_list.js
@@ -192,6 +192,7 @@ export default class ChannelPostList extends PureComponent {
} else {
component = (
-
+
);
} else {
displayError = (
-
+
);
diff --git a/app/screens/edit_profile/edit_profile.js b/app/screens/edit_profile/edit_profile.js
index f08c19639..08a00f5a7 100644
--- a/app/screens/edit_profile/edit_profile.js
+++ b/app/screens/edit_profile/edit_profile.js
@@ -583,6 +583,7 @@ export default class EditProfile extends PureComponent {
@@ -592,7 +593,10 @@ export default class EditProfile extends PureComponent {
}
return (
-
+
@@ -148,7 +149,10 @@ export default class ForgotPassword extends PureComponent {
);
}
return (
-
+
+
{error && (
diff --git a/app/screens/login/login.js b/app/screens/login/login.js
index 31c36f095..cba786010 100644
--- a/app/screens/login/login.js
+++ b/app/screens/login/login.js
@@ -338,7 +338,7 @@ export default class Login extends PureComponent {
proceed = (
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/app/screens/search/recent_item.js b/app/screens/search/recent_item.js
index a0acb90e6..0179b0d17 100644
--- a/app/screens/search/recent_item.js
+++ b/app/screens/search/recent_item.js
@@ -32,6 +32,7 @@ export default class RecentItem extends PureComponent {
render() {
const {item, theme} = this.props;
const style = getStyleFromTheme(theme);
+ const testID = `search.recent_item.${item.terms}`;
return (
{
+ const baseProps = {
+ actions: {
+ clearSearch: jest.fn(),
+ closePermalink: jest.fn(),
+ handleSearchDraftChanged: jest.fn(),
+ getPostThread: jest.fn(),
+ removeSearchTerms: jest.fn(),
+ searchPostsWithParams: jest.fn(),
+ getMorePostsForSearch: jest.fn(),
+ selectPost: jest.fn(),
+ showPermalink: jest.fn(),
+ },
+ currentTeamId: 'current-team-id',
+ initialValue: 'initial value',
+ isLandscape: false,
+ postIds: [],
+ archivedPostIds: [],
+ recent: [],
+ isSearchGettingMore: true,
+ theme: Preferences.THEMES.default,
+ enableDateSuggestion: true,
+ timezoneOffsetInSeconds: 0,
+ viewArchivedChannels: false,
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallowWithIntl();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
diff --git a/app/screens/select_server/select_server.js b/app/screens/select_server/select_server.js
index 44c19f335..cb6ff065f 100644
--- a/app/screens/select_server/select_server.js
+++ b/app/screens/select_server/select_server.js
@@ -520,7 +520,7 @@ export default class SelectServer extends PureComponent {
style={GlobalStyles.logo}
/>
-
+
-
+
diff --git a/app/screens/select_server/select_server.test.js b/app/screens/select_server/select_server.test.js
index 443f3751e..f23e6650b 100644
--- a/app/screens/select_server/select_server.test.js
+++ b/app/screens/select_server/select_server.test.js
@@ -32,7 +32,7 @@ describe('SelectServer', () => {
const button = getByText('Connect');
fireEvent.press(button);
- await waitFor(() => expect(getByTestId('error.text')).toBeTruthy());
+ await waitFor(() => expect(getByTestId('select_server.error.text')).toBeTruthy());
expect(getByText('Please enter a valid server URL')).toBeTruthy();
});
@@ -41,13 +41,13 @@ describe('SelectServer', () => {
,
);
- const urlInput = getByTestId('server_url.input');
+ const urlInput = getByTestId('select_server.server_url.input');
fireEvent.changeText(urlInput, ' ');
const button = getByText('Connect');
fireEvent.press(button);
- await waitFor(() => expect(getByTestId('error.text')).toBeTruthy());
+ await waitFor(() => expect(getByTestId('select_server.error.text')).toBeTruthy());
expect(getByText('Please enter a valid server URL')).toBeTruthy();
});
@@ -56,13 +56,13 @@ describe('SelectServer', () => {
,
);
- const urlInput = getByTestId('server_url.input');
+ const urlInput = getByTestId('select_server.server_url.input');
fireEvent.changeText(urlInput, 'ht://invalid:8065');
const button = getByText('Connect');
fireEvent.press(button);
- await waitFor(() => expect(getByTestId('error.text')).toBeTruthy());
+ await waitFor(() => expect(getByTestId('select_server.error.text')).toBeTruthy());
expect(getByText('URL must start with http:// or https://')).toBeTruthy();
});
@@ -71,13 +71,13 @@ describe('SelectServer', () => {
,
);
- const urlInput = getByTestId('server_url.input');
+ const urlInput = getByTestId('select_server.server_url.input');
fireEvent.changeText(urlInput, 'http://localhost:8065');
const button = getByText('Connect');
fireEvent.press(button);
- expect(queryByTestId('error.text')).toBeNull();
+ expect(queryByTestId('select_server.error.text')).toBeNull();
await waitFor(() => expect(getByText('Connecting...')).toBeTruthy());
});
});
\ No newline at end of file
diff --git a/app/screens/selector_screen/__snapshots__/selector_screen.test.js.snap b/app/screens/selector_screen/__snapshots__/selector_screen.test.js.snap
index 6487fab2e..19e531bc2 100644
--- a/app/screens/selector_screen/__snapshots__/selector_screen.test.js.snap
+++ b/app/screens/selector_screen/__snapshots__/selector_screen.test.js.snap
@@ -17,6 +17,7 @@ exports[`SelectorScreen should match snapshot for channels 1`] = `
"paddingLeft": 8,
}
}
+ testID="selector.screen"
>
-
+
+
+
+
+
+
+
+`;
diff --git a/app/screens/settings/timezone/select_timezone/select_timezone.js b/app/screens/settings/timezone/select_timezone/select_timezone.js
index d5ed58395..bcf093457 100644
--- a/app/screens/settings/timezone/select_timezone/select_timezone.js
+++ b/app/screens/settings/timezone/select_timezone/select_timezone.js
@@ -108,12 +108,14 @@ export default class Timezone extends PureComponent {
return (
{
+ const baseProps = {
+ onBack: jest.fn(),
+ selectedTimezone: 'selected-timezone',
+ initialScrollIndex: 1,
+ timezones: [],
+ theme: Preferences.THEMES.default,
+ isLandscape: false,
+ };
+
+ test('should match snapshot', () => {
+ const wrapper = shallowWithIntl();
+
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+});
diff --git a/app/screens/thread/__snapshots__/thread.ios.test.js.snap b/app/screens/thread/__snapshots__/thread.ios.test.js.snap
index d39023eaa..112aa801b 100644
--- a/app/screens/thread/__snapshots__/thread.ios.test.js.snap
+++ b/app/screens/thread/__snapshots__/thread.ios.test.js.snap
@@ -23,6 +23,7 @@ exports[`thread should match snapshot, has root post 1`] = `
"paddingBottom": 0,
}
}
+ testID="thread.screen"
>
}
scrollViewNativeID="threadPostList"
+ testID="thread.post_list"
/>
@@ -58,6 +60,7 @@ exports[`thread should match snapshot, has root post 1`] = `
registerTypingAnimation={[Function]}
rootId="root_id"
scrollViewNativeID="threadPostList"
+ testID="thread.post_draft"
valueEvent="onThreadTextBoxValueChange"
/>
}
scrollViewNativeID="threadPostList"
+ testID="thread.post_list"
/>
`;
@@ -154,6 +158,7 @@ exports[`thread should match snapshot, render footer 2`] = `
}
renderFooter={null}
scrollViewNativeID="threadPostList"
+ testID="thread.post_list"
/>
`;
diff --git a/app/screens/thread/thread.android.js b/app/screens/thread/thread.android.js
index cf208b667..c4e3d2d76 100644
--- a/app/screens/thread/thread.android.js
+++ b/app/screens/thread/thread.android.js
@@ -30,8 +30,12 @@ export default class ThreadAndroid extends ThreadBase {
if (this.hasRootPost()) {
content = (
<>
-
+
-
+
{
+ return element(by.id(`${screenPrefix}${this.testID.cameraActionSuffix}`));
+ }
- toBeVisible = async (options = {disabled: false}) => {
- if (options.disabled) {
- await expect(this.cameraQuickActionDisabled).toBeVisible();
- return this.cameraQuickActionDisabled;
- }
-
- await expect(this.cameraQuickAction).toBeVisible();
- return this.cameraQuickAction;
+ getCameraQuickActionDisabled = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.cameraActionDisabledSuffix}`));
}
}
diff --git a/detox/e2e/support/ui/component/edit_channel_info.js b/detox/e2e/support/ui/component/edit_channel_info.js
new file mode 100644
index 000000000..f3c7c0b6e
--- /dev/null
+++ b/detox/e2e/support/ui/component/edit_channel_info.js
@@ -0,0 +1,17 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+class EditChannelInfo {
+ testID = {
+ nameInput: 'edit_channel_info.name.input',
+ purposeInput: 'edit_channel_info.purpose.input',
+ headerInput: 'edit_channel_info.header.input',
+ }
+
+ nameInput = element(by.id(this.testID.nameInput));
+ purposeInput = element(by.id(this.testID.purposeInput));
+ headerInput = element(by.id(this.testID.headerInput));
+}
+
+const editChannelInfo = new EditChannelInfo();
+export default editChannelInfo;
diff --git a/detox/e2e/support/ui/component/file_quick_action.js b/detox/e2e/support/ui/component/file_quick_action.js
index 410e1bdad..86f9d6630 100644
--- a/detox/e2e/support/ui/component/file_quick_action.js
+++ b/detox/e2e/support/ui/component/file_quick_action.js
@@ -3,21 +3,16 @@
class FileQuickAction {
testID = {
- fileQuickAction: 'post_draft.file_quick_action',
- fileQuickActionDisabled: 'post_draft.file_quick_action.disabled',
+ fileActionSuffix: 'post_draft.quick_actions.file_action',
+ fileActionDisabledSuffix: 'post_draft.quick_actions.file_action.disabled',
}
- fileQuickAction = element(by.id(this.testID.fileQuickAction));
- fileQuickActionDisabled = element(by.id(this.testID.fileQuickActionDisabled));
+ getFileQuickAction = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.fileActionSuffix}`));
+ }
- toBeVisible = async (options = {disabled: false}) => {
- if (options.disabled) {
- await expect(this.fileQuickActionDisabled).toBeVisible();
- return this.fileQuickActionDisabled;
- }
-
- await expect(this.fileQuickAction).toBeVisible();
- return this.fileQuickAction;
+ getFileQuickActionDisabled = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.fileActionDisabledSuffix}`));
}
}
diff --git a/detox/e2e/support/ui/component/image_quick_action.js b/detox/e2e/support/ui/component/image_quick_action.js
index b041ffec2..d0c0c89e6 100644
--- a/detox/e2e/support/ui/component/image_quick_action.js
+++ b/detox/e2e/support/ui/component/image_quick_action.js
@@ -3,21 +3,16 @@
class ImageQuickAction {
testID = {
- imageQuickAction: 'post_draft.image_quick_action',
- imageQuickActionDisabled: 'post_draft.image_quick_action.disabled',
+ imageActionSuffix: 'post_draft.quick_actions.image_action',
+ imageActionDisabledSuffix: 'post_draft.quick_actions.image_action.disabled',
}
- imageQuickAction = element(by.id(this.testID.imageQuickAction));
- imageQuickActionDisabled = element(by.id(this.testID.imageQuickActionDisabled));
+ getImageQuickAction = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.imageActionSuffix}`));
+ }
- toBeVisible = async (options = {disabled: false}) => {
- if (options.disabled) {
- await expect(this.imageQuickActionDisabled).toBeVisible();
- return this.imageQuickActionDisabled;
- }
-
- await expect(this.imageQuickAction).toBeVisible();
- return this.imageQuickAction;
+ getImageQuickActionDisabled = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.imageActionDisabledSuffix}`));
}
}
diff --git a/detox/e2e/support/ui/component/index.js b/detox/e2e/support/ui/component/index.js
index 230ff9c3a..3e05b638c 100644
--- a/detox/e2e/support/ui/component/index.js
+++ b/detox/e2e/support/ui/component/index.js
@@ -3,24 +3,32 @@
import Autocomplete from './autocomplete';
import CameraQuickAction from './camera_quick_action';
+import EditChannelInfo from './edit_channel_info';
import FileQuickAction from './file_quick_action';
import ImageQuickAction from './image_quick_action';
+import InputQuickAction from './input_quick_action';
import MainSidebar from './main_sidebar';
import Post from './post';
import PostDraft from './post_draft';
import PostOptions from './post_options';
+import RecentItem from './recent_item';
+import SearchBar from './search_bar';
import SendButton from './send_button';
import SettingsSidebar from './settings_sidebar';
export {
Autocomplete,
CameraQuickAction,
+ EditChannelInfo,
FileQuickAction,
ImageQuickAction,
+ InputQuickAction,
MainSidebar,
Post,
PostDraft,
PostOptions,
+ RecentItem,
+ SearchBar,
SendButton,
SettingsSidebar,
};
diff --git a/detox/e2e/support/ui/component/input_quick_action.js b/detox/e2e/support/ui/component/input_quick_action.js
new file mode 100644
index 000000000..1fcc0b9e3
--- /dev/null
+++ b/detox/e2e/support/ui/component/input_quick_action.js
@@ -0,0 +1,30 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+class InputQuickAction {
+ testID = {
+ atInputActionSuffix: 'post_draft.quick_actions.at_input_action',
+ atInputActionDisabledSuffix: 'post_draft.quick_actions.at_input_action.disabled',
+ slashInputActionSuffix: 'post_draft.quick_actions.slash_input_action',
+ slashInputActionDisabledSuffix: 'post_draft.quick_actions.slash_input_action.disabled',
+ }
+
+ getAtInputQuickAction = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.atInputActionSuffix}`));
+ }
+
+ getAtInputQuickActionDisabled = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.atInputActionDisabledSuffix}`));
+ }
+
+ getSlashInputQuickAction = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.slashInputActionSuffix}`));
+ }
+
+ getSlashInputQuickActionDisabled = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.slashInputActionDisabledSuffix}`));
+ }
+}
+
+const inputQuickAction = new InputQuickAction();
+export default inputQuickAction;
diff --git a/detox/e2e/support/ui/component/main_sidebar.js b/detox/e2e/support/ui/component/main_sidebar.js
index d929e50e2..c0fb9e98c 100644
--- a/detox/e2e/support/ui/component/main_sidebar.js
+++ b/detox/e2e/support/ui/component/main_sidebar.js
@@ -4,16 +4,18 @@
class MainSidebar {
testID = {
mainSidebar: 'main.sidebar',
- channelItemDisplayName: 'channel_item.display_name',
- channelsList: 'channels.list',
+ channelsList: 'main.sidebar.channels_list',
+ channelItemDisplayName: 'main.sidebar.channels_list.list.channel_item.display_name',
+ filteredChannelItemDisplayName: 'main.sidebar.channels_list.filtered_list.channel_item.display_name',
openMoreChannelsButton: 'action_button_sidebar.channels',
openCreatePrivateChannelButton: 'action_button_sidebar.pg',
openMoreDirectMessagesButton: 'action_button_sidebar.direct',
}
mainSidebar = element(by.id(this.testID.mainSidebar));
- channelItemDisplayName = element(by.id(this.testID.channelItemDisplayName));
channelsList = element(by.id(this.testID.channelsList));
+ channelItemDisplayName = element(by.id(this.testID.channelItemDisplayName));
+ filteredChannelItemDisplayName = element(by.id(this.testID.filteredChannelItemDisplayName));
openMoreChannelsButton = element(by.id(this.testID.openMoreChannelsButton));
openCreatePrivateChannelButton = element(by.id(this.testID.openCreatePrivateChannelButton));
openMoreDirectMessagesButton = element(by.id(this.testID.openMoreDirectMessagesButton));
@@ -30,9 +32,15 @@ class MainSidebar {
hasChannelAtIndex = async (index, channelDisplayName) => {
await expect(
- element(by.id(this.testID.channelItemDisplayName).withAncestor(by.id(this.testID.channelsList))).atIndex(index),
+ element(by.id(this.testID.channelItemDisplayName)).atIndex(index),
).toHaveText(channelDisplayName);
}
+
+ hasFilteredChannelAtIndex = async (index, filteredChannelItemDisplayName) => {
+ await expect(
+ element(by.id(this.testID.filteredChannelItemDisplayName)).atIndex(index),
+ ).toHaveText(filteredChannelItemDisplayName);
+ }
}
const mainSidebar = new MainSidebar();
diff --git a/detox/e2e/support/ui/component/post.js b/detox/e2e/support/ui/component/post.js
index baae556b4..d78c2ee96 100644
--- a/detox/e2e/support/ui/component/post.js
+++ b/detox/e2e/support/ui/component/post.js
@@ -4,13 +4,21 @@
class Post {
testID = {
postPrefix: 'post.',
+ postHeaderReply: 'post_header.reply',
}
getPost = (postTypePrefix, postId, text) => {
+ const postTestID = `${postTypePrefix}${this.testID.postPrefix}${postId}`;
if (text) {
- return element(by.id(`${postTypePrefix}${this.testID.postPrefix}${postId}`).withDescendant(by.text(text)));
+ return {
+ postItem: element(by.id(postTestID).withDescendant(by.text(text))),
+ postItemHeaderReply: element(by.id(this.testID.postHeaderReply).withAncestor(by.id(postTestID).withDescendant(by.text(text)))),
+ };
}
- return element(by.id(`${postTypePrefix}${this.testID.postPrefix}${postId}`));
+ return {
+ postItem: element(by.id(postTestID)),
+ postItemHeaderReply: element(by.id(this.testID.postHeaderReply).withAncestor(by.id(postTestID))),
+ };
}
}
diff --git a/detox/e2e/support/ui/component/post_draft.js b/detox/e2e/support/ui/component/post_draft.js
index 22342d1e9..45f2e787b 100644
--- a/detox/e2e/support/ui/component/post_draft.js
+++ b/detox/e2e/support/ui/component/post_draft.js
@@ -3,30 +3,26 @@
class PostDraft {
testID = {
- postDraft: 'post_draft',
- postDraftArchived: 'post_draft.archived',
- postDraftReadOnly: 'post_draft.archived',
- postInput: 'post_draft.post.input',
+ postDraftSuffix: 'post_draft',
+ postDraftArchivedSuffix: 'post_draft.archived',
+ postDraftReadOnlySuffix: 'post_draft.read_only',
+ postInputSuffix: 'post_draft.post.input',
}
- postDraft = element(by.id(this.testID.postDraft));
- postDraftArchived = element(by.id(this.testID.postDraftArchived));
- postDraftReadOnly = element(by.id(this.testID.postDraftReadOnly));
- postInput = element(by.id(this.testID.postInput));
+ getPostDraft = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.postDraftSuffix}`));
+ }
- toBeVisible = async (options = {archived: false, readOnly: false}) => {
- if (options.archived) {
- await expect(this.postDraftArchived).toBeVisible();
- return this.postDraftArchived;
- }
+ getPostDraftArchived = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.postDraftArchivedSuffix}`));
+ }
- if (options.readOnly) {
- await expect(this.postDraftReadOnly).toBeVisible();
- return this.postDraftReadOnly;
- }
+ getPostDraftReadOnly = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.postDraftReadOnlySuffix}`));
+ }
- await expect(this.postDraft).toBeVisible();
- return this.postDraft;
+ getPostInput = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.postInputSuffix}`));
}
}
diff --git a/detox/e2e/support/ui/component/recent_item.js b/detox/e2e/support/ui/component/recent_item.js
new file mode 100644
index 000000000..c36440a1d
--- /dev/null
+++ b/detox/e2e/support/ui/component/recent_item.js
@@ -0,0 +1,15 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+class RecentItem {
+ testID = {
+ recentItemPrefix: 'search.recent_item.',
+ }
+
+ getRecentItem = (searchTerms) => {
+ return element(by.id(`${this.testID.recentItemPrefix}${searchTerms}`));
+ }
+}
+
+const recentItem = new RecentItem();
+export default recentItem;
diff --git a/detox/e2e/support/ui/component/search_bar.js b/detox/e2e/support/ui/component/search_bar.js
new file mode 100644
index 000000000..90e6b85b5
--- /dev/null
+++ b/detox/e2e/support/ui/component/search_bar.js
@@ -0,0 +1,34 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+class SearchBar {
+ testID = {
+ searchBarSuffix: 'search_bar',
+ searchInputSuffix: 'search_bar.search.input',
+ backButtonSuffix: 'search_bar.search.back.button',
+ clearButtonSuffix: 'search_bar.search.clear.button',
+ }
+
+ getSearchBar = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.searchBarSuffix}`));
+ }
+
+ getSearchInput = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.searchInputSuffix}`)).atIndex(0);
+ }
+
+ getBackButton = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.backButtonSuffix}`)).atIndex(0);
+ }
+
+ getCancelButton = (screenPrefix) => {
+ return element(by.text('Cancel').withAncestor(by.id(`${screenPrefix}${this.testID.searchBarSuffix}`))).atIndex(0);
+ }
+
+ getClearButton = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.clearButtonSuffix}`)).atIndex(0);
+ }
+}
+
+const searchBar = new SearchBar();
+export default searchBar;
diff --git a/detox/e2e/support/ui/component/send_button.js b/detox/e2e/support/ui/component/send_button.js
index ca6205220..466a0f96f 100644
--- a/detox/e2e/support/ui/component/send_button.js
+++ b/detox/e2e/support/ui/component/send_button.js
@@ -3,21 +3,16 @@
class SendButton {
testID = {
- sendButton: 'post_draft.send.button',
- sendButtonDisabled: 'post_draft.send.button.disabled',
+ sendButtonSuffix: 'post_draft.send_action.send.button',
+ sendButtonDisabledSuffix: 'post_draft.send_action.send.button.disabled',
}
- sendButton = element(by.id(this.testID.sendButton));
- sendButtonDisabled = element(by.id(this.testID.sendButtonDisabled));
+ getSendButton = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.sendButtonSuffix}`));
+ }
- toBeVisible = async (options = {disabled: false}) => {
- if (options.disabled) {
- await expect(this.sendButtonDisabled).toBeVisible();
- return this.sendButtonDisabled;
- }
-
- await expect(this.sendButton).toBeVisible();
- return this.sendButton;
+ getSendButtonDisabled = (screenPrefix) => {
+ return element(by.id(`${screenPrefix}${this.testID.sendButtonDisabledSuffix}`));
}
}
diff --git a/detox/e2e/support/ui/screen/channel.js b/detox/e2e/support/ui/screen/channel.js
index efaad997f..1c3147d86 100644
--- a/detox/e2e/support/ui/screen/channel.js
+++ b/detox/e2e/support/ui/screen/channel.js
@@ -5,6 +5,7 @@ import {
CameraQuickAction,
FileQuickAction,
ImageQuickAction,
+ InputQuickAction,
MainSidebar,
PostDraft,
PostOptions,
@@ -20,6 +21,7 @@ import {
class ChannelScreen {
testID = {
+ channelScreenPrefix: 'channel.',
channelScreen: 'channel.screen',
mainSidebarDrawerButton: 'main_sidebar_drawer.button',
channelIntro: 'channel_intro.beginning.text',
@@ -38,25 +40,29 @@ class ChannelScreen {
settingsSidebarDrawerButton = element(by.id(this.testID.settingsSidebarDrawerButton));
// convenience props
- cameraQuickAction = CameraQuickAction.cameraQuickAction;
- cameraQuickActionDisabled = CameraQuickAction.cameraQuickActionDisabled;
- imageQuickAction = ImageQuickAction.imageQuickAction;
- imageQuickActionDisabled = ImageQuickAction.imageQuickActionDisabled;
- fileQuickAction = FileQuickAction.fileQuickAction;
- fileQuickActionDisabled = FileQuickAction.fileQuickActionDisabled;
- postDraft = PostDraft.postDraft;
- postDraftArchived = PostDraft.postDraftArchived;
- postDraftReadOnly = PostDraft.postDraftReadOnly;
- postInput = PostDraft.postInput;
- sendButton = SendButton.sendButton;
- sendButtonDisabled = SendButton.sendButtonDisabled;
+ atInputQuickAction = InputQuickAction.getAtInputQuickAction(this.testID.channelScreenPrefix);
+ atInputQuickActionDisabled = InputQuickAction.getAtInputQuickActionDisabled(this.testID.channelScreenPrefix);
+ slashInputQuickAction = InputQuickAction.getSlashInputQuickAction(this.testID.channelScreenPrefix);
+ slashInputQuickActionDisabled = InputQuickAction.getSlashInputQuickActionDisabled(this.testID.channelScreenPrefix);
+ fileQuickAction = FileQuickAction.getFileQuickAction(this.testID.channelScreenPrefix);
+ fileQuickActionDisabled = FileQuickAction.getFileQuickActionDisabled(this.testID.channelScreenPrefix);
+ imageQuickAction = ImageQuickAction.getImageQuickAction(this.testID.channelScreenPrefix);
+ imageQuickActionDisabled = ImageQuickAction.getImageQuickActionDisabled(this.testID.channelScreenPrefix);
+ cameraQuickAction = CameraQuickAction.getCameraQuickAction(this.testID.channelScreenPrefix);
+ cameraQuickActionDisabled = CameraQuickAction.getCameraQuickActionDisabled(this.testID.channelScreenPrefix);
+ postDraft = PostDraft.getPostDraft(this.testID.channelScreenPrefix);
+ postDraftArchived = PostDraft.getPostDraftArchived(this.testID.channelScreenPrefix);
+ postDraftReadOnly = PostDraft.getPostDraftReadOnly(this.testID.channelScreenPrefix);
+ postInput = PostDraft.getPostInput(this.testID.channelScreenPrefix);
+ sendButton = SendButton.getSendButton(this.testID.channelScreenPrefix);
+ sendButtonDisabled = SendButton.getSendButtonDisabled(this.testID.channelScreenPrefix);
getLongPostPostItem = (postId, text) => {
return LongPostScreen.getPost(postId, text);
}
getPostListPostItem = (postId, text) => {
- return PostListScreen.getPost(postId, text);
+ return PostListScreen.getPost(this.testID.channelScreenPrefix, postId, text);
}
toBeVisible = async () => {
@@ -67,7 +73,7 @@ class ChannelScreen {
open = async (user) => {
// # Open channel screen
- await SelectServerScreen.connectToServer();
+ await LoginScreen.open();
await LoginScreen.login(user);
return this.toBeVisible();
@@ -92,14 +98,21 @@ class ChannelScreen {
}
openPostOptionsFor = async (postId, text) => {
- const post = await this.getPostListPostItem(postId, text);
- await expect(post).toBeVisible();
+ const {postListPostItem} = await this.getPostListPostItem(postId, text);
+ await expect(postListPostItem).toBeVisible();
// # Open post options
- await post.longPress();
+ await postListPostItem.longPress();
await PostOptions.toBeVisible();
}
+ postMessage = async (message) => {
+ // # Post message
+ await this.postInput.tap();
+ await this.postInput.typeText(message);
+ await this.tapSendButton();
+ }
+
tapSendButton = async () => {
// # Tap send button
await this.sendButton.tap();
diff --git a/detox/e2e/support/ui/screen/create_channel.js b/detox/e2e/support/ui/screen/create_channel.js
index 459fed5d0..2b7c8024e 100644
--- a/detox/e2e/support/ui/screen/create_channel.js
+++ b/detox/e2e/support/ui/screen/create_channel.js
@@ -1,23 +1,24 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
+import {EditChannelInfo} from '@support/ui/component';
+
class CreateChannelScreen {
testID = {
createChannelScreen: 'create_channel.screen',
- nameInput: 'edit_channel.name.input',
- purposeInput: 'edit_channel.purpose.input',
- headerInput: 'edit_channel.header.input',
- createButton: 'edit_channel.create.button',
+ createButton: 'create_channel.create.button',
backButton: 'screen.back.button',
}
createChannelScreen = element(by.id(this.testID.createChannelScreen));
- nameInput = element(by.id(this.testID.nameInput));
- purposeInput = element(by.id(this.testID.purposeInput));
- headerInput = element(by.id(this.testID.headerInput));
createButton = element(by.id(this.testID.createButton));
backButton = element(by.id(this.testID.backButton));
+ // convenience props
+ nameInput = EditChannelInfo.nameInput;
+ purposeInput = EditChannelInfo.purposeInput;
+ headerInput = EditChannelInfo.headerInput;
+
toBeVisible = async () => {
await expect(this.createChannelScreen).toBeVisible();
diff --git a/detox/e2e/support/ui/screen/edit_channel.js b/detox/e2e/support/ui/screen/edit_channel.js
index 5b7b03b05..f45ad9cbd 100644
--- a/detox/e2e/support/ui/screen/edit_channel.js
+++ b/detox/e2e/support/ui/screen/edit_channel.js
@@ -1,19 +1,25 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
+import {EditChannelInfo} from '@support/ui/component';
import {ChannelInfoScreen} from '@support/ui/screen';
class EditChannelScreen {
testID = {
editChannelScreen: 'edit_channel.screen',
- editChannelHeaderInput: 'edit_channel.header.input',
+ saveButton: 'edit_channel.save.button',
backButton: 'screen.back.button',
}
editChannelScreen = element(by.id(this.testID.editChannelScreen));
- editChannelHeaderInput = element(by.id(this.testID.editChannelHeaderInput));
+ saveButton = element(by.id(this.testID.saveButton));
backButton = element(by.id(this.testID.backButton));
+ // convenience props
+ nameInput = EditChannelInfo.nameInput;
+ purposeInput = EditChannelInfo.purposeInput;
+ headerInput = EditChannelInfo.headerInput;
+
toBeVisible = async () => {
await expect(this.editChannelScreen).toBeVisible();
diff --git a/detox/e2e/support/ui/screen/index.js b/detox/e2e/support/ui/screen/index.js
index 6e30b45f3..ba15d56f3 100644
--- a/detox/e2e/support/ui/screen/index.js
+++ b/detox/e2e/support/ui/screen/index.js
@@ -21,6 +21,7 @@ import RecentMentionsScreen from './recent_mentions';
import SearchResultPostScreen from './search_result_post';
import SearchScreen from './search';
import SelectServerScreen from './select_server';
+import ThreadScreen from './thread';
export {
AddReactionScreen,
@@ -43,4 +44,5 @@ export {
SearchResultPostScreen,
SearchScreen,
SelectServerScreen,
+ ThreadScreen,
};
diff --git a/detox/e2e/support/ui/screen/login.js b/detox/e2e/support/ui/screen/login.js
index 110456fdb..270593aea 100644
--- a/detox/e2e/support/ui/screen/login.js
+++ b/detox/e2e/support/ui/screen/login.js
@@ -6,17 +6,17 @@ import {SelectServerScreen} from '@support/ui/screen';
class LoginScreen {
testID = {
loginScreen: 'login.screen',
- errorText: 'error.text',
- passwordInput: 'password.input',
- signinButton: 'signin.button',
- usernameInput: 'username.input',
+ usernameInput: 'login.username.input',
+ passwordInput: 'login.password.input',
+ signinButton: 'login.signin.button',
+ errorText: 'login.error.text',
}
loginScreen = element(by.id(this.testID.loginScreen));
- errorText = element(by.id(this.testID.errorText));
+ usernameInput = element(by.id(this.testID.usernameInput));
passwordInput = element(by.id(this.testID.passwordInput));
signinButton = element(by.id(this.testID.signinButton));
- usernameInput = element(by.id(this.testID.usernameInput));
+ errorText = element(by.id(this.testID.errorText));
toBeVisible = async () => {
await expect(this.loginScreen).toBeVisible();
diff --git a/detox/e2e/support/ui/screen/long_post.js b/detox/e2e/support/ui/screen/long_post.js
index ab61d3e42..7624e9c02 100644
--- a/detox/e2e/support/ui/screen/long_post.js
+++ b/detox/e2e/support/ui/screen/long_post.js
@@ -9,7 +9,11 @@ class LongPostScreen {
}
getPost = (postId, text) => {
- return Post.getPost(this.testID.longPostScreenPrefix, postId, text);
+ const {postItem, postItemHeaderReply} = Post.getPost(this.testID.longPostScreenPrefix, postId, text);
+ return {
+ longPostItem: postItem,
+ longPostItemHeaderReply: postItemHeaderReply,
+ };
}
}
diff --git a/detox/e2e/support/ui/screen/post_list.js b/detox/e2e/support/ui/screen/post_list.js
index 13093e9b7..4a86a5719 100644
--- a/detox/e2e/support/ui/screen/post_list.js
+++ b/detox/e2e/support/ui/screen/post_list.js
@@ -8,8 +8,12 @@ class PostListScreen {
postListScreenPrefix: 'post_list.',
}
- getPost = (postId, text) => {
- return Post.getPost(this.testID.postListScreenPrefix, postId, text);
+ getPost = (screenPrefix, postId, text) => {
+ const {postItem, postItemHeaderReply} = Post.getPost(`${screenPrefix}${this.testID.postListScreenPrefix}`, postId, text);
+ return {
+ postListPostItem: postItem,
+ postListPostItemHeaderReply: postItemHeaderReply,
+ };
}
}
diff --git a/detox/e2e/support/ui/screen/recent_mentions.js b/detox/e2e/support/ui/screen/recent_mentions.js
index 8d800a7c0..c49ab5e7f 100644
--- a/detox/e2e/support/ui/screen/recent_mentions.js
+++ b/detox/e2e/support/ui/screen/recent_mentions.js
@@ -39,11 +39,11 @@ class RecentMentionsScreen {
}
openPostOptionsFor = async (postId, text) => {
- const post = await this.getSearchResultPostItem(postId, text);
- await expect(post).toBeVisible();
+ const {searchResultPostItem} = await this.getSearchResultPostItem(postId, text);
+ await expect(searchResultPostItem).toBeVisible();
// # Open post options
- await post.longPress();
+ await searchResultPostItem.longPress();
await PostOptions.toBeVisible();
}
}
diff --git a/detox/e2e/support/ui/screen/search.js b/detox/e2e/support/ui/screen/search.js
index f3b86bd81..7ad9f8ae0 100644
--- a/detox/e2e/support/ui/screen/search.js
+++ b/detox/e2e/support/ui/screen/search.js
@@ -1,23 +1,54 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
-import {ChannelScreen} from '@support/ui/screen';
+import {
+ RecentItem,
+ SearchBar,
+} from '@support/ui/component';
+import {
+ ChannelScreen,
+ SearchResultPostScreen,
+} from '@support/ui/screen';
import {isAndroid} from '@support/utils';
class SearchScreen {
testID = {
+ searchScreenPrefix: 'search.',
searchScreen: 'search.screen',
- searchInput: 'searchInput',
- searchFromSection: 'search_from.section',
- searchInSection: 'search_in.section',
- searchOnSection: 'search_on.section',
+ searchFromSection: 'search.from_section',
+ searchInSection: 'search.in_section',
+ searchOnSection: 'search.on_section',
+ searchAfterSection: 'search.after_section',
+ searchBeforeSection: 'search.before_section',
}
searchScreen = element(by.id(this.testID.searchScreen));
- searchInput = element(by.id(this.testID.searchInput));
searchFromSection = element(by.id(this.testID.searchFromSection));
searchInSection = element(by.id(this.testID.searchInSection));
searchOnSection = element(by.id(this.testID.searchOnSection));
+ searchAfterSection = element(by.id(this.testID.searchAfterSection));
+ searchBeforeSection = element(by.id(this.testID.searchBeforeSection));
+
+ searchFromModifier = 'from:';
+ searchInModifier = 'in:';
+ searchOnModifier = 'on:';
+ searchAfterModifier = 'after:';
+ searchBeforeModifier = 'before:';
+
+ // convenience props
+ searchBar = SearchBar.getSearchBar(this.testID.searchScreenPrefix);
+ searchInput = SearchBar.getSearchInput(this.testID.searchScreenPrefix);
+ backButton = SearchBar.getBackButton(this.testID.searchScreenPrefix);
+ cancelButton = SearchBar.getCancelButton(this.testID.searchScreenPrefix);
+ clearButton = SearchBar.getClearButton(this.testID.searchScreenPrefix);
+
+ getRecentSearchItem = (searchTerms) => {
+ return RecentItem.getRecentItem(searchTerms);
+ }
+
+ getSearchResultPostItem = (postId, text) => {
+ return SearchResultPostScreen.getPost(postId, text);
+ }
toBeVisible = async () => {
await expect(this.searchScreen).toBeVisible();
@@ -32,12 +63,17 @@ class SearchScreen {
return this.toBeVisible();
}
- cancel = async () => {
+ back = async () => {
if (isAndroid()) {
- await device.pressBack();
+ await this.backButton.tap();
} else {
- await element(by.text('Cancel')).atIndex(0).tap();
+ await this.cancelButton.tap();
}
+ await expect(this.searchScreen).not.toBeVisible();
+ }
+
+ clear = async () => {
+ await this.clearButton.tap();
}
}
diff --git a/detox/e2e/support/ui/screen/search_result_post.js b/detox/e2e/support/ui/screen/search_result_post.js
index 0af5d4f7d..75fb1322d 100644
--- a/detox/e2e/support/ui/screen/search_result_post.js
+++ b/detox/e2e/support/ui/screen/search_result_post.js
@@ -9,7 +9,11 @@ class SearchResultPostScreen {
}
getPost = (postId, text) => {
- return Post.getPost(this.testID.searchResultPostScreenPrefix, postId, text);
+ const {postItem, postItemHeaderReply} = Post.getPost(this.testID.searchResultPostScreenPrefix, postId, text);
+ return {
+ searchResultPostItem: postItem,
+ searchResultPostItemHeaderReply: postItemHeaderReply,
+ };
}
}
diff --git a/detox/e2e/support/ui/screen/select_server.js b/detox/e2e/support/ui/screen/select_server.js
index f2924b2ac..4890a2fc7 100644
--- a/detox/e2e/support/ui/screen/select_server.js
+++ b/detox/e2e/support/ui/screen/select_server.js
@@ -2,23 +2,25 @@
// See LICENSE.txt for license information.
import {serverUrl} from '@support/test_config';
+import {timeouts} from '@support/utils';
class SelectServerScreen {
testID = {
selectServerScreen: 'select_server.screen',
- connectButton: 'connect.button',
- errorText: 'error.text',
- headerText: 'header.text',
- serverUrlInput: 'server_url.input',
+ headerText: 'select_server.header.text',
+ serverUrlInput: 'select_server.server_url.input',
+ connectButton: 'select_server.connect.button',
+ errorText: 'select_server.error.text',
}
selectServerScreen = element(by.id(this.testID.selectServerScreen));
+ headerText = element(by.id(this.testID.headerText));
serverUrlInput = element(by.id(this.testID.serverUrlInput));
connectButton = element(by.id(this.testID.connectButton));
errorText = element(by.id(this.testID.errorText));
toBeVisible = async () => {
- await expect(this.selectServerScreen).toBeVisible();
+ await waitFor(this.selectServerScreen).toBeVisible().withTimeout(timeouts.FOUR_SEC);
return this.selectServerScreen;
}
diff --git a/detox/e2e/support/ui/screen/thread.js b/detox/e2e/support/ui/screen/thread.js
new file mode 100644
index 000000000..5d41e121e
--- /dev/null
+++ b/detox/e2e/support/ui/screen/thread.js
@@ -0,0 +1,82 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {
+ CameraQuickAction,
+ FileQuickAction,
+ ImageQuickAction,
+ InputQuickAction,
+ PostDraft,
+ SendButton,
+} from '@support/ui/component';
+import {
+ LongPostScreen,
+ PostListScreen,
+} from '@support/ui/screen';
+import {timeouts, wait} from '@support/utils';
+
+class ThreadScreen {
+ testID = {
+ threadScreenPrefix: 'thread.',
+ threadScreen: 'thread.screen',
+ backButton: 'screen.back.button',
+ }
+
+ threadScreen = element(by.id(this.testID.threadScreen));
+ backButton = element(by.id(this.testID.backButton));
+
+ // convenience props
+ atInputQuickAction = InputQuickAction.getAtInputQuickAction(this.testID.threadScreenPrefix);
+ atInputQuickActionDisabled = InputQuickAction.getAtInputQuickActionDisabled(this.testID.threadScreenPrefix);
+ slashInputQuickAction = InputQuickAction.getSlashInputQuickAction(this.testID.threadScreenPrefix);
+ slashInputQuickActionDisabled = InputQuickAction.getSlashInputQuickActionDisabled(this.testID.threadScreenPrefix);
+ fileQuickAction = FileQuickAction.getFileQuickAction(this.testID.threadScreenPrefix);
+ fileQuickActionDisabled = FileQuickAction.getFileQuickActionDisabled(this.testID.threadScreenPrefix);
+ imageQuickAction = ImageQuickAction.getImageQuickAction(this.testID.threadScreenPrefix);
+ imageQuickActionDisabled = ImageQuickAction.getImageQuickActionDisabled(this.testID.threadScreenPrefix);
+ cameraQuickAction = CameraQuickAction.getCameraQuickAction(this.testID.threadScreenPrefix);
+ cameraQuickActionDisabled = CameraQuickAction.getCameraQuickActionDisabled(this.testID.threadScreenPrefix);
+ postDraft = PostDraft.getPostDraft(this.testID.threadScreenPrefix);
+ postDraftArchived = PostDraft.getPostDraftArchived(this.testID.threadScreenPrefix);
+ postDraftReadOnly = PostDraft.getPostDraftReadOnly(this.testID.threadScreenPrefix);
+ postInput = PostDraft.getPostInput(this.testID.threadScreenPrefix);
+ sendButton = SendButton.getSendButton(this.testID.threadScreenPrefix);
+ sendButtonDisabled = SendButton.getSendButtonDisabled(this.testID.threadScreenPrefix);
+
+ getLongPostPostItem = (postId, text) => {
+ return LongPostScreen.getPost(postId, text);
+ }
+
+ getPostListPostItem = (postId, text) => {
+ return PostListScreen.getPost(this.testID.threadScreenPrefix, postId, text);
+ }
+
+ toBeVisible = async () => {
+ await wait(timeouts.HALF_SEC);
+ await expect(this.threadScreen).toBeVisible();
+
+ return this.threadScreen;
+ }
+
+ back = async () => {
+ await this.backButton.tap();
+ await expect(this.threadScreen).not.toBeVisible();
+ }
+
+ postMessage = async (message) => {
+ // # Post message
+ await this.postInput.tap();
+ await this.postInput.typeText(message);
+ await this.tapSendButton();
+ }
+
+ tapSendButton = async () => {
+ // # Tap send button
+ await this.sendButton.tap();
+ await expect(this.sendButton).not.toExist();
+ await expect(this.sendButtonDisabled).toBeVisible();
+ }
+}
+
+const threadScreen = new ThreadScreen();
+export default threadScreen;
diff --git a/detox/e2e/test/autocomplete/edit_channel.e2e.js b/detox/e2e/test/autocomplete/edit_channel.e2e.js
index 928cc5630..3cdf51ab0 100644
--- a/detox/e2e/test/autocomplete/edit_channel.e2e.js
+++ b/detox/e2e/test/autocomplete/edit_channel.e2e.js
@@ -33,7 +33,7 @@ describe('Autocomplete', () => {
await EditChannelScreen.open();
// # Activate at_mention autocomplete
- await EditChannelScreen.editChannelHeaderInput.typeText('@');
+ await EditChannelScreen.headerInput.typeText('@');
// * Expect autocomplete to render
await Autocomplete.toBeVisible();
diff --git a/detox/e2e/test/autocomplete/search.e2e.js b/detox/e2e/test/autocomplete/search.e2e.js
index 862c0162d..5c109b6f2 100644
--- a/detox/e2e/test/autocomplete/search.e2e.js
+++ b/detox/e2e/test/autocomplete/search.e2e.js
@@ -8,7 +8,10 @@
// *******************************************************************
import {Autocomplete} from '@support/ui/component';
-import {ChannelScreen, SearchScreen} from '@support/ui/screen';
+import {
+ ChannelScreen,
+ SearchScreen,
+} from '@support/ui/screen';
import {Setup} from '@support/server_api';
describe('Autocomplete', () => {
@@ -27,7 +30,7 @@ describe('Autocomplete', () => {
});
beforeEach(async () => {
- await SearchScreen.searchInput.atIndex(0).clearText();
+ await SearchScreen.searchInput.clearText();
});
afterAll(async () => {
diff --git a/detox/e2e/test/channels/create_public_channel.e2e.js b/detox/e2e/test/channels/create_public_channel.e2e.js
index cfd2dd20b..43b88a528 100644
--- a/detox/e2e/test/channels/create_public_channel.e2e.js
+++ b/detox/e2e/test/channels/create_public_channel.e2e.js
@@ -16,6 +16,7 @@ import {
MoreChannelsScreen,
} from '@support/ui/screen';
import {Setup} from '@support/server_api';
+import {isAndroid} from '@support/utils';
describe('Channels', () => {
beforeAll(async () => {
@@ -52,7 +53,7 @@ describe('Channels', () => {
// # Fill data
await nameInput.typeText('a');
- await attemptToTapButton('edit_channel.create.button');
+ await attemptToTapCreateButton();
// * Expect to be in the same screen since the channel name must be longer
await expect(nameInput).toBeVisible();
@@ -61,7 +62,12 @@ describe('Channels', () => {
await purposeInput.typeText('This sentence has');
await purposeInput.tapReturnKey();
await purposeInput.typeText('multiple lines');
- await createChannelScreen.scroll(200, 'down');
+
+ // # Scroll down if Android
+ if (isAndroid()) {
+ await createChannelScreen.scroll(200, 'down');
+ }
+
await expect(headerInput).toBeVisible();
const expectedChannelHeader = 'I 🌮 love 🌮 tacos 🌮';
await headerInput.replaceText(expectedChannelHeader);
@@ -86,12 +92,12 @@ describe('Channels', () => {
});
});
-async function attemptToTapButton(id) {
- if (device.getPlatform() === 'ios') {
- const attributes = await element(by.id(id)).getAttributes();
+async function attemptToTapCreateButton() {
+ if (isAndroid()) {
+ await CreateChannelScreen.createButton.tap();
+ } else {
+ const attributes = await CreateChannelScreen.createButton.getAttributes();
jestExpect(attributes.visible).toEqual(true);
jestExpect(attributes.enabled).toEqual(false);
- } else {
- await element(by.id(id)).tap();
}
}
diff --git a/detox/e2e/test/on_boarding/login.e2e.js b/detox/e2e/test/signin_authentication/login.e2e.js
similarity index 60%
rename from detox/e2e/test/on_boarding/login.e2e.js
rename to detox/e2e/test/signin_authentication/login.e2e.js
index c9d83b242..c4613aeed 100644
--- a/detox/e2e/test/on_boarding/login.e2e.js
+++ b/detox/e2e/test/signin_authentication/login.e2e.js
@@ -11,20 +11,11 @@ import {Setup} from '@support/server_api';
import {
ChannelScreen,
LoginScreen,
- SelectServerScreen,
} from '@support/ui/screen';
-import {serverUrl} from '@support/test_config';
-import {isAndroid, timeouts, wait} from '@support/utils';
-describe('On boarding', () => {
+describe('Login', () => {
let user;
- const {
- connectButton,
- errorText,
- serverUrlInput,
- } = SelectServerScreen;
-
const {
errorText: loginErrorText,
usernameInput,
@@ -44,73 +35,6 @@ describe('On boarding', () => {
await ChannelScreen.logout();
});
- it('should show Select server screen on initial load', async () => {
- // * Verify basic elements on Select Server screen
- await SelectServerScreen.toBeVisible();
-
- await expect(serverUrlInput).toBeVisible();
- await expect(connectButton).toBeVisible();
- });
-
- it('MM-T3383 should show error on empty server URL', async () => {
- const screen = await SelectServerScreen.toBeVisible();
-
- // # Enter an empty server URL
- await serverUrlInput.typeText(' ');
-
- // # Tap anywhere to hide keyboard
- await screen.tap({x: 5, y: 10});
-
- // * Verify that the error message does not exist
- await waitFor(errorText).not.toExist().withTimeout(timeouts.HALF_SEC);
-
- // # Tap connect button
- await connectButton.tap();
-
- // # Explicitly wait on Android before verifying error message
- if (isAndroid()) {
- await wait(timeouts.ONE_SEC);
- }
-
- // * Verify error message
- await waitFor(errorText).toBeVisible().withTimeout(timeouts.ONE_SEC);
- await expect(errorText).toHaveText('Please enter a valid server URL');
- });
-
- it('should show error on invalid server URL', async () => {
- const screen = await SelectServerScreen.toBeVisible();
-
- // # Enter invalid server URL
- await serverUrlInput.clearText();
- await serverUrlInput.typeText(serverUrl.substring(0, serverUrl.length - 1));
-
- // # Tap anywhere to hide keyboard
- await screen.tap({x: 5, y: 10});
-
- // * Verify that the error message does not exist
- await waitFor(errorText).not.toExist().withTimeout(timeouts.HALF_SEC);
-
- // # Tap connect button
- await connectButton.tap();
-
- // * Verify error message
- await waitFor(errorText).toBeVisible().withTimeout(timeouts.ONE_SEC);
- await expect(errorText).toHaveText('Cannot connect to the server. Please check your server URL and internet connection.');
- });
-
- it('should move to Login screen on valid server URL', async () => {
- await SelectServerScreen.toBeVisible();
-
- // # Enter valid server URL
- await serverUrlInput.replaceText(serverUrl);
-
- // # Tap connect button
- await connectButton.tap();
-
- // * Verify that it goes into Login screen
- await LoginScreen.toBeVisible();
- });
-
it('should match elements on Login screen', async () => {
await LoginScreen.open();
diff --git a/detox/e2e/test/signin_authentication/select_server.e2e.js b/detox/e2e/test/signin_authentication/select_server.e2e.js
new file mode 100644
index 000000000..0d316ae7a
--- /dev/null
+++ b/detox/e2e/test/signin_authentication/select_server.e2e.js
@@ -0,0 +1,89 @@
+// 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 {
+ LoginScreen,
+ SelectServerScreen,
+} from '@support/ui/screen';
+import {serverUrl} from '@support/test_config';
+import {timeouts} from '@support/utils';
+
+describe('Select Server', () => {
+ const {
+ connectButton,
+ errorText,
+ serverUrlInput,
+ } = SelectServerScreen;
+
+ beforeEach(async () => {
+ await device.reloadReactNative();
+ });
+
+ it('should show Select server screen on initial load', async () => {
+ // * Verify basic elements on Select Server screen
+ await SelectServerScreen.toBeVisible();
+
+ await expect(serverUrlInput).toBeVisible();
+ await expect(connectButton).toBeVisible();
+ });
+
+ it('MM-T3383 should show error on empty server URL', async () => {
+ const screen = await SelectServerScreen.toBeVisible();
+
+ // # Enter an empty server URL
+ await serverUrlInput.typeText(' ');
+
+ // # Tap anywhere to hide keyboard
+ await screen.tap({x: 5, y: 10});
+
+ // * Verify that the error message does not exist
+ await waitFor(errorText).not.toExist().withTimeout(timeouts.HALF_SEC);
+
+ // # Tap connect button
+ await connectButton.tap();
+
+ // * Verify error message
+ await waitFor(errorText).toBeVisible().withTimeout(timeouts.ONE_SEC);
+ await expect(errorText).toHaveText('Please enter a valid server URL');
+ });
+
+ it('should show error on invalid server URL', async () => {
+ const screen = await SelectServerScreen.toBeVisible();
+
+ // # Enter invalid server URL
+ await serverUrlInput.clearText();
+ await serverUrlInput.typeText(serverUrl.substring(0, serverUrl.length - 1));
+
+ // # Tap anywhere to hide keyboard
+ await screen.tap({x: 5, y: 10});
+
+ // * Verify that the error message does not exist
+ await waitFor(errorText).not.toExist().withTimeout(timeouts.HALF_SEC);
+
+ // # Tap connect button
+ await connectButton.tap();
+
+ // * Verify error message
+ await waitFor(errorText).toBeVisible().withTimeout(timeouts.ONE_SEC);
+ await expect(errorText).toHaveText('Cannot connect to the server. Please check your server URL and internet connection.');
+ });
+
+ it('should move to Login screen on valid server URL', async () => {
+ await SelectServerScreen.toBeVisible();
+
+ // # Enter valid server URL
+ await serverUrlInput.replaceText(serverUrl);
+
+ // # Tap connect button
+ await connectButton.tap();
+
+ // * Verify that it goes into Login screen
+ await LoginScreen.toBeVisible();
+ });
+});
diff --git a/detox/e2e/test/smoke_test/recent_mentions.e2e.js b/detox/e2e/test/smoke_test/recent_mentions.e2e.js
index 1d0848ec0..6848f6eef 100644
--- a/detox/e2e/test/smoke_test/recent_mentions.e2e.js
+++ b/detox/e2e/test/smoke_test/recent_mentions.e2e.js
@@ -55,7 +55,7 @@ describe('Recent Mentions', () => {
// * Verify most recent post has the message
const lastPost = await Post.apiGetLastPostInChannel(testChannel.id);
- const postListPostItem = await ChannelScreen.getPostListPostItem(lastPost.post.id, testMessage);
+ const {postListPostItem} = await ChannelScreen.getPostListPostItem(lastPost.post.id, testMessage);
await expect(postListPostItem).toBeVisible();
// # Open recent mentions screen
@@ -64,7 +64,7 @@ describe('Recent Mentions', () => {
// * Verify most recent search result post has the at-mention message
const lastSearchResultPost = await Post.apiGetLastPostInChannel(testChannel.id);
- const searchResultPostItem = await RecentMentionsScreen.getSearchResultPostItem(lastSearchResultPost.post.id, testMessage);
+ const {searchResultPostItem} = await RecentMentionsScreen.getSearchResultPostItem(lastSearchResultPost.post.id, testMessage);
await expect(searchResultPostItem).toBeVisible();
// * Verify recent mentions post item does not have option to add a reaction
diff --git a/detox/e2e/test/smoke_test/search.e2e.js b/detox/e2e/test/smoke_test/search.e2e.js
new file mode 100644
index 000000000..2d3f2782f
--- /dev/null
+++ b/detox/e2e/test/smoke_test/search.e2e.js
@@ -0,0 +1,104 @@
+// 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,
+ ThreadScreen,
+} from '@support/ui/screen';
+import {
+ Channel,
+ Post,
+ Setup,
+} from '@support/server_api';
+
+describe('Search', () => {
+ let testUser;
+ let testChannel;
+
+ const {atMentionSuggestionList} = Autocomplete;
+
+ beforeAll(async () => {
+ const {team, user} = await Setup.apiInit();
+ testUser = user;
+
+ const {channel} = await Channel.apiGetChannelByName(team.name, 'town-square');
+ testChannel = channel;
+
+ // # Open channel screen
+ await ChannelScreen.open(user);
+ });
+
+ afterAll(async () => {
+ await ChannelScreen.logout();
+ });
+
+ it('MM-T3236 search on sender, select from autocomplete, reply from search results', async () => {
+ const testMessage = Date.now().toString();
+ const {
+ searchFromModifier,
+ searchFromSection,
+ searchInput,
+ } = SearchScreen;
+
+ // # Post a message
+ await ChannelScreen.postMessage(testMessage);
+
+ // # Open search screen
+ await SearchScreen.open();
+
+ // # Tap "from:" modifier
+ await searchInput.clearText();
+ await searchFromSection.tap();
+
+ // # Type beginning of search term
+ const searchTerm = testUser.first_name;
+ await searchInput.typeText(searchTerm);
+
+ // # Select user from autocomplete
+ await expect(atMentionSuggestionList).toExist();
+ const userAtMentionAutocomplete = await Autocomplete.getAtMentionItem(testUser.id);
+ await userAtMentionAutocomplete.tap();
+
+ // # Search user
+ await searchInput.tapReturnKey();
+ await expect(atMentionSuggestionList).not.toExist();
+
+ // * Verify recent search item is displayed
+ const searchTerms = `${searchFromModifier} ${testUser.username}`;
+ const recentSearchItem = await SearchScreen.getRecentSearchItem(searchTerms);
+ await expect(recentSearchItem).toBeVisible();
+
+ // * Verify search result post has the message
+ const lastPost = await Post.apiGetLastPostInChannel(testChannel.id);
+ const {
+ searchResultPostItem,
+ searchResultPostItemHeaderReply,
+ } = await SearchScreen.getSearchResultPostItem(lastPost.post.id, testMessage);
+ await expect(searchResultPostItem).toBeVisible();
+
+ // # Open reply thread from search result post item
+ const replyTestMessage = `reply-${testMessage}`;
+ searchResultPostItemHeaderReply.tap();
+
+ // # Post a reply message
+ await ThreadScreen.toBeVisible();
+ await ThreadScreen.postMessage(replyTestMessage);
+
+ // * Verify most recent post has the reply message
+ const replyPost = await Post.apiGetLastPostInChannel(testChannel.id);
+ const {postListPostItem} = await ThreadScreen.getPostListPostItem(replyPost.post.id, replyTestMessage);
+ await expect(postListPostItem).toBeVisible();
+
+ // # Go back to channel
+ await ThreadScreen.back();
+ await SearchScreen.back();
+ });
+});
diff --git a/share_extension/screens/channel_list.tsx b/share_extension/screens/channel_list.tsx
index 2034315cf..487a31c60 100644
--- a/share_extension/screens/channel_list.tsx
+++ b/share_extension/screens/channel_list.tsx
@@ -146,9 +146,13 @@ const ChannelList = ({intl}: ChannnelListProps) => {
}
return (
-
+