diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index f7bffd1cc..55d49f7d5 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -236,7 +236,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } else if (success is PrintEmailSuccess) { _handlePrintEmailSuccess(success); } else if (success is CalendarEventReplySuccess) { - _calendarEventSuccess(success); + calendarEventSuccess(success); } else if (success is StoreEventAttendanceStatusSuccess) { _showToastMessageEventAttendanceSuccess(success); } @@ -1768,7 +1768,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { } } - void _calendarEventSuccess(CalendarEventReplySuccess success) { + void calendarEventSuccess(CalendarEventReplySuccess success) { final session = mailboxDashBoardController.sessionCurrent; final accountId = mailboxDashBoardController.accountId.value; diff --git a/test/features/email/domain/usecases/store_event_attendance_status_interactor_test.dart b/test/features/email/domain/usecases/store_event_attendance_status_interactor_test.dart new file mode 100644 index 000000000..e30b9a7f9 --- /dev/null +++ b/test/features/email/domain/usecases/store_event_attendance_status_interactor_test.dart @@ -0,0 +1,107 @@ +import 'package:dartz/dartz.dart' hide State; +import 'package:flutter_test/flutter_test.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; +import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; +import 'package:tmail_ui_user/features/email/domain/state/store_event_attendance_status_state.dart'; +import 'package:tmail_ui_user/features/email/domain/usecases/store_event_attendance_status_interactor.dart'; + +import '../../../../fixtures/account_fixtures.dart'; +import '../../../../fixtures/email_fixtures.dart'; +import '../../../../fixtures/session_fixtures.dart'; + +import 'store_event_attendance_status_interactor_test.mocks.dart'; + +@GenerateNiceMocks([ + MockSpec() +]) +void main() { + group('StoreEventAttendanceStatusInteractor test', () { + late MockEmailRepository mockEmailRepository; + late StoreEventAttendanceStatusInteractor storeEventAttendanceStatusInteractor; + + setUp(() { + mockEmailRepository = MockEmailRepository(); + storeEventAttendanceStatusInteractor = StoreEventAttendanceStatusInteractor(mockEmailRepository); + }); + + final sessionFixture = SessionFixtures.aliceSession; + final accountIdFixture = AccountFixtures.aliceAccountId; + final emailIdFixture = EmailFixtures.emailId; + const eventActionType = EventActionType.yes; + + test('SHOULD emit loading and success states when storeEventAttendanceStatus is successful', () async { + final currentEmailState = State('abc123'); + final updatedEmail = Email(id: emailIdFixture); + + when(mockEmailRepository.getEmailState( + sessionFixture, + accountIdFixture + )).thenAnswer((_) async => currentEmailState); + when(mockEmailRepository.storeEventAttendanceStatus( + sessionFixture, + accountIdFixture, + emailIdFixture, + eventActionType + )).thenAnswer((_) async => updatedEmail); + + final result = storeEventAttendanceStatusInteractor.execute( + sessionFixture, + accountIdFixture, + emailIdFixture, + eventActionType); + + await expectLater( + result, + emitsInOrder([ + Right(StoreEventAttendanceStatusLoading()), + Right(StoreEventAttendanceStatusSuccess( + eventActionType, + updatedEmail, + currentEmailState: currentEmailState)), + ]), + ); + + verify(mockEmailRepository.getEmailState(sessionFixture, accountIdFixture)).called(1); + verify(mockEmailRepository.storeEventAttendanceStatus( + sessionFixture, + accountIdFixture, + emailIdFixture, + eventActionType + )).called(1); + verifyNoMoreInteractions(mockEmailRepository); + }); + + test('SHOULD emit loading and failure states when storeEventAttendanceStatus throws an exception', () async { + final exception = Exception(); + + when(mockEmailRepository.getEmailState( + sessionFixture, + accountIdFixture + )).thenThrow(exception); + + final result = storeEventAttendanceStatusInteractor.execute( + sessionFixture, + accountIdFixture, + emailIdFixture, + eventActionType); + + await expectLater( + result, + emitsInOrder([ + Right(StoreEventAttendanceStatusLoading()), + Left(StoreEventAttendanceStatusFailure(exception: exception)), + ]), + ); + + verify(mockEmailRepository.getEmailState( + sessionFixture, + accountIdFixture + )).called(1); + verifyNoMoreInteractions(mockEmailRepository); + }); + }); +} \ No newline at end of file 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 0af277ffe..c78f59f96 100644 --- a/test/features/email/presentation/controller/single_email_controller_test.dart +++ b/test/features/email/presentation/controller/single_email_controller_test.dart @@ -10,12 +10,14 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart'; +import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_response.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/email/domain/model/event_action.dart'; +import 'package:tmail_ui_user/features/email/domain/state/calendar_event_accept_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/view_attachment_for_web_state.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/calendar_event_accept_interactor.dart'; @@ -45,6 +47,7 @@ import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oi import 'package:tmail_ui_user/main/bindings/network/binding_tag.dart'; import 'package:uuid/uuid.dart'; +import '../../../../fixtures/email_fixtures.dart'; import 'single_email_controller_test.mocks.dart'; mockControllerCallback() => InternalFinalCallback(callback: () {}); @@ -307,8 +310,8 @@ void main() { group('maybe test:', () { final maybeCalendarEventInteractor = MockMaybeCalendarEventInteractor(); - test('should call execute on AcceptCalendarEventInteractor ' - 'when onCalendarEventReplyAction is called on EventActionType.yes', () async { + test('should call execute on MaybeCalendarEventInteractor ' + 'when onCalendarEventReplyAction is called on EventActionType.maybe', () async { // arrange when(mailboxDashboardController.selectedEmail).thenReturn(Rxn(null)); when(mailboxDashboardController.emailUIAction).thenReturn(Rxn(null)); @@ -335,7 +338,7 @@ void main() { final rejectCalendarEventInteractor = MockRejectCalendarEventInteractor(); test('should call execute on RejectCalendarEventInteractor ' - 'when onCalendarEventReplyAction is called on EventActionType.yes', () async { + 'when onCalendarEventReplyAction is called on EventActionType.no', () async { // arrange when(mailboxDashboardController.selectedEmail).thenReturn(Rxn(null)); when(mailboxDashboardController.emailUIAction).thenReturn(Rxn(null)); @@ -358,4 +361,77 @@ void main() { }); }); }); + + group('StoreEventAttendanceStatusInteractor test', () { + group('calendarEventSuccess method test', () { + test( + 'SHOULD call execute on StoreEventAttendanceStatusInteractor\n' + 'WHEN calendarEventSuccess method is called', + () { + when(mailboxDashboardController.sessionCurrent).thenReturn(testSession); + + final eventAcceptedSuccess = CalendarEventAccepted( + CalendarEventAcceptResponse(testAccountId, null), + EmailFixtures.emailId); + + singleEmailController.calendarEventSuccess(eventAcceptedSuccess); + + verify(storeEventAttendanceStatusInteractor.execute( + testSession, + testAccountId, + EmailFixtures.emailId, + EventActionType.yes, + )).called(1); + }); + }); + + group('onCalendarEventReplyAction method test', () { + test( + 'SHOULD call execute on StoreEventAttendanceStatusInteractor\n' + 'WHEN onCalendarEventReplyAction is called on EventActionType.yes\n' + 'AND return success', + () async { + final acceptCalendarEventInteractor = MockAcceptCalendarEventInteractor(); + final blobId = Id('abc123'); + final emailId = EmailId(Id('xyz123')); + final calendarEvent = CalendarEvent(); + + when(mailboxDashboardController.sessionCurrent).thenReturn(testSession); + when(mailboxDashboardController.selectedEmail).thenReturn(Rxn(null)); + when(mailboxDashboardController.emailUIAction).thenReturn(Rxn(null)); + when(mailboxDashboardController.viewState).thenReturn(Rx(Right(UIState.idle))); + + singleEmailController.onInit(); + + Get.put(acceptCalendarEventInteractor); + + mailboxDashboardController.accountId.refresh(); + + singleEmailController.handleSuccessViewState( + ParseCalendarEventSuccess([ + BlobCalendarEvent( + blobId: blobId, + calendarEventList: [calendarEvent] + ) + ]) + ); + + singleEmailController.onCalendarEventReplyAction(EventActionType.yes, emailId); + + singleEmailController.calendarEventSuccess(CalendarEventAccepted( + CalendarEventAcceptResponse(testAccountId, null), + emailId + )); + + await untilCalled(storeEventAttendanceStatusInteractor.execute(any, any, any, any)); + + verify(storeEventAttendanceStatusInteractor.execute( + testSession, + testAccountId, + emailId, + EventActionType.yes, + )).called(1); + }); + }); + }); } diff --git a/test/fixtures/account_fixtures.dart b/test/fixtures/account_fixtures.dart index 3b2dcc313..583ce4935 100644 --- a/test/fixtures/account_fixtures.dart +++ b/test/fixtures/account_fixtures.dart @@ -5,7 +5,7 @@ import 'package:model/account/authentication_type.dart'; import 'package:model/account/personal_account.dart'; class AccountFixtures { - static final aliceAccountId = AccountId(Id('411ce')); + static final aliceAccountId = AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')); static final aliceAccount = PersonalAccount( 'dab', AuthenticationType.oidc, diff --git a/test/fixtures/email_fixtures.dart b/test/fixtures/email_fixtures.dart index 13290ad3c..16b583e7c 100644 --- a/test/fixtures/email_fixtures.dart +++ b/test/fixtures/email_fixtures.dart @@ -106,4 +106,6 @@ class EmailFixtures { keywords: {KeyWordIdentifier.emailSeen : true}, mailboxIds: {MailboxFixtures.inboxMailbox.id! : true} ); + + static final emailId = EmailId(Id("382312d0-fa5c-11eb-b647-2fef1ee78d9e")); } \ No newline at end of file diff --git a/test/fixtures/session_fixtures.dart b/test/fixtures/session_fixtures.dart index fdf5b4dab..b416492f7 100644 --- a/test/fixtures/session_fixtures.dart +++ b/test/fixtures/session_fixtures.dart @@ -1,4 +1,3 @@ -import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/account/account.dart'; import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; import 'package:jmap_dart_client/jmap/core/capability/core_capability.dart'; @@ -8,13 +7,14 @@ import 'package:jmap_dart_client/jmap/core/capability/mdn_capability.dart'; import 'package:jmap_dart_client/jmap/core/capability/submission_capability.dart'; import 'package:jmap_dart_client/jmap/core/capability/vacation_capability.dart'; import 'package:jmap_dart_client/jmap/core/capability/websocket_capability.dart'; -import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/sort/collation_identifier.dart'; import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; import 'package:jmap_dart_client/jmap/core/user_name.dart'; +import 'account_fixtures.dart'; + class SessionFixtures { static final aliceSession = Session( { @@ -48,8 +48,8 @@ class SessionFixtures { CapabilityIdentifier.jmapMdn: MdnCapability(), }, { - AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')): Account( - AccountName('bob@domain.tld'), + AccountFixtures.aliceAccountId: Account( + AccountName('alice@domain.tld'), true, false, { @@ -85,16 +85,16 @@ class SessionFixtures { ) }, { - CapabilityIdentifier.jmapSubmission: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), - CapabilityIdentifier.jmapWebSocket: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), - CapabilityIdentifier.jmapCore: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), - CapabilityIdentifier.jmapMail: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), - CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:quota')): AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), - CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:shares')): AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), - CapabilityIdentifier.jmapVacationResponse: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), - CapabilityIdentifier.jmapMdn: AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')), + CapabilityIdentifier.jmapSubmission: AccountFixtures.aliceAccountId, + CapabilityIdentifier.jmapWebSocket: AccountFixtures.aliceAccountId, + CapabilityIdentifier.jmapCore: AccountFixtures.aliceAccountId, + CapabilityIdentifier.jmapMail: AccountFixtures.aliceAccountId, + CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:quota')): AccountFixtures.aliceAccountId, + CapabilityIdentifier(Uri.parse('urn:apache:james:params:jmap:mail:shares')): AccountFixtures.aliceAccountId, + CapabilityIdentifier.jmapVacationResponse: AccountFixtures.aliceAccountId, + CapabilityIdentifier.jmapMdn: AccountFixtures.aliceAccountId, }, - UserName('bob@domain.tld'), + UserName('alice@domain.tld'), Uri.parse('http://domain.com/jmap'), Uri.parse('http://domain.com/download/{accountId}/{blobId}/?type={type}&name={name}'), Uri.parse('http://domain.com/upload/{accountId}'),