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 82254c1f8..07a832129 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
@@ -22,7 +22,7 @@ export default class ChannelItem extends PureComponent {
channelId: PropTypes.string.isRequired,
channel: PropTypes.object,
currentChannelId: PropTypes.string.isRequired,
- displayName: PropTypes.string.isRequired,
+ displayName: PropTypes.string,
isArchived: PropTypes.bool,
isChannelMuted: PropTypes.bool,
isManualUnread: PropTypes.bool,
diff --git a/app/screens/about/about.js b/app/screens/about/about.js
index 46f71a7d9..5a5793c68 100644
--- a/app/screens/about/about.js
+++ b/app/screens/about/about.js
@@ -86,6 +86,7 @@ export default class About extends PureComponent {
id='about.teamEditiont0'
defaultMessage='Team Edition'
style={style.title}
+ testID='about.title'
/>
);
@@ -94,6 +95,7 @@ export default class About extends PureComponent {
id='about.teamEditionSt'
defaultMessage='All your team communication in one place, instantly searchable and accessible anywhere.'
style={style.subtitle}
+ testID='about.subtitle'
/>
);
@@ -103,11 +105,15 @@ export default class About extends PureComponent {
id='about.teamEditionLearn'
defaultMessage='Join the Mattermost community at '
style={style.learn}
+ testID='about.learn_more'
/>
-
+
{Config.TeamEditionLearnURL}
@@ -121,6 +127,7 @@ export default class About extends PureComponent {
id='about.teamEditiont1'
defaultMessage='Enterprise Edition'
style={style.title}
+ testID='about.title'
/>
);
@@ -129,6 +136,7 @@ export default class About extends PureComponent {
id='about.enterpriseEditionSt'
defaultMessage='Modern communication from behind your firewall.'
style={style.subtitle}
+ testID='about.subtitle'
/>
);
@@ -138,11 +146,15 @@ export default class About extends PureComponent {
id='about.enterpriseEditionLearn'
defaultMessage='Learn more about Enterprise Edition at '
style={style.learn}
+ testID='about.learn_more'
/>
-
+
{Config.EELearnURL}
@@ -155,6 +167,7 @@ export default class About extends PureComponent {
id='about.enterpriseEditione1'
defaultMessage='Enterprise Edition'
style={style.title}
+ testID='about.title'
/>
);
@@ -167,6 +180,7 @@ export default class About extends PureComponent {
values={{
company: license.Company,
}}
+ testID='about.licensee'
/>
);
@@ -183,6 +197,7 @@ export default class About extends PureComponent {
values={{
version: config.Version,
}}
+ testID='about.server_version'
/>
);
} else {
@@ -195,6 +210,7 @@ export default class About extends PureComponent {
version: config.Version,
number: config.BuildNumber,
}}
+ testID='about.server_version'
/>
);
}
@@ -207,6 +223,7 @@ export default class About extends PureComponent {
defaultMessage='Terms of Service'
style={style.noticeLink}
onPress={this.handleTermsOfService}
+ testID='about.terms_of_service'
/>
);
}
@@ -219,6 +236,7 @@ export default class About extends PureComponent {
defaultMessage='Privacy Policy'
style={style.noticeLink}
onPress={this.handlePrivacyPolicy}
+ testID='about.privacy_policy'
/>
);
}
@@ -236,22 +254,28 @@ export default class About extends PureComponent {
-
+
{`${config.SiteName} `}
{title}
@@ -265,6 +289,7 @@ export default class About extends PureComponent {
version: DeviceInfo.getVersion(),
number: DeviceInfo.getBuildNumber(),
}}
+ testID='about.app_version'
/>
{serverVersion}
{licensee}
{learnMore}
@@ -285,6 +311,7 @@ export default class About extends PureComponent {
values={{
site: this.props.config.SiteName,
}}
+ testID='about.powered_by'
/>
}
{termsOfService}
@@ -324,6 +352,7 @@ export default class About extends PureComponent {
/>
),
}}
+ testID='about.notice_text'
/>
@@ -333,8 +362,12 @@ export default class About extends PureComponent {
id='about.hash'
defaultMessage='Build Hash:'
style={style.footerTitleText}
+ testID='about.build_hash.title'
/>
-
+
{config.BuildHash}
@@ -343,8 +376,12 @@ export default class About extends PureComponent {
id='about.hashee'
defaultMessage='EE Build Hash:'
style={style.footerTitleText}
+ testID='about.build_hash_enterprise.title'
/>
-
+
{config.BuildHashEnterprise}
@@ -354,8 +391,12 @@ export default class About extends PureComponent {
id='about.date'
defaultMessage='Build Date:'
style={style.footerTitleText}
+ testID='about.build_date.title'
/>
-
+
{config.BuildDate}
diff --git a/app/screens/settings/advanced_settings/advanced_settings.js b/app/screens/settings/advanced_settings/advanced_settings.js
index 7cd439e1d..f94d8e8e3 100644
--- a/app/screens/settings/advanced_settings/advanced_settings.js
+++ b/app/screens/settings/advanced_settings/advanced_settings.js
@@ -145,11 +145,13 @@ class AdvancedSettings extends Component {
{this.renderSentryDebugOptions()}
diff --git a/app/screens/user_profile/__snapshots__/user_profile.test.js.snap b/app/screens/user_profile/__snapshots__/user_profile.test.js.snap
index 0b61dc2f3..0f8eb72a5 100644
--- a/app/screens/user_profile/__snapshots__/user_profile.test.js.snap
+++ b/app/screens/user_profile/__snapshots__/user_profile.test.js.snap
@@ -7,6 +7,7 @@ exports[`user_profile should match snapshot 1`] = `
"flex": 1,
}
}
+ testID="user_profile.screen"
>
-
+
nick
@@ -110,6 +116,7 @@ exports[`user_profile should match snapshot 1`] = `
icon="send"
iconColor="rgba(0, 0, 0, 0.7)"
iconSize={24}
+ testID="user_profile.send_message.action"
textColor="#000"
textId="mobile.routes.user_profile.send_message"
theme={
diff --git a/app/screens/user_profile/user_profile.js b/app/screens/user_profile/user_profile.js
index f1840fb1e..ad0fd92ef 100644
--- a/app/screens/user_profile/user_profile.js
+++ b/app/screens/user_profile/user_profile.js
@@ -160,9 +160,19 @@ export default class UserProfile extends PureComponent {
}
return (
-
- {label}
- {user[property]}
+
+
+ {label}
+
+
+ {user[property]}
+
);
}
@@ -186,12 +196,14 @@ export default class UserProfile extends PureComponent {
id='mobile.routes.user_profile.local_time'
defaultMessage='LOCAL TIME'
style={style.header}
+ testID='user_profile.timezone_block.local_time.label'
/>
@@ -287,6 +299,7 @@ export default class UserProfile extends PureComponent {
icon={l.icon}
theme={this.props.theme}
iconSize={l.iconSize}
+ testID='user_profile.additional_options.action'
/>
);
});
@@ -331,11 +344,15 @@ export default class UserProfile extends PureComponent {
}
return (
-
+
{this.renderAdditionalOptions()}
diff --git a/app/screens/user_profile/user_profile_row.js b/app/screens/user_profile/user_profile_row.js
index 9912c1053..85f4fdda9 100644
--- a/app/screens/user_profile/user_profile_row.js
+++ b/app/screens/user_profile/user_profile_row.js
@@ -57,7 +57,7 @@ function createTouchableComponent(children, action) {
}
function userProfileRow(props) {
- const {action, defaultMessage, detail, icon, textId, togglable, theme, iconSize, shouldRender = true} = props;
+ const {action, defaultMessage, detail, icon, textId, togglable, theme, iconSize, shouldRender = true, testID} = props;
if (!shouldRender) {
return null;
@@ -74,7 +74,10 @@ function userProfileRow(props) {
);
const RowComponent = (
-
+
{iconComponent}
{
+ await expect(this.aboutScreen).toBeVisible();
+
+ return this.aboutScreen;
+ }
+
+ open = async () => {
+ // # Open about screen
+ await GeneralSettingsScreen.aboutAction.tap();
+
+ return this.toBeVisible();
+ }
+
+ back = async () => {
+ await this.backButton.tap();
+ await expect(this.aboutScreen).not.toBeVisible();
+ }
+}
+
+const aboutScreen = new AboutScreen();
+export default aboutScreen;
diff --git a/detox/e2e/support/ui/screen/advanced_settings.js b/detox/e2e/support/ui/screen/advanced_settings.js
new file mode 100644
index 000000000..51baffa0d
--- /dev/null
+++ b/detox/e2e/support/ui/screen/advanced_settings.js
@@ -0,0 +1,62 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {Alert} from '@support/ui/component';
+import {GeneralSettingsScreen} from '@support/ui/screen';
+import {timeouts, wait} from '@support/utils';
+
+class AdvancedSettingsScreen {
+ testID = {
+ advancedSettingsScreen: 'advanced_settings.screen',
+ advancedSettingsScrollView: 'advanced_settings.scroll_view',
+ backButton: 'screen.back.button',
+ deleteDocumentsAndDataAction: 'advanced_settings.delete_documents_and_data.action',
+ }
+
+ advancedSettingsScreen = element(by.id(this.testID.advancedSettingsScreen));
+ advancedSettingsScrollView = element(by.id(this.testID.advancedSettingsScrollView));
+ backButton = element(by.id(this.testID.backButton));
+ deleteDocumentsAndDataAction = element(by.id(this.testID.deleteDocumentsAndDataAction));
+
+ toBeVisible = async () => {
+ await expect(this.advancedSettingsScreen).toBeVisible();
+
+ return this.advancedSettingsScreen;
+ }
+
+ open = async () => {
+ // # Open advanced settings screen
+ await GeneralSettingsScreen.advancedAction.tap();
+
+ return this.toBeVisible();
+ }
+
+ back = async () => {
+ await this.backButton.tap();
+ await expect(this.advancedSettingsScreen).not.toBeVisible();
+ }
+
+ deleteDocumentsAndData = async ({confirm = true} = {}) => {
+ await this.deleteDocumentsAndDataAction.tap();
+ const {
+ deleteDocumentsAndDataTitle,
+ cancelButton,
+ deleteButton,
+ } = Alert;
+ await expect(deleteDocumentsAndDataTitle).toBeVisible();
+ await expect(cancelButton).toBeVisible();
+ await expect(deleteButton).toBeVisible();
+ if (confirm) {
+ deleteButton.tap();
+ await wait(timeouts.ONE_SEC);
+ await expect(this.advancedSettingsScreen).not.toBeVisible();
+ } else {
+ cancelButton.tap();
+ await wait(timeouts.ONE_SEC);
+ await expect(this.advancedSettingsScreen).toBeVisible();
+ }
+ }
+}
+
+const advancedSettingsScreen = new AdvancedSettingsScreen();
+export default advancedSettingsScreen;
diff --git a/detox/e2e/support/ui/screen/channel_add_members.js b/detox/e2e/support/ui/screen/channel_add_members.js
index 41bd47fe4..20337374f 100644
--- a/detox/e2e/support/ui/screen/channel_add_members.js
+++ b/detox/e2e/support/ui/screen/channel_add_members.js
@@ -2,11 +2,9 @@
// See LICENSE.txt for license information.
import {
- Alert,
MainSidebar,
SearchBar,
} from '@support/ui/component';
-import {timeouts, wait} from '@support/utils';
class ChannelAddMembersScreen {
testID = {
@@ -72,31 +70,6 @@ class ChannelAddMembersScreen {
await expect(this.channelAddMembersScreen).not.toBeVisible();
}
- removeMembers = async (displayUsernameList, {confirm = true} = {}) => {
- displayUsernameList.forEach(async (displayUsername) => {
- await this.getUserByDisplayUsername(`@${displayUsername}`).tap();
- });
- await wait(timeouts.ONE_SEC);
- await this.removeButton.tap();
- const {
- removeMembersTitle,
- noButton,
- yesButton,
- } = Alert;
- await expect(removeMembersTitle).toBeVisible();
- await expect(noButton).toBeVisible();
- await expect(yesButton).toBeVisible();
- if (confirm) {
- yesButton.tap();
- await wait(timeouts.ONE_SEC);
- await expect(this.channelAddMembersScreen).not.toBeVisible();
- } else {
- noButton.tap();
- await wait(timeouts.ONE_SEC);
- await expect(this.channelAddMembersScreen).toBeVisible();
- }
- }
-
hasUserDisplayUsernameAtIndex = async (index, displayUsername) => {
await expect(
this.getDisplayUsernameAtIndex(index),
diff --git a/detox/e2e/support/ui/screen/index.js b/detox/e2e/support/ui/screen/index.js
index 0f74ca234..9759397f1 100644
--- a/detox/e2e/support/ui/screen/index.js
+++ b/detox/e2e/support/ui/screen/index.js
@@ -1,6 +1,8 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
+import AboutScreen from './about';
+import AdvancedSettingsScreen from './advanced_settings';
import AddReactionScreen from './add_reaction';
import ChannelInfoScreen from './channel_info';
import ChannelAddMembersScreen from './channel_add_members';
@@ -30,8 +32,11 @@ import SearchScreen from './search';
import SelectServerScreen from './select_server';
import SelectTeamScreen from './select_team';
import ThreadScreen from './thread';
+import UserProfileScreen from './user_profile';
export {
+ AboutScreen,
+ AdvancedSettingsScreen,
AddReactionScreen,
ChannelInfoScreen,
ChannelAddMembersScreen,
@@ -61,4 +66,5 @@ export {
SelectServerScreen,
SelectTeamScreen,
ThreadScreen,
+ UserProfileScreen,
};
diff --git a/detox/e2e/support/ui/screen/user_profile.js b/detox/e2e/support/ui/screen/user_profile.js
new file mode 100644
index 000000000..0f570b865
--- /dev/null
+++ b/detox/e2e/support/ui/screen/user_profile.js
@@ -0,0 +1,49 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+class UserProfileScreen {
+ testID = {
+ userProfileScreen: 'user_profile.screen',
+ userProfileScrollView: 'user_profile.scroll_view',
+ emailLabel: 'user_profile.display_block.email.label',
+ emailValue: 'user_profile.display_block.email.value',
+ firstNameLabel: 'user_profile.display_block.first_name.label',
+ firstNameValue: 'user_profile.display_block.first_name.value',
+ lastNameLabel: 'user_profile.display_block.last_name.label',
+ lastNameValue: 'user_profile.display_block.last_name.value',
+ nicknameLabel: 'user_profile.display_block.nickname.label',
+ nicknameValue: 'user_profile.display_block.nickname.value',
+ positionLabel: 'user_profile.display_block.position.label',
+ positionValue: 'user_profile.display_block.position.value',
+ localTimeLabel: 'user_profile.timezone_block.local_time.label',
+ localTimeValue: 'user_profile.timezone_block.local_time.value',
+ additionalOptionsAction: 'user_profile.additional_options.action',
+ sendMessageAction: 'user_profile.send_message.action',
+ }
+
+ userProfileScreen = element(by.id(this.testID.userProfileScreen));
+ userProfileScrollView = element(by.id(this.testID.userProfileScrollView));
+ emailLabel = element(by.id(this.testID.emailLabel));
+ emailValue = element(by.id(this.testID.emailValue));
+ firstNameLabel = element(by.id(this.testID.firstNameLabel));
+ firstNameValue = element(by.id(this.testID.firstNameValue));
+ lastNameLabel = element(by.id(this.testID.lastNameLabel));
+ lastNameValue = element(by.id(this.testID.lastNameValue));
+ nicknameLabel = element(by.id(this.testID.nicknameLabel));
+ nicknameValue = element(by.id(this.testID.nicknameValue));
+ positionLabel = element(by.id(this.testID.positionLabel));
+ positionValue = element(by.id(this.testID.positionValue));
+ localTimeLabel = element(by.id(this.testID.localTimeLabel));
+ localTimeValue = element(by.id(this.testID.localTimeValue));
+ additionalOptionsAction = element(by.id(this.testID.additionalOptionsAction));
+ sendMessageAction = element(by.id(this.testID.sendMessageAction));
+
+ toBeVisible = async () => {
+ await expect(this.userProfileScreen).toBeVisible();
+
+ return this.userProfileScreen;
+ }
+}
+
+const userProfileScreen = new UserProfileScreen();
+export default userProfileScreen;
diff --git a/detox/e2e/test/smoke_test/about.e2e.js b/detox/e2e/test/smoke_test/about.e2e.js
new file mode 100644
index 000000000..229337e63
--- /dev/null
+++ b/detox/e2e/test/smoke_test/about.e2e.js
@@ -0,0 +1,73 @@
+// 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 {
+ AboutScreen,
+ ChannelScreen,
+ GeneralSettingsScreen,
+} from '@support/ui/screen';
+import {Setup} from '@support/server_api';
+
+describe('About', () => {
+ beforeAll(async () => {
+ const {user} = await Setup.apiInit();
+
+ // # Open channel screen
+ await ChannelScreen.open(user);
+ });
+
+ afterAll(async () => {
+ await ChannelScreen.logout();
+ });
+
+ it('MM-T3264 should be able to display about info', async () => {
+ const {
+ aboutAppVersion,
+ aboutBuildDateTitle,
+ aboutBuildDateValue,
+ aboutBuildHashTitle,
+ aboutBuildHashValue,
+ aboutBuildHashEnterpriseTitle,
+ aboutBuildHashEnterpriseValue,
+ aboutDatabase,
+ aboutLicensee,
+ aboutLogo,
+ aboutScrollView,
+ aboutServerVersion,
+ aboutSubtitle,
+ aboutTitle,
+ } = AboutScreen;
+
+ // # Open about screen
+ await ChannelScreen.openSettingsSidebar();
+ await GeneralSettingsScreen.open();
+ await AboutScreen.open();
+
+ // * Verify about info
+ await expect(aboutLogo).toBeVisible();
+ await expect(aboutSubtitle).toBeVisible();
+ await expect(aboutTitle).toBeVisible();
+ await expect(aboutSubtitle).toBeVisible();
+ await expect(aboutAppVersion).toBeVisible();
+ await expect(aboutServerVersion).toBeVisible();
+ await expect(aboutDatabase).toBeVisible();
+ await expect(aboutLicensee).toBeVisible();
+ await aboutScrollView.scrollTo('bottom');
+ await expect(aboutBuildHashTitle).toBeVisible();
+ await expect(aboutBuildHashValue).toBeVisible();
+ await expect(aboutBuildHashEnterpriseTitle).toBeVisible();
+ await expect(aboutBuildHashEnterpriseValue).toBeVisible();
+ await expect(aboutBuildDateTitle).toBeVisible();
+ await expect(aboutBuildDateValue).toBeVisible();
+
+ // # Go back to channel
+ await AboutScreen.back();
+ await GeneralSettingsScreen.close();
+ });
+});
diff --git a/detox/e2e/test/smoke_test/advanced_settings.e2e.js b/detox/e2e/test/smoke_test/advanced_settings.e2e.js
new file mode 100644
index 000000000..b6d904701
--- /dev/null
+++ b/detox/e2e/test/smoke_test/advanced_settings.e2e.js
@@ -0,0 +1,49 @@
+// 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 {
+ AdvancedSettingsScreen,
+ ChannelScreen,
+ GeneralSettingsScreen,
+} from '@support/ui/screen';
+import {
+ Channel,
+ Setup,
+} from '@support/server_api';
+
+describe('Advanced Settings', () => {
+ let townSquareChannel;
+
+ beforeAll(async () => {
+ const {team, user} = await Setup.apiInit();
+
+ ({channel: townSquareChannel} = await Channel.apiGetChannelByName(team.name, 'town-square'));
+
+ // # Open channel screen
+ await ChannelScreen.open(user);
+ });
+
+ afterAll(async () => {
+ await ChannelScreen.logout();
+ });
+
+ it('MM-T3262 should be able to delete documents and data', async () => {
+ // # Open advanced settings screen
+ await ChannelScreen.openSettingsSidebar();
+ await GeneralSettingsScreen.open();
+ await AdvancedSettingsScreen.open();
+
+ // # Delete documents and data
+ await AdvancedSettingsScreen.deleteDocumentsAndData();
+
+ // * Verify redirects to town square
+ await ChannelScreen.toBeVisible();
+ await expect(ChannelScreen.channelNavBarTitle).toHaveText(townSquareChannel.display_name);
+ });
+});
diff --git a/detox/e2e/test/smoke_test/channel_add_members.e2e.js b/detox/e2e/test/smoke_test/channel_add_members.e2e.js
index 4c6185cc0..aa9465e68 100644
--- a/detox/e2e/test/smoke_test/channel_add_members.e2e.js
+++ b/detox/e2e/test/smoke_test/channel_add_members.e2e.js
@@ -19,7 +19,21 @@ import {
} from '@support/server_api';
describe('Channel Add Members', () => {
+ const {
+ goToChannel,
+ postMessage,
+ } = ChannelScreen;
+ const {
+ addMembersAction,
+ channelInfoScrollView,
+ } = ChannelInfoScreen;
+ const {
+ addButton,
+ getUserByDisplayUsername,
+ searchInput,
+ } = ChannelAddMembersScreen;
let testChannel;
+ let testAnotherUser;
let testLastUser;
beforeAll(async () => {
@@ -30,7 +44,9 @@ describe('Channel Add Members', () => {
const {user: testOtherUser} = await User.apiCreateUser({prefix: `a-${key}-`});
await Team.apiAddUserToTeam(testOtherUser.id, team.id);
});
+ ({user: testAnotherUser} = await User.apiCreateUser({prefix: 'b-other-'}));
({user: testLastUser} = await User.apiCreateUser({prefix: 'z-'}));
+ await Team.apiAddUserToTeam(testAnotherUser.id, team.id);
await Team.apiAddUserToTeam(testLastUser.id, team.id);
// # Open channel screen
@@ -41,20 +57,37 @@ describe('Channel Add Members', () => {
await ChannelScreen.logout();
});
- it('MM-T3197 should be able load users in long add members list', async () => {
- const {
- addMembersAction,
- channelInfoScrollView,
- } = ChannelInfoScreen;
-
+ it('MM-T3196 should be able to add members to channel', async () => {
// # Open add members screen
- await ChannelScreen.goToChannel(testChannel.display_name);
+ await goToChannel(testChannel.display_name);
+ await postMessage('divider');
+ await ChannelInfoScreen.open();
+ await expect(element(by.id(ChannelInfoScreen.testID.manageMembersAction).withDescendant(by.text('2')))).toBeVisible();
+ await channelInfoScrollView.scrollTo('bottom');
+ await addMembersAction.tap();
+
+ // # Add members to channel
+ await searchInput.typeText('b-other');
+ await getUserByDisplayUsername(`@${testAnotherUser.username}`).tap();
+ await addButton.tap();
+
+ // * Verify members are added
+ await expect(element(by.id(ChannelInfoScreen.testID.manageMembersAction).withDescendant(by.text('3')))).toBeVisible();
+
+ // * Verify system message
+ await ChannelInfoScreen.close();
+ await expect(element(by.text(`@${testAnotherUser.username} added to the channel by you.`))).toBeVisible();
+ });
+
+ it('MM-T3197 should be able load users in long add members list', async () => {
+ // # Open add members screen
+ await goToChannel(testChannel.display_name);
await ChannelInfoScreen.open();
await channelInfoScrollView.scrollTo('bottom');
await addMembersAction.tap();
// * Verify user can scroll down multiple times until last user is seen
- await waitFor(ChannelAddMembersScreen.getUserByDisplayUsername(`@${testLastUser.username}`)).toBeVisible().whileElement(by.id(ChannelAddMembersScreen.testID.usersList)).scroll(500, 'down');
+ await waitFor(getUserByDisplayUsername(`@${testLastUser.username}`)).toBeVisible().whileElement(by.id(ChannelAddMembersScreen.testID.usersList)).scroll(500, 'down');
await ChannelAddMembersScreen.back();
// # Close channel info screen
diff --git a/detox/e2e/test/smoke_test/direct_messages.e2e.js b/detox/e2e/test/smoke_test/direct_messages.e2e.js
index e08b3ef37..56df981ba 100644
--- a/detox/e2e/test/smoke_test/direct_messages.e2e.js
+++ b/detox/e2e/test/smoke_test/direct_messages.e2e.js
@@ -12,9 +12,12 @@ import {
ChannelInfoScreen,
ChannelScreen,
MoreDirectMessagesScreen,
+ ThreadScreen,
+ UserProfileScreen,
} from '@support/ui/screen';
import {
Channel,
+ Post,
Setup,
Team,
User,
@@ -26,8 +29,10 @@ describe('Direct Messages', () => {
const {
channelNavBarTitle,
closeMainSidebar,
+ getPostListPostItem,
goToChannel,
openMainSidebar,
+ openReplyThreadFor,
} = ChannelScreen;
const {
getUserAtIndex,
@@ -38,6 +43,7 @@ describe('Direct Messages', () => {
let testUser;
let testOtherUser;
let townSquareChannel;
+ let testMessage;
beforeAll(async () => {
const {user, team} = await Setup.apiInit();
@@ -48,6 +54,14 @@ describe('Direct Messages', () => {
({channel: townSquareChannel} = await Channel.apiGetChannelByName(team.name, 'town-square'));
+ // # Post message by other user
+ testMessage = `Message by ${testOtherUser.username}`;
+ await User.apiLogin(testOtherUser);
+ await Post.apiCreatePost({
+ channelId: townSquareChannel.id,
+ message: testMessage,
+ });
+
// # Open channel screen
await ChannelScreen.open(testUser);
});
@@ -56,6 +70,35 @@ describe('Direct Messages', () => {
await ChannelScreen.logout();
});
+ it('MM-T3210 should be able to open direct message from profile info in channel', async () => {
+ // # Open user profile screen from channel
+ const {post} = await Post.apiGetLastPostInChannel(townSquareChannel.id);
+ const {postListPostItemProfilePicture} = await getPostListPostItem(post.id, testMessage, {userId: testOtherUser.id});
+ await postListPostItemProfilePicture.tap();
+ await UserProfileScreen.toBeVisible();
+
+ // # Open direct message from profile and verify can post message
+ await openDirectMessageFromProfileAndVerifyCanPostMessage(testOtherUser);
+
+ // # Go back to channel
+ await goToChannel(townSquareChannel.display_name);
+ });
+
+ it('MM-T3211 should be able to open direct message from profile info in reply thread', async () => {
+ // # Open user profile screen from reply thread
+ const {post} = await Post.apiGetLastPostInChannel(townSquareChannel.id);
+ await openReplyThreadFor(post.id, testMessage);
+ const {postListPostItemProfilePicture} = await ThreadScreen.getPostListPostItem(post.id, testMessage, {userId: testOtherUser.id});
+ await postListPostItemProfilePicture.tap();
+ await UserProfileScreen.toBeVisible();
+
+ // # Open direct message from profile and verify can post message
+ await openDirectMessageFromProfileAndVerifyCanPostMessage(testOtherUser);
+
+ // # Go back to channel
+ await goToChannel(townSquareChannel.display_name);
+ });
+
it('MM-T3215 should be able to close direct message', async () => {
// # Create a DM with the other user
await openMainSidebar();
@@ -94,3 +137,24 @@ describe('Direct Messages', () => {
await expect(channelNavBarTitle).toHaveText(`${testUser.username} (you) `);
});
});
+
+async function openDirectMessageFromProfileAndVerifyCanPostMessage(testOtherUser) {
+ const {
+ sendMessageAction,
+ userProfileScrollView,
+ } = UserProfileScreen;
+
+ // # Open direct message from profile
+ await userProfileScrollView.scrollTo('bottom');
+ await sendMessageAction.tap();
+
+ // * Verify DM channel is created
+ await ChannelInfoScreen.open();
+ await expect(ChannelInfoScreen.channelDisplayName).toHaveText(testOtherUser.username);
+
+ // * Verify direct message can be posted
+ const directMessage = Date.now().toString();
+ await ChannelInfoScreen.close();
+ await ChannelScreen.postMessage(directMessage);
+ await expect(element(by.text(directMessage))).toBeVisible();
+}
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 6f390dd27..2c28f7f3e 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -651,10 +651,10 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
- DoubleConversion: cde416483dac037923206447da6e1454df403714
+ DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de
FBLazyVector: 49cbe4b43e445b06bf29199b6ad2057649e4c8f5
FBReactNativeSpec: 4862b23f27a9cdb8fdb1710af411fa677dcdd3cf
- glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
+ glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
jail-monkey: 80c9e34da2cd54023e5ad08bf7051ec75bd43d5b
libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3
MMKV: 22e5136f7d00197bc0fc9694b7f71519f0d1ca12