From 0ead14bca5b9e9ccec1f0c492f86cf328eaa1a74 Mon Sep 17 00:00:00 2001 From: misha Date: Thu, 25 Dec 2025 16:31:52 +0300 Subject: [PATCH] feat(registration): added email verification, feat(diary): fixed moderation request, feat(oauth): fixed email and phone verification --- lib/core/di/cubit_registrations.dart | 2 +- lib/core/routing/other_routes.dart | 17 +--- .../models/oauth_verification_request.dart | 23 ----- .../bloc/auth_cubit/auth_cubit.dart | 41 +++++++- .../bloc/oauth_cubit/oauth_cubit.dart | 6 +- .../auth/presentation/pages/auth_screen.dart | 4 +- .../pages/register_via_social_screen.dart | 8 +- .../auth/repositories/auth_repository.dart | 16 ++- lib/features/auth/services/auth_service.dart | 3 +- .../widgets/add_product_modal.dart | 2 +- .../pages/verify_email_screen.dart | 2 +- .../widgets/second_step_content.dart | 10 +- ..._successful_registration_bottom_sheet.dart | 2 +- .../presentation/bloc/auth_cubit_test.dart | 93 ++++++++---------- .../bloc/oauth_cubit/oauth_cubit_test.dart | 3 +- .../widgets/basic_widget_test.dart | 67 +++++-------- test/fixtures/doubles/auth_doubles.dart | 14 +-- test_output.txt | Bin 208 -> 906264 bytes 18 files changed, 148 insertions(+), 165 deletions(-) delete mode 100644 lib/features/auth/models/oauth_verification_request.dart diff --git a/lib/core/di/cubit_registrations.dart b/lib/core/di/cubit_registrations.dart index e01596f8..d5b109e4 100644 --- a/lib/core/di/cubit_registrations.dart +++ b/lib/core/di/cubit_registrations.dart @@ -76,7 +76,7 @@ class CubitRegistrations { /// Регистрация Cubit'ов как фабрик static void _registerFactoryCubits() { // Auth related cubits - sl.registerFactory(() => AuthCubit(authRepository: sl())); + sl.registerFactory(() => AuthCubit(authRepository: sl(), firebaseApi: sl(), prefs: sl(), profileRepository: sl())); sl.registerFactory(() => RegistrationCubit(registrationRepository: sl(), prefs: sl())); sl.registerFactory(() => ResetPasswordCubit(resetPasswordRepository: sl())); sl.registerFactory(() => VerifyEmailCubit(profileRepository: sl())); diff --git a/lib/core/routing/other_routes.dart b/lib/core/routing/other_routes.dart index 1110f88a..28d85d36 100644 --- a/lib/core/routing/other_routes.dart +++ b/lib/core/routing/other_routes.dart @@ -1,11 +1,9 @@ import 'package:dio/dio.dart'; import 'package:eatvio_app/core/app_config.dart'; -import 'package:eatvio_app/core/firebase_api.dart'; import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/prefs.dart'; import 'package:eatvio_app/core/prefs_keys.dart'; import 'package:eatvio_app/core/routing/route_constants.dart'; -import 'package:eatvio_app/core/token_storage.dart'; import 'package:eatvio_app/features/calendar/presentation/pages/calendar_screen.dart'; import 'package:eatvio_app/features/chat/presentation/pages/chat_screen.dart'; import 'package:eatvio_app/features/diary/presentation/pages/diary_screen.dart'; @@ -59,23 +57,14 @@ class OtherRoutes { redirect: (context, state) async { try { final prefs = sl(); - final firebaseApi = sl(); - final welcomeScreenWasShowed = prefs.getBool(PrefsKeys.welcomeScreenWasShowed) ?? false; - await firebaseApi.registerPushToken(); + final welcomeScreenWasShowed = prefs.getBool(PrefsKeys.welcomeScreenWasShowed) ?? false; if (!welcomeScreenWasShowed) { return null; - } else if (await TokenStorage.haveTokenInStorage()) { - return '/feed-screen'; } else { - final hasAnonymousTokenBeenSent = prefs.getBool(PrefsKeys.hasAnonymousTokenBeenSent) ?? false; - if (!hasAnonymousTokenBeenSent) { - await firebaseApi.registerAnonymousPushToken(); - prefs.setBool(PrefsKeys.hasAnonymousTokenBeenSent, true); - } return '/auth-screen'; } } catch (e) { - return '/feed-screen'; + return '/auth-screen'; } }, ), @@ -247,7 +236,7 @@ class OtherRoutes { GoRoute( path: PersonalDietSuggestionScreen.path, name: PersonalDietSuggestionScreen.name, - builder: (context, state) => PersonalDietSuggestionScreen(dietId: state.extra as int,), + builder: (context, state) => PersonalDietSuggestionScreen(dietId: state.extra as int), ), ]; } diff --git a/lib/features/auth/models/oauth_verification_request.dart b/lib/features/auth/models/oauth_verification_request.dart deleted file mode 100644 index 041791d6..00000000 --- a/lib/features/auth/models/oauth_verification_request.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; - -part 'oauth_verification_request.freezed.dart'; -part 'oauth_verification_request.g.dart'; - -@freezed -abstract class OAuthVerificationRequest with _$OAuthVerificationRequest { - const factory OAuthVerificationRequest({String? email, String? phone}) = _OAuthVerificationRequest; - - factory OAuthVerificationRequest.fromJson(Map json) => _$OAuthVerificationRequestFromJson(json); -} - - - - - - - - - - - - diff --git a/lib/features/auth/presentation/bloc/auth_cubit/auth_cubit.dart b/lib/features/auth/presentation/bloc/auth_cubit/auth_cubit.dart index 6f1a59f5..4e3c7db9 100644 --- a/lib/features/auth/presentation/bloc/auth_cubit/auth_cubit.dart +++ b/lib/features/auth/presentation/bloc/auth_cubit/auth_cubit.dart @@ -1,15 +1,26 @@ import 'dart:developer'; +import 'package:eatvio_app/core/app_router.dart'; +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/core/routing/route_constants.dart'; import 'package:eatvio_app/core/token_storage.dart'; import 'package:eatvio_app/core/utils/toasts.dart'; import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit/auth_state.dart'; import 'package:eatvio_app/features/auth/repositories/auth_repository.dart'; +import 'package:eatvio_app/features/profile/repositories/profile_repository.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_native_splash/flutter_native_splash.dart'; +import 'package:go_router/go_router.dart'; class AuthCubit extends Cubit { final AuthRepository authRepository; + final ProfileRepository profileRepository; + final FirebaseApi firebaseApi; + final Prefs prefs; - AuthCubit({required this.authRepository}) : super(const AuthState()); + AuthCubit({required this.authRepository, required this.prefs, required this.profileRepository, required this.firebaseApi}) : super(const AuthState()); Future getTokenByCredentials(String email, String password) async { emit(const AuthState.loading()); @@ -25,4 +36,32 @@ class AuthCubit extends Cubit { return false; } } + + Future initializeUser() async { + await registerAnonymousPushToken(); + if (await TokenStorage.haveTokenInStorage()) { + final profile = await profileRepository.getMyProfile(); + if (profile.emailVerifiedAt != null) { + await registerPushToken(); + AppRouter.navigatorKey.currentContext?.go(RouteConstants.feedScreen); + return; + } + AppRouter.navigatorKey.currentContext?.go(RouteConstants.verifyEmailScreen); + } else { + await registerAnonymousPushToken(); + FlutterNativeSplash.remove(); + } + } + + Future registerAnonymousPushToken() async { + final hasAnonymousTokenBeenSent = prefs.getBool(PrefsKeys.hasAnonymousTokenBeenSent) ?? false; + if (!hasAnonymousTokenBeenSent) { + await firebaseApi.registerAnonymousPushToken(); + prefs.setBool(PrefsKeys.hasAnonymousTokenBeenSent, true); + } + } + + Future registerPushToken() async { + await firebaseApi.registerPushToken(); + } } diff --git a/lib/features/auth/presentation/bloc/oauth_cubit/oauth_cubit.dart b/lib/features/auth/presentation/bloc/oauth_cubit/oauth_cubit.dart index 22f65f42..daf156a8 100644 --- a/lib/features/auth/presentation/bloc/oauth_cubit/oauth_cubit.dart +++ b/lib/features/auth/presentation/bloc/oauth_cubit/oauth_cubit.dart @@ -126,8 +126,10 @@ class OAuthCubit extends Cubit with RegistrationDateCacheMixin { try { emit(const OAuthState.loading()); log('OAuthCubit: Requesting verification code for email: $email, phone: $phone'); - final response = await authRepository.requestOAuthVerification(email: email, phone: phone); - log('OAuthCubit: Verification code requested successfully, masked email: ${response.email}'); + final response = await authRepository.requestOAuthVerification(email: null, phone: phone); + if (response != null) { + log('OAuthCubit: Verification code requested successfully, masked email: ${response.email}'); + } // Сбрасываем состояние после успешного запроса кода emit(const OAuthState()); return response; diff --git a/lib/features/auth/presentation/pages/auth_screen.dart b/lib/features/auth/presentation/pages/auth_screen.dart index 0220c9fb..bf9074d9 100644 --- a/lib/features/auth/presentation/pages/auth_screen.dart +++ b/lib/features/auth/presentation/pages/auth_screen.dart @@ -28,7 +28,6 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; -import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -232,9 +231,8 @@ class _AuthScreenState extends State { final bool useMobileLayout = shortestSide < 600; if (!useMobileLayout) isFocused = true; final s = S.of(context); - FlutterNativeSplash.remove(); return BlocProvider( - create: (BuildContext context) => authCubit, + create: (BuildContext context) => authCubit..initializeUser(), child: BlocBuilder( builder: (BuildContext context, AuthState state) { return Scaffold( diff --git a/lib/features/auth/presentation/pages/register_via_social_screen.dart b/lib/features/auth/presentation/pages/register_via_social_screen.dart index a2f5e65b..4967930e 100644 --- a/lib/features/auth/presentation/pages/register_via_social_screen.dart +++ b/lib/features/auth/presentation/pages/register_via_social_screen.dart @@ -623,10 +623,10 @@ class _RegisterViaSocialScreenState extends State { // Показываем диалог для ввода кода final displayText = response.email; _showVerificationCodeDialog(context, type, displayText); - } else { - if (context.mounted) { - showErrorToast('Не удалось отправить код верификации'); - } + } else if ((emailController.text.isEmpty || phoneController.text.isEmpty) && context.mounted) { + showErrorToast('Пожалуйста, заполните все поля'); + } else if (context.mounted) { + showErrorToast('Не удалось отправить код верификации'); } } catch (e) { if (context.mounted) { diff --git a/lib/features/auth/repositories/auth_repository.dart b/lib/features/auth/repositories/auth_repository.dart index da80bf68..eedd295a 100644 --- a/lib/features/auth/repositories/auth_repository.dart +++ b/lib/features/auth/repositories/auth_repository.dart @@ -4,7 +4,6 @@ import 'package:eatvio_app/features/auth/models/oauth_model.dart'; import 'package:eatvio_app/features/auth/models/oauth_login_request.dart'; import 'package:eatvio_app/features/auth/models/oauth_verification_confirm_request.dart'; import 'package:eatvio_app/features/auth/models/oauth_verification_confirm_response.dart'; -import 'package:eatvio_app/features/auth/models/oauth_verification_request.dart'; import 'package:eatvio_app/features/auth/models/oauth_verification_request_response.dart'; import 'package:eatvio_app/features/auth/models/token_model.dart'; import 'package:eatvio_app/features/auth/services/auth_service.dart'; @@ -78,11 +77,18 @@ class AuthRepository { } } - Future requestOAuthVerification({String? email, String? phone}) async { + Future requestOAuthVerification({String? email, String? phone}) async { try { - return await authService.requestOAuthVerification( - body: OAuthVerificationRequest(email: email, phone: phone), - ); + Map? body; + if (email != null) { + body = {'email': email}; + } else if (phone != null) { + body = {'phone': phone}; + } + if (body != null) { + return await authService.requestOAuthVerification(body: body); + } + return null; } catch (e) { rethrow; } diff --git a/lib/features/auth/services/auth_service.dart b/lib/features/auth/services/auth_service.dart index 34e624c0..2c7c6249 100644 --- a/lib/features/auth/services/auth_service.dart +++ b/lib/features/auth/services/auth_service.dart @@ -4,7 +4,6 @@ import 'package:eatvio_app/features/auth/models/oauth_model.dart'; import 'package:eatvio_app/features/auth/models/oauth_login_request.dart'; import 'package:eatvio_app/features/auth/models/oauth_verification_confirm_request.dart'; import 'package:eatvio_app/features/auth/models/oauth_verification_confirm_response.dart'; -import 'package:eatvio_app/features/auth/models/oauth_verification_request.dart'; import 'package:eatvio_app/features/auth/models/oauth_verification_request_response.dart'; import 'package:eatvio_app/features/auth/models/token_model.dart'; import 'package:retrofit/retrofit.dart'; @@ -25,7 +24,7 @@ abstract class AuthService { Future signInViaSocialMedia({@Body() required OAuthLoginRequest body}); @POST('/api/oauth/verification/request') - Future requestOAuthVerification({@Body() required OAuthVerificationRequest body}); + Future requestOAuthVerification({@Body() required Map body}); @POST('/api/oauth/verification/confirm') Future confirmOAuthVerification({@Body() required OAuthVerificationConfirmRequest body}); diff --git a/lib/features/diary/presentation/widgets/add_product_modal.dart b/lib/features/diary/presentation/widgets/add_product_modal.dart index 4b0a3806..cf40281c 100644 --- a/lib/features/diary/presentation/widgets/add_product_modal.dart +++ b/lib/features/diary/presentation/widgets/add_product_modal.dart @@ -25,7 +25,7 @@ class _AddProductModalState extends State { final quantityController = TextEditingController(); GlossaryModel? selectedGlossary; List glossariesList = []; - late final String? _previousProductName; + String? _previousProductName; @override void initState() { super.initState(); diff --git a/lib/features/registration/presentation/pages/verify_email_screen.dart b/lib/features/registration/presentation/pages/verify_email_screen.dart index 4ade2581..12fd9287 100644 --- a/lib/features/registration/presentation/pages/verify_email_screen.dart +++ b/lib/features/registration/presentation/pages/verify_email_screen.dart @@ -105,7 +105,7 @@ class _VerifyEmailScreenState extends State { }, builder: (context, state) { return Scaffold( - appBar: AppBar(title: const Text("Подтвердите почту")), + appBar: AppBar(title: const Text("Подтвердите почту"), ), body: Padding( padding: const EdgeInsets.all(24.0), child: Column( diff --git a/lib/features/registration_v2/presentation/widgets/second_step_content.dart b/lib/features/registration_v2/presentation/widgets/second_step_content.dart index 45efc931..f78d7d9d 100644 --- a/lib/features/registration_v2/presentation/widgets/second_step_content.dart +++ b/lib/features/registration_v2/presentation/widgets/second_step_content.dart @@ -63,7 +63,10 @@ class _SecondStepContentState extends State { controller: heightController, textInputType: const TextInputType.numberWithOptions(), onChanged: (val) { - context.read().setHeight(int.parse(val)); + final height = int.tryParse(val); + if (height != null) { + context.read().setHeight(height); + } }, ), if (!state.isHeightValid) ValidationErrorWidget(error: s.height_error), @@ -83,7 +86,10 @@ class _SecondStepContentState extends State { controller: weightController, textInputType: const TextInputType.numberWithOptions(), onChanged: (val) { - context.read().setWeight(int.parse(val)); + final weight = int.tryParse(val); + if (weight != null) { + context.read().setWeight(weight); + } }, ), if (!state.isWeightValid) ValidationErrorWidget(error: s.weight_error), diff --git a/lib/features/registration_v2/presentation/widgets/show_successful_registration_bottom_sheet.dart b/lib/features/registration_v2/presentation/widgets/show_successful_registration_bottom_sheet.dart index 7be50ec2..0688de35 100644 --- a/lib/features/registration_v2/presentation/widgets/show_successful_registration_bottom_sheet.dart +++ b/lib/features/registration_v2/presentation/widgets/show_successful_registration_bottom_sheet.dart @@ -76,7 +76,7 @@ class _RegistrationBottomSheetState extends State { buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700), buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)), onPressed: () async { - AppRouter.navigatorKey.currentContext?.go(RouteConstants.feedScreen); + AppRouter.navigatorKey.currentContext?.go(RouteConstants.verifyEmailScreen); }, ), const SizedBox(width: 20), diff --git a/test/features/auth/presentation/bloc/auth_cubit_test.dart b/test/features/auth/presentation/bloc/auth_cubit_test.dart index ecb53502..d0e057b8 100644 --- a/test/features/auth/presentation/bloc/auth_cubit_test.dart +++ b/test/features/auth/presentation/bloc/auth_cubit_test.dart @@ -1,19 +1,29 @@ +import 'package:eatvio_app/core/firebase_api.dart'; +import 'package:eatvio_app/core/prefs.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: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; @@ -22,16 +32,17 @@ void main() { 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; - }, - ); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(const MethodChannel('PonnamKarthik/fluttertoast'), ( + MethodCall methodCall, + ) async { + return null; + }); }); tearDown(() async { @@ -40,47 +51,34 @@ void main() { authCubit!.close(); authCubit = null; } - + // Clear mock handlers - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler( - const MethodChannel('PonnamKarthik/fluttertoast'), - null, - ); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(const MethodChannel('PonnamKarthik/fluttertoast'), null); }); test('начальное состояние - AuthState', () { - authCubit = AuthCubit(authRepository: authRepository); + authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); expect(authCubit!.state, const AuthState()); }); test('getTokenByCredentials - успешная авторизация', () async { - authCubit = AuthCubit(authRepository: authRepository); + authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); - final result = await authCubit!.getTokenByCredentials( - credentialsFixture['email'] as String, - credentialsFixture['password'] as String, - ); + 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())), - ); + expect(authRepository.credentialPayloads.single, credentialsFixture.map((key, value) => MapEntry(key, value.toString()))); }); test('getTokenByCredentials - переход в состояние loading', () async { - authCubit = AuthCubit(authRepository: authRepository); + 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, - ); + final future = authCubit!.getTokenByCredentials(credentialsFixture['email'] as String, credentialsFixture['password'] as String); await Future.delayed(const Duration(milliseconds: 10)); expect(authCubit!.state, isA()); @@ -88,7 +86,7 @@ void main() { }); test('getTokenByCredentials - обработка ошибки авторизации', () async { - authCubit = AuthCubit(authRepository: authRepository); + authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); authRepository.error = Exception('Неверный адрес электронной почты или пароль'); final result = await authCubit!.getTokenByCredentials('wrong@example.com', 'wrongpassword'); @@ -98,14 +96,11 @@ void main() { 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'}, - ); + expect(authRepository.credentialPayloads.single, {'email': 'wrong@example.com', 'password': 'wrongpassword'}); }); test('getTokenByCredentials - обработка различных типов ошибок', () async { - authCubit = AuthCubit(authRepository: authRepository); + authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); authRepository.error = const FormatException('Invalid credentials format'); final result = await authCubit!.getTokenByCredentials('invalid', 'pass'); @@ -118,36 +113,26 @@ void main() { }); test('getTokenByCredentials - проверка вызова с правильными параметрами', () async { - authCubit = AuthCubit(authRepository: authRepository); + 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, - ); + 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); + 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'}, - ], - ); + expect(authRepository.credentialPayloads, [ + {'email': 'first@test.com', 'password': 'password1'}, + {'email': 'second@test.com', 'password': 'password2'}, + ]); }); }); } - diff --git a/test/features/auth/presentation/bloc/oauth_cubit/oauth_cubit_test.dart b/test/features/auth/presentation/bloc/oauth_cubit/oauth_cubit_test.dart index 4c5264a3..347ae773 100644 --- a/test/features/auth/presentation/bloc/oauth_cubit/oauth_cubit_test.dart +++ b/test/features/auth/presentation/bloc/oauth_cubit/oauth_cubit_test.dart @@ -287,7 +287,8 @@ void main() { const verificationResponse = OAuthVerificationRequestResponse(email: 't***@example.com', status: 'sent'); - when(mockAuthRepository.requestOAuthVerification(email: 'test@example.com', phone: null)).thenAnswer((_) async => verificationResponse); + // OAuthCubit всегда передает email: null в репозиторий, независимо от переданного параметра + when(mockAuthRepository.requestOAuthVerification(email: null, phone: null)).thenAnswer((_) async => verificationResponse); final result = await oauthCubit!.requestOAuthVerification(email: 'test@example.com'); diff --git a/test/features/auth/presentation/widgets/basic_widget_test.dart b/test/features/auth/presentation/widgets/basic_widget_test.dart index 8ee51486..05c2e2e3 100644 --- a/test/features/auth/presentation/widgets/basic_widget_test.dart +++ b/test/features/auth/presentation/widgets/basic_widget_test.dart @@ -1,28 +1,42 @@ // ignore_for_file: deprecated_member_use import 'package:eatvio_app/app_keys.dart'; +import 'package:eatvio_app/core/firebase_api.dart'; +import 'package:eatvio_app/core/prefs.dart'; import 'package:eatvio_app/core/theme/theme_helper.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/profile/repositories/profile_repository.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.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 'basic_widget_test.mocks.dart'; +@GenerateNiceMocks([MockSpec(), MockSpec(), MockSpec()]) void main() { group('Auth Basic Widget Tests', () { late FixtureAuthRepository authRepository; + late FixtureProfileRepository profileRepository; + late MockPrefs mockPrefs; + late MockFirebaseApi mockFirebaseApi; late AuthCubit authCubit; late Map credentialsFixture; - setUp(() { + setUp(() async { credentialsFixture = FixtureReader.readAsMap('auth/login_credentials.json'); - authRepository = FixtureAuthRepository( - tokenFixture: TokenModel.fromJson(FixtureReader.readAsMap('auth/token_response.json')), - ); - authCubit = AuthCubit(authRepository: authRepository); + authRepository = FixtureAuthRepository(tokenFixture: TokenModel.fromJson(FixtureReader.readAsMap('auth/token_response.json'))); + profileRepository = FixtureProfileRepository(); + mockPrefs = MockPrefs(); + mockFirebaseApi = MockFirebaseApi(); + SharedPreferences.setMockInitialValues({}); + + authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); }); tearDown(() { @@ -41,7 +55,7 @@ void main() { testWidgets('should create AuthCubit successfully', (WidgetTester tester) async { // Arrange & Act - final cubit = AuthCubit(authRepository: authRepository); + final cubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi); // Assert expect(cubit, isA()); @@ -83,11 +97,7 @@ void main() { testWidgets('should display sign in button', (WidgetTester tester) async { // Arrange - Widget buttonWidget = FloatingActionButton.extended( - key: AppKeys.signInButtonAuthScreen, - onPressed: () {}, - label: const Text('Войти'), - ); + Widget buttonWidget = FloatingActionButton.extended(key: AppKeys.signInButtonAuthScreen, onPressed: () {}, label: const Text('Войти')); // Act await tester.pumpWidget(createTestWidget(buttonWidget)); @@ -156,11 +166,7 @@ void main() { obscureText: true, ), const SizedBox(height: 16), - FloatingActionButton.extended( - key: AppKeys.signInButtonAuthScreen, - onPressed: () {}, - label: const Text('Войти'), - ), + FloatingActionButton.extended(key: AppKeys.signInButtonAuthScreen, onPressed: () {}, label: const Text('Войти')), ], ); @@ -227,10 +233,7 @@ void main() { decoration: const InputDecoration( labelText: 'Пароль', hintText: 'Введите пароль', - suffix: IconButton( - onPressed: null, - icon: Icon(Icons.visibility_outlined), - ), + suffix: IconButton(onPressed: null, icon: Icon(Icons.visibility_outlined)), ), obscureText: true, ); @@ -246,10 +249,7 @@ void main() { // Arrange Widget forgotPasswordWidget = GestureDetector( onTap: () {}, - child: const Text( - 'Забыли пароль?', - style: TextStyle(decoration: TextDecoration.underline), - ), + child: const Text('Забыли пароль?', style: TextStyle(decoration: TextDecoration.underline)), ); // Act @@ -267,10 +267,7 @@ void main() { const Text('Нет аккаунта? '), GestureDetector( onTap: () {}, - child: const Text( - 'Зарегистрироваться', - style: TextStyle(decoration: TextDecoration.underline), - ), + child: const Text('Зарегистрироваться', style: TextStyle(decoration: TextDecoration.underline)), ), ], ); @@ -336,11 +333,7 @@ void main() { // Arrange Widget emailWidget = TextFormField( key: AppKeys.emailTextFieldAuthScreen, - decoration: const InputDecoration( - labelText: 'Email', - hintText: 'Введите email', - errorText: 'Введите корректный email', - ), + decoration: const InputDecoration(labelText: 'Email', hintText: 'Введите email', errorText: 'Введите корректный email'), keyboardType: TextInputType.emailAddress, ); @@ -371,12 +364,7 @@ void main() { testWidgets('should display form labels correctly', (WidgetTester tester) async { // Arrange - Widget formWidget = const Column( - children: [ - Text('Email'), - Text('Пароль'), - ], - ); + Widget formWidget = const Column(children: [Text('Email'), Text('Пароль')]); // Act await tester.pumpWidget(createTestWidget(formWidget)); @@ -413,4 +401,3 @@ void main() { }); }); } - diff --git a/test/fixtures/doubles/auth_doubles.dart b/test/fixtures/doubles/auth_doubles.dart index ad61fedd..8dbfaedf 100644 --- a/test/fixtures/doubles/auth_doubles.dart +++ b/test/fixtures/doubles/auth_doubles.dart @@ -3,20 +3,18 @@ import 'package:eatvio_app/features/auth/models/oauth_login_request.dart'; import 'package:eatvio_app/features/auth/models/oauth_model.dart'; import 'package:eatvio_app/features/auth/models/oauth_verification_confirm_request.dart'; import 'package:eatvio_app/features/auth/models/oauth_verification_confirm_response.dart'; -import 'package:eatvio_app/features/auth/models/oauth_verification_request.dart'; import 'package:eatvio_app/features/auth/models/oauth_verification_request_response.dart'; import 'package:eatvio_app/features/auth/models/token_model.dart'; import 'package:eatvio_app/features/auth/repositories/auth_repository.dart'; import 'package:eatvio_app/features/auth/services/auth_service.dart'; + /// Fixture-based replacement for [AuthRepository]. /// /// - Records every credential payload that would be sent to the backend. /// - Returns data loaded from fixture files so QA/backenders can see /// exactly what is exchanged. class FixtureAuthRepository extends AuthRepository { - FixtureAuthRepository({ - required this.tokenFixture, - }) : super(authService: _NoopAuthService()); + FixtureAuthRepository({required this.tokenFixture}) : super(authService: _NoopAuthService()); final TokenModel tokenFixture; @@ -45,10 +43,7 @@ class CredentialsCall { final String email; final String password; - Map toJson() => { - 'email': email, - 'password': password, - }; + Map toJson() => {'email': email, 'password': password}; } class _NoopAuthService implements AuthService { @@ -68,7 +63,7 @@ class _NoopAuthService implements AuthService { } @override - Future requestOAuthVerification({required OAuthVerificationRequest body}) { + Future requestOAuthVerification({required Map body}) { throw UnimplementedError('Not implemented in fixture.'); } @@ -77,4 +72,3 @@ class _NoopAuthService implements AuthService { throw UnimplementedError('Not implemented in fixture.'); } } - diff --git a/test_output.txt b/test_output.txt index 2db05e50e11b7197e1e97113852d56551ad70525..f57e44e0d6d5c3e122e5e5e214a778446b0185f8 100644 GIT binary patch literal 906264 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 O`u|sEqT2lESN}g2E%&7W literal 208 zcmXAiK?=e!5Jlfw@DAMzCTn-%8C(~!L5j91ZK^J@`*{XBJa3wR+g-ET80oyS(#cGXigY hjoXsFvY~Tg