From b6de5d9391d7f6ae600a94fbdbfbc1aeaf7c66f9 Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 6 May 2025 23:44:24 +0700 Subject: [PATCH] TF-3707 Add integration test for case empty trash Signed-off-by: dab246 --- .../mixin/scenario_utils_mixin.dart | 6 +- integration_test/robots/thread_robot.dart | 7 ++ .../mailbox/empty_trash_scenario.dart | 79 +++++++++++++++++++ .../tests/mailbox/empty_trash_test.dart | 9 +++ .../mailbox_dashboard_view_web.dart | 4 +- .../thread/presentation/thread_view.dart | 6 +- .../widgets/banner_empty_trash_widget.dart | 13 +-- 7 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 integration_test/scenarios/mailbox/empty_trash_scenario.dart create mode 100644 integration_test/tests/mailbox/empty_trash_test.dart diff --git a/integration_test/mixin/scenario_utils_mixin.dart b/integration_test/mixin/scenario_utils_mixin.dart index 5c4713e91..d322129be 100644 --- a/integration_test/mixin/scenario_utils_mixin.dart +++ b/integration_test/mixin/scenario_utils_mixin.dart @@ -10,6 +10,7 @@ import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:jmap_dart_client/jmap/jmap_request.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/email/set/set_email_method.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:path_provider/path_provider.dart'; import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart'; @@ -31,6 +32,7 @@ mixin ScenarioUtilsMixin { List provisioningEmails, { bool refreshEmailView = true, bool requestReadReceipt = true, + Role? folderLocationRole, }) async { ComposerBindings().dependencies(); @@ -56,7 +58,9 @@ mixin ScenarioUtilsMixin { emailContent: provisioningEmail.content, toRecipients: {EmailAddress(null, provisioningEmail.toEmail)}, outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId, - sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent], + sentMailboxId: folderLocationRole != null + ? mailboxDashBoardController.mapDefaultMailboxIdByRole[folderLocationRole] + : mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent], identity: identity, attachments: attachments, hasRequestReadReceipt: requestReadReceipt, diff --git a/integration_test/robots/thread_robot.dart b/integration_test/robots/thread_robot.dart index d21a76d05..58f95b355 100644 --- a/integration_test/robots/thread_robot.dart +++ b/integration_test/robots/thread_robot.dart @@ -4,6 +4,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:tmail_ui_user/features/base/widget/compose_floating_button.dart'; import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import '../base/core_robot.dart'; @@ -33,4 +34,10 @@ class ThreadRobot extends CoreRobot { Future openMailbox() async { await $(#mobile_mailbox_menu_button).tap(); } + + Future tapEmptyTrashBanner() => $(#empty_trash_banner).tap(); + + Future tapDeleteAllButtonOnEmptyTrashConfirmDialog( + AppLocalizations appLocalizations, + ) => $(appLocalizations.delete_all).tap(); } \ No newline at end of file diff --git a/integration_test/scenarios/mailbox/empty_trash_scenario.dart b/integration_test/scenarios/mailbox/empty_trash_scenario.dart new file mode 100644 index 000000000..8937a947e --- /dev/null +++ b/integration_test/scenarios/mailbox/empty_trash_scenario.dart @@ -0,0 +1,79 @@ + +import 'package:flutter_test/flutter_test.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/widgets/label_mailbox_item_widget.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_item_widget.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +import '../../base/base_test_scenario.dart'; +import '../../models/provisioning_email.dart'; +import '../../robots/mailbox_menu_robot.dart'; +import '../../robots/thread_robot.dart'; + +class EmptyTrashScenario extends BaseTestScenario { + + const EmptyTrashScenario(super.$); + + @override + Future runTestLogic() async { + const emailUser = String.fromEnvironment('BASIC_AUTH_EMAIL'); + const subject = 'Empty trash'; + + final threadRobot = ThreadRobot($); + final mailboxMenuRobot = MailboxMenuRobot($); + final appLocalizations = AppLocalizations(); + + await provisionEmail( + [ + ProvisioningEmail( + toEmail: emailUser, + subject: subject, + content: subject, + ), + ], + folderLocationRole: PresentationMailbox.roleTrash, + ); + await $.pumpAndSettle(); + + await threadRobot.openMailbox(); + await _expectMailboxViewVisible(); + await _expectFolderVisible(appLocalizations.trashMailboxDisplayName); + + await mailboxMenuRobot.openFolderByName( + appLocalizations.trashMailboxDisplayName, + ); + await $.pumpAndSettle(); + await _expectEmptyTrashBannerVisible(); + await _expectEmailWithSubjectVisible(subject); + + await threadRobot.tapEmptyTrashBanner(); + await _expectEmptyTrashConfirmDialogVisible(appLocalizations); + await threadRobot.tapDeleteAllButtonOnEmptyTrashConfirmDialog( + appLocalizations, + ); + await $.pumpAndSettle(duration: const Duration(seconds: 3)); + await _expectEmptyViewVisible(); + } + + Future _expectMailboxViewVisible() => expectViewVisible($(MailboxView)); + + Future _expectFolderVisible(String folderName) { + return expectViewVisible($(MailboxItemWidget) + .$(LabelMailboxItemWidget) + .$(find.text(folderName))); + } + + Future _expectEmptyTrashBannerVisible() => + expectViewVisible($(#empty_trash_banner)); + + Future _expectEmailWithSubjectVisible(String subject) => + expectViewVisible($(subject)); + + Future _expectEmptyTrashConfirmDialogVisible( + AppLocalizations appLocalizations, + ) => expectViewVisible($(appLocalizations.empty_trash_dialog_message)); + + Future _expectEmptyViewVisible() => + expectViewVisible($(#empty_thread_view)); +} \ No newline at end of file diff --git a/integration_test/tests/mailbox/empty_trash_test.dart b/integration_test/tests/mailbox/empty_trash_test.dart new file mode 100644 index 000000000..76296f891 --- /dev/null +++ b/integration_test/tests/mailbox/empty_trash_test.dart @@ -0,0 +1,9 @@ +import '../../base/test_base.dart'; +import '../../scenarios/mailbox/empty_trash_scenario.dart'; + +void main() { + TestBase().runPatrolTest( + description: 'Should empty view and hide empty trash banner when empty trash successfully', + scenarioBuilder: ($) => EmptyTrashScenario($), + ); +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart index 6a30400e1..3585bc0a6 100644 --- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart +++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart @@ -116,7 +116,9 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView { final presentationMailbox = controller.selectedMailbox.value; if (controller.isEmptyTrashBannerEnabledOnWeb(context, presentationMailbox)) { return BannerEmptyTrashWidget( - onTapAction: controller.emptyTrashAction + responsiveUtils: controller.responsiveUtils, + imagePaths: controller.imagePaths, + onTapAction: controller.emptyTrashAction, ); } else { return const SizedBox.shrink(); diff --git a/lib/features/thread/presentation/thread_view.dart b/lib/features/thread/presentation/thread_view.dart index 7a9797019..3a3241ff2 100644 --- a/lib/features/thread/presentation/thread_view.dart +++ b/lib/features/thread/presentation/thread_view.dart @@ -152,9 +152,13 @@ class ThreadView extends GetWidget final presentationMailbox = controller.mailboxDashBoardController.selectedMailbox.value; if (controller.mailboxDashBoardController.isEmptyTrashBannerEnabledOnMobile(context, presentationMailbox)) { return BannerEmptyTrashWidget( + key: const Key('empty_trash_banner'), + responsiveUtils: controller.responsiveUtils, + imagePaths: controller.imagePaths, onTapAction: () => controller.deleteSelectionEmailsPermanently( context, - DeleteActionType.all) + DeleteActionType.all, + ), ); } else { return const SizedBox.shrink(); diff --git a/lib/features/thread/presentation/widgets/banner_empty_trash_widget.dart b/lib/features/thread/presentation/widgets/banner_empty_trash_widget.dart index 88d227a66..9603be014 100644 --- a/lib/features/thread/presentation/widgets/banner_empty_trash_widget.dart +++ b/lib/features/thread/presentation/widgets/banner_empty_trash_widget.dart @@ -3,21 +3,24 @@ import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; import 'package:tmail_ui_user/features/thread/presentation/styles/banner_empty_trash_styles.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class BannerEmptyTrashWidget extends StatelessWidget { final VoidCallback onTapAction; + final ResponsiveUtils responsiveUtils; + final ImagePaths imagePaths; - const BannerEmptyTrashWidget({super.key, required this.onTapAction}); + const BannerEmptyTrashWidget({ + super.key, + required this.responsiveUtils, + required this.imagePaths, + required this.onTapAction, + }); @override Widget build(BuildContext context) { - final imagePaths = Get.find(); - final responsiveUtils = Get.find(); - return Container( decoration: const ShapeDecoration( color: BannerEmptyTrashStyles.backgroundColor,