import 'package:bloc_test/bloc_test.dart'; import 'package:fake_async/fake_async.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:formz/formz.dart'; import 'package:mocktail/mocktail.dart'; import 'package:social_app/features/auth/data/auth_repository.dart'; import 'package:social_app/features/auth/presentation/cubits/login_cubit.dart'; class MockAuthRepository extends Mock implements AuthRepository {} void main() { late LoginCubit cubit; late MockAuthRepository mockRepository; setUp(() { mockRepository = MockAuthRepository(); cubit = LoginCubit(mockRepository); }); tearDown(() { cubit.close(); }); group('LoginCubit', () { test('initial state has pure status', () { expect(cubit.state.status, FormzSubmissionStatus.initial); }); blocTest( 'phoneChanged updates phone', build: () => cubit, act: (c) => c.phoneChanged('+8613812345678'), expect: () => [isA()], ); blocTest( 'codeChanged updates code', build: () => cubit, act: (c) => c.codeChanged('123456'), expect: () => [isA()], ); test('sendCode success starts 60s cooldown', () { when(() => mockRepository.sendOtp(any())).thenAnswer((_) async {}); fakeAsync((async) { cubit.phoneChanged('13812345678'); cubit.sendCode(); async.flushMicrotasks(); expect(cubit.state.resendCooldownSeconds, 60); async.elapse(const Duration(seconds: 1)); expect(cubit.state.resendCooldownSeconds, 59); async.elapse(const Duration(seconds: 59)); expect(cubit.state.resendCooldownSeconds, 0); }); }); test('sendCode is blocked during cooldown', () async { when(() => mockRepository.sendOtp(any())).thenAnswer((_) async {}); cubit.phoneChanged('13812345678'); final first = await cubit.sendCode(); final second = await cubit.sendCode(); expect(first, isTrue); expect(second, isFalse); verify(() => mockRepository.sendOtp(any())).called(1); }); test('phone change resets cooldown and code state', () { when(() => mockRepository.sendOtp(any())).thenAnswer((_) async {}); fakeAsync((async) { cubit.phoneChanged('13812345678'); cubit.codeChanged('123456'); cubit.sendCode(); async.flushMicrotasks(); expect(cubit.state.resendCooldownSeconds, 60); expect(cubit.state.codeSent, isTrue); cubit.phoneChanged('14155552671'); expect(cubit.state.resendCooldownSeconds, 0); expect(cubit.state.codeSent, isFalse); expect(cubit.state.code.value, ''); }); }); }); }