E2E Fix integration test Twake Mail v0.18.4

E2E Fix integration test Twake Mail v0.18.4
This commit is contained in:
Dang Dat
2025-09-09 10:22:14 +07:00
committed by Dat H. Pham
parent fb53ba6568
commit c6ace7a9b5
29 changed files with 97 additions and 114 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ class TestBase {
description,
config: const PatrolTesterConfig(
settlePolicy: SettlePolicy.trySettle,
visibleTimeout: Duration(minutes: 1),
visibleTimeout: Duration(seconds: 30),
printLogs: true,
),
nativeAutomatorConfig: const NativeAutomatorConfig(
@@ -4,6 +4,7 @@ import 'dart:io' hide HttpClient;
import 'package:collection/collection.dart';
import 'package:core/utils/app_logger.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
@@ -270,4 +271,8 @@ mixin ScenarioUtilsMixin {
IdentityInteractorsBindings().dispose();
}
Future<void> hideKeyboard() async {
await SystemChannels.textInput.invokeMethod('TextInput.hide');
}
}
+5 -7
View File
@@ -10,6 +10,7 @@ import 'package:model/extensions/session_extension.dart';
import 'package:model/upload/file_info.dart';
import 'package:rich_text_composer/rich_text_composer.dart';
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_base64_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart';
import 'package:tmail_ui_user/features/composer/presentation/view/mobile/mobile_editor_view.dart';
@@ -33,13 +34,6 @@ class ComposerRobot extends CoreRobot {
}) async {
final finder = $(RecipientComposerWidget).which<RecipientComposerWidget>(
(widget) => widget.prefix == prefixEmailAddress);
final isTextFieldFocused = finder
.which<RecipientComposerWidget>(
(view) => view.focusNode?.hasFocus ?? false)
.exists;
if (!isTextFieldFocused) {
await finder.tap();
}
await finder.enterTextWithoutTapAction(email);
await $(RecipientSuggestionItemWidget)
@@ -163,6 +157,10 @@ class ComposerRobot extends CoreRobot {
fileSize: await file.length(),
fileName: file.path.split('/').last,
)));
await controller.viewState.stream.firstWhere((state) => state.fold(
(failure) => false,
(success) => success is DownloadImageAsBase64Success,
));
}
Future<void> toggleReadReceipt() async {
@@ -12,7 +12,7 @@ class EmailAddressDialogRobot extends CoreRobot {
}
Future<void> tapCopyEmailAddressButton(AppLocalizations appLocalizations) async {
await $(appLocalizations.copy_email_address).tap();
await $(#copy_email_address).tap();
}
Future<void> tapComposeEmailButton(AppLocalizations appLocalizations) async {
+14 -20
View File
@@ -1,7 +1,6 @@
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tmail_ui_user/features/base/widget/material_text_button.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_back_button.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/information_sender_and_receiver_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import '../base/core_robot.dart';
@@ -40,47 +39,42 @@ class EmailRobot extends CoreRobot {
}
Future<void> tapMarkAsUnreadOptionInContextMenu() async {
await $(#markAsUnread_action).tap();
await $(AppLocalizations().mark_as_unread).tap();
}
Future<void> tapEmailDetailedStarButton() async {
await $(#email_detailed_star_button).tap();
await $(AppLocalizations().starred).tap();
}
Future<void> tapEmailDetailedUnstarButton() async {
await $(AppLocalizations().not_starred).tap();
}
Future<void> tapEmailDetailedMoveEmailButton() async {
await $(#email_detailed_move_email_button).tap();
await $(AppLocalizations().moveMessage).tap();
}
Future<void> tapEmailDetailedDeleteEmailButton() async {
await $(#email_detailed_delete_email_button).tap();
await $(AppLocalizations().move_to_trash).tap();
}
Future<void> tapMarkAsSpamOptionInContextMenu() async {
await $(#moveToSpam_action).tap();
await $(AppLocalizations().markAsSpam).tap();
}
Future<void> tapArchiveMessageOptionInContextMenu() async {
await $(#archiveMessage_action).tap();
await $(AppLocalizations().archiveMessage).tap();
}
Future<void> tapSenderEmailAddress(String email) async {
await $(MaterialTextButton)
.which<MaterialTextButton>((widget) => widget.label.contains(email))
.first
.tap();
await $(InformationSenderAndReceiverBuilder).$(email).tap();
}
Future<void> tapRecipientEmailAddress(String email) async {
await $(TMailButtonWidget)
.which<TMailButtonWidget>((widget) => widget.text.contains(email))
.first
.tap();
await $(InformationSenderAndReceiverBuilder).$(email).tap();
}
Future<void> longPressSenderEmailAddress(String email) async {
await $(MaterialTextButton)
.which<MaterialTextButton>((widget) => widget.label.contains(email))
.first
.longPress();
await $(InformationSenderAndReceiverBuilder).$(email).longPress();
}
}
@@ -2,7 +2,6 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/presentation/views/text/text_field_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/label_mailbox_item_widget.dart';
@@ -71,11 +70,7 @@ class MailboxMenuRobot extends CoreRobot {
}
Future<void> closeMenu() async {
await $(IconButton)
.which<IconButton>((widget) {
return widget.tooltip == AppLocalizations().close;
})
.tap();
await $.native.swipe(from: const Offset(0.9, 0.5), to: const Offset(0, 0.5));
}
int getCurrentInboxCount() {
+3 -3
View File
@@ -57,14 +57,14 @@ class ThreadRobot extends CoreRobot {
}
Future<void> selectAttachmentFilter() async {
await $(#filter_email_attachments).tap();
await $(#attachments_filter).tap();
}
Future<void> selectUnreadFilter() async {
await $(#filter_email_unread).tap();
await $(#unread_filter).tap();
}
Future<void> selectStarredFilter() async {
await $(#filter_email_starred).tap();
await $(#starred_filter).tap();
}
}
@@ -27,10 +27,11 @@ class ComposerUploadAttachmentAndInlineImageScenario extends BaseTestScenario {
final png = await preparingPngWithName(pngName);
await composerRobot.addAttachment(png);
await $.pumpAndSettle();
await _expectAttachment(pngName);
await composerRobot.addInline(png);
await $.pumpAndSettle();
_expectAttachment(pngName);
await _expectInline();
await composerRobot.addAttachment(png);
@@ -50,13 +51,11 @@ class ComposerUploadAttachmentAndInlineImageScenario extends BaseTestScenario {
);
}
void _expectAttachment(String pngName) {
return expect(
$(AttachmentItemComposerWidget)
.which<AttachmentItemComposerWidget>(
(widget) => widget.fileName.contains(pngName)
),
findsOneWidget,
Future<void> _expectAttachment(String pngName) async {
await expectViewVisible(
$(AttachmentItemComposerWidget).which<AttachmentItemComposerWidget>(
(widget) => widget.fileName.contains(pngName),
),
);
}
@@ -38,10 +38,10 @@ class ArchiveEmailScenario extends BaseTestScenario {
_expectEmailDetailedMoreButtonVisible();
await emailRobot.tapEmailDetailedMoreButton();
await $.pumpAndSettle(duration: const Duration(seconds: 2));
await $.pumpAndSettle(duration: const Duration(seconds: 1));
await emailRobot.tapArchiveMessageOptionInContextMenu();
await $.pumpAndSettle(duration: const Duration(seconds: 3));
await $.pumpAndSettle(duration: const Duration(seconds: 1));
await emailRobot.onTapBackButton();
await $.pumpAndSettle();
@@ -37,8 +37,9 @@ class DeleteEmailScenario extends BaseTestScenario {
await threadRobot.openEmailWithSubject(subject);
await $.pumpAndSettle();
await emailRobot.tapEmailDetailedMoreButton();
await emailRobot.tapEmailDetailedDeleteEmailButton();
await $.pumpAndSettle(duration: const Duration(seconds: 3));
await $.pumpAndSettle(duration: const Duration(seconds: 1));
_expectEmailViewInvisible();
@@ -52,7 +52,7 @@ class DisplayEmailAddressInfoDialogScenario extends BaseTestScenario {
Future<void> _expectEmailAddressInfoDialogVisible(
AppLocalizations appLocalizations,
) async {
await expectViewVisible($(appLocalizations.copy_email_address));
await expectViewVisible($(#copy_email_address));
await expectViewVisible($(appLocalizations.quickCreatingRule));
await expectViewVisible($(appLocalizations.compose_email));
}
@@ -1,6 +1,3 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../base/base_test_scenario.dart';
@@ -18,7 +15,6 @@ class MarkAsStarEmailScenario extends BaseTestScenario {
const emailUser = String.fromEnvironment('BASIC_AUTH_EMAIL');
final threadRobot = ThreadRobot($);
final emailRobot = EmailRobot($);
final imagePaths = ImagePaths();
await provisionEmail(
[
@@ -34,32 +30,29 @@ class MarkAsStarEmailScenario extends BaseTestScenario {
await threadRobot.openEmailWithSubject(subject);
await $.pumpAndSettle();
_expectEmailDetailedStarButtonVisible();
await emailRobot.tapEmailDetailedMoreButton();
await _expectEmailDetailedStarButtonVisible();
await emailRobot.tapEmailDetailedStarButton();
await $.pumpAndSettle(duration: const Duration(seconds: 2));
await _expectDisplayedStarIcon(imagePaths);
await $.pumpAndSettle(duration: const Duration(seconds: 1));
await emailRobot.tapEmailDetailedMoreButton();
await _expectDisplayedUnStarIcon();
await emailRobot.tapEmailDetailedStarButton();
await $.pumpAndSettle(duration: const Duration(seconds: 2));
await _expectDisplayedUnStarIcon(imagePaths);
await emailRobot.tapEmailDetailedUnstarButton();
await $.pumpAndSettle(duration: const Duration(seconds: 1));
await emailRobot.tapEmailDetailedMoreButton();
await _expectDisplayedStarIcon();
}
void _expectEmailDetailedStarButtonVisible() {
expect($(#email_detailed_star_button), findsOneWidget);
Future<void> _expectEmailDetailedStarButtonVisible() async {
await expectViewVisible($(#markAsStarred_action));
}
Future<void> _expectDisplayedStarIcon(ImagePaths imagePaths) async {
await expectViewVisible(
$(#email_detailed_star_button).which<TMailButtonWidget>(
(widget) => widget.icon == imagePaths.icStar),
);
Future<void> _expectDisplayedStarIcon() async {
await expectViewVisible($(#markAsStarred_action));
}
Future<void> _expectDisplayedUnStarIcon(ImagePaths imagePaths) async {
await expectViewVisible(
$(#email_detailed_star_button).which<TMailButtonWidget>(
(widget) => widget.icon == imagePaths.icUnStar),
);
Future<void> _expectDisplayedUnStarIcon() async {
await expectViewVisible($(#unMarkAsStarred_action));
}
}
@@ -38,6 +38,7 @@ class MoveEmailToFolderScenario extends BaseTestScenario {
await threadRobot.openEmailWithSubject(subject);
await $.pumpAndSettle();
await emailRobot.tapEmailDetailedMoreButton();
await emailRobot.tapEmailDetailedMoveEmailButton();
await $.pumpAndSettle(duration: const Duration(seconds: 2));
@@ -79,12 +79,15 @@ class ReplyEmailWithReplyToScenario extends BaseTestScenario {
}
Future<void> _expectToFieldContainReplyToEmailAddress() async {
expect(
$(RecipientComposerWidget).which<RecipientComposerWidget>((widget) =>
widget.prefix == PrefixEmailAddress.to &&
isMatchingEmailList(widget.listEmailAddress, {'emma-reply-to@example.com'})
).visible,
isTrue,
await expectViewVisible(
$(RecipientComposerWidget).which<RecipientComposerWidget>(
(widget) =>
widget.prefix == PrefixEmailAddress.to &&
isMatchingEmailList(
widget.listEmailAddress,
{'emma-reply-to@example.com'},
),
),
);
}
}
@@ -14,7 +14,7 @@ import '../robots/thread_robot.dart';
class ForwardEmailScenario extends BaseTestScenario {
static const String queryString = 'Fwd: Forward email to Bob';
static const String queryString = 'Forward email';
const ForwardEmailScenario(super.$);
@@ -21,7 +21,7 @@ class SaveAsTemplateScenario extends BaseTestScenario {
await _expectSaveToastSuccessVisible();
await composerRobot.addSubject('test subject');
await hideKeyboard();
await composerRobot.saveAsTemplate();
await _expectUpdateToastSuccessVisible();
@@ -42,12 +42,15 @@ class ThreadDetailReplyRealTimeUpdateScenario extends BaseTestScenario {
await composerRobot.grantContactPermission();
await composerRobot.addContent(replyContent);
await composerRobot.sendEmail(imagePaths);
await $.waitUntilVisible($(ThreadDetailCollapsedEmail));
expect(
$(ThreadDetailCollapsedEmail).which<ThreadDetailCollapsedEmail>((widget) {
return widget.preview.contains(replyContent);
}),
findsOneWidget,
);
await _expectNewCollapsedEmail(replyContent);
}
Future<void> _expectNewCollapsedEmail(String replyContent) async {
final collapsedEmail = $(ThreadDetailCollapsedEmail)
.which<ThreadDetailCollapsedEmail>((widget) {
return widget.preview.contains(replyContent);
});
await expectViewVisible(collapsedEmail);
}
}