import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:rasadyar_chicken/features/common/data/datasources/remote/auth/auth_remote.dart'; import 'package:rasadyar_chicken/features/common/data/model/response/user_info/user_info_model.dart'; import 'package:rasadyar_chicken/features/common/data/model/response/user_profile_model/user_profile_model.dart'; class MockAuthRemoteDataSource extends Mock implements AuthRemoteDataSource {} void main() { late AuthRepositoryImpl authRepository; late MockAuthRemoteDataSource mockAuthRemote; setUp(() { mockAuthRemote = MockAuthRemoteDataSource(); authRepository = AuthRepositoryImpl(mockAuthRemote); }); group('Authentication Flow Integration Tests', () { group('Complete Login Flow', () { test('should complete full login flow successfully', () async { // Arrange const phoneNumber = '09123456789'; final authRequest = { 'username': 'test@example.com', 'password': 'password', }; final expectedUserInfo = UserInfoModel( isUser: true, address: 'Test Address', backend: 'test-backend', apiKey: 'test-api-key', ); final expectedUserProfile = UserProfileModel( accessToken: 'access-token', expiresIn: '3600', scope: 'read write', expireTime: '2024-12-31T23:59:59Z', mobile: phoneNumber, fullname: 'John Doe', firstname: 'John', lastname: 'Doe', ); // Mock the flow when( () => mockAuthRemote.getUserInfo(phoneNumber), ).thenAnswer((_) async => expectedUserInfo); when( () => mockAuthRemote.login(authRequest: authRequest), ).thenAnswer((_) async => expectedUserProfile); // Act - Step 1: Get user info final userInfo = await authRepository.getUserInfo(phoneNumber); expect(userInfo, equals(expectedUserInfo)); // Act - Step 2: Login final userProfile = await authRepository.login( authRequest: authRequest, ); // Assert expect(userProfile, equals(expectedUserProfile)); verify(() => mockAuthRemote.getUserInfo(phoneNumber)).called(1); verify(() => mockAuthRemote.login(authRequest: authRequest)).called(1); }); test('should handle login flow with authentication check', () async { // Arrange final authRequest = { 'username': 'test@example.com', 'password': 'password', }; final expectedUserProfile = UserProfileModel( accessToken: 'access-token', expiresIn: '3600', scope: 'read write', expireTime: '2024-12-31T23:59:59Z', mobile: '09123456789', fullname: 'John Doe', firstname: 'John', lastname: 'Doe', ); // Mock the flow when( () => mockAuthRemote.hasAuthenticated(), ).thenAnswer((_) async => false); when( () => mockAuthRemote.login(authRequest: authRequest), ).thenAnswer((_) async => expectedUserProfile); // Act - Step 1: Check authentication status final isAuthenticated = await authRepository.hasAuthenticated(); expect(isAuthenticated, isFalse); // Act - Step 2: Login final userProfile = await authRepository.login( authRequest: authRequest, ); // Assert expect(userProfile, equals(expectedUserProfile)); verify(() => mockAuthRemote.hasAuthenticated()).called(1); verify(() => mockAuthRemote.login(authRequest: authRequest)).called(1); }); }); group('Error Handling in Authentication Flow', () { test('should handle user info retrieval failure', () async { // Arrange const phoneNumber = '09123456789'; when( () => mockAuthRemote.getUserInfo(phoneNumber), ).thenAnswer((_) async => null); // Act final userInfo = await authRepository.getUserInfo(phoneNumber); // Assert expect(userInfo, isNull); verify(() => mockAuthRemote.getUserInfo(phoneNumber)).called(1); }); test('should handle login failure after successful user info', () async { // Arrange const phoneNumber = '09123456789'; final authRequest = { 'username': 'test@example.com', 'password': 'wrong', }; final expectedUserInfo = UserInfoModel( isUser: true, address: 'Test Address', backend: 'test-backend', apiKey: 'test-api-key', ); // Mock the flow when( () => mockAuthRemote.getUserInfo(phoneNumber), ).thenAnswer((_) async => expectedUserInfo); when( () => mockAuthRemote.login(authRequest: authRequest), ).thenAnswer((_) async => null); // Act - Step 1: Get user info (success) final userInfo = await authRepository.getUserInfo(phoneNumber); expect(userInfo, equals(expectedUserInfo)); // Act - Step 2: Login (failure) final userProfile = await authRepository.login( authRequest: authRequest, ); // Assert expect(userProfile, isNull); verify(() => mockAuthRemote.getUserInfo(phoneNumber)).called(1); verify(() => mockAuthRemote.login(authRequest: authRequest)).called(1); }); }); group('Logout Flow', () { test('should complete logout flow', () async { // Arrange when(() => mockAuthRemote.logout()).thenAnswer((_) async {}); // Act await authRepository.logout(); // Assert verify(() => mockAuthRemote.logout()).called(1); }); }); group('Authentication State Management', () { test('should track authentication state correctly', () async { // Arrange when( () => mockAuthRemote.hasAuthenticated(), ).thenAnswer((_) async => true); // Act final isAuthenticated = await authRepository.hasAuthenticated(); // Assert expect(isAuthenticated, isTrue); verify(() => mockAuthRemote.hasAuthenticated()).called(1); }); test('should handle authentication state changes', () async { // Arrange when( () => mockAuthRemote.hasAuthenticated(), ).thenAnswer((_) async => false); // Act final isAuthenticated = await authRepository.hasAuthenticated(); // Assert expect(isAuthenticated, isFalse); verify(() => mockAuthRemote.hasAuthenticated()).called(1); }); }); group('User Info Management', () { test('should get user info by phone', () async { // Arrange const phone = '09123456789'; final expectedUserInfo = UserInfoModel( isUser: true, address: 'Test Address', backend: 'test-backend', apiKey: 'test-api-key', ); when( () => mockAuthRemote.getUserInfo(phone), ).thenAnswer((_) async => expectedUserInfo); // Act final res = await authRepository.getUserInfo(phone); // Assert expect(res, expectedUserInfo); verify(() => mockAuthRemote.getUserInfo(phone)).called(1); }); }); }); }