import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tm_app/core/utils/result.dart'; import 'package:tm_app/view_models/auth_view_model.dart'; import '../fixtures/test_fixtures.dart'; import '../mocks/mock_auth_repository.dart'; void main() { group('AuthViewModel OTP Verification', () { late MockAuthRepository mockRepository; late AuthViewModel authViewModel; late BuildContext mockContext; setUp(() { mockRepository = MockAuthRepository(); authViewModel = AuthViewModel(authRepository: mockRepository); mockContext = const TestWidget().createElement(); }); tearDown(() { authViewModel.dispose(); }); test('should verify OTP successfully', () async { mockRepository.setVerifyOtpResult( const Result.ok(TestFixtures.verifyOtpResponse), ); authViewModel.otpController.text = '123456'; authViewModel.emailController.text = 'test@example.com'; await authViewModel.verifyOtp(mockContext); expect(authViewModel.isLoadingOtp, false); expect(authViewModel.verifyOtpSuccess, true); expect(authViewModel.resetToken, 'reset_token_123'); expect( authViewModel.successMessageOtp, null, ); // Cleared after notify for toast expect(authViewModel.errorMessageOtp, null); // Cleared after notify }); test('should handle OTP verification error', () async { const errorMessage = 'Invalid OTP'; mockRepository.setVerifyOtpResult(Result.error(Exception(errorMessage))); authViewModel.otpController.text = '000000'; authViewModel.emailController.text = 'test@example.com'; await authViewModel.verifyOtp(mockContext); expect(authViewModel.isLoadingOtp, false); expect(authViewModel.verifyOtpSuccess, false); expect(authViewModel.errorMessageOtp, null); // Cleared after notify expect(authViewModel.successMessageOtp, null); // Cleared after notify }); test('should set loading state during OTP verification', () async { mockRepository.setVerifyOtpResult( const Result.ok(TestFixtures.verifyOtpResponse), ); authViewModel.otpController.text = '123456'; authViewModel.emailController.text = 'test@example.com'; final verifyOtpFuture = authViewModel.verifyOtp(mockContext); // Check loading state is set expect(authViewModel.isLoadingOtp, true); expect(authViewModel.errorMessageOtp, null); expect(authViewModel.verifyOtpSuccess, false); await verifyOtpFuture; expect(authViewModel.isLoadingOtp, false); }); test('should clear OTP flow', () { // Set some state first authViewModel.otpController.text = '123456'; authViewModel.resetToken = 'some_token'; authViewModel.clearOtpFlow(); expect(authViewModel.errorMessageOtp, null); expect(authViewModel.successMessageOtp, null); expect(authViewModel.isLoadingOtp, false); expect(authViewModel.verifyOtpSuccess, false); expect(authViewModel.otpController.text, isEmpty); expect(authViewModel.resetToken, 'some_token'); // Should not be cleared }); test('should reset verifyOtpSuccess before verification', () async { mockRepository.setVerifyOtpResult( const Result.ok(TestFixtures.verifyOtpResponse), ); // Set verifyOtpSuccess to true first authViewModel.otpController.text = '123456'; authViewModel.emailController.text = 'test@example.com'; await authViewModel.verifyOtp(mockContext); expect(authViewModel.verifyOtpSuccess, true); // Now test with error mockRepository.setVerifyOtpResult(Result.error(Exception('Invalid OTP'))); await authViewModel.verifyOtp(mockContext); expect(authViewModel.verifyOtpSuccess, false); }); }); } class TestWidget extends StatelessWidget { const TestWidget({super.key}); @override Widget build(BuildContext context) { return Container(); } }