MM-30426 Detox/E2E: Add e2e for MM-T3188, MM-T3193, MM-T3198, MM-T3229 (#5228)

This commit is contained in:
Joseph Baylon 2021-03-17 04:02:17 -07:00 committed by GitHub
parent 27cafc8288
commit a610e7ae5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 417 additions and 124 deletions

View file

@ -380,10 +380,7 @@ class FilteredList extends Component {
const {styles, testID} = this.props;
const dataSource = this.buildData(this.props);
return (
<View
testID={testID}
style={styles.container}
>
<View style={styles.container}>
<SectionList
sections={dataSource}
renderItem={this.renderItem}
@ -393,6 +390,7 @@ class FilteredList extends Component {
keyboardShouldPersistTaps={'always'}
maxToRenderPerBatch={10}
stickySectionHeadersEnabled={true}
testID={testID}
viewabilityConfig={VIEWABILITY_CONFIG}
/>
</View>

View file

@ -3,7 +3,6 @@
exports[`ChannelsList List should match snapshot 1`] = `
<View
onLayout={[Function]}
testID="main.sidebar.channels_list.list"
>
<SectionList
contentContainerStyle={
@ -27,6 +26,7 @@ exports[`ChannelsList List should match snapshot 1`] = `
scrollEventThrottle={50}
sections={Array []}
stickySectionHeadersEnabled={true}
testID="main.sidebar.channels_list.list"
updateCellsBatchingPeriod={50}
viewabilityConfig={
Object {

View file

@ -404,7 +404,6 @@ export default class List extends PureComponent {
return (
<View
testID={testID}
style={styles.container}
onLayout={this.onLayout}
>
@ -419,6 +418,7 @@ export default class List extends PureComponent {
onViewableItemsChanged={this.updateUnreadIndicators}
maxToRenderPerBatch={10}
stickySectionHeadersEnabled={true}
testID={testID}
viewabilityConfig={VIEWABILITY_CONFIG}
{...this.keyboardDismissProp}
/>

View file

@ -35,6 +35,7 @@ export default class UnreadIndicatorBase extends PureComponent {
<View
style={[style.wrapper, this.props.style]}
pointerEvents={visible ? 'auto' : 'none'}
testID='channels_list.unread_indicator'
>
<CompassIcon
name='arrow-up'

View file

@ -78,6 +78,7 @@ exports[`ChannelMembers should match snapshot 1`] = `
renderItem={[Function]}
shouldRenderSeparator={true}
showNoResults={true}
testID="channel_members.custom_list"
theme={
Object {
"awayIndicator": "#ffbc42",

View file

@ -67,6 +67,7 @@ export default class ChannelMembers extends PureComponent {
enabled: false,
id: 'remove-members',
showAsAction: 'always',
testID: 'channel_members.remove.button',
text: context.intl.formatMessage({id: 'channel_members_modal.remove', defaultMessage: 'Remove'}),
};
@ -391,6 +392,7 @@ export default class ChannelMembers extends PureComponent {
onLoadMore={this.getProfiles}
onRowPress={this.handleSelectProfile}
renderItem={canManageUsers ? this.renderSelectableItem : this.renderUnselectableItem}
testID='channel_members.custom_list'
theme={theme}
/>
</SafeAreaView>

View file

@ -277,6 +277,7 @@ LongPost {
"width": 40,
}
}
testID="close.long_post.button"
>
<CompassIcon
color="#3d3c40"

View file

@ -135,6 +135,7 @@ export default class LongPost extends PureComponent {
<TouchableOpacity
style={style.close}
onPress={this.handleClose}
testID='close.long_post.button'
>
<CompassIcon
name='close'

View file

@ -8,6 +8,7 @@ class Alert {
archivePublicChannelTitle = isAndroid() ? element(by.text('Archive Public Channel')) : element(by.label('Archive Public Channel')).atIndex(0);
deletePostTitle = isAndroid() ? element(by.text('Delete Post')) : element(by.label('Delete Post')).atIndex(0);
joinPrivateChannelTitle = isAndroid() ? element(by.text('Join private channel')) : element(by.label('Join private channel')).atIndex(0);
removeMembersTitle = isAndroid() ? element(by.text('Remove Members')) : element(by.label('Remove Members')).atIndex(0);
// alert buttons
cancelButton = isAndroid() ? element(by.text('CANCEL')) : element(by.label('Cancel')).atIndex(0);

View file

@ -7,6 +7,7 @@ class ChannelsList {
testID = {
channelsListPrefix: 'main.sidebar.channels_list.',
channelsList: 'main.sidebar.channels_list.list',
channelsListUnreadIndicator: 'channels_list.unread_indicator',
channelItem: 'main.sidebar.channels_list.list.channel_item',
channelItemDisplayName: 'main.sidebar.channels_list.list.channel_item.display_name',
filteredChannelsList: 'main.sidebar.channels_list.filtered_list',
@ -19,6 +20,7 @@ class ChannelsList {
}
channelsList = element(by.id(this.testID.channelsList));
channelsListUnreadIndicator = element(by.id(this.testID.channelsListUnreadIndicator));
filteredChannelsList = element(by.id(this.testID.channelsList));
switchTeamsButton = element(by.id(this.testID.switchTeamsButton));
switchTeamsButtonBadge = element(by.id(this.testID.switchTeamsButtonBadge));

View file

@ -23,6 +23,7 @@ class MainSidebar {
cancelButton = ChannelsList.cancelButton;
clearButton = ChannelsList.clearButton;
channelsList = ChannelsList.channelsList;
channelsListUnreadIndicator = ChannelsList.channelsListUnreadIndicator;
filteredChannelsList = ChannelsList.filteredChannelsList;
switchTeamsButton = ChannelsList.switchTeamsButton;
switchTeamsButtonBadge = ChannelsList.switchTeamsButtonBadge;

View file

@ -3,7 +3,7 @@
class TeamsList {
testID = {
teamsList: 'main.sidebar.teams_list',
teamsList: 'main.sidebar.teams_list.flat_list',
teamItem: 'main.sidebar.teams_list.flat_list.teams_list_item',
teamItemBadge: 'main.sidebar.teams_list.flat_list.teams_list_item.badge',
teamItemBadgeUnreadCount: 'main.sidebar.teams_list.flat_list.teams_list_item.badge.unread_count',

View file

@ -139,6 +139,13 @@ class ChannelScreen {
await this.toBeVisible();
}
goToChannel = async (displayName) => {
await this.openMainSidebar();
const channelItem = MainSidebar.getChannelByDisplayName(displayName);
await channelItem.tap();
await expect(this.channelNavBarTitle).toHaveText(displayName);
}
openMainSidebar = async () => {
// # Open main sidebar
await this.mainSidebarDrawerButton.tap();

View file

@ -0,0 +1,104 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {
Alert,
MainSidebar,
SearchBar,
} from '@support/ui/component';
import {timeouts, wait} from '@support/utils';
class ChannelMembersScreen {
testID = {
channelMembersScreenPrefix: 'channel_members.',
channelMembersScreen: 'channel_members.screen',
removeButton: 'channel_members.remove.button',
backButton: 'screen.back.button',
usersList: 'channel_members.custom_list',
userItem: 'channel_members.custom_list.user_item',
userItemDisplayUsername: 'channel_members.custom_list.user_item.display_username',
}
channelMembersScreen = element(by.id(this.testID.channelMembersScreen));
removeButton = element(by.id(this.testID.removeButton));
backButton = element(by.id(this.testID.backButton));
usersList = element(by.id(this.testID.usersList));
// convenience props
searchBar = SearchBar.getSearchBar(this.testID.channelMembersScreenPrefix);
searchInput = SearchBar.getSearchInput(this.testID.channelMembersScreenPrefix);
cancelButton = SearchBar.getCancelButton(this.testID.channelMembersScreenPrefix);
clearButton = SearchBar.getClearButton(this.testID.channelMembersScreenPrefix);
getUser = (userId, diplayUsername) => {
const userItemTestID = `${this.testID.userItem}.${userId}`;
const baseMatcher = by.id(userItemTestID);
const userItemMatcher = diplayUsername ? baseMatcher.withDescendant(by.text(diplayUsername)) : baseMatcher;
const userItemUsernameDisplayMatcher = by.id(this.testID.userItemDisplayUsername).withAncestor(userItemMatcher);
return {
userItem: element(userItemMatcher),
userItemUsernameDisplay: element(userItemUsernameDisplayMatcher),
};
}
getUserAtIndex = (index) => {
return element(by.id(this.testID.userItem).withAncestor(by.id(this.testID.usersList))).atIndex(index);
}
getUserByDisplayUsername = (displayUsername) => {
return element(by.text(displayUsername).withAncestor(by.id(this.testID.usersList)));
}
getDisplayUsernameAtIndex = (index) => {
return element(by.id(this.testID.userItemDisplayUsername)).atIndex(index);
}
toBeVisible = async () => {
await expect(this.channelMembersScreen).toBeVisible();
return this.channelMembersScreen;
}
open = async () => {
// # Open more direct messages screen
await MainSidebar.openChannelMembersButton.tap();
return this.toBeVisible();
}
back = async () => {
await this.backButton.tap();
await expect(this.channelMembersScreen).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();
if (confirm) {
yesButton.tap();
} else {
noButton.tap();
}
await wait(timeouts.ONE_SEC);
await expect(this.channelMembersScreen).not.toBeVisible();
}
hasUserDisplayUsernameAtIndex = async (index, displayUsername) => {
await expect(
this.getDisplayUsernameAtIndex(index),
).toHaveText(displayUsername);
}
}
const channelMembersScreen = new ChannelMembersScreen();
export default channelMembersScreen;

View file

@ -3,6 +3,7 @@
import AddReactionScreen from './add_reaction';
import ChannelInfoScreen from './channel_info';
import ChannelMembersScreen from './channel_members';
import ChannelNotificationPreferenceScreen from './channel_notification_preference';
import ChannelScreen from './channel';
import ClockDisplaySettingsScreen from './clock_display_settings';
@ -32,6 +33,7 @@ import ThreadScreen from './thread';
export {
AddReactionScreen,
ChannelInfoScreen,
ChannelMembersScreen,
ChannelNotificationPreferenceScreen,
ChannelScreen,
ClockDisplaySettingsScreen,

View file

@ -6,8 +6,11 @@ import {Post} from '@support/ui/component';
class LongPostScreen {
testID = {
longPostItem: 'long_post.post',
closeLongPostButton: 'close.long_post.button',
}
closeLongPostButton = element(by.id(this.testID.closeLongPostButton));
getPost = (postId, postMessage, postProfileOptions = {}) => {
const {
postItem,

View file

@ -7,7 +7,6 @@
// - Use element testID when selecting an element. Create one if none.
// *******************************************************************
import {MainSidebar} from '@support/ui/component';
import {
ChannelScreen,
ChannelInfoScreen,
@ -41,7 +40,10 @@ describe('Archived Channels', () => {
});
it('MM-T3618 should display archived channels list', async () => {
const {openMainSidebar} = ChannelScreen;
const {
goToChannel,
openMainSidebar,
} = ChannelScreen;
const {
getChannelByDisplayName,
hasChannelDisplayNameAtIndex,
@ -51,8 +53,7 @@ describe('Archived Channels', () => {
} = MoreChannelsScreen;
// # Archive channel
await openMainSidebar();
await MainSidebar.getChannelByDisplayName(archivedChannel.display_name).tap();
await goToChannel(archivedChannel.display_name);
await ChannelInfoScreen.open();
await ChannelInfoScreen.archiveChannel();

View file

@ -9,7 +9,6 @@
import {MainSidebar} from '@support/ui/component';
import {ChannelScreen} from '@support/ui/screen';
import {isAndroid} from '@support/utils';
import {Setup} from '@support/server_api';
describe('Select channel', () => {
@ -28,26 +27,19 @@ describe('Select channel', () => {
});
it('MM-T3412 should close the sidebar menu when selecting the same channel', async () => {
const {channelNavBarTitle} = ChannelScreen;
const {
channelNavBarTitle,
goToChannel,
} = ChannelScreen;
// # Open main sidebar (with at least one unread channel)
await ChannelScreen.openMainSidebar();
// # Go to unread channel
await goToChannel(newChannel.display_name);
// # Tap a channel to view it
const channelItem = MainSidebar.getChannelByDisplayName(newChannel.display_name);
await channelItem.tap();
// # Go to the same channel again
await goToChannel(newChannel.display_name);
// * Selected channel should be visible
await expect(channelNavBarTitle).toHaveText(newChannel.display_name);
// # Open main sidebar again and select the same channel
await ChannelScreen.openMainSidebar();
await channelItem.tap();
// * Drawer should not be visible on Android
if (isAndroid()) {
await expect(MainSidebar.mainSidebar).not.toBeVisible();
}
// * Verify sidebar menu is not open
await expect(MainSidebar.mainSidebar).not.toBeVisible();
// * Selected channel should remain the same
await expect(channelNavBarTitle).toHaveText(newChannel.display_name);

View file

@ -7,7 +7,6 @@
// - Use element testID when selecting an element. Create one if none.
// *******************************************************************
import {MainSidebar} from '@support/ui/component';
import {ChannelScreen, PermalinkScreen} from '@support/ui/screen';
import {User, Setup, Channel, Post} from '@support/server_api';
@ -40,9 +39,7 @@ describe('Permalink', () => {
});
// # Go to test channel
await ChannelScreen.openMainSidebar();
await MainSidebar.getChannelByDisplayName(testChannel.display_name).tap();
await ChannelScreen.toBeVisible();
await ChannelScreen.goToChannel(testChannel.display_name);
// # Tap the channel permalink
await element(by.text(permalinkLabel)).tap({x: 5, y: 10});

View file

@ -7,18 +7,43 @@
// - Use element testID when selecting an element. Create one if none.
// *******************************************************************
import {Alert, MainSidebar} from '@support/ui/component';
import {ChannelScreen, CreateChannelScreen, PermalinkScreen} from '@support/ui/screen';
import {Channel, Post, Setup, Team, User} from '@support/server_api';
import {adminUsername, adminPassword, serverUrl} from '@support/test_config';
import {getRandomId} from '@support/utils';
import {
Alert,
MainSidebar,
TeamsList,
} from '@support/ui/component';
import {
ChannelScreen,
CreateChannelScreen,
PermalinkScreen,
} from '@support/ui/screen';
import {
Channel,
Post,
Setup,
Team,
User,
} from '@support/server_api';
import {
serverUrl,
} from '@support/test_config';
import {
getAdminAccount,
getRandomId,
} from '@support/utils';
describe('Messaging', () => {
const {
channelNavBarTitle,
goToChannel,
logout,
openTeamSidebar,
postMessage,
} = ChannelScreen;
let testChannel;
let testTeam;
beforeEach(async () => {
beforeAll(async () => {
const {channel, team, user} = await Setup.apiInit();
testChannel = channel;
testTeam = team;
@ -26,25 +51,19 @@ describe('Messaging', () => {
await ChannelScreen.open(user);
});
afterEach(async () => {
afterAll(async () => {
await ChannelScreen.logout();
});
it('MM-T3471 Tapping channel URL link joins public channel', async () => {
const {
channelNavBarTitle,
logout,
postMessage,
} = ChannelScreen;
// # Go to the Town Square channel
await gotoChannel('Town Square');
await goToChannel('Town Square');
// # There's no way to get a channel permalink on mobile so we make one manually
const channelPermalink = `${serverUrl}/${testTeam.name}/channels/${testChannel.name}`;
// # Post the channel permalink to the test channel in Town Square
await postMessage(channelPermalink);
await postMessage(channelPermalink, {quickReplace: true});
await expect(element(by.text(channelPermalink))).toBeVisible();
// # Create another user in the same team, log in and go to town square
@ -52,7 +71,7 @@ describe('Messaging', () => {
await Team.apiAddUserToTeam(otherUser.id, testTeam.id);
await logout();
await ChannelScreen.open(otherUser);
await gotoChannel('Town Square');
await goToChannel('Town Square');
// # As this new user, tap the channel permalink we posted earlier
await tapLink(channelPermalink);
@ -66,11 +85,6 @@ describe('Messaging', () => {
// - Post a message in second channel and post the permalink of it in the public channel
// - Confirm the prompt and join the channel
it('MM-30237 System admins prompted before joining private channel via permalink', async () => {
const {
logout,
openTeamSidebar,
postMessage,
} = ChannelScreen;
const {getTeamByDisplayName} = MainSidebar;
// # Create Private Channel 1
@ -89,34 +103,32 @@ describe('Messaging', () => {
const {post} = await Post.apiGetLastPostInChannel(privateChannel2.id);
// # Go to the Town Square channel
await gotoChannel('Town Square');
await goToChannel('Town Square');
// # Post Private Channel 1 Permalink
const message1 = `${serverUrl}/${testTeam.name}/channels/${privateChannel1Name}`;
await postMessage(message1);
await postMessage(message1, {quickReplace: true});
// * Check that message is successfully posted
await expect(element(by.text(message1))).toExist();
// # Post Private Channel 2's POST Permalink
const message2 = `${serverUrl}/${testTeam.name}/pl/${post.id}`;
await postMessage(message2);
await postMessage(message2, {quickReplace: true});
// * Check that message is successfully posted
await expect(element(by.text(message2))).toExist();
// # Logout and login as sysadmin
await logout();
await ChannelScreen.open({
username: adminUsername,
password: adminPassword,
});
await ChannelScreen.open(getAdminAccount());
// * Verify channel screen is visible
await ChannelScreen.toBeVisible();
// # Go to the team
await openTeamSidebar();
await waitFor(getTeamByDisplayName(testTeam.display_name)).toBeVisible().whileElement(by.id(TeamsList.testID.teamsList)).scroll(500, 'down');
await getTeamByDisplayName(testTeam.display_name).tap();
// # Press on message 1
@ -129,7 +141,7 @@ describe('Messaging', () => {
await expect(ChannelScreen.channelIntro).toHaveText('Beginning of ' + privateChannel1Name);
// # Go to Townsquare
await gotoChannel('Town Square');
await goToChannel('Town Square');
// # Press on message 2
await tapLink(message2);
@ -166,13 +178,6 @@ async function createPrivateChannel(channelName) {
await expect(ChannelScreen.channelIntro).toHaveText('Beginning of ' + channelName);
}
async function gotoChannel(name) {
await ChannelScreen.openMainSidebar();
const channelItem = MainSidebar.getChannelByDisplayName(name);
await channelItem.tap();
await expect(ChannelScreen.channelNavBarTitle).toHaveText(name);
}
async function joinPrivateChannel() {
await expect(Alert.joinPrivateChannelTitle).toBeVisible();
await Alert.joinButton.tap();

View file

@ -7,7 +7,6 @@
// - Use element testID when selecting an element. Create one if none.
// *******************************************************************
import {MainSidebar} from '@support/ui/component';
import {
ChannelInfoScreen,
ChannelNotificationPreferenceScreen,
@ -32,8 +31,7 @@ describe('Channel Notification Preference - Default', () => {
beforeEach(async () => {
// # Go to channel
await ChannelScreen.openMainSidebar();
await MainSidebar.getChannelByDisplayName(testChannel.display_name).tap();
await ChannelScreen.goToChannel(testChannel.display_name);
});
afterAll(async () => {

View file

@ -7,7 +7,6 @@
// - Use element testID when selecting an element. Create one if none.
// *******************************************************************
import {MainSidebar} from '@support/ui/component';
import {
ChannelInfoScreen,
ChannelNotificationPreferenceScreen,
@ -30,8 +29,7 @@ describe('Channel Notification Preference', () => {
beforeEach(async () => {
// # Go to channel
await ChannelScreen.openMainSidebar();
await MainSidebar.getChannelByDisplayName(testChannel.display_name).tap();
await ChannelScreen.goToChannel(testChannel.display_name);
});
afterAll(async () => {

View file

@ -31,10 +31,10 @@ describe('Channels', () => {
const {
channelNavBarTitle,
closeMainSidebar,
goToChannel,
openMainSidebar,
} = ChannelScreen;
const {
getChannelByDisplayName,
getFilteredChannelByDisplayName,
hasChannelDisplayNameAtIndex,
hasFilteredChannelDisplayNameAtIndex,
@ -94,18 +94,16 @@ describe('Channels', () => {
await hasChannelDisplayNameAtIndex(6, 'Town Square');
await expect(element(by.id(nonJoinedChannel.display_name))).not.toBeVisible();
await expect(element(by.id(nonDmOtherUser.username))).not.toBeVisible();
await closeMainSidebar();
// # Visit private, public, favorite, and direct message channels
await getChannelByDisplayName(privateChannel.display_name).tap();
await openMainSidebar();
await getChannelByDisplayName(publicChannel.display_name).tap();
await openMainSidebar();
await getChannelByDisplayName(favoriteChannel.display_name).tap();
await openMainSidebar();
await getChannelByDisplayName(dmOtherUser.username).tap();
await openMainSidebar();
await goToChannel(privateChannel.display_name);
await goToChannel(publicChannel.display_name);
await goToChannel(favoriteChannel.display_name);
await goToChannel(dmOtherUser.username);
// * Verify order when all channels are read except for unread channel
await openMainSidebar();
await hasChannelDisplayNameAtIndex(0, unreadChannel.display_name);
await hasChannelDisplayNameAtIndex(1, favoriteChannel.display_name);
await hasChannelDisplayNameAtIndex(2, publicChannel.display_name);

View file

@ -26,6 +26,7 @@ describe('Direct Messages', () => {
const {
channelNavBarTitle,
closeMainSidebar,
goToChannel,
openMainSidebar,
} = ChannelScreen;
const {
@ -67,8 +68,7 @@ describe('Direct Messages', () => {
await ChannelInfoScreen.open();
await expect(ChannelInfoScreen.headerDisplayName).toHaveText(testOtherUser.username);
await ChannelInfoScreen.close();
await openMainSidebar();
await getChannelByDisplayName(testOtherUser.username).tap();
await goToChannel(testOtherUser.username);
// # Close DM channel
await ChannelInfoScreen.open();
@ -78,6 +78,8 @@ describe('Direct Messages', () => {
await expect(channelNavBarTitle).toHaveText(townSquareChannel.display_name);
await openMainSidebar();
await expect(getChannelByDisplayName(testOtherUser.username)).not.toBeVisible();
// # Close main sidebar
await closeMainSidebar();
});

View file

@ -17,16 +17,14 @@ import {Setup} from '@support/server_api';
describe('Favorite Channels', () => {
const {
closeMainSidebar,
goToChannel,
openMainSidebar,
} = ChannelScreen;
const {
favoriteSwitchFalse,
favoriteSwitchTrue,
} = ChannelInfoScreen;
const {
getChannelByDisplayName,
hasChannelDisplayNameAtIndex,
} = MainSidebar;
const {hasChannelDisplayNameAtIndex} = MainSidebar;
let testChannel;
beforeAll(async () => {
@ -43,8 +41,7 @@ describe('Favorite Channels', () => {
it('MM-T3191 should be able to favorite a channel', async () => {
// # Open channel info screen
await openMainSidebar();
await getChannelByDisplayName(testChannel.display_name).tap();
await goToChannel(testChannel.display_name);
await ChannelInfoScreen.open();
// * Verify favorite switch is toggled off
@ -70,8 +67,7 @@ describe('Favorite Channels', () => {
it('MM-T3192 should be able to un-favorite a channel', async () => {
// # Open channel info screen
await openMainSidebar();
await getChannelByDisplayName(testChannel.display_name).tap();
await goToChannel(testChannel.display_name);
await ChannelInfoScreen.open();
// * Verify favorite switch is toggled on

View file

@ -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 {
ChannelInfoScreen,
ChannelMembersScreen,
ChannelScreen,
} from '@support/ui/screen';
import {
Channel,
Setup,
Team,
User,
} from '@support/server_api';
import {getRandomId} from '@support/utils';
describe('Manage Members', () => {
const searchTerm = getRandomId();
const {
removeMembers,
searchInput,
} = ChannelMembersScreen;
let testChannel;
let testUser;
let testOtherUser;
beforeAll(async () => {
const {channel, team, user} = await Setup.apiInit();
testChannel = channel;
testUser = user;
({user: testOtherUser} = await User.apiCreateUser({prefix: searchTerm}));
await Team.apiAddUserToTeam(testOtherUser.id, team.id);
await Channel.apiAddUserToChannel(testOtherUser.id, testChannel.id);
// # Open channel screen
await ChannelScreen.open(testUser);
});
afterAll(async () => {
await ChannelScreen.logout();
});
it('MM-T3198 should be able to remove a member', async () => {
// # Go to channel
await ChannelScreen.goToChannel(testChannel.display_name);
// * Verify initial member count is 3
await ChannelInfoScreen.open();
await expect(element(by.id(ChannelInfoScreen.testID.manageMembersAction).withDescendant(by.text('3')))).toBeVisible();
// # Remove 1 member
await ChannelInfoScreen.manageMembersAction.tap();
await searchInput.typeText(searchTerm);
await removeMembers([testOtherUser.username]);
// * Verify member count is 2 and member is removed
await expect(element(by.id(ChannelInfoScreen.testID.manageMembersAction).withDescendant(by.text('2')))).toBeVisible();
await ChannelInfoScreen.manageMembersAction.tap();
await searchInput.typeText(searchTerm);
await expect(element(by.text('No Results'))).toBeVisible();
await ChannelMembersScreen.back();
// # Close channel info screen
await ChannelInfoScreen.close();
});
});

View file

@ -7,7 +7,10 @@
// - Use element testID when selecting an element. Create one if none.
// *******************************************************************
import {ChannelScreen} from '@support/ui/screen';
import {
ChannelScreen,
LongPostScreen,
} from '@support/ui/screen';
import {
Channel,
Post,
@ -15,7 +18,9 @@ import {
} from '@support/server_api';
describe('Message Posting', () => {
const longMessage = 'The quick brown fox jumps over the lazy dog.'.repeat(30);
const {
getLongPostItem,
getPostListPostItem,
postMessage,
} = ChannelScreen;
@ -37,19 +42,32 @@ describe('Message Posting', () => {
it('MM-T3217 should be able to post a long message', async () => {
// # Post a long message
const message = 'The quick brown fox jumps over the lazy dog.'.repeat(30);
await postMessage(message, {quickReplace: true});
await postMessage(longMessage, {quickReplace: true});
// * Verify message is posted
const {post} = await Post.apiGetLastPostInChannel(testChannel.id);
const {
postListPostItem,
postListPostItemShowMoreButton,
} = await getPostListPostItem(post.id, message);
} = await getPostListPostItem(post.id, longMessage);
await expect(postListPostItem).toExist();
await expect(postListPostItemShowMoreButton).toExist();
});
it('MM-T3229 should be able to open long post via show more', async () => {
// # Open long post via show more
const {post} = await Post.apiGetLastPostInChannel(testChannel.id);
const {postListPostItemShowMoreButton} = await getPostListPostItem(post.id, longMessage);
await postListPostItemShowMoreButton.tap();
// * Verify long post is displayed
const {longPostItem} = getLongPostItem(post.id, longMessage);
await expect(longPostItem).toExist();
// # Close long post screen
await LongPostScreen.closeLongPostButton.tap();
});
it('MM-T3269 should be able to post a markdown image', async () => {
// # Post a markdown image
const message = '![alt text that displays if loading fails](https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png)';

View file

@ -0,0 +1,66 @@
// 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 {MainSidebar} from '@support/ui/component';
import {
ChannelInfoScreen,
ChannelScreen,
} from '@support/ui/screen';
import {Setup} from '@support/server_api';
describe('Mute Channels', () => {
const {
closeMainSidebar,
goToChannel,
openMainSidebar,
} = ChannelScreen;
const {
muteSwitchFalse,
muteSwitchTrue,
} = ChannelInfoScreen;
const {hasChannelDisplayNameAtIndex} = MainSidebar;
let testChannel;
beforeAll(async () => {
const {channel, user} = await Setup.apiInit();
testChannel = channel;
// # Open channel screen
await ChannelScreen.open(user);
});
afterAll(async () => {
await ChannelScreen.logout();
});
it('MM-T3193 should be able to mute a channel', async () => {
// # Open channel info screen
await goToChannel(testChannel.display_name);
await ChannelInfoScreen.open();
// * Verify favorite switch is toggled off
await expect(muteSwitchFalse).toBeVisible();
await expect(muteSwitchTrue).not.toBeVisible();
// # Toggle on mute switch
await muteSwitchFalse.tap();
// * Verify mute switch is toggled on
await expect(muteSwitchTrue).toBeVisible();
await expect(muteSwitchFalse).not.toBeVisible();
// * Verify channel appears last in the channels list
await ChannelInfoScreen.close();
await openMainSidebar();
await hasChannelDisplayNameAtIndex(2, testChannel.display_name);
// # Close main sidebar
await closeMainSidebar();
});
});

View file

@ -15,22 +15,36 @@ import {
} from '@support/server_api';
describe('Unread channels', () => {
const {
goToChannel,
closeMainSidebar,
openMainSidebar,
} = ChannelScreen;
const {
channelsList,
channelsListUnreadIndicator,
hasChannelDisplayNameAtIndex,
} = MainSidebar;
let testUser;
let testTeam;
let newChannel;
let aChannel;
let zChannel;
beforeAll(async () => {
const {user, channel, team} = await Setup.apiInit();
const {channel, team, user} = await Setup.apiInit();
testUser = user;
testTeam = team;
newChannel = channel;
({channel: aChannel} = await Channel.apiCreateChannel({type: 'O', prefix: 'a-channel', teamId: team.id}));
await Channel.apiAddUserToChannel(user.id, aChannel.id);
({channel: aChannel} = await Channel.apiCreateChannel({type: 'O', prefix: 'a-channel', teamId: testTeam.id}));
await Channel.apiAddUserToChannel(testUser.id, aChannel.id);
({channel: zChannel} = await Channel.apiCreateChannel({type: 'O', prefix: 'z-channel', teamId: team.id}));
await Channel.apiAddUserToChannel(user.id, zChannel.id);
({channel: zChannel} = await Channel.apiCreateChannel({type: 'O', prefix: 'z-channel', teamId: testTeam.id}));
await Channel.apiAddUserToChannel(testUser.id, zChannel.id);
// # Open channel screen
await ChannelScreen.open(user);
await ChannelScreen.open(testUser);
});
afterAll(async () => {
@ -38,12 +52,6 @@ describe('Unread channels', () => {
});
it('MM-T3187 Unread channels sort at top', async () => {
const {openMainSidebar} = ChannelScreen;
const {
getChannelByDisplayName,
hasChannelDisplayNameAtIndex,
} = MainSidebar;
// # Open main sidebar (with at least one unread channel)
await openMainSidebar();
@ -52,13 +60,12 @@ describe('Unread channels', () => {
await hasChannelDisplayNameAtIndex(0, aChannel.display_name);
await hasChannelDisplayNameAtIndex(1, newChannel.display_name);
await hasChannelDisplayNameAtIndex(2, zChannel.display_name);
await closeMainSidebar();
// # Tap an unread channel to view it
await getChannelByDisplayName(aChannel.display_name).tap();
await openMainSidebar();
await getChannelByDisplayName(newChannel.display_name).tap();
await openMainSidebar();
await getChannelByDisplayName(zChannel.display_name).tap();
await goToChannel(aChannel.display_name);
await goToChannel(newChannel.display_name);
await goToChannel(zChannel.display_name);
// * Channel you just read is no longer listed in Unreads
await openMainSidebar();
@ -69,6 +76,28 @@ describe('Unread channels', () => {
await hasChannelDisplayNameAtIndex(2, 'Off-Topic');
await hasChannelDisplayNameAtIndex(3, 'Town Square');
await hasChannelDisplayNameAtIndex(4, zChannel.display_name);
await getChannelByDisplayName(aChannel.display_name).tap();
// # Close main sidebar
await closeMainSidebar();
});
it('MM-T3188 should display more unreads indicator when unreads are off-screen in channels list', async () => {
// # Create 10 unread channels
[...Array(10).keys()].forEach(async (key) => {
const {channel} = await Channel.apiCreateChannel({type: 'O', prefix: `unread-channel-${key}`, teamId: testTeam.id});
await Channel.apiAddUserToChannel(testUser.id, channel.id);
});
// # Open main sidebar (with at least one unread channel)
await openMainSidebar();
// # Scroll to bottom
await channelsList.scroll(500, 'down');
// * Verify more unreads indicator is displayed
await expect(channelsListUnreadIndicator).toBeVisible();
// # Close main sidebar
await closeMainSidebar();
});
});

View file

@ -7,10 +7,7 @@
// - Use element testID when selecting an element. Create one if none.
// *******************************************************************
import {
MainSidebar,
SettingsSidebar,
} from '@support/ui/component';
import {SettingsSidebar} from '@support/ui/component';
import {ChannelScreen} from '@support/ui/screen';
import {
Channel,
@ -52,7 +49,7 @@ describe('User Status', () => {
const {
closeSettingsSidebar,
getPostListPostItem,
openMainSidebar,
goToChannel,
openSettingsSidebar,
} = ChannelScreen;
@ -66,8 +63,7 @@ describe('User Status', () => {
await ChannelScreen.open(testOtherUser);
// * Verify user's profile has status away as seen by other user
await openMainSidebar();
await MainSidebar.getChannelByDisplayName(testUser.username).tap();
await goToChannel(testUser.username);
const {post} = await Post.apiGetLastPostInChannel(testChannel.id);
const {postListPostItemProfilePictureUserStatus} = await getPostListPostItem(post.id, testMessage, {userId: testUser.id, userStatus: 'away'});
await expect(postListPostItemProfilePictureUserStatus).toBeVisible();