import 'package:eatvio_app/core/firebase_api.dart'; import 'package:eatvio_app/core/prefs.dart'; import 'package:eatvio_app/core/prefs_keys.dart'; import 'package:eatvio_app/features/auth/models/token_model.dart'; import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit/auth_cubit.dart'; import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit/auth_state.dart'; import 'package:eatvio_app/features/profile/repositories/profile_repository.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../../fixtures/doubles/auth_doubles.dart'; import '../../../../fixtures/doubles/profile_doubles.dart'; import '../../../../fixtures/fixture_reader.dart'; import 'auth_cubit_test.mocks.dart'; @GenerateNiceMocks([MockSpec(), MockSpec(), MockSpec()]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('AuthCubit', () { AuthCubit? authCubit; late FixtureAuthRepository authRepository; late FixtureProfileRepository profileRepository; late MockPrefs mockPrefs; late MockFirebaseApi mockFirebaseApi; late Map credentialsFixture; late TokenModel tokenFixture; setUp(() async { tokenFixture = TokenModel.fromJson(FixtureReader.readAsMap('auth/token_response.json')); credentialsFixture = FixtureReader.readAsMap('auth/login_credentials.json'); authRepository = FixtureAuthRepository(tokenFixture: tokenFixture); profileRepository = FixtureProfileRepository(); mockPrefs = MockPrefs(); mockFirebaseApi = MockFirebaseApi(); SharedPreferences.setMockInitialValues({}); // Mock Fluttertoast plugin TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(const MethodChannel('PonnamKarthik/fluttertoast'), ( MethodCall methodCall, ) async { return null; }); }); tearDown(() async { if (authCubit != null && !authCubit!.isClosed) { await Future.delayed(const Duration(milliseconds: 100)); authCubit!.close(); authCubit = null; } // Clear mock handlers TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(const MethodChannel('PonnamKarthik/fluttertoast'), null); }); test('начальное состояние - AuthState', () { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); expect(authCubit!.state, const AuthState()); }); test('getTokenByCredentials - успешная авторизация', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); final result = await authCubit!.getTokenByCredentials(credentialsFixture['email'] as String, credentialsFixture['password'] as String); expect(result, true); await Future.delayed(const Duration(milliseconds: 100)); expect(authCubit!.state, isA()); final loadedState = authCubit!.state as AuthStateLoaded; expect(loadedState.token, tokenFixture.token); expect(authRepository.credentialPayloads.single, credentialsFixture.map((key, value) => MapEntry(key, value.toString()))); }); test('getTokenByCredentials - переход в состояние loading', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); authRepository.responseDelay = const Duration(milliseconds: 50); final future = authCubit!.getTokenByCredentials(credentialsFixture['email'] as String, credentialsFixture['password'] as String); await Future.delayed(const Duration(milliseconds: 10)); expect(authCubit!.state, isA()); await future; }); test('getTokenByCredentials - обработка ошибки авторизации', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); authRepository.error = Exception('Неверный адрес электронной почты или пароль'); final result = await authCubit!.getTokenByCredentials('wrong@example.com', 'wrongpassword'); expect(result, false); await Future.delayed(const Duration(milliseconds: 100)); expect(authCubit!.state, isA()); final errorState = authCubit!.state as AuthStateError; expect(errorState.errorMessage, contains('Exception')); expect(authRepository.credentialPayloads.single, {'email': 'wrong@example.com', 'password': 'wrongpassword'}); }); test('getTokenByCredentials - обработка различных типов ошибок', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); authRepository.error = const FormatException('Invalid credentials format'); final result = await authCubit!.getTokenByCredentials('invalid', 'pass'); expect(result, false); await Future.delayed(const Duration(milliseconds: 100)); expect(authCubit!.state, isA()); final errorState = authCubit!.state as AuthStateError; expect(errorState.errorMessage, contains('FormatException')); }); test('getTokenByCredentials - проверка вызова с правильными параметрами', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); await authCubit!.getTokenByCredentials('user@test.com', 'securePassword123'); expect(authRepository.credentialPayloads.single, {'email': 'user@test.com', 'password': 'securePassword123'}); expect(authRepository.credentialPayloads.where((call) => call['email'] == 'other@test.com'), isEmpty); }); test('getTokenByCredentials - множественные вызовы', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); await authCubit!.getTokenByCredentials('first@test.com', 'password1'); await Future.delayed(const Duration(milliseconds: 100)); await authCubit!.getTokenByCredentials('second@test.com', 'password2'); expect(authRepository.credentialPayloads.length, 2); expect(authRepository.credentialPayloads, [ {'email': 'first@test.com', 'password': 'password1'}, {'email': 'second@test.com', 'password': 'password2'}, ]); }); test('registerAnonymousPushToken - регистрирует токен если не был отправлен', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); when(mockPrefs.getBool(PrefsKeys.hasAnonymousTokenBeenSent)).thenReturn(false); when(mockFirebaseApi.registerAnonymousPushToken()).thenAnswer((_) async => {}); when(mockPrefs.setBool(PrefsKeys.hasAnonymousTokenBeenSent, true)).thenAnswer((_) async => {}); await authCubit!.registerAnonymousPushToken(); verify(mockFirebaseApi.registerAnonymousPushToken()).called(1); verify(mockPrefs.setBool(PrefsKeys.hasAnonymousTokenBeenSent, true)).called(1); }); test('registerAnonymousPushToken - не регистрирует токен если уже был отправлен', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); when(mockPrefs.getBool(PrefsKeys.hasAnonymousTokenBeenSent)).thenReturn(true); await authCubit!.registerAnonymousPushToken(); verifyNever(mockFirebaseApi.registerAnonymousPushToken()); }); test('registerPushToken - регистрирует push токен', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); when(mockFirebaseApi.registerPushToken()).thenAnswer((_) async => {}); await authCubit!.registerPushToken(); verify(mockFirebaseApi.registerPushToken()).called(1); }); test('registerAnonymousPushToken - обрабатывает null значение hasAnonymousTokenBeenSent', () async { authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); when(mockPrefs.getBool(PrefsKeys.hasAnonymousTokenBeenSent)).thenReturn(null); when(mockFirebaseApi.registerAnonymousPushToken()).thenAnswer((_) async => {}); when(mockPrefs.setBool(PrefsKeys.hasAnonymousTokenBeenSent, true)).thenAnswer((_) async => {}); await authCubit!.registerAnonymousPushToken(); verify(mockFirebaseApi.registerAnonymousPushToken()).called(1); verify(mockPrefs.setBool(PrefsKeys.hasAnonymousTokenBeenSent, true)).called(1); }); }); }