E2E: Mobile Drafts tests cases (#8469)
This commit is contained in:
parent
44bce6c319
commit
2830d06fc2
11 changed files with 342 additions and 3 deletions
|
|
@ -119,7 +119,12 @@ const DraftsButton: React.FC<DraftListProps> = ({
|
|||
color={theme.sidebarText}
|
||||
style={customStyles.opacity}
|
||||
/>
|
||||
<Text style={customStyles.count}>{draftsCount}</Text>
|
||||
<Text
|
||||
testID='channel_list.drafts.count'
|
||||
style={customStyles.count}
|
||||
>
|
||||
{draftsCount}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ const OptionItem = ({
|
|||
value={selected}
|
||||
trackColor={trackColor}
|
||||
thumbColor={thumbColor}
|
||||
testID={`${testID}.toggled.${selected}`}
|
||||
testID={`${testID}.toggled.${selected}.${value}`}
|
||||
/>
|
||||
);
|
||||
} else if (type === OptionType.ARROW) {
|
||||
|
|
|
|||
|
|
@ -50,12 +50,14 @@ export default function DraftInputHeader({
|
|||
{postPriority.requested_ack && (
|
||||
<>
|
||||
<CompassIcon
|
||||
testID='drafts.requested_ack.icon'
|
||||
color={theme.onlineIndicator}
|
||||
name='check-circle-outline'
|
||||
size={14}
|
||||
/>
|
||||
{!postPriority.priority && (
|
||||
<FormattedText
|
||||
testID='requested_ack.title'
|
||||
id='requested_ack.title'
|
||||
defaultMessage='Request Acknowledgements'
|
||||
style={{color: theme.onlineIndicator}}
|
||||
|
|
@ -66,12 +68,14 @@ export default function DraftInputHeader({
|
|||
{postPriority.persistent_notifications && (
|
||||
<>
|
||||
<CompassIcon
|
||||
testID='drafts.persistent_notifications.icon'
|
||||
color={PostPriorityColors.URGENT}
|
||||
name='bell-ring-outline'
|
||||
size={14}
|
||||
/>
|
||||
{noMentionsError && (
|
||||
<FormattedText
|
||||
testID='drafts.persistent_notifications.error.no_mentions.title'
|
||||
id='persistent_notifications.error.no_mentions.title'
|
||||
defaultMessage='Recipients must be @mentioned'
|
||||
style={style.error}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,10 @@ const PostPriorityLabel = ({label}: Props) => {
|
|||
labelText = intl.formatMessage({id: 'post_priority.label.important', defaultMessage: 'IMPORTANT'});
|
||||
}
|
||||
return (
|
||||
<View style={containerStyle}>
|
||||
<View
|
||||
testID={`${label}_post_priority_label`}
|
||||
style={containerStyle}
|
||||
>
|
||||
<CompassIcon
|
||||
name={iconName}
|
||||
style={style.icon}
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ const PostPriorityPicker = ({
|
|||
type='toggle'
|
||||
selected={data.requested_ack}
|
||||
descriptionNumberOfLines={2}
|
||||
value='requested_ack'
|
||||
/>
|
||||
</View>
|
||||
{displayPersistentNotifications && (
|
||||
|
|
@ -211,6 +212,7 @@ const PostPriorityPicker = ({
|
|||
type='toggle'
|
||||
selected={data.persistent_notifications}
|
||||
descriptionNumberOfLines={2}
|
||||
value='persistent_notifications'
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class Alert {
|
|||
removeButton3 = isAndroid() ? element(by.text('REMOVE')) : element(by.label('Remove')).atIndex(3);
|
||||
yesButton = isAndroid() ? element(by.text('YES')) : element(by.label('Yes')).atIndex(0);
|
||||
yesButton2 = isAndroid() ? element(by.text('YES')) : element(by.label('Yes')).atIndex(1);
|
||||
sendButton = isAndroid() ? element(by.text('SEND')) : element(by.label('Send')).atIndex(1);
|
||||
}
|
||||
|
||||
const alert = new Alert();
|
||||
|
|
|
|||
|
|
@ -42,8 +42,18 @@ class ChannelScreen {
|
|||
introUnfavoriteAction: 'channel_post_list.intro_options.unfavorite.action',
|
||||
introChannelInfoAction: 'channel_post_list.intro_options.channel_info.action',
|
||||
toastMessage: 'toast.message',
|
||||
postPriorityPicker: 'channel.post_draft.quick_actions.post_priority_action',
|
||||
postPriorityImportantMessage: 'post_priority_picker_item.important',
|
||||
postPriorityUrgentMessage: 'post_priority_picker_item.urgent',
|
||||
postPriorityRequestAck: 'post_priority_picker_item.requested_ack.toggled.false.requested_ack',
|
||||
postPriorityPersistentNotification: 'post_priority_picker_item.persistent_notifications.toggled.undefined.persistent_notifications',
|
||||
};
|
||||
|
||||
postPriorityPersistentNotification = element(by.id(this.testID.postPriorityPersistentNotification));
|
||||
postPriorityUrgentMessage = element(by.id(this.testID.postPriorityUrgentMessage));
|
||||
postPriorityRequestAck = element(by.id(this.testID.postPriorityRequestAck));
|
||||
postPriorityImportantMessage = element(by.id(this.testID.postPriorityImportantMessage));
|
||||
postPriorityPicker = element(by.id(this.testID.postPriorityPicker));
|
||||
archievedCloseChannelButton = element(by.id(this.testID.archievedCloseChannelButton));
|
||||
channelScreen = element(by.id(this.testID.channelScreen));
|
||||
channelQuickActionsButton = element(by.id(this.testID.channelQuickActionsButton));
|
||||
|
|
@ -63,6 +73,7 @@ class ChannelScreen {
|
|||
introUnfavoriteAction = element(by.id(this.testID.introUnfavoriteAction));
|
||||
introChannelInfoAction = element(by.id(this.testID.introChannelInfoAction));
|
||||
toastMessage = element(by.id(this.testID.toastMessage));
|
||||
applyPostPriority = element(by.text('Apply'));
|
||||
|
||||
// convenience props
|
||||
backButton = NavigationHeader.backButton;
|
||||
|
|
@ -196,6 +207,30 @@ class ChannelScreen {
|
|||
this.getPostMessageAtIndex(index),
|
||||
).toHaveText(postMessage);
|
||||
};
|
||||
|
||||
openPostPriorityPicker = async () => {
|
||||
await this.postPriorityPicker.tap();
|
||||
};
|
||||
|
||||
clickPostPriorityImportantMessage = async () => {
|
||||
await this.postPriorityImportantMessage.tap();
|
||||
};
|
||||
|
||||
clickPostPriorityUrgentMessage = async () => {
|
||||
await this.postPriorityUrgentMessage.tap();
|
||||
};
|
||||
|
||||
toggleRequestAckPostpriority = async () => {
|
||||
await this.postPriorityRequestAck.tap();
|
||||
};
|
||||
|
||||
togglePersistentNotificationPostpriority = async () => {
|
||||
await this.postPriorityPersistentNotification.tap();
|
||||
};
|
||||
|
||||
applyPostPrioritySettings = async () => {
|
||||
await this.applyPostPriority.tap();
|
||||
};
|
||||
}
|
||||
|
||||
const channelScreen = new ChannelScreen();
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ class ChannelListScreen {
|
|||
testID = {
|
||||
categoryHeaderPrefix: 'channel_list.category_header.',
|
||||
categoryPrefix: 'channel_list.category.',
|
||||
draftChannelInfo: 'draft_post.channel_info',
|
||||
draftbuttonListScreen: 'channel_list.drafts.button',
|
||||
draftCountListScreen: 'channel_list.drafts.count',
|
||||
teamItemPrefix: 'team_sidebar.team_list.team_item.',
|
||||
channelListScreen: 'channel_list.screen',
|
||||
serverIcon: 'channel_list.servers.server_icon',
|
||||
|
|
@ -83,6 +86,22 @@ class ChannelListScreen {
|
|||
|
||||
return this.toBeVisible();
|
||||
};
|
||||
|
||||
draftsButton = {
|
||||
toBeVisible: async () => {
|
||||
await waitFor(element(by.id(this.testID.draftbuttonListScreen))).toBeVisible().withTimeout(timeouts.ONE_SEC);
|
||||
},
|
||||
toNotBeVisible: async () => {
|
||||
await waitFor(element(by.id(this.testID.draftbuttonListScreen))).not.toBeVisible().withTimeout(timeouts.ONE_SEC);
|
||||
},
|
||||
tap: async () => {
|
||||
await element(by.id(this.testID.draftbuttonListScreen)).tap();
|
||||
},
|
||||
};
|
||||
|
||||
getDraftChannelInfo = () => {
|
||||
return element(by.id(this.testID.draftChannelInfo));
|
||||
};
|
||||
}
|
||||
|
||||
const channelListScreen = new ChannelListScreen();
|
||||
|
|
|
|||
90
detox/e2e/support/ui/screen/draft_screen.ts
Normal file
90
detox/e2e/support/ui/screen/draft_screen.ts
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Alert, NavigationHeader} from '@support/ui/component';
|
||||
import {timeouts, wait} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
class DraftScreen {
|
||||
testID = {
|
||||
editDraft: 'edit_draft',
|
||||
deleteDraft: 'delete_draft',
|
||||
draftMessageContent: 'draft_message',
|
||||
draftScreen: 'global_drafts_list',
|
||||
draftTooltipCloseButton: 'draft.tooltip.close.button',
|
||||
draftPost: 'draft_post',
|
||||
draftSendButton: 'send_draft_button',
|
||||
draftEmptyTitle: 'drafts.empty.title',
|
||||
requestACKIcon: 'drafts.requested_ack.icon',
|
||||
persistentNotificationIcon: 'drafts.persistent_notifications.icon',
|
||||
};
|
||||
|
||||
persistentNotificationIcon = element(by.id(this.testID.persistentNotificationIcon));
|
||||
requestACKIcon = element(by.id(this.testID.requestACKIcon));
|
||||
editDraft = element(by.id(this.testID.editDraft));
|
||||
backButton = NavigationHeader.backButton;
|
||||
draftScreen = element(by.id(this.testID.draftScreen));
|
||||
draftPost = element(by.id(this.testID.draftPost));
|
||||
draftSendButton = element(by.id(this.testID.draftSendButton));
|
||||
draftEmptyTitle = element(by.id(this.testID.draftEmptyTitle));
|
||||
deleteDraftSwipeAction = element(by.text('Delete draft'));
|
||||
draftMessageContent = element(by.id(this.testID.draftMessageContent));
|
||||
deleteDraft = element(by.id(this.testID.deleteDraft));
|
||||
|
||||
draftTooltipCloseButton = {
|
||||
tap: async () => {
|
||||
await element(by.id(this.testID.draftTooltipCloseButton)).tap();
|
||||
},
|
||||
};
|
||||
|
||||
openDraftPostActions = async () => {
|
||||
await this.draftPost.longPress();
|
||||
};
|
||||
|
||||
swipeDraftPostLeft = async () => {
|
||||
await this.draftPost.swipe('left');
|
||||
};
|
||||
|
||||
deleteDraftPost = async (deleteAction: any) => {
|
||||
await expect(deleteAction).toBeVisible();
|
||||
await deleteAction.tap();
|
||||
await waitFor(Alert.deleteButton).toExist().withTimeout(timeouts.TEN_SEC);
|
||||
await Alert.deleteButton.tap();
|
||||
};
|
||||
|
||||
deleteDraftPostFromSwipeActions = async () => {
|
||||
await this.deleteDraftPost(this.deleteDraftSwipeAction);
|
||||
};
|
||||
|
||||
deleteDraftPostFromDraftActions = async () => {
|
||||
await this.deleteDraftPost(this.deleteDraft);
|
||||
};
|
||||
|
||||
sendDraft = async () => {
|
||||
await this.draftSendButton.tap();
|
||||
await waitFor(Alert.sendButton).toExist().withTimeout(timeouts.TEN_SEC);
|
||||
await Alert.sendButton.tap();
|
||||
};
|
||||
|
||||
editDraftPost = async () => {
|
||||
await this.editDraft.tap();
|
||||
};
|
||||
|
||||
draftEmptyScreen = async () => {
|
||||
return this.draftEmptyTitle;
|
||||
};
|
||||
|
||||
back = async () => {
|
||||
await wait(timeouts.ONE_SEC);
|
||||
await this.backButton.tap();
|
||||
expect(this.draftScreen).not.toBeVisible();
|
||||
};
|
||||
|
||||
getDraftMessageContentText = async () => {
|
||||
await expect(this.draftMessageContent).toBeVisible();
|
||||
return this.draftMessageContent;
|
||||
};
|
||||
}
|
||||
|
||||
const draftScreen = new DraftScreen();
|
||||
export default draftScreen;
|
||||
|
|
@ -15,6 +15,7 @@ import CreateDirectMessageScreen from './create_direct_message';
|
|||
import CreateOrEditChannelScreen from './create_or_edit_channel';
|
||||
import CustomStatusScreen from './custom_status';
|
||||
import DisplaySettingsScreen from './display_settings';
|
||||
import DraftScreen from './draft_screen';
|
||||
import EditPostScreen from './edit_post';
|
||||
import EditProfileScreen from './edit_profile';
|
||||
import EditServerScreen from './edit_server';
|
||||
|
|
@ -93,4 +94,5 @@ export {
|
|||
ThreadOptionsScreen,
|
||||
TimezoneDisplaySettingsScreen,
|
||||
UserProfileScreen,
|
||||
DraftScreen,
|
||||
};
|
||||
|
|
|
|||
178
detox/e2e/test/messaging/message_local_drafts.e2e.ts
Normal file
178
detox/e2e/test/messaging/message_local_drafts.e2e.ts
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// *******************************************************************
|
||||
// - [#] indicates a test step (e.g. # Go to a screen)
|
||||
// - [*] indicates an assertion (e.g. * Check the title)
|
||||
// - Use element testID when selecting an element. Create one if none.
|
||||
// *******************************************************************
|
||||
|
||||
import {
|
||||
Post,
|
||||
Setup,
|
||||
} from '@support/server_api';
|
||||
import {
|
||||
serverOneUrl,
|
||||
siteOneUrl,
|
||||
} from '@support/test_config';
|
||||
import {
|
||||
ChannelScreen,
|
||||
ChannelListScreen,
|
||||
DraftScreen,
|
||||
HomeScreen,
|
||||
LoginScreen,
|
||||
ServerScreen,
|
||||
} from '@support/ui/screen';
|
||||
import {getRandomId, isIos} from '@support/utils';
|
||||
import {expect} from 'detox';
|
||||
|
||||
describe('Messaging - Message Draft', () => {
|
||||
const serverOneDisplayName = 'Server 1';
|
||||
const channelsCategory = 'channels';
|
||||
let testChannel: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {channel, user} = await Setup.apiInit(siteOneUrl);
|
||||
testChannel = channel;
|
||||
|
||||
// # Log in to server
|
||||
await ServerScreen.connectToServer(serverOneUrl, serverOneDisplayName);
|
||||
await LoginScreen.login(user);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
// * Verify on channel list screen
|
||||
await ChannelListScreen.toBeVisible();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// # Log out
|
||||
await HomeScreen.logout();
|
||||
});
|
||||
|
||||
it('MM-T5637 should be able to send the draft message from Draft screen', async () => {
|
||||
// # Open a channel screen and create a message draft
|
||||
const message = `Message ${getRandomId()}`;
|
||||
await openChannel(channelsCategory, testChannel);
|
||||
await createDraft(message, testChannel);
|
||||
await verifyDraftonChannelList('1');
|
||||
await ChannelListScreen.draftsButton.tap();
|
||||
await DraftScreen.draftTooltipCloseButton.tap();
|
||||
await DraftScreen.openDraftPostActions();
|
||||
await DraftScreen.sendDraft();
|
||||
await DraftScreen.backButton.tap();
|
||||
});
|
||||
|
||||
it('MM-T5638 should be able to swipe left and delete a draft message', async () => {
|
||||
// # Open a channel screen and create a message draft
|
||||
const message = `Message ${getRandomId()}`;
|
||||
await openChannel(channelsCategory, testChannel);
|
||||
await createDraft(message, testChannel);
|
||||
await verifyDraftonChannelList('1');
|
||||
await ChannelListScreen.draftsButton.tap();
|
||||
await DraftScreen.swipeDraftPostLeft();
|
||||
await DraftScreen.deleteDraftPostFromSwipeActions();
|
||||
await DraftScreen.backButton.tap();
|
||||
});
|
||||
|
||||
it('MM-T5638 should be able to delete a draft message from long press Draft actions', async () => {
|
||||
// # Open a channel screen and create a message draft
|
||||
const message = `Message ${getRandomId()}`;
|
||||
await openChannel(channelsCategory, testChannel);
|
||||
await createDraft(message, testChannel);
|
||||
await verifyDraftonChannelList('1');
|
||||
await ChannelListScreen.draftsButton.tap();
|
||||
await DraftScreen.openDraftPostActions();
|
||||
await DraftScreen.deleteDraftPostFromDraftActions();
|
||||
await DraftScreen.backButton.tap();
|
||||
});
|
||||
|
||||
it('MM-T5636 should be able to Edit a draft message', async () => {
|
||||
// # Open a channel screen and create a message draft
|
||||
const FirstMessage = `Message ${getRandomId()}`;
|
||||
const SecondMessage = `Message ${getRandomId()}`;
|
||||
|
||||
await openChannel(channelsCategory, testChannel);
|
||||
await createDraft(FirstMessage, testChannel);
|
||||
await verifyDraftonChannelList('1');
|
||||
await ChannelListScreen.draftsButton.tap();
|
||||
await DraftScreen.openDraftPostActions();
|
||||
await DraftScreen.editDraftPost();
|
||||
await ChannelScreen.postInput.tap();
|
||||
await ChannelScreen.postInput.clearText();
|
||||
await ChannelScreen.postInput.replaceText(SecondMessage);
|
||||
await ChannelScreen.back();
|
||||
|
||||
// # Verify the draft message is updated
|
||||
await expect(element(by.text(SecondMessage))).toBeVisible();
|
||||
await cleanupDrafts();
|
||||
await DraftScreen.backButton.tap();
|
||||
});
|
||||
|
||||
it('MM-T5668 should be able to verify drafts tab shows message priority "Important" and request acknowledgement', async () => {
|
||||
// # Open a channel screen and create a message draft
|
||||
const message = `Message ${getRandomId()}`;
|
||||
|
||||
await openChannel(channelsCategory, testChannel);
|
||||
await createDraft(message, testChannel);
|
||||
|
||||
await ChannelScreen.openPostPriorityPicker();
|
||||
await ChannelScreen.clickPostPriorityImportantMessage();
|
||||
await ChannelScreen.toggleRequestAckPostpriority();
|
||||
await ChannelScreen.applyPostPrioritySettings();
|
||||
await verifyDraftonChannelList('1');
|
||||
await ChannelListScreen.draftsButton.tap();
|
||||
await expect(DraftScreen.requestACKIcon).toBeVisible();
|
||||
await cleanupDrafts();
|
||||
await DraftScreen.backButton.tap();
|
||||
});
|
||||
|
||||
it('MM-T5668 should be able to verify drafts tab shows message priority "Urgent" and persistent notification', async () => {
|
||||
// # Open a channel screen and create a message draft
|
||||
const message = `Message ${getRandomId()}`;
|
||||
|
||||
await openChannel(channelsCategory, testChannel);
|
||||
await createDraft(message, testChannel);
|
||||
|
||||
await ChannelScreen.openPostPriorityPicker();
|
||||
await ChannelScreen.clickPostPriorityUrgentMessage();
|
||||
await ChannelScreen.togglePersistentNotificationPostpriority();
|
||||
await ChannelScreen.applyPostPrioritySettings();
|
||||
await verifyDraftonChannelList('1');
|
||||
await ChannelListScreen.draftsButton.tap();
|
||||
await expect(DraftScreen.persistentNotificationIcon).toBeVisible();
|
||||
await DraftScreen.backButton.tap();
|
||||
});
|
||||
});
|
||||
|
||||
async function openChannel(channelsCategory: string, testChannel: any) {
|
||||
await ChannelListScreen.draftsButton.toNotBeVisible();
|
||||
await ChannelScreen.open(channelsCategory, testChannel.name);
|
||||
}
|
||||
|
||||
async function createDraft(message: string, testChannel: any): Promise<void> {
|
||||
await ChannelScreen.postInput.tap();
|
||||
await ChannelScreen.postInput.replaceText(message);
|
||||
|
||||
// * Verify message exists in post draft and is not yet added to post list
|
||||
if (isIos()) {
|
||||
await expect(ChannelScreen.postInput).toHaveValue(message);
|
||||
} else {
|
||||
await expect(ChannelScreen.postInput).toHaveText(message);
|
||||
}
|
||||
const {post} = await Post.apiGetLastPostInChannel(siteOneUrl, testChannel.id);
|
||||
const {postListPostItem} = ChannelScreen.getPostListPostItem(post.id, message);
|
||||
await expect(postListPostItem).not.toExist();
|
||||
}
|
||||
|
||||
async function verifyDraftonChannelList(draftCount: string) {
|
||||
await ChannelScreen.back();
|
||||
await ChannelListScreen.draftsButton.toBeVisible();
|
||||
await expect(element(by.id(ChannelListScreen.testID.draftCountListScreen))).toHaveText(draftCount);
|
||||
}
|
||||
|
||||
async function cleanupDrafts() {
|
||||
// # Clean up drafts
|
||||
await DraftScreen.openDraftPostActions();
|
||||
await DraftScreen.deleteDraftPostFromDraftActions();
|
||||
}
|
||||
Loading…
Reference in a new issue