From 175da2a8b71d38355541f8520a2a343a86a7823d Mon Sep 17 00:00:00 2001 From: qzl Date: Thu, 26 Feb 2026 10:35:46 +0800 Subject: [PATCH] feat(auth): add sendCodeSilently with isSending state --- .../presentation/cubits/register_cubit.dart | 32 +++++++++++++++ .../cubits/register_cubit_test.dart | 41 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/apps/lib/features/auth/presentation/cubits/register_cubit.dart b/apps/lib/features/auth/presentation/cubits/register_cubit.dart index 47188a7..d011a42 100644 --- a/apps/lib/features/auth/presentation/cubits/register_cubit.dart +++ b/apps/lib/features/auth/presentation/cubits/register_cubit.dart @@ -16,6 +16,7 @@ class RegisterState extends Equatable { final String? errorMessage; final String? pendingEmail; final bool codeSent; + final bool isSending; const RegisterState({ this.username = const Username.pure(), @@ -26,6 +27,7 @@ class RegisterState extends Equatable { this.errorMessage, this.pendingEmail, this.codeSent = false, + this.isSending = false, }); bool get isStep1Valid => @@ -41,6 +43,7 @@ class RegisterState extends Equatable { String? errorMessage, String? pendingEmail, bool? codeSent, + bool? isSending, }) { return RegisterState( username: username ?? this.username, @@ -51,6 +54,7 @@ class RegisterState extends Equatable { errorMessage: errorMessage, pendingEmail: pendingEmail ?? this.pendingEmail, codeSent: codeSent ?? this.codeSent, + isSending: isSending ?? this.isSending, ); } @@ -64,6 +68,7 @@ class RegisterState extends Equatable { errorMessage, pendingEmail, codeSent, + isSending, ]; } @@ -160,4 +165,31 @@ class RegisterCubit extends Cubit { emit(state.copyWith(errorMessage: message)); } } + + Future sendCodeSilently() async { + if (!state.isStep1Valid) return; + + emit(state.copyWith(isSending: true)); + + try { + final response = await _repository.signupStart( + SignupStartRequest( + username: state.username.value, + email: state.email.value, + password: state.password.value, + ), + ); + emit( + state.copyWith( + isSending: false, + pendingEmail: response.email, + codeSent: true, + errorMessage: null, + ), + ); + } catch (e) { + final message = e is ApiException ? e.message : '验证码发送失败,请重试'; + emit(state.copyWith(isSending: false, errorMessage: message)); + } + } } diff --git a/apps/test/features/auth/presentation/cubits/register_cubit_test.dart b/apps/test/features/auth/presentation/cubits/register_cubit_test.dart index a2bfc56..a87784c 100644 --- a/apps/test/features/auth/presentation/cubits/register_cubit_test.dart +++ b/apps/test/features/auth/presentation/cubits/register_cubit_test.dart @@ -2,7 +2,10 @@ import 'package:bloc_test/bloc_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:formz/formz.dart'; import 'package:mocktail/mocktail.dart'; +import 'package:social_app/core/form_inputs/form_inputs.dart'; import 'package:social_app/features/auth/data/auth_repository.dart'; +import 'package:social_app/features/auth/data/models/auth_response.dart'; +import 'package:social_app/features/auth/data/models/signup_request.dart'; import 'package:social_app/features/auth/presentation/cubits/register_cubit.dart'; class MockAuthRepository extends Mock implements AuthRepository {} @@ -14,6 +17,9 @@ void main() { setUp(() { mockRepository = MockAuthRepository(); cubit = RegisterCubit(mockRepository); + registerFallbackValue( + SignupStartRequest(username: '', email: '', password: ''), + ); }); tearDown(() { @@ -46,4 +52,39 @@ void main() { expect: () => [isA()], ); }); + + group('sendCodeSilently', () { + blocTest( + 'sets isSending to true then false on success', + build: () => cubit, + seed: () => RegisterState( + username: const Username.dirty('testuser'), + email: const Email.dirty('test@example.com'), + password: const Password.dirty('password123'), + ), + setUp: () { + when(() => mockRepository.signupStart(any())).thenAnswer( + (_) async => SignupStartResponse( + status: 'ok', + email: 'test@example.com', + message: 'Code sent', + ), + ); + }, + act: (c) => c.sendCodeSilently(), + expect: () => [ + predicate((state) => state.isSending == true), + predicate( + (state) => + state.isSending == false && + state.codeSent == true && + state.pendingEmail == 'test@example.com' && + state.errorMessage == null, + ), + ], + verify: (_) { + verify(() => mockRepository.signupStart(any())).called(1); + }, + ); + }); }