mattermost-mobile-upstream/detox/e2e/support/ui/screen/draft_screen.ts
yasser khan ef1ecc1d9e
fix: stabilize server switch, saved posts, favorites, and related runtime races (#10122)
test(e2e): stabilize Detox and Maestro suites and harden CI

- Re-enable stabilized cases and document remaining iOS skips.
- Improve selectors, navigation recovery, state assertions, and retry limits.
- Harden API retries, fixture setup, and server configuration cleanup.
- Increase Detox shards to 24 and improve reporting, artifact uploads, and timeout handling.
- Add testIDs and unit-test fixes; revert unproven app behavior changes.
2026-09-09 00:35:15 +05:30

128 lines
4.4 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Alert, NavigationHeader} from '@support/ui/component';
import {longPressWithScrollRetry, timeouts, wait} from '@support/utils';
import {expect, waitFor} from 'detox';
class DraftScreen {
testID = {
editDraft: 'edit_draft',
deleteDraft: 'delete_draft',
draftMessageContent: 'draft_message',
draftScreen: 'global_drafts_list',
scheduledList: 'global_scheduled_post_list',
draftTooltipCloseButton: 'draft.tooltip.close.button',
draftPost: 'draft_post',
draftOptions: 'draft_options.screen',
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));
dismissTutorialTooltip = async () => {
const closeButton = element(by.id(this.testID.draftTooltipCloseButton));
try {
await waitFor(closeButton).toBeVisible().withTimeout(timeouts.TWO_SEC);
} catch {
// Tutorial already watched on this app install — nothing to dismiss.
return;
}
await closeButton.tap();
await waitFor(closeButton).not.toExist().withTimeout(timeouts.TEN_SEC);
};
draftTooltipCloseButton = {
tap: async () => {
await this.dismissTutorialTooltip();
},
};
private getListScrollMatcher = async () => {
// Prefer scheduled list when on that tab; fall back to drafts list.
const scheduled = by.id(this.testID.scheduledList);
try {
await waitFor(element(scheduled)).toExist().withTimeout(timeouts.ONE_SEC);
return scheduled;
} catch {
return by.id(this.testID.draftScreen);
}
};
private getFirstDraftPost = () => {
return element(by.id(this.testID.draftPost)).atIndex(0);
};
openDraftPostActions = async () => {
await this.dismissTutorialTooltip();
const scrollMatcher = await this.getListScrollMatcher();
await longPressWithScrollRetry(
this.getFirstDraftPost(),
scrollMatcher,
element(by.id(this.testID.draftOptions)),
);
};
swipeDraftPostLeft = async () => {
await this.dismissTutorialTooltip();
await this.getFirstDraftPost().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;