From 4d045bbf1a75d77d64a4e0d41b285fcd10d93d4a Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 14 Aug 2024 17:04:43 +0700 Subject: [PATCH] Hotfix conflict role `Spam/Junk` --- lib/features/base/base_controller.dart | 2 + .../reloadable/reloadable_controller.dart | 12 +- .../controller/single_email_controller.dart | 4 +- .../widgets/login_message_widget.dart | 11 +- .../data/local/mailbox_cache_manager.dart | 4 +- .../mailbox/data/network/mailbox_api.dart | 1 + .../domain/constants/mailbox_constants.dart | 2 +- .../domain/exceptions/mailbox_exception.dart | 4 + .../set_mailbox_method_exception.dart | 4 +- .../domain/extensions/role_extension.dart | 2 +- .../presentation_mailbox_extension.dart | 2 + .../mailbox_dashboard_controller.dart | 127 ++++++++++--- .../data/repository/fcm_repository_impl.dart | 2 +- .../domain/utils/fcm_constants.dart | 11 -- .../rules_filter_creator_controller.dart | 11 +- .../mixin/email_action_controller.dart | 4 +- lib/l10n/intl_messages.arb | 14 +- lib/main/bindings/core/core_bindings.dart | 2 + lib/main/localizations/app_localizations.dart | 12 ++ lib/main/utils/message_toast_utils.dart | 36 ---- lib/main/utils/toast_manager.dart | 71 +++++++ model/lib/extensions/mailbox_extension.dart | 2 +- .../presentation_mailbox_extension.dart | 2 +- model/lib/mailbox/presentation_mailbox.dart | 4 +- test/features/base/base_controller_test.dart | 5 + .../single_email_controller_test.dart | 4 + test/features/fcm/fcm_repository_test.dart | 140 ++++++++++++++ .../presentation/home_controller_test.dart | 5 + .../identity_creator_controller_test.dart | 5 + .../presentation/login_controller_test.dart | 5 + .../repository/mailbox_respository_test.dart | 2 +- .../mailbox_dashboard_controller_test.dart | 174 +++++++++++------- .../identities_controller_test.dart | 5 + 33 files changed, 519 insertions(+), 172 deletions(-) create mode 100644 lib/features/mailbox/domain/exceptions/mailbox_exception.dart delete mode 100644 lib/main/utils/message_toast_utils.dart create mode 100644 lib/main/utils/toast_manager.dart create mode 100644 test/features/fcm/fcm_repository_test.dart diff --git a/lib/features/base/base_controller.dart b/lib/features/base/base_controller.dart index 39f9d3dc2..ecb070a56 100644 --- a/lib/features/base/base_controller.dart +++ b/lib/features/base/base_controller.dart @@ -63,6 +63,7 @@ import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/utils/app_config.dart'; import 'package:tmail_ui_user/main/universal_import/html_stub.dart' as html; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; abstract class BaseController extends GetxController @@ -82,6 +83,7 @@ abstract class BaseController extends GetxController final ResponsiveUtils responsiveUtils = Get.find(); final Uuid uuid = Get.find(); final ApplicationManager applicationManager = Get.find(); + final ToastManager toastManager = Get.find(); bool _isFcmEnabled = false; diff --git a/lib/features/base/reloadable/reloadable_controller.dart b/lib/features/base/reloadable/reloadable_controller.dart index 040c8d3d6..d788c09d2 100644 --- a/lib/features/base/reloadable/reloadable_controller.dart +++ b/lib/features/base/reloadable/reloadable_controller.dart @@ -21,9 +21,6 @@ import 'package:tmail_ui_user/features/login/domain/usecases/update_account_cach import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_interactors_bindings.dart'; import 'package:tmail_ui_user/main/error/capability_validator.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -import 'package:tmail_ui_user/main/routes/route_navigation.dart'; -import 'package:tmail_ui_user/main/utils/message_toast_utils.dart'; abstract class ReloadableController extends BaseController { final GetSessionInteractor _getSessionInteractor = Get.find(); @@ -130,12 +127,9 @@ abstract class ReloadableController extends BaseController { consumeState(_getSessionInteractor.execute()); } - void _handleGetSessionFailure(dynamic exception) { - if (currentContext != null && currentOverlayContext != null && exception !is BadCredentialsException) { - appToast.showToastErrorMessage( - currentOverlayContext!, - MessageToastUtils.getMessageByException(currentContext!, exception) ?? AppLocalizations.of(currentContext!).unknownError - ); + void _handleGetSessionFailure(GetSessionFailure failure) { + if (failure.exception !is BadCredentialsException) { + toastManager.showMessageFailure(failure); } clearDataAndGoToLoginPage(); } diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index 70d6df7cb..af4705526 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -1016,7 +1016,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { void moveToSpam(BuildContext context, PresentationEmail email) async { final session = mailboxDashBoardController.sessionCurrent; final accountId = mailboxDashBoardController.accountId.value; - final spamMailboxId = mailboxDashBoardController.getMailboxIdByRole(PresentationMailbox.roleSpam); + final spamMailboxId = mailboxDashBoardController.spamMailboxId; final currentMailbox = getMailboxContain(email); if (session != null && accountId != null && currentMailbox != null && spamMailboxId != null) { @@ -1036,7 +1036,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { void unSpam(BuildContext context, PresentationEmail email) async { final session = mailboxDashBoardController.sessionCurrent; final accountId = mailboxDashBoardController.accountId.value; - final spamMailboxId = mailboxDashBoardController.getMailboxIdByRole(PresentationMailbox.roleSpam); + final spamMailboxId = mailboxDashBoardController.spamMailboxId; final inboxMailboxId = mailboxDashBoardController.getMailboxIdByRole(PresentationMailbox.roleInbox); if (session != null && accountId != null && spamMailboxId != null && inboxMailboxId != null) { diff --git a/lib/features/login/presentation/widgets/login_message_widget.dart b/lib/features/login/presentation/widgets/login_message_widget.dart index 52ffe7ad4..be82e3da6 100644 --- a/lib/features/login/presentation/widgets/login_message_widget.dart +++ b/lib/features/login/presentation/widgets/login_message_widget.dart @@ -12,7 +12,8 @@ import 'package:tmail_ui_user/features/login/domain/state/get_oidc_configuration import 'package:tmail_ui_user/features/login/domain/state/get_token_oidc_state.dart'; import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -import 'package:tmail_ui_user/main/utils/message_toast_utils.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; class LoginMessageWidget extends StatelessWidget { @@ -22,7 +23,9 @@ class LoginMessageWidget extends StatelessWidget { final LoginFormType formType; final Either viewState; - const LoginMessageWidget({ + final ToastManager? _toastManager = getBinding(); + + LoginMessageWidget({ super.key, required this.formType, required this.viewState @@ -51,8 +54,8 @@ class LoginMessageWidget extends StatelessWidget { } else if (failure is GetTokenOIDCFailure && failure.exception is NoSuitableBrowserForOIDCException) { return AppLocalizations.of(context).noSuitableBrowserForOIDC; } else if (failure is FeatureFailure) { - final errorMessage = MessageToastUtils.getMessageByException(context, failure.exception); - return errorMessage ?? AppLocalizations.of(context).unknownError; + return _toastManager?.getMessageByException(context, failure.exception) + ?? AppLocalizations.of(context).unknownError; } else { return AppLocalizations.of(context).unknownError; } diff --git a/lib/features/mailbox/data/local/mailbox_cache_manager.dart b/lib/features/mailbox/data/local/mailbox_cache_manager.dart index 1d0f8da83..22100e977 100644 --- a/lib/features/mailbox/data/local/mailbox_cache_manager.dart +++ b/lib/features/mailbox/data/local/mailbox_cache_manager.dart @@ -4,7 +4,7 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/extensions/account_id_extensions.dart'; -import 'package:model/mailbox/presentation_mailbox.dart'; +import 'package:model/extensions/mailbox_extension.dart'; import 'package:tmail_ui_user/features/caching/clients/mailbox_cache_client.dart'; import 'package:tmail_ui_user/features/caching/utils/cache_utils.dart'; import 'package:tmail_ui_user/features/mailbox/data/extensions/list_mailbox_cache_extension.dart'; @@ -49,7 +49,7 @@ class MailboxCacheManager { Future getSpamMailbox(AccountId accountId, UserName userName) async { final mailboxList = await getAllMailbox(accountId, userName); - final spamMailbox = mailboxList.firstWhereOrNull((mailbox) => mailbox.role == PresentationMailbox.roleSpam); + final spamMailbox = mailboxList.firstWhereOrNull((mailbox) => mailbox.isSpam); if (spamMailbox != null) { return spamMailbox; } else { diff --git a/lib/features/mailbox/data/network/mailbox_api.dart b/lib/features/mailbox/data/network/mailbox_api.dart index 901a0c473..462b72ebc 100644 --- a/lib/features/mailbox/data/network/mailbox_api.dart +++ b/lib/features/mailbox/data/network/mailbox_api.dart @@ -30,6 +30,7 @@ import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart'; import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/exceptions/mailbox_exception.dart'; import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart'; import 'package:tmail_ui_user/features/mailbox/domain/extensions/list_mailbox_id_extension.dart'; import 'package:tmail_ui_user/features/mailbox/domain/extensions/role_extension.dart'; diff --git a/lib/features/mailbox/domain/constants/mailbox_constants.dart b/lib/features/mailbox/domain/constants/mailbox_constants.dart index 5dcbced28..36f7d97bf 100644 --- a/lib/features/mailbox/domain/constants/mailbox_constants.dart +++ b/lib/features/mailbox/domain/constants/mailbox_constants.dart @@ -25,7 +25,7 @@ class MailboxConstants { PresentationMailbox.roleDrafts, PresentationMailbox.roleSent, PresentationMailbox.roleTrash, - PresentationMailbox.roleSpam, + PresentationMailbox.roleJunk, PresentationMailbox.roleTemplates, ]; } \ No newline at end of file diff --git a/lib/features/mailbox/domain/exceptions/mailbox_exception.dart b/lib/features/mailbox/domain/exceptions/mailbox_exception.dart new file mode 100644 index 000000000..bc474e117 --- /dev/null +++ b/lib/features/mailbox/domain/exceptions/mailbox_exception.dart @@ -0,0 +1,4 @@ + +class NotFoundInboxMailboxException implements Exception {} + +class NotFoundMailboxException implements Exception {} diff --git a/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart b/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart index fed18f8e1..9578d6727 100644 --- a/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart +++ b/lib/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart @@ -11,6 +11,4 @@ class SetMailboxMethodException implements Exception { class NotFoundMailboxCreatedException implements Exception {} -class NotFoundMailboxUpdatedRoleException implements Exception {} - -class NotFoundMailboxException implements Exception {} \ No newline at end of file +class NotFoundMailboxUpdatedRoleException implements Exception {} \ No newline at end of file diff --git a/lib/features/mailbox/domain/extensions/role_extension.dart b/lib/features/mailbox/domain/extensions/role_extension.dart index 017949d66..c1dfac919 100644 --- a/lib/features/mailbox/domain/extensions/role_extension.dart +++ b/lib/features/mailbox/domain/extensions/role_extension.dart @@ -15,7 +15,7 @@ extension RoleExtension on Role { return 'Drafts'; } else if (this == PresentationMailbox.roleTrash) { return 'Trash'; - } else if (this == PresentationMailbox.roleSpam) { + } else if (this == PresentationMailbox.roleSpam || this == PresentationMailbox.roleJunk) { return 'Spam'; } else if (this == PresentationMailbox.roleTemplates) { return 'Templates'; diff --git a/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart b/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart index d2b2df4b4..01f7b45cc 100644 --- a/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart +++ b/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart @@ -26,6 +26,7 @@ extension PresentationMailboxExtension on PresentationMailbox { case PresentationMailbox.trashRole: return AppLocalizations.of(context).trashMailboxDisplayName; case PresentationMailbox.spamRole: + case PresentationMailbox.junkRole: return AppLocalizations.of(context).spamMailboxDisplayName; case PresentationMailbox.templatesRole: return AppLocalizations.of(context).templatesMailboxDisplayName; @@ -52,6 +53,7 @@ extension PresentationMailboxExtension on PresentationMailbox { case PresentationMailbox.trashRole: return imagePaths.icMailboxTrash; case PresentationMailbox.spamRole: + case PresentationMailbox.junkRole: return imagePaths.icMailboxSpam; case PresentationMailbox.templatesRole: return imagePaths.icMailboxTemplate; diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart index 49498ff5f..4af1aa25e 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -70,13 +70,16 @@ import 'package:tmail_ui_user/features/email/presentation/extensions/composer_ar import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart'; import 'package:tmail_ui_user/features/email_recovery/presentation/model/email_recovery_arguments.dart'; +import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart'; import 'package:tmail_ui_user/features/home/domain/usecases/store_session_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/exceptions/mailbox_exception.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/mark_as_mailbox_read_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/exceptions/spam_report_exception.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/spam_report_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_app_dashboard_configuration_state.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_composer_cache_state.dart'; @@ -405,6 +408,9 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo _handleRestoreDeletedMessageFailed(); } else if (failure is GetRestoredDeletedMessageFailure) { _handleRestoreDeletedMessageFailed(); + } else if (failure is EmptySpamFolderFailure + || failure is MoveMultipleEmailToMailboxFailure) { + toastManager.showMessageFailure(failure); } } @@ -573,6 +579,11 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo return mapDefaultMailboxIdByRole[role]; } + MailboxId? get spamMailboxId { + return mapDefaultMailboxIdByRole[PresentationMailbox.roleJunk] + ?? mapDefaultMailboxIdByRole[PresentationMailbox.roleSpam]; + } + void setMapDefaultMailboxIdByRole(Map newMapMailboxId) { mapDefaultMailboxIdByRole = newMapMailboxId; } @@ -1106,34 +1117,83 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo } void moveSelectedMultipleEmailToSpam(List listEmail, PresentationMailbox mailboxCurrent) { - final spamMailboxId = getMailboxIdByRole(PresentationMailbox.roleSpam); - if (accountId.value != null && spamMailboxId != null && sessionCurrent != null) { - _moveSelectedEmailMultipleToMailboxAction( - sessionCurrent!, - accountId.value!, - MoveToMailboxRequest( - {mailboxCurrent.id: listEmail.listEmailIds}, - spamMailboxId, + if (accountId.value == null || sessionCurrent == null) { + consumeState(Stream.value( + Left(MoveMultipleEmailToMailboxFailure( + EmailActionType.moveToSpam, MoveAction.moving, - EmailActionType.moveToSpam) - ); + NotFoundSessionException() + )) + )); + return; } + + if (spamMailboxId == null) { + consumeState(Stream.value( + Left(MoveMultipleEmailToMailboxFailure( + EmailActionType.moveToSpam, + MoveAction.moving, + NotFoundSpamMailboxException() + )) + )); + return; + } + + _moveSelectedEmailMultipleToMailboxAction( + sessionCurrent!, + accountId.value!, + MoveToMailboxRequest( + {mailboxCurrent.id: listEmail.listEmailIds}, + spamMailboxId!, + MoveAction.moving, + EmailActionType.moveToSpam) + ); } void unSpamSelectedMultipleEmail(List listEmail) { - final spamMailboxId = getMailboxIdByRole(PresentationMailbox.roleSpam); - final inboxMailboxId = getMailboxIdByRole(PresentationMailbox.roleInbox); - if (inboxMailboxId != null && accountId.value != null && spamMailboxId != null && sessionCurrent != null) { - _moveSelectedEmailMultipleToMailboxAction( - sessionCurrent!, - accountId.value!, - MoveToMailboxRequest( - {spamMailboxId: listEmail.listEmailIds}, - inboxMailboxId, + if (accountId.value == null || sessionCurrent == null) { + consumeState(Stream.value( + Left(MoveMultipleEmailToMailboxFailure( + EmailActionType.unSpam, MoveAction.moving, - EmailActionType.unSpam) - ); + NotFoundSessionException() + )) + )); + return; } + + if (spamMailboxId == null) { + consumeState(Stream.value( + Left(MoveMultipleEmailToMailboxFailure( + EmailActionType.unSpam, + MoveAction.moving, + NotFoundSpamMailboxException() + )) + )); + return; + } + + final inboxMailboxId = getMailboxIdByRole(PresentationMailbox.roleInbox); + if (inboxMailboxId == null) { + consumeState(Stream.value( + Left(MoveMultipleEmailToMailboxFailure( + EmailActionType.unSpam, + MoveAction.moving, + NotFoundInboxMailboxException() + )) + )); + return; + } + + _moveSelectedEmailMultipleToMailboxAction( + sessionCurrent!, + accountId.value!, + MoveToMailboxRequest( + {spamMailboxId!: listEmail.listEmailIds}, + inboxMailboxId, + MoveAction.moving, + EmailActionType.unSpam) + ); } void deleteSelectionEmailsPermanently( @@ -2081,16 +2141,23 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo void emptySpamFolderAction({Function? onCancelSelectionEmail, MailboxId? spamFolderId}) { onCancelSelectionEmail?.call(); - final spamMailboxId = spamFolderId ?? mapDefaultMailboxIdByRole[PresentationMailbox.roleSpam]; - if (sessionCurrent != null && accountId.value != null && spamMailboxId != null) { - consumeState( - _emptySpamFolderInteractor.execute( - sessionCurrent!, - accountId.value!, - spamMailboxId - ) - ); + spamFolderId ??= spamMailboxId; + + if (accountId.value == null || sessionCurrent == null) { + consumeState(Stream.value(Left(EmptySpamFolderFailure(NotFoundSessionException())))); + return; } + + if (spamFolderId == null) { + consumeState(Stream.value(Left(EmptySpamFolderFailure(NotFoundSpamMailboxException())))); + return; + } + + consumeState(_emptySpamFolderInteractor.execute( + sessionCurrent!, + accountId.value!, + spamFolderId + )); } void _emptySpamFolderSuccess(EmptySpamFolderSuccess success) { diff --git a/lib/features/push_notification/data/repository/fcm_repository_impl.dart b/lib/features/push_notification/data/repository/fcm_repository_impl.dart index f20e00008..216d7fb33 100644 --- a/lib/features/push_notification/data/repository/fcm_repository_impl.dart +++ b/lib/features/push_notification/data/repository/fcm_repository_impl.dart @@ -132,7 +132,7 @@ class FCMRepositoryImpl extends FCMRepository { .where((presentationMailbox) => presentationMailbox.pushNotificationDeactivated) .toList(); log('FCMRepositoryImpl::getMailboxesNotPutNotifications():mailboxesCacheNotPutNotifications: $mailboxesCacheNotPutNotifications'); - if (mailboxesCacheNotPutNotifications.isNotEmpty && mailboxesCacheNotPutNotifications.length == FcmConstants.mailboxRuleDoNotAllowPushNotifications.length) { + if (mailboxesCacheNotPutNotifications.isNotEmpty) { return mailboxesCacheNotPutNotifications; } else { final mailboxResponse = await _mapMailboxDataSource[DataSourceType.network]!.getAllMailbox(session, accountId); diff --git a/lib/features/push_notification/domain/utils/fcm_constants.dart b/lib/features/push_notification/domain/utils/fcm_constants.dart index d9260b899..75ac9797b 100644 --- a/lib/features/push_notification/domain/utils/fcm_constants.dart +++ b/lib/features/push_notification/domain/utils/fcm_constants.dart @@ -1,16 +1,5 @@ -import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; -import 'package:model/mailbox/presentation_mailbox.dart'; - class FcmConstants { - static final List mailboxRuleDoNotAllowPushNotifications = [ - PresentationMailbox.roleDrafts, - PresentationMailbox.roleSent, - PresentationMailbox.roleOutbox, - PresentationMailbox.roleSpam, - PresentationMailbox.roleTrash - ]; - static const String firebaseRegistrationExpiredTimeProperty = 'expires'; static const int MAX_NUMBER_NEW_EMAILS_RETRIEVED = 5; diff --git a/lib/features/rules_filter_creator/presentation/rules_filter_creator_controller.dart b/lib/features/rules_filter_creator/presentation/rules_filter_creator_controller.dart index 933ece82d..77189e013 100644 --- a/lib/features/rules_filter_creator/presentation/rules_filter_creator_controller.dart +++ b/lib/features/rules_filter_creator/presentation/rules_filter_creator_controller.dart @@ -219,8 +219,10 @@ class RulesFilterCreatorController extends BaseMailboxController { listEmailRuleFilterActionSelected.add(newRuleFilterAction); } if (currentAction.appendIn.mailboxIds.isNotEmpty == true) { + final spamMailboxId = findMailboxNodeByRole(PresentationMailbox.roleSpam)?.item.id + ?? findMailboxNodeByRole(PresentationMailbox.roleJunk)?.item.id; for (var mailboxId in currentAction.appendIn.mailboxIds) { - if (mailboxId == findMailboxNodeByRole(PresentationMailbox.roleSpam)?.item.id) { + if (mailboxId == spamMailboxId) { EmailRuleFilterAction? action = EmailRuleFilterAction.markAsSpam; RuleFilterActionArguments newRuleFilterAction = RuleFilterActionArguments.newAction(action); listEmailRuleFilterActionSelected.add(newRuleFilterAction); @@ -266,8 +268,10 @@ class RulesFilterCreatorController extends BaseMailboxController { void _setUpMailboxSelected() { if (_currentTMailRule != null) { final mailboxIdsOfRule = _currentTMailRule!.action.appendIn.mailboxIds; + final spamMailboxId = findMailboxNodeByRole(PresentationMailbox.roleSpam)?.item.id + ?? findMailboxNodeByRole(PresentationMailbox.roleJunk)?.item.id; for (var mailboxId in mailboxIdsOfRule) { - if (mailboxId != findMailboxNodeByRole(PresentationMailbox.roleSpam)?.item.id) { + if (mailboxId == spamMailboxId) { final mailboxNode = findMailboxNodeById(mailboxId); if (mailboxNode != null) { mailboxSelected.value = mailboxNode.item; @@ -482,7 +486,8 @@ class RulesFilterCreatorController extends BaseMailboxController { mailboxIds.add(ruleFilterAction.mailbox!.id); } if (ruleFilterAction.action is MarAsSpamActionArguments) { - MailboxId? spamMailboxId = findMailboxNodeByRole(PresentationMailbox.roleSpam)?.item.id; + final spamMailboxId = findMailboxNodeByRole(PresentationMailbox.roleSpam)?.item.id + ?? findMailboxNodeByRole(PresentationMailbox.roleJunk)?.item.id; if (spamMailboxId != null) { mailboxIds.add(spamMailboxId); } diff --git a/lib/features/thread/presentation/mixin/email_action_controller.dart b/lib/features/thread/presentation/mixin/email_action_controller.dart index 16c462650..1a4dd5e9b 100644 --- a/lib/features/thread/presentation/mixin/email_action_controller.dart +++ b/lib/features/thread/presentation/mixin/email_action_controller.dart @@ -72,7 +72,7 @@ mixin EmailActionController { void moveToSpam(PresentationEmail email, {PresentationMailbox? mailboxContain}) async { final session = mailboxDashBoardController.sessionCurrent; final accountId = mailboxDashBoardController.accountId.value; - final spamMailboxId = mailboxDashBoardController.getMailboxIdByRole(PresentationMailbox.roleSpam); + final spamMailboxId = mailboxDashBoardController.spamMailboxId; if (session != null && mailboxContain != null && accountId != null && spamMailboxId != null) { moveToSpamAction( @@ -90,7 +90,7 @@ mixin EmailActionController { void unSpam(PresentationEmail email) async { final session = mailboxDashBoardController.sessionCurrent; final accountId = mailboxDashBoardController.accountId.value; - final spamMailboxId = mailboxDashBoardController.getMailboxIdByRole(PresentationMailbox.roleSpam); + final spamMailboxId = mailboxDashBoardController.spamMailboxId; final inboxMailboxId = mailboxDashBoardController.getMailboxIdByRole(PresentationMailbox.roleInbox); if (session != null && inboxMailboxId != null && accountId != null && spamMailboxId != null) { diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index c76085944..d5d46b8a3 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2024-08-12T18:11:14.971152", + "@@last_modified": "2024-08-14T16:51:31.191735", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -3981,5 +3981,17 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "emptySpamFolderFailed": "Empty spam folder failed", + "@emptySpamFolderFailed": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "markAsSpamFailed": "Mark as spam failed", + "@markAsSpamFailed": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/bindings/core/core_bindings.dart b/lib/main/bindings/core/core_bindings.dart index 4eda5e448..9725bac0d 100644 --- a/lib/main/bindings/core/core_bindings.dart +++ b/lib/main/bindings/core/core_bindings.dart @@ -17,6 +17,7 @@ import 'package:tmail_ui_user/features/sending_queue/presentation/utils/sending_ import 'package:tmail_ui_user/main/utils/app_config.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; import 'package:tmail_ui_user/main/utils/ios_notification_manager.dart'; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; class CoreBindings extends Bindings { @@ -48,6 +49,7 @@ class CoreBindings extends Bindings { void _bindingToast() { Get.put(AppToast()); + Get.put(ToastManager(Get.find())); } void _bindingDeviceManager() { diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 0167e7783..ea922deda 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -4168,4 +4168,16 @@ class AppLocalizations { name: 'sMimeBadSignatureMessage', ); } + + String get emptySpamFolderFailed { + return Intl.message('' + 'Empty spam folder failed', + name: 'emptySpamFolderFailed'); + } + + String get markAsSpamFailed { + return Intl.message('' + 'Mark as spam failed', + name: 'markAsSpamFailed'); + } } \ No newline at end of file diff --git a/lib/main/utils/message_toast_utils.dart b/lib/main/utils/message_toast_utils.dart deleted file mode 100644 index 9344da538..000000000 --- a/lib/main/utils/message_toast_utils.dart +++ /dev/null @@ -1,36 +0,0 @@ - -import 'package:flutter/material.dart'; -import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart'; -import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart'; -import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart'; -import 'package:tmail_ui_user/main/exceptions/remote_exception.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; - -class MessageToastUtils { - - static String? getMessageByException(BuildContext context, dynamic exception) { - if (exception is CanNotFoundBaseUrl) { - return AppLocalizations.of(context).requiredUrl; - } else if (exception is CanNotFoundUserName) { - return AppLocalizations.of(context).requiredEmail; - } else if (exception is CanNotFoundPassword) { - return AppLocalizations.of(context).requiredPassword; - } else if (exception is CanNotFoundOIDCLinks) { - return AppLocalizations.of(context).ssoNotAvailable; - } else if (exception is CanNotFoundToken) { - return AppLocalizations.of(context).canNotGetToken; - } else if (exception is ConnectionTimeout || exception is BadGateway || exception is SocketError) { - return AppLocalizations.of(context).wrongUrlMessage; - } else if (exception is BadCredentialsException) { - return AppLocalizations.of(context).badCredentials; - } else if (exception is ConnectionError) { - return AppLocalizations.of(context).connectionError; - } else if (exception is UnknownError && exception.message != null) { - return '[${exception.code ?? ''}] ${exception.message}'; - } else if (exception is NotFoundSessionException) { - return AppLocalizations.of(context).notFoundSession; - } else { - return null; - } - } -} diff --git a/lib/main/utils/toast_manager.dart b/lib/main/utils/toast_manager.dart new file mode 100644 index 000000000..c5e8bc06f --- /dev/null +++ b/lib/main/utils/toast_manager.dart @@ -0,0 +1,71 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/utils/app_toast.dart'; +import 'package:core/utils/app_logger.dart'; +import 'package:flutter/material.dart'; +import 'package:model/email/email_action_type.dart'; +import 'package:tmail_ui_user/features/email/domain/model/move_action.dart'; +import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart'; +import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart'; +import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart'; +import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart'; +import 'package:tmail_ui_user/features/thread/domain/state/empty_spam_folder_state.dart'; +import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart'; +import 'package:tmail_ui_user/main/exceptions/remote_exception.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; + +class ToastManager { + final AppToast appToast; + + ToastManager(this.appToast); + + String? getMessageByException(BuildContext context, dynamic exception) { + if (exception is CanNotFoundBaseUrl) { + return AppLocalizations.of(context).requiredUrl; + } else if (exception is CanNotFoundUserName) { + return AppLocalizations.of(context).requiredEmail; + } else if (exception is CanNotFoundPassword) { + return AppLocalizations.of(context).requiredPassword; + } else if (exception is CanNotFoundOIDCLinks) { + return AppLocalizations.of(context).ssoNotAvailable; + } else if (exception is CanNotFoundToken) { + return AppLocalizations.of(context).canNotGetToken; + } else if (exception is ConnectionTimeout || exception is BadGateway || exception is SocketError) { + return AppLocalizations.of(context).wrongUrlMessage; + } else if (exception is BadCredentialsException) { + return AppLocalizations.of(context).badCredentials; + } else if (exception is ConnectionError) { + return AppLocalizations.of(context).connectionError; + } else if (exception is UnknownError && exception.message != null) { + return '[${exception.code ?? ''}] ${exception.message}'; + } else if (exception is NotFoundSessionException) { + return AppLocalizations.of(context).notFoundSession; + } else { + return null; + } + } + + void showMessageFailure(Failure failure) { + if (currentContext == null || currentOverlayContext == null) { + logError('ToastManager::showMessageFailure: Context is null'); + return; + } + + String? message; + + if (failure is GetSessionFailure) { + message = getMessageByException(currentContext!, failure.exception) + ?? AppLocalizations.of(currentContext!).unknownError; + } else if (failure is EmptySpamFolderFailure) { + message = AppLocalizations.of(currentContext!).emptySpamFolderFailed; + } else if (failure is MoveMultipleEmailToMailboxFailure + && failure.emailActionType == EmailActionType.moveToSpam + && failure.moveAction == MoveAction.moving) { + message = AppLocalizations.of(currentContext!).markAsSpamFailed; + } + + if (message?.isNotEmpty == true) { + appToast.showToastErrorMessage(currentOverlayContext!, message!); + } + } +} diff --git a/model/lib/extensions/mailbox_extension.dart b/model/lib/extensions/mailbox_extension.dart index 712f84701..44dcefa26 100644 --- a/model/lib/extensions/mailbox_extension.dart +++ b/model/lib/extensions/mailbox_extension.dart @@ -6,7 +6,7 @@ extension MailboxExtension on Mailbox { bool hasRole() => role != null && role!.value.isNotEmpty; - bool get isSpam => role == PresentationMailbox.roleSpam; + bool get isSpam => role == PresentationMailbox.roleSpam || role == PresentationMailbox.roleJunk; bool get isTrash => role == PresentationMailbox.roleTrash; diff --git a/model/lib/extensions/presentation_mailbox_extension.dart b/model/lib/extensions/presentation_mailbox_extension.dart index 6419a5aea..6b1f57d36 100644 --- a/model/lib/extensions/presentation_mailbox_extension.dart +++ b/model/lib/extensions/presentation_mailbox_extension.dart @@ -31,7 +31,7 @@ extension PresentationMailboxExtension on PresentationMailbox { bool get isInbox => role == PresentationMailbox.roleInbox; - bool get isSpam => role == PresentationMailbox.roleSpam; + bool get isSpam => role == PresentationMailbox.roleSpam || role == PresentationMailbox.roleJunk; bool get isTrash => role == PresentationMailbox.roleTrash; diff --git a/model/lib/mailbox/presentation_mailbox.dart b/model/lib/mailbox/presentation_mailbox.dart index 52e24c436..a810e1037 100644 --- a/model/lib/mailbox/presentation_mailbox.dart +++ b/model/lib/mailbox/presentation_mailbox.dart @@ -14,7 +14,8 @@ class PresentationMailbox with EquatableMixin { static const String templatesRole= 'templates'; static const String outboxRole = 'outbox'; static const String draftsRole = 'drafts'; - static const String spamRole = 'junk'; + static const String junkRole = 'junk'; + static const String spamRole = 'spam'; static const String archiveRole = 'archive'; static const String recoveredRole = 'restored messages'; @@ -27,6 +28,7 @@ class PresentationMailbox with EquatableMixin { static final roleOutbox = Role(outboxRole); static final roleDrafts = Role(draftsRole); static final roleSpam = Role(spamRole); + static final roleJunk = Role(junkRole); static final roleArchive = Role(archiveRole); static final roleRecovered = Role(recoveredRole); diff --git a/test/features/base/base_controller_test.dart b/test/features/base/base_controller_test.dart index 916a347c0..8380fae76 100644 --- a/test/features/base/base_controller_test.dart +++ b/test/features/base/base_controller_test.dart @@ -16,6 +16,7 @@ import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_ import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception.dart'; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; import 'base_controller_test.mocks.dart'; @@ -58,6 +59,7 @@ class SomeOtherException extends RemoteException {} MockSpec(), MockSpec(), MockSpec(), + MockSpec(), ]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -75,6 +77,7 @@ void main() { late MockResponsiveUtils mockResponsiveUtils; late MockUuid mockUuid; late MockApplicationManager mockApplicationManager; + late MockToastManager mockToastManager; setUpAll(() { mockCachingManager = MockCachingManager(); @@ -89,6 +92,7 @@ void main() { mockResponsiveUtils = MockResponsiveUtils(); mockUuid = MockUuid(); mockApplicationManager = MockApplicationManager(); + mockToastManager = MockToastManager(); Get.put(mockCachingManager); Get.put(mockLanguageCacheManager); @@ -106,6 +110,7 @@ void main() { Get.put(mockResponsiveUtils); Get.put(mockUuid); Get.put(mockApplicationManager); + Get.put(mockToastManager); Get.testMode = true; mockBaseController = MockBaseController(); diff --git a/test/features/email/presentation/controller/single_email_controller_test.dart b/test/features/email/presentation/controller/single_email_controller_test.dart index 82ae55253..1768bc934 100644 --- a/test/features/email/presentation/controller/single_email_controller_test.dart +++ b/test/features/email/presentation/controller/single_email_controller_test.dart @@ -46,6 +46,7 @@ import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_ import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; import '../../../../fixtures/email_fixtures.dart'; @@ -89,6 +90,7 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), + MockSpec(), ]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -122,6 +124,7 @@ void main() { final storeEventAttendanceStatusInteractor = MockStoreEventAttendanceStatusInteractor(); final printUtils = MockPrintUtils(); final applicationManager = MockApplicationManager(); + final mockToastManager = MockToastManager(); late SingleEmailController singleEmailController; @@ -156,6 +159,7 @@ void main() { Get.put(uuid); Get.put(printUtils); Get.put(applicationManager); + Get.put(mockToastManager); when(mailboxDashboardController.accountId).thenReturn(Rxn(testAccountId)); when(uuid.v4()).thenReturn(testTaskId); diff --git a/test/features/fcm/fcm_repository_test.dart b/test/features/fcm/fcm_repository_test.dart new file mode 100644 index 000000000..bb8833553 --- /dev/null +++ b/test/features/fcm/fcm_repository_test.dart @@ -0,0 +1,140 @@ +import 'package:core/data/model/source_type/data_source_type.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:model/extensions/mailbox_extension.dart'; +import 'package:model/extensions/presentation_mailbox_extension.dart'; +import 'package:model/extensions/session_extension.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; +import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart'; +import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/jmap_mailbox_response.dart'; +import 'package:tmail_ui_user/features/push_notification/data/datasource/fcm_datasource.dart'; +import 'package:tmail_ui_user/features/push_notification/data/datasource_impl/cache_fcm_datasource_impl.dart'; +import 'package:tmail_ui_user/features/push_notification/data/repository/fcm_repository_impl.dart'; +import 'package:tmail_ui_user/features/push_notification/domain/repository/fcm_repository.dart'; +import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart'; + +import '../../fixtures/session_fixtures.dart'; + +import 'fcm_repository_test.mocks.dart'; + +@GenerateMocks([ + FCMDatasource, + CacheFCMDatasourceImpl, + MailboxDataSource, + MailboxCacheDataSourceImpl, + ThreadDataSource +]) +void main() { + late FCMDatasource fcmDatasource; + late CacheFCMDatasourceImpl cacheFCMDatasourceImpl; + late MailboxDataSource mailboxDataSource; + late MailboxCacheDataSourceImpl mailboxCacheDataSourceImpl; + late ThreadDataSource threadDataSource; + late FCMRepository fcmRepository; + + final sessionFixture = SessionFixtures.aliceSession; + final accountIdFixture = SessionFixtures.aliceSession.accountId; + final userNameFixture = SessionFixtures.aliceSession.username; + + group('getMailboxesNotPutNotifications_method::test', () { + setUp(() { + fcmDatasource = MockFCMDatasource(); + cacheFCMDatasourceImpl = MockCacheFCMDatasourceImpl(); + mailboxDataSource = MockMailboxDataSource(); + mailboxCacheDataSourceImpl = MockMailboxCacheDataSourceImpl(); + threadDataSource = MockThreadDataSource(); + fcmRepository = FCMRepositoryImpl( + { + DataSourceType.network: fcmDatasource, + DataSourceType.local: cacheFCMDatasourceImpl + }, + threadDataSource, + { + DataSourceType.network: mailboxDataSource, + DataSourceType.local: mailboxCacheDataSourceImpl + }, + ); + }); + + test('should returns mailboxes with notifications deactivated from local cache', () async { + // Arrange + final Mailbox mailbox1 = Mailbox( + id: MailboxId(Id('spam-id')), + role: PresentationMailbox.roleSpam); + final Mailbox mailbox2 = Mailbox( + id: MailboxId(Id('inbox-id')), + role: PresentationMailbox.roleInbox); + when(mailboxCacheDataSourceImpl.getAllMailboxCache( + accountIdFixture, + userNameFixture + )).thenAnswer((_) async => [mailbox1, mailbox2]); + + // Act + final result = await fcmRepository.getMailboxesNotPutNotifications( + sessionFixture, + accountIdFixture); + + // Assert + expect(mailbox1.pushNotificationDeactivated, isTrue); + expect(mailbox2.pushNotificationDeactivated, isFalse); + expect(result, hasLength(1)); + expect(result.first.pushNotificationDeactivated, isTrue); + }); + + test('should falls back to network source if local cache is empty', () async { + // Arrange + when(mailboxCacheDataSourceImpl.getAllMailboxCache( + accountIdFixture, + userNameFixture + )).thenAnswer((_) async => []); + + final Mailbox mailbox1 = Mailbox( + id: MailboxId(Id('spam-id')), + role: PresentationMailbox.roleSpam); + final mailboxResponse = JmapMailboxResponse(mailboxes: [mailbox1]); + when(mailboxDataSource.getAllMailbox( + sessionFixture, + accountIdFixture + )).thenAnswer((_) async => mailboxResponse); + + // Act + final result = await fcmRepository.getMailboxesNotPutNotifications( + sessionFixture, + accountIdFixture); + + // Assert + expect(mailbox1.pushNotificationDeactivated, isTrue); + expect(result, hasLength(1)); + expect(result.first.pushNotificationDeactivated, isTrue); + }); + + test('should returns empty list if no mailboxes have notifications deactivated', () async { + // Arrange + final Mailbox mailbox1 = Mailbox( + id: MailboxId(Id('inbox-id')), + role: PresentationMailbox.roleInbox); + when(mailboxCacheDataSourceImpl.getAllMailboxCache( + accountIdFixture, + userNameFixture + )).thenAnswer((_) async => [mailbox1]); + final mailboxResponse = JmapMailboxResponse(mailboxes: [mailbox1]); + when(mailboxDataSource.getAllMailbox( + sessionFixture, + accountIdFixture + )).thenAnswer((_) async => mailboxResponse); + + // Act + final result = await fcmRepository.getMailboxesNotPutNotifications( + sessionFixture, + accountIdFixture); + + // Assert + expect(mailbox1.pushNotificationDeactivated, isFalse); + expect(result, isEmpty); + }); + }); +} \ No newline at end of file diff --git a/test/features/home/presentation/home_controller_test.dart b/test/features/home/presentation/home_controller_test.dart index eea721ebf..86328dae1 100644 --- a/test/features/home/presentation/home_controller_test.dart +++ b/test/features/home/presentation/home_controller_test.dart @@ -28,6 +28,7 @@ import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_ import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; import 'home_controller_test.mocks.dart'; @@ -53,6 +54,7 @@ import 'home_controller_test.mocks.dart'; MockSpec(), MockSpec(), MockSpec(), + MockSpec(), ]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -80,6 +82,7 @@ void main() { late MockResponsiveUtils mockResponsiveUtils; late MockUuid mockUuid; late MockApplicationManager mockApplicationManager; + late MockToastManager mockToastManager; setUpAll(() { cleanupEmailCacheInteractor = MockCleanupEmailCacheInteractor(); @@ -106,6 +109,7 @@ void main() { mockResponsiveUtils = MockResponsiveUtils(); mockUuid = MockUuid(); mockApplicationManager = MockApplicationManager(); + mockToastManager = MockToastManager(); Get.put(mockGetSessionInteractor); Get.put(mockGetAuthenticatedAccountInteractor); @@ -127,6 +131,7 @@ void main() { Get.put(mockResponsiveUtils); Get.put(mockUuid); Get.put(mockApplicationManager); + Get.put(mockToastManager); Get.testMode = true; homeController = HomeController( diff --git a/test/features/identity_creator/presentation/identity_creator_controller_test.dart b/test/features/identity_creator/presentation/identity_creator_controller_test.dart index 1c60c945c..629d507ea 100644 --- a/test/features/identity_creator/presentation/identity_creator_controller_test.dart +++ b/test/features/identity_creator/presentation/identity_creator_controller_test.dart @@ -37,6 +37,7 @@ import 'package:tmail_ui_user/features/public_asset/domain/usecase/create_public import 'package:tmail_ui_user/features/public_asset/domain/usecase/delete_public_assets_interactor.dart'; import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart'; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; import 'package:worker_manager/worker_manager.dart'; @@ -56,6 +57,7 @@ import 'identity_creator_controller_test.mocks.dart'; MockSpec(), MockSpec(), MockSpec(), + MockSpec(), // Identity creator controller mockspecs MockSpec(), MockSpec(), @@ -95,6 +97,7 @@ void main() { late MockResponsiveUtils mockResponsiveUtils; late MockUuid mockUuid; late MockApplicationManager mockApplicationManager; + late MockToastManager mockToastManager; setUpAll(() { //mock base controller @@ -110,6 +113,7 @@ void main() { mockResponsiveUtils = MockResponsiveUtils(); mockUuid = MockUuid(); mockApplicationManager = MockApplicationManager(); + mockToastManager = MockToastManager(); Get.put(mockCachingManager); Get.put(mockLanguageCacheManager); @@ -127,6 +131,7 @@ void main() { Get.put(mockResponsiveUtils); Get.put(mockUuid); Get.put(mockApplicationManager); + Get.put(mockToastManager); //mock identity creator controller mockVerifyNameInteractor = MockVerifyNameInteractor(); diff --git a/test/features/login/presentation/login_controller_test.dart b/test/features/login/presentation/login_controller_test.dart index a29d5aecb..9442b782c 100644 --- a/test/features/login/presentation/login_controller_test.dart +++ b/test/features/login/presentation/login_controller_test.dart @@ -34,6 +34,7 @@ import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; import 'login_controller_test.mocks.dart'; @@ -67,6 +68,7 @@ import 'login_controller_test.mocks.dart'; MockSpec(), MockSpec(), MockSpec(), + MockSpec(), ]) void main() { late MockAuthenticationInteractor mockAuthenticationInteractor; @@ -97,6 +99,7 @@ void main() { late MockResponsiveUtils mockResponsiveUtils; late MockUuid mockUuid; late MockApplicationManager mockApplicationManager; + late MockToastManager mockToastManager; late LoginController loginController; @@ -134,6 +137,7 @@ void main() { mockResponsiveUtils = MockResponsiveUtils(); mockUuid = MockUuid(); mockApplicationManager = MockApplicationManager(); + mockToastManager = MockToastManager(); Get.put(mockGetSessionInteractor); Get.put(mockGetAuthenticatedAccountInteractor); @@ -154,6 +158,7 @@ void main() { Get.put(mockResponsiveUtils); Get.put(mockUuid); Get.put(mockApplicationManager); + Get.put(mockToastManager); Get.testMode = true; loginController = LoginController( diff --git a/test/features/mailbox/repository/mailbox_respository_test.dart b/test/features/mailbox/repository/mailbox_respository_test.dart index 0407a7748..d204fd614 100644 --- a/test/features/mailbox/repository/mailbox_respository_test.dart +++ b/test/features/mailbox/repository/mailbox_respository_test.dart @@ -8,7 +8,7 @@ import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource. import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart'; import 'package:tmail_ui_user/features/mailbox/data/repository/mailbox_repository_impl.dart'; -import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/exceptions/mailbox_exception.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/cache_mailbox_response.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/jmap_mailbox_response.dart'; import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; diff --git a/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart b/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart index a79febbd4..15e641a1e 100644 --- a/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart +++ b/test/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller_test.dart @@ -92,6 +92,7 @@ import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; import 'package:tmail_ui_user/features/network_connection/presentation/network_connection_controller.dart' if (dart.library.html) 'package:tmail_ui_user/features/network_connection/presentation/web_network_connection_controller.dart'; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; import 'mailbox_dashboard_controller_test.mocks.dart'; @@ -168,6 +169,7 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), + MockSpec(), MockSpec(), ]) void main() { @@ -230,6 +232,7 @@ void main() { final responsiveUtils = MockResponsiveUtils(); final uuid = MockUuid(); final applicationManager = MockApplicationManager(); + final mockToastManager = MockToastManager(); // mock reloadable controller Get dependencies final getSessionInteractor = MockGetSessionInteractor(); @@ -271,76 +274,80 @@ void main() { final testMailboxId = MailboxId(Id('1')); final testAccountId = AccountId(Id('123')); + setUp(() { + Get.put(removeEmailDraftsInteractor); + Get.put(emailReceiveManager); + Get.put(downloadController); + Get.put(appGridDashboardController); + Get.put(spamReportController); + Get.put(networkConnectionController); + Get.put(cachingManager); + Get.put(languageCacheManager); + Get.put(authorizationInterceptors); + Get.put( + authorizationInterceptors, + tag: BindingTag.isolateTag, + ); + Get.put(dynamicUrlInterceptors); + Get.put(deleteCredentialInteractor); + Get.put(logoutOidcInteractor); + Get.put(deleteAuthorityOidcInteractor); + Get.put(appToast); + Get.put(imagePaths); + Get.put(responsiveUtils); + Get.put(uuid); + Get.put(applicationManager); + Get.put(mockToastManager); + Get.put(getSessionInteractor); + Get.put(getAuthenticatedAccountInteractor); + Get.put(updateAccountCacheInteractor); + Get.put(getAllIdentitiesInteractor); + Get.put(removeComposerCacheOnWebInteractor); + + searchController = SearchController( + quickSearchEmailInteractor, + saveRecentSearchInteractor, + getAllRecentSearchLatestInteractor); + Get.put(searchController); + + Get.testMode = true; + + mailboxDashboardController = MailboxDashBoardController( + moveToMailboxInteractor, + deleteEmailPermanentlyInteractor, + markAsMailboxReadInteractor, + getEmailCacheOnWebInteractor, + markAsEmailReadInteractor, + markAsStarEmailInteractor, + markAsMultipleEmailReadInteractor, + markAsStarMultipleEmailInteractor, + moveMultipleEmailToMailboxInteractor, + emptyTrashFolderInteractor, + deleteMultipleEmailsPermanentlyInteractor, + getEmailByIdInteractor, + sendEmailInteractor, + storeSendingEmailInteractor, + updateSendingEmailInteractor, + getAllSendingEmailInteractor, + storeSessionInteractor, + emptySpamFolderInteractor, + deleteSendingEmailInteractor, + unsubscribeEmailInteractor, + restoreDeletedMessageInteractor, + getRestoredDeletedMessageInteractor, + removeComposerCacheOnWebInteractor, + getAllIdentitiesInteractor, + ); + }); + group('search/sort/filter feature:', () { setUp(() { getEmailsInMailboxInteractor = MockGetEmailsInMailboxInteractor(); - Get.put(removeEmailDraftsInteractor); - Get.put(emailReceiveManager); - Get.put(downloadController); - Get.put(appGridDashboardController); - Get.put(spamReportController); - Get.put(networkConnectionController); - Get.put(cachingManager); - Get.put(languageCacheManager); - Get.put(authorizationInterceptors); - Get.put( - authorizationInterceptors, - tag: BindingTag.isolateTag, - ); - Get.put(dynamicUrlInterceptors); - Get.put(deleteCredentialInteractor); - Get.put(logoutOidcInteractor); - Get.put(deleteAuthorityOidcInteractor); - Get.put(appToast); - Get.put(imagePaths); - Get.put(responsiveUtils); - Get.put(uuid); - Get.put(applicationManager); - Get.put(getSessionInteractor); - Get.put(getAuthenticatedAccountInteractor); - Get.put(updateAccountCacheInteractor); - Get.put(getAllIdentitiesInteractor); - Get.put(removeComposerCacheOnWebInteractor); - - Get.testMode = true; - when(emailReceiveManager.pendingEmailAddressInfo).thenAnswer((_) => BehaviorSubject.seeded(null)); when(emailReceiveManager.pendingEmailContentInfo).thenAnswer((_) => BehaviorSubject.seeded(null)); when(emailReceiveManager.pendingFileInfo).thenAnswer((_) => BehaviorSubject.seeded([])); - searchController = SearchController( - quickSearchEmailInteractor, - saveRecentSearchInteractor, - getAllRecentSearchLatestInteractor); - Get.put(searchController); - - mailboxDashboardController = MailboxDashBoardController( - moveToMailboxInteractor, - deleteEmailPermanentlyInteractor, - markAsMailboxReadInteractor, - getEmailCacheOnWebInteractor, - markAsEmailReadInteractor, - markAsStarEmailInteractor, - markAsMultipleEmailReadInteractor, - markAsStarMultipleEmailInteractor, - moveMultipleEmailToMailboxInteractor, - emptyTrashFolderInteractor, - deleteMultipleEmailsPermanentlyInteractor, - getEmailByIdInteractor, - sendEmailInteractor, - storeSendingEmailInteractor, - updateSendingEmailInteractor, - getAllSendingEmailInteractor, - storeSessionInteractor, - emptySpamFolderInteractor, - deleteSendingEmailInteractor, - unsubscribeEmailInteractor, - restoreDeletedMessageInteractor, - getRestoredDeletedMessageInteractor, - removeComposerCacheOnWebInteractor, - getAllIdentitiesInteractor, - ); Get.put(mailboxDashboardController); mailboxDashboardController.onReady(); @@ -483,4 +490,47 @@ void main() { tearDown(Get.deleteAll); }); + + group('spamMailboxId:test', () { + test('should returns Junk mailbox ID if it exists', () { + // Arrange + final spamMailboxId = MailboxId(Id('spam-id')); + final junkMailboxId = MailboxId(Id('junk-id')); + final mapDefaultMailboxIdByRole = { + PresentationMailbox.roleSpam: spamMailboxId, + PresentationMailbox.roleJunk: junkMailboxId, + }; + mailboxDashboardController.setMapDefaultMailboxIdByRole(mapDefaultMailboxIdByRole); + // Act + final spamId = mailboxDashboardController.spamMailboxId; + + // Assert + expect(spamId, equals(junkMailboxId)); + }); + + test('should returns junk mailbox ID if spam ID does not exist', () { + // Arrange + final junkMailboxId = MailboxId(Id('junk-id')); + final mapDefaultMailboxIdByRole = { + PresentationMailbox.roleJunk: junkMailboxId, + }; + mailboxDashboardController.setMapDefaultMailboxIdByRole(mapDefaultMailboxIdByRole); + // Act + final spamId = mailboxDashboardController.spamMailboxId; + + // Assert + expect(spamId, equals(junkMailboxId)); + }); + + test('should returns null if neither spam nor junk mailbox ID exists', () { + // Arrange + final mapDefaultMailboxIdByRole = {}; + mailboxDashboardController.setMapDefaultMailboxIdByRole(mapDefaultMailboxIdByRole); + // Act + final spamId = mailboxDashboardController.spamMailboxId; + + // Assert + expect(spamId, isNull); + }); + }); } diff --git a/test/features/manage_account/presentation/profiles/identities/identities_controller_test.dart b/test/features/manage_account/presentation/profiles/identities/identities_controller_test.dart index 9c4448191..fb4e2a1d7 100644 --- a/test/features/manage_account/presentation/profiles/identities/identities_controller_test.dart +++ b/test/features/manage_account/presentation/profiles/identities/identities_controller_test.dart @@ -27,6 +27,7 @@ import 'package:tmail_ui_user/features/public_asset/domain/usecase/delete_public import 'package:tmail_ui_user/features/public_asset/domain/usecase/remove_identity_from_public_assets_interactor.dart'; import 'package:tmail_ui_user/features/public_asset/presentation/clean_up_public_assets_interactor_bindings.dart'; import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; +import 'package:tmail_ui_user/main/utils/toast_manager.dart'; import 'package:uuid/uuid.dart'; import 'identities_controller_test.mocks.dart'; @@ -51,6 +52,7 @@ const fallbackGenerators = { MockSpec(), MockSpec(), MockSpec(), + MockSpec(), // Identities controller mockspecs MockSpec(), @@ -87,6 +89,7 @@ void main() { late MockResponsiveUtils mockResponsiveUtils; late MockUuid mockUuid; late MockApplicationManager mockApplicationManager; + late MockToastManager mockToastManager; setUpAll(() { //mock base controller @@ -102,6 +105,7 @@ void main() { mockResponsiveUtils = MockResponsiveUtils(); mockUuid = MockUuid(); mockApplicationManager = MockApplicationManager(); + mockToastManager = MockToastManager(); Get.put(mockCachingManager); Get.put(mockLanguageCacheManager); @@ -119,6 +123,7 @@ void main() { Get.put(mockResponsiveUtils); Get.put(mockUuid); Get.put(mockApplicationManager); + Get.put(mockToastManager); // mock identities controller mockGetAllIdentitiesInteractor = MockGetAllIdentitiesInteractor();