From d9d300edc180700dc526922626f6e85019151061 Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 4 Mar 2025 12:18:59 +0700 Subject: [PATCH] TF-3484 Add unit test to verify get oidc configuration when check oidc available fail Signed-off-by: dab246 --- .../presentation/login_controller_test.dart | 232 ++++++++++++------ 1 file changed, 158 insertions(+), 74 deletions(-) diff --git a/test/features/login/presentation/login_controller_test.dart b/test/features/login/presentation/login_controller_test.dart index 717a620d9..9f958c5db 100644 --- a/test/features/login/presentation/login_controller_test.dart +++ b/test/features/login/presentation/login_controller_test.dart @@ -4,13 +4,20 @@ import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/app_toast.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/utils/application_manager.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:get/get.dart'; import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:model/oidc/response/oidc_link_dto.dart'; +import 'package:model/oidc/response/oidc_response.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interactor.dart'; import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart'; +import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart'; import 'package:tmail_ui_user/features/login/domain/exceptions/login_exception.dart'; +import 'package:tmail_ui_user/features/login/domain/state/check_oidc_is_available_state.dart'; +import 'package:tmail_ui_user/features/login/domain/state/get_oidc_configuration_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/get_token_oidc_state.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/authentication_user_interactor.dart'; @@ -28,6 +35,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/get_token_oidc_inte import 'package:tmail_ui_user/features/login/domain/usecases/save_login_url_on_mobile_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/save_login_username_on_mobile_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/update_account_cache_interactor.dart'; +import 'package:tmail_ui_user/features/login/presentation/extensions/handle_openid_configuration.dart'; import 'package:tmail_ui_user/features/login/presentation/login_controller.dart'; 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'; @@ -106,85 +114,87 @@ void main() { late LoginController loginController; - group('Test handleFailureViewState with GetTokenOIDCFailure', () { - setUp(() { - mockAuthenticationInteractor = MockAuthenticationInteractor(); - mockCheckOIDCIsAvailableInteractor = MockCheckOIDCIsAvailableInteractor(); - mockGetOIDCConfigurationInteractor = MockGetOIDCConfigurationInteractor(); - mockGetTokenOIDCInteractor = MockGetTokenOIDCInteractor(); - mockAuthenticateOidcOnBrowserInteractor = MockAuthenticateOidcOnBrowserInteractor(); - mockGetAuthenticationInfoInteractor = MockGetAuthenticationInfoInteractor(); - mockGetStoredOidcConfigurationInteractor = MockGetStoredOidcConfigurationInteractor(); - mockSaveLoginUrlOnMobileInteractor = MockSaveLoginUrlOnMobileInteractor(); - mockGetAllRecentLoginUrlOnMobileInteractor = MockGetAllRecentLoginUrlOnMobileInteractor(); - mockSaveLoginUsernameOnMobileInteractor = MockSaveLoginUsernameOnMobileInteractor(); - mockGetAllRecentLoginUsernameOnMobileInteractor = MockGetAllRecentLoginUsernameOnMobileInteractor(); - mockDNSLookupToGetJmapUrlInteractor = MockDNSLookupToGetJmapUrlInteractor(); - mockSignInTwakeWorkplaceInteractor = MockSignInTwakeWorkplaceInteractor(); + setUp(() { + mockAuthenticationInteractor = MockAuthenticationInteractor(); + mockCheckOIDCIsAvailableInteractor = MockCheckOIDCIsAvailableInteractor(); + mockGetOIDCConfigurationInteractor = MockGetOIDCConfigurationInteractor(); + mockGetTokenOIDCInteractor = MockGetTokenOIDCInteractor(); + mockAuthenticateOidcOnBrowserInteractor = MockAuthenticateOidcOnBrowserInteractor(); + mockGetAuthenticationInfoInteractor = MockGetAuthenticationInfoInteractor(); + mockGetStoredOidcConfigurationInteractor = MockGetStoredOidcConfigurationInteractor(); + mockSaveLoginUrlOnMobileInteractor = MockSaveLoginUrlOnMobileInteractor(); + mockGetAllRecentLoginUrlOnMobileInteractor = MockGetAllRecentLoginUrlOnMobileInteractor(); + mockSaveLoginUsernameOnMobileInteractor = MockSaveLoginUsernameOnMobileInteractor(); + mockGetAllRecentLoginUsernameOnMobileInteractor = MockGetAllRecentLoginUsernameOnMobileInteractor(); + mockDNSLookupToGetJmapUrlInteractor = MockDNSLookupToGetJmapUrlInteractor(); + mockSignInTwakeWorkplaceInteractor = MockSignInTwakeWorkplaceInteractor(); - // mock reloadable controller - mockGetSessionInteractor = MockGetSessionInteractor(); - mockGetAuthenticatedAccountInteractor = MockGetAuthenticatedAccountInteractor(); - mockUpdateAccountCacheInteractor = MockUpdateAccountCacheInteractor(); + // mock reloadable controller + mockGetSessionInteractor = MockGetSessionInteractor(); + mockGetAuthenticatedAccountInteractor = MockGetAuthenticatedAccountInteractor(); + mockUpdateAccountCacheInteractor = MockUpdateAccountCacheInteractor(); - //mock base controller - mockCachingManager = MockCachingManager(); - mockLanguageCacheManager = MockLanguageCacheManager(); - mockAuthorizationInterceptors = MockAuthorizationInterceptors(); - mockDynamicUrlInterceptors = MockDynamicUrlInterceptors(); - mockDeleteCredentialInteractor = MockDeleteCredentialInteractor(); - mockLogoutOidcInteractor = MockLogoutOidcInteractor(); - mockDeleteAuthorityOidcInteractor = MockDeleteAuthorityOidcInteractor(); - mockAppToast = MockAppToast(); - mockImagePaths = MockImagePaths(); - mockResponsiveUtils = MockResponsiveUtils(); - mockUuid = MockUuid(); - mockApplicationManager = MockApplicationManager(); - mockToastManager = MockToastManager(); - mockTwakeAppManager = MockTwakeAppManager(); - - Get.put(mockGetSessionInteractor); - Get.put(mockGetAuthenticatedAccountInteractor); - Get.put(mockUpdateAccountCacheInteractor); - Get.put(mockCachingManager); - Get.put(mockLanguageCacheManager); - Get.put(mockAuthorizationInterceptors); - Get.put( - mockAuthorizationInterceptors, - tag: BindingTag.isolateTag, - ); - Get.put(mockDynamicUrlInterceptors); - Get.put(mockDeleteCredentialInteractor); - Get.put(mockLogoutOidcInteractor); - Get.put(mockDeleteAuthorityOidcInteractor); - Get.put(mockAppToast); - Get.put(mockImagePaths); - Get.put(mockResponsiveUtils); - Get.put(mockUuid); - Get.put(mockApplicationManager); - Get.put(mockToastManager); - Get.put(mockTwakeAppManager); - Get.testMode = true; - - loginController = LoginController( - mockAuthenticationInteractor, - mockCheckOIDCIsAvailableInteractor, - mockGetOIDCConfigurationInteractor, - mockGetTokenOIDCInteractor, - mockAuthenticateOidcOnBrowserInteractor, - mockGetAuthenticationInfoInteractor, - mockGetStoredOidcConfigurationInteractor, - mockSaveLoginUrlOnMobileInteractor, - mockGetAllRecentLoginUrlOnMobileInteractor, - mockSaveLoginUsernameOnMobileInteractor, - mockGetAllRecentLoginUsernameOnMobileInteractor, - mockDNSLookupToGetJmapUrlInteractor, - mockSignInTwakeWorkplaceInteractor, - ); + //mock base controller + mockCachingManager = MockCachingManager(); + mockLanguageCacheManager = MockLanguageCacheManager(); + mockAuthorizationInterceptors = MockAuthorizationInterceptors(); + mockDynamicUrlInterceptors = MockDynamicUrlInterceptors(); + mockDeleteCredentialInteractor = MockDeleteCredentialInteractor(); + mockLogoutOidcInteractor = MockLogoutOidcInteractor(); + mockDeleteAuthorityOidcInteractor = MockDeleteAuthorityOidcInteractor(); + mockAppToast = MockAppToast(); + mockImagePaths = MockImagePaths(); + mockResponsiveUtils = MockResponsiveUtils(); + mockUuid = MockUuid(); + mockApplicationManager = MockApplicationManager(); + mockToastManager = MockToastManager(); + mockTwakeAppManager = MockTwakeAppManager(); + Get.put(mockGetSessionInteractor); + Get.put(mockGetAuthenticatedAccountInteractor); + Get.put(mockUpdateAccountCacheInteractor); + Get.put(mockCachingManager); + Get.put(mockLanguageCacheManager); + Get.put(mockAuthorizationInterceptors); + Get.put( + mockAuthorizationInterceptors, + tag: BindingTag.isolateTag, + ); + Get.put(mockDynamicUrlInterceptors); + Get.put(mockDeleteCredentialInteractor); + Get.put(mockLogoutOidcInteractor); + Get.put(mockDeleteAuthorityOidcInteractor); + Get.put(mockAppToast); + Get.put(mockImagePaths); + Get.put(mockResponsiveUtils); + Get.put(mockUuid); + Get.put(mockApplicationManager); + Get.put(mockToastManager); + Get.put(mockTwakeAppManager); + Get.testMode = true; + dotenv.testLoad(mergeWith: { + 'SERVER_URL': 'https://example.com' }); + loginController = LoginController( + mockAuthenticationInteractor, + mockCheckOIDCIsAvailableInteractor, + mockGetOIDCConfigurationInteractor, + mockGetTokenOIDCInteractor, + mockAuthenticateOidcOnBrowserInteractor, + mockGetAuthenticationInfoInteractor, + mockGetStoredOidcConfigurationInteractor, + mockSaveLoginUrlOnMobileInteractor, + mockGetAllRecentLoginUrlOnMobileInteractor, + mockSaveLoginUsernameOnMobileInteractor, + mockGetAllRecentLoginUsernameOnMobileInteractor, + mockDNSLookupToGetJmapUrlInteractor, + mockSignInTwakeWorkplaceInteractor, + ); + }); + + group('Test handleFailureViewState with GetTokenOIDCFailure', () { test('WHEN handleFailureViewState is called with GetTokenOIDCFailure \n' 'AND loginFormType is dnsLookup \n' 'BUT EXCEPTION is not NoSuitableBrowserForOIDCException \n' @@ -230,7 +240,81 @@ void main() { final failure = GetTokenOIDCFailure(NoSuitableBrowserForOIDCException()); loginController.handleFailureViewState(failure); - expect(loginController.loginFormType.value, equals(LoginFormType.baseUrlForm)); + expect(loginController.loginFormType.value, + equals(LoginFormType.baseUrlForm)); + }); + }); + + group('LoginController::handleFailureViewState::', () { + test('should call _getOIDCConfigurationInteractor when failure is CheckOIDCIsAvailableFailure', () { + // Arrange + final failure = CheckOIDCIsAvailableFailure(CanNotFoundOIDCLinks()); + loginController.onBaseUrlChange('https://example.com'); + // Act + loginController.handleFailureViewState(failure); + + // Assert + verify(mockGetOIDCConfigurationInteractor.execute(any)).called(1); + }); + + test('should update loginFormType when failure is GetOIDCConfigurationFromBaseUrlFailure', () { + // Arrange + final failure = GetOIDCConfigurationFromBaseUrlFailure(Exception()); + + // Act + loginController.handleFailureViewState(failure); + + // Assert + expect(loginController.loginFormType.value, LoginFormType.retry); + }); + }); + + group('LoginController::handleUrgentException::', () { + test('should call _getOIDCConfigurationInteractor when failure is CheckOIDCIsAvailableFailure', () { + // Arrange + final failure = CheckOIDCIsAvailableFailure(CanNotFoundOIDCLinks()); + loginController.onBaseUrlChange('https://example.com'); + // Act + loginController.handleUrgentException(failure: failure); + + // Assert + verify(mockGetOIDCConfigurationInteractor.execute(any)).called(1); + }); + + test('should update loginFormType when failure is GetOIDCConfigurationFromBaseUrlFailure', () { + // Arrange + final failure = GetOIDCConfigurationFromBaseUrlFailure(Exception()); + + // Act + loginController.handleUrgentException(failure: failure); + + // Assert + expect(loginController.loginFormType.value, LoginFormType.retry); + }); + }); + + group('LoginController::handleSuccessViewState::', () { + test('should not call _getOIDCConfigurationInteractor when success is CheckOIDCIsAvailableSuccess', () { + // Arrange + const baseUrl = 'https://example.com'; + final oidcResponse = OIDCResponse( + 'subject', + [ + OIDCLinkDto( + Uri.parse(baseUrl), + Uri.parse(baseUrl), + ) + ] + ); + final success = CheckOIDCIsAvailableSuccess(oidcResponse); + loginController.onBaseUrlChange(baseUrl); + + // Act + loginController.handleSuccessViewState(success); + + // Assert + verifyNever(loginController.tryGetOIDCConfigurationFromBaseUrl(Uri.parse(baseUrl))); + verify(loginController.getOIDCConfiguration(oidcResponse)).called(1); }); }); } \ No newline at end of file