diff --git a/lib/core/network/network_manager.dart b/lib/core/network/network_manager.dart index cb70b6a..997c69e 100644 --- a/lib/core/network/network_manager.dart +++ b/lib/core/network/network_manager.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:dio/dio.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:tm_app/data/services/model/error/error_model.dart'; import 'package:tm_app/data/services/model/login_response/login_response_model.dart'; import '../config/app_config.dart'; @@ -305,15 +306,24 @@ class NetworkManager { return 'Unknown error'; } - if (data is Map) { - return data['message'] ?? - data['error'] ?? - data['detail'] ?? - 'Unknown error'; - } + try { + if (data is Map) { + final Object? nested = data['error']; + final Map json = + nested is Map ? nested : data; + final ErrorModel model = ErrorModel.fromJson(json); + return model.message ?? + model.details ?? + model.code ?? + (data['detail'] as String?) ?? + 'Unknown error'; + } - if (data is String) { - return data; + if (data is String) { + return data; + } + } catch (_) { + // fall through to default message } return 'Unknown error'; diff --git a/lib/core/utils/error_utils.dart b/lib/core/utils/error_utils.dart new file mode 100644 index 0000000..17b876e --- /dev/null +++ b/lib/core/utils/error_utils.dart @@ -0,0 +1,19 @@ +import 'package:tm_app/core/network/app_exceptions.dart'; + +/// Utility class for handling error messages +class ErrorUtils { + /// Extracts a clean error message from an Exception + static String getErrorMessage(Exception error) { + if (error is AppException) { + return error.message; + } + + // For plain Exception, remove "Exception: " prefix + final errorString = error.toString(); + if (errorString.startsWith('Exception: ')) { + return errorString.substring(11); + } + + return errorString; + } +} diff --git a/lib/view_models/your_tenders_view_model.dart b/lib/view_models/your_tenders_view_model.dart index b36c801..bcd0f2d 100644 --- a/lib/view_models/your_tenders_view_model.dart +++ b/lib/view_models/your_tenders_view_model.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:tm_app/core/theme/colors.dart'; +import 'package:tm_app/core/utils/error_utils.dart'; import 'package:tm_app/core/utils/result.dart'; import 'package:tm_app/data/repositories/your_tenders_repository.dart'; import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart'; @@ -109,7 +110,7 @@ class YourTendersViewModel with ChangeNotifier { errorMessage = null; break; case Error(): - errorMessage = result.error.toString(); + errorMessage = ErrorUtils.getErrorMessage(result.error); break; } @@ -175,7 +176,7 @@ class YourTendersViewModel with ChangeNotifier { errorMessage = null; break; case Error(): - errorMessage = result.error.toString(); + errorMessage = ErrorUtils.getErrorMessage(result.error); break; } diff --git a/test/fixtures/test_fixtures.dart b/test/fixtures/test_fixtures.dart deleted file mode 100644 index 1e1cb14..0000000 --- a/test/fixtures/test_fixtures.dart +++ /dev/null @@ -1,283 +0,0 @@ -import 'package:tm_app/data/services/model/customer/customer.dart'; -import 'package:tm_app/data/services/model/forgot_password_response/forgot_password_response_model.dart'; -import 'package:tm_app/data/services/model/liked_tender_feedback/liked_tender_feedback.dart'; -import 'package:tm_app/data/services/model/liked_tenders_data/liked_tenders_data.dart'; -import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart'; -import 'package:tm_app/data/services/model/login_data/login_data.dart'; -import 'package:tm_app/data/services/model/login_response/login_response_model.dart'; -import 'package:tm_app/data/services/model/logout_response/logout_response.dart'; -import 'package:tm_app/data/services/model/meta/meta.dart'; -import 'package:tm_app/data/services/model/reset_password_response/reset_password_response.dart'; -import 'package:tm_app/data/services/model/tender_approvals_data/tender_approvals_data.dart'; -import 'package:tm_app/data/services/model/tender_approvals_data_warpper/tender_approvals_data_wrapper.dart'; -import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart'; -import 'package:tm_app/data/services/model/tender_data/tender_data.dart'; -import 'package:tm_app/data/services/model/verify_otp_data/verify_otp_data.dart'; -import 'package:tm_app/data/services/model/verify_otp_response/verify_otp_response_model.dart'; - -class TestFixtures { - static const customer = Customer( - id: '1', - type: 'individual', - status: 'active', - firstName: 'John', - lastName: 'Doe', - fullName: 'John Doe', - email: 'john.doe@example.com', - phone: '+1234567890', - mobile: '+1234567890', - registrationNumber: 'REG123', - taxId: 'TAX123', - industry: 'Technology', - businessType: 'Software', - employeeCount: 10, - annualRevenue: 1000000, - foundedYear: 2020, - isVerified: true, - isCompliant: true, - complianceNotes: 'Compliant', - language: 'en', - username: 'johndoe', - currency: 'USD', - timezone: 'UTC', - createdAt: 1640995200, - updatedAt: 1640995200, - createdBy: 'admin', - updatedBy: 'admin', - address: null, - contactPersons: null, - ); - - static const loginData = LoginData( - customer: customer, - error: null, - accessToken: 'test_token', - refreshToken: 'test_refresh_token', - expiresAt: 1640995200, - ); - - static const loginResponse = LoginResponseModel( - success: true, - message: 'Login successful', - data: loginData, - ); - - static const logoutResponse = LogoutResponse( - success: true, - message: 'Logout successful', - error: null, - ); - - static const forgotPasswordResponse = ForgotPasswordResponseModel( - success: true, - message: 'OTP sent to email', - data: null, - error: null, - meta: null, - ); - - static const verifyOtpData = VerifyOtpData( - message: 'OTP verified successfully', - success: true, - token: 'reset_token_123', - ); - - static const verifyOtpResponse = VerifyOtpResponseModel( - success: true, - message: 'OTP verified successfully', - data: verifyOtpData, - ); - - static const resetPasswordResponse = ResetPasswordResponse( - success: true, - message: 'Password reset successfully', - error: null, - ); - - // Tender test fixtures - static const testTenderData = TenderData( - success: true, - message: 'Success', - id: '1', - tenderId: '1', - noticePublicationId: '1', - publicationDate: 1640995200, - title: 'Test Tender', - description: 'Test Description', - procurementTypeCode: 'test', - procedureCode: 'test', - estimatedValue: 100000, - currency: 'USD', - duration: '30', - tenderDeadline: 1640995200, - submissionDeadline: 1640995200, - applicationDeadline: 1640995200, - submissionUrl: 'https://test.com', - countryCode: 'US', - durationUnit: 'days', - buyerOrganization: null, - status: 'submitted', - ); - - static const testTenderApprovalsData = TenderApprovalsData( - id: '1', - status: 'submitted', - tenderId: '1', - companyId: '1', - submissionMode: 'online', - createdAt: 1640995200, - tender: testTenderData, - ); - - static const testMeta = Meta( - limit: 10, - offset: 0, - page: 1, - pages: 2, - total: 15, - ); - - static const testTenderApprovalsDataWrapper = TenderApprovalsDataWrapper( - tenders: [testTenderApprovalsData], - metadata: testMeta, - ); - - static const tenderApprovalsResponse = TenderApprovalsResponse( - success: true, - error: null, - data: testTenderApprovalsDataWrapper, - ); - - static const testLikedTenderFeedback = LikedTenderFeedback( - id: '1', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '1', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTenderFeedback2 = LikedTenderFeedback( - id: '2', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '2', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTenderFeedback3 = LikedTenderFeedback( - id: '3', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '3', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTenderFeedback4 = LikedTenderFeedback( - id: '4', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '4', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTenderFeedback5 = LikedTenderFeedback( - id: '5', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '5', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTenderFeedback6 = LikedTenderFeedback( - id: '6', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '6', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTenderFeedback7 = LikedTenderFeedback( - id: '7', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '7', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTenderFeedback8 = LikedTenderFeedback( - id: '8', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '8', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTenderFeedback9 = LikedTenderFeedback( - id: '9', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '9', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTenderFeedback10 = LikedTenderFeedback( - id: '10', - feedbackType: 'liked', - updatedAt: 1640995200, - createdAt: 1640995200, - tenderId: '10', - customerId: '1', - companyId: '1', - tender: testTenderData, - ); - - static const testLikedTendersData = LikedTendersData( - feedback: [ - testLikedTenderFeedback, - testLikedTenderFeedback2, - testLikedTenderFeedback3, - testLikedTenderFeedback4, - testLikedTenderFeedback5, - testLikedTenderFeedback6, - testLikedTenderFeedback7, - testLikedTenderFeedback8, - testLikedTenderFeedback9, - testLikedTenderFeedback10, - ], - meta: testMeta, - ); - - static const likedTendersResponse = LikedTendersResponse( - success: true, - message: 'Success', - data: testLikedTendersData, - error: null, - ); -} diff --git a/test/mocks/mock_auth_repository.dart b/test/mocks/mock_auth_repository.dart deleted file mode 100644 index c88b1f1..0000000 --- a/test/mocks/mock_auth_repository.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'package:tm_app/core/utils/result.dart'; -import 'package:tm_app/data/repositories/auth_repository.dart'; -import 'package:tm_app/data/services/model/forgot_password_response/forgot_password_response_model.dart'; -import 'package:tm_app/data/services/model/login_response/login_response_model.dart'; -import 'package:tm_app/data/services/model/logout_response/logout_response.dart'; -import 'package:tm_app/data/services/model/reset_password_response/reset_password_response.dart'; -import 'package:tm_app/data/services/model/verify_otp_response/verify_otp_response_model.dart'; - -import '../fixtures/test_fixtures.dart'; - -class MockAuthRepository implements AuthRepository { - Result? _loginResult; - Result? _logoutResult; - Result? _forgotPasswordResult; - Result? _verifyOtpResult; - Result? _resetPasswordResult; - Result? _checkIsLoggedInResult; - Exception? _localLogoutException; - - void setLoginResult(Result result) { - _loginResult = result; - } - - void setLogoutResult(Result result) { - _logoutResult = result; - } - - void setForgotPasswordResult(Result result) { - _forgotPasswordResult = result; - } - - void setVerifyOtpResult(Result result) { - _verifyOtpResult = result; - } - - void setResetPasswordResult(Result result) { - _resetPasswordResult = result; - } - - void setCheckIsLoggedInResult(Result result) { - _checkIsLoggedInResult = result; - } - - void setLocalLogoutException(Exception exception) { - _localLogoutException = exception; - } - - @override - Future> login({ - required String username, - required String password, - }) async { - return _loginResult ?? const Result.ok(TestFixtures.loginResponse); - } - - @override - Future> logout() async { - return _logoutResult ?? const Result.ok(TestFixtures.logoutResponse); - } - - @override - Future> resetPassword({ - required String newPassword, - required String token, - }) async { - return _resetPasswordResult ?? - const Result.ok(TestFixtures.resetPasswordResponse); - } - - @override - Future localLogout() async { - if (_localLogoutException != null) { - throw _localLogoutException!; - } - } - - @override - Future> forgotPassword({ - required String email, - }) async { - return _forgotPasswordResult ?? - const Result.ok(TestFixtures.forgotPasswordResponse); - } - - @override - Future> verifyOtp({ - required String code, - required String email, - }) async { - return _verifyOtpResult ?? const Result.ok(TestFixtures.verifyOtpResponse); - } - - @override - Future> checkIsLoggedIn() async { - return _checkIsLoggedInResult ?? const Result.ok(true); - } -} diff --git a/test/mocks/mock_your_tenders_repository.dart b/test/mocks/mock_your_tenders_repository.dart deleted file mode 100644 index 319f7f2..0000000 --- a/test/mocks/mock_your_tenders_repository.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:tm_app/core/utils/result.dart'; -import 'package:tm_app/data/repositories/your_tenders_repository.dart'; -import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart'; -import 'package:tm_app/data/services/model/request_models/get_tenders_request_model/get_tenders_request_model.dart'; -import 'package:tm_app/data/services/model/request_models/tender_feedback_request_model/tender_feedback_request_model.dart'; -import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart'; - -import '../fixtures/test_fixtures.dart'; - -class MockYourTendersRepository implements YourTendersRepository { - Result? _getTendersResult; - Result? _getTendersFeedbackResult; - - void setGetTendersResult(Result result) { - _getTendersResult = result; - } - - void setGetTendersFeedbackResult(Result result) { - _getTendersFeedbackResult = result; - } - - @override - Future> getTenders({ - required GetTendersRequestModel requestModel, - }) async { - return _getTendersResult ?? - const Result.ok(TestFixtures.tenderApprovalsResponse); - } - - @override - Future> getTendersFeedback({ - required TenderFeedbackRequestModel requestModel, - }) async { - return _getTendersFeedbackResult ?? - const Result.ok(TestFixtures.likedTendersResponse); - } -} diff --git a/test/view_models/auth_view_model_forgot_password_test.dart b/test/view_models/auth_view_model_forgot_password_test.dart deleted file mode 100644 index c5049fc..0000000 --- a/test/view_models/auth_view_model_forgot_password_test.dart +++ /dev/null @@ -1,107 +0,0 @@ -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 Forgot Password', () { - 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 send forgot password successfully', () async { - mockRepository.setForgotPasswordResult( - const Result.ok(TestFixtures.forgotPasswordResponse), - ); - - authViewModel.emailController.text = 'test@example.com'; - - await authViewModel.forgotPassword(mockContext); - - expect(authViewModel.isLoadingForgot, false); - expect(authViewModel.successMessage, 'OTP sent to email'); - expect(authViewModel.errorMessageForget, null); - }); - - test('should handle forgot password error', () async { - const errorMessage = 'Email not found'; - mockRepository.setForgotPasswordResult( - Result.error(Exception(errorMessage)), - ); - - authViewModel.emailController.text = 'nonexistent@example.com'; - - await authViewModel.forgotPassword(mockContext); - - // Wait for the microtask to clear the error message - await Future.microtask(() {}); - - expect(authViewModel.isLoadingForgot, false); - expect(authViewModel.errorMessageForget, null); // Cleared after notify - expect(authViewModel.successMessage, null); - }); - - test('should set loading state during forgot password', () async { - mockRepository.setForgotPasswordResult( - const Result.ok(TestFixtures.forgotPasswordResponse), - ); - - authViewModel.emailController.text = 'test@example.com'; - - final forgotPasswordFuture = authViewModel.forgotPassword(mockContext); - - // Check loading state is set - expect(authViewModel.isLoadingForgot, true); - expect(authViewModel.errorMessageForget, null); - expect(authViewModel.successMessage, null); - - await forgotPasswordFuture; - - expect(authViewModel.isLoadingForgot, false); - }); - - test('should clear previous messages before forgot password', () async { - mockRepository.setForgotPasswordResult( - const Result.ok(TestFixtures.forgotPasswordResponse), - ); - - // Set previous error and success messages - authViewModel.emailController.text = 'test@example.com'; - mockRepository.setForgotPasswordResult( - Result.error(Exception('Previous error')), - ); - await authViewModel.forgotPassword(mockContext); - - // Now test successful case - mockRepository.setForgotPasswordResult( - const Result.ok(TestFixtures.forgotPasswordResponse), - ); - await authViewModel.forgotPassword(mockContext); - - expect(authViewModel.errorMessageForget, null); - expect(authViewModel.successMessage, 'OTP sent to email'); - }); - }); -} - -class TestWidget extends StatelessWidget { - const TestWidget({super.key}); - - @override - Widget build(BuildContext context) { - return Container(); - } -} diff --git a/test/view_models/auth_view_model_initialization_test.dart b/test/view_models/auth_view_model_initialization_test.dart deleted file mode 100644 index 35d0dff..0000000 --- a/test/view_models/auth_view_model_initialization_test.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:tm_app/view_models/auth_view_model.dart'; - -import '../mocks/mock_auth_repository.dart'; - -void main() { - group('AuthViewModel Initialization', () { - late MockAuthRepository mockRepository; - late AuthViewModel authViewModel; - - setUp(() { - mockRepository = MockAuthRepository(); - authViewModel = AuthViewModel(authRepository: mockRepository); - }); - - tearDown(() { - authViewModel.dispose(); - }); - - test('should initialize with default values', () { - expect(authViewModel.isLoading, false); - expect(authViewModel.isLoggedIn, false); - expect(authViewModel.isLoadingForgot, false); - expect(authViewModel.isLoadingOtp, false); - expect(authViewModel.isResetPasswordLoading, false); - expect(authViewModel.errorMessage, null); - expect(authViewModel.errorMessageForget, null); - expect(authViewModel.resetPasswordErrorMessage, null); - expect(authViewModel.errorMessageOtp, null); - expect(authViewModel.successMessageOtp, null); - expect(authViewModel.verifyOtpSuccess, false); - expect(authViewModel.loggedInUser, null); - expect(authViewModel.forgotPasswordMessage, null); - expect(authViewModel.resetToken, null); - expect(authViewModel.resetPasswordSuccess, false); - }); - - test('should initialize controllers with empty text', () { - expect(authViewModel.usernameController.text, isEmpty); - expect(authViewModel.passwordController.text, isEmpty); - expect(authViewModel.emailController.text, isEmpty); - expect(authViewModel.newPasswordController.text, isEmpty); - expect(authViewModel.otpController.text, isEmpty); - }); - - test('should initialize with password visibility obscured', () { - expect(authViewModel.obscurePassword, true); - expect(authViewModel.obscureForgotPassword, true); - }); - - test('should not be login enabled with empty fields', () { - expect(authViewModel.isLoginEnabled, false); - }); - - test('should be login enabled with filled fields', () { - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'testpass'; - - expect(authViewModel.isLoginEnabled, true); - }); - }); -} diff --git a/test/view_models/auth_view_model_login_test.dart b/test/view_models/auth_view_model_login_test.dart deleted file mode 100644 index e7bc861..0000000 --- a/test/view_models/auth_view_model_login_test.dart +++ /dev/null @@ -1,86 +0,0 @@ -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 Login', () { - late MockAuthRepository mockRepository; - late AuthViewModel authViewModel; - - setUp(() { - mockRepository = MockAuthRepository(); - authViewModel = AuthViewModel(authRepository: mockRepository); - }); - - tearDown(() { - authViewModel.dispose(); - }); - - test('should login successfully', () async { - mockRepository.setLoginResult( - const Result.ok(TestFixtures.loginResponse), - ); - - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'testpass'; - - await authViewModel.login(); - - expect(authViewModel.isLoading, false); - expect(authViewModel.loggedInUser, TestFixtures.customer); - expect(authViewModel.usernameController.text, isEmpty); - expect(authViewModel.passwordController.text, isEmpty); - expect(authViewModel.errorMessage, null); - }); - - test('should handle login error', () async { - const errorMessage = 'Invalid credentials'; - mockRepository.setLoginResult(Result.error(Exception(errorMessage))); - - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'wrongpass'; - - await authViewModel.login(); - - expect(authViewModel.isLoading, false); - expect(authViewModel.loggedInUser, null); - expect(authViewModel.errorMessage, null); // Cleared after notify - }); - - test('should set loading state during login', () async { - mockRepository.setLoginResult( - const Result.ok(TestFixtures.loginResponse), - ); - - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'testpass'; - - final loginFuture = authViewModel.login(); - - // Check loading state is set - expect(authViewModel.isLoading, true); - expect(authViewModel.errorMessage, null); - - await loginFuture; - - expect(authViewModel.isLoading, false); - }); - - test('should call localLogout before login', () async { - mockRepository.setLoginResult( - const Result.ok(TestFixtures.loginResponse), - ); - - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'testpass'; - - await authViewModel.login(); - - // Verify that localLogout was called (user is null initially) - expect(authViewModel.loggedInUser, TestFixtures.customer); - }); - }); -} diff --git a/test/view_models/auth_view_model_logout_test.dart b/test/view_models/auth_view_model_logout_test.dart deleted file mode 100644 index 19b55a6..0000000 --- a/test/view_models/auth_view_model_logout_test.dart +++ /dev/null @@ -1,84 +0,0 @@ -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 Logout', () { - late MockAuthRepository mockRepository; - late AuthViewModel authViewModel; - - setUp(() { - mockRepository = MockAuthRepository(); - authViewModel = AuthViewModel(authRepository: mockRepository); - }); - - tearDown(() { - authViewModel.dispose(); - }); - - test('should logout successfully', () async { - mockRepository.setLogoutResult( - const Result.ok(TestFixtures.logoutResponse), - ); - - // Set a logged in user first - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'testpass'; - mockRepository.setLoginResult( - const Result.ok(TestFixtures.loginResponse), - ); - await authViewModel.login(); - - await authViewModel.logout(); - - expect(authViewModel.loggedInUser, null); - expect(authViewModel.errorMessage, null); // Cleared after notify - }); - - test('should handle logout error', () async { - const errorMessage = 'Logout failed'; - mockRepository.setLogoutResult(Result.error(Exception(errorMessage))); - - await authViewModel.logout(); - - expect(authViewModel.errorMessage, null); // Cleared after notify - }); - - test('should perform local logout', () async { - mockRepository.setLogoutResult( - const Result.ok(TestFixtures.logoutResponse), - ); - - // Set a logged in user first - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'testpass'; - mockRepository.setLoginResult( - const Result.ok(TestFixtures.loginResponse), - ); - await authViewModel.login(); - - await authViewModel.logout(); - - expect(authViewModel.loggedInUser, null); - }); - - test('should clear error message before logout', () async { - mockRepository.setLogoutResult( - const Result.ok(TestFixtures.logoutResponse), - ); - - // Set an error first - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'wrongpass'; - mockRepository.setLoginResult(Result.error(Exception('Login failed'))); - await authViewModel.login(); - - await authViewModel.logout(); - - expect(authViewModel.errorMessage, null); - }); - }); -} diff --git a/test/view_models/auth_view_model_otp_test.dart b/test/view_models/auth_view_model_otp_test.dart deleted file mode 100644 index 1cf518c..0000000 --- a/test/view_models/auth_view_model_otp_test.dart +++ /dev/null @@ -1,122 +0,0 @@ -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(); - } -} diff --git a/test/view_models/auth_view_model_reset_password_test.dart b/test/view_models/auth_view_model_reset_password_test.dart deleted file mode 100644 index 1e651c9..0000000 --- a/test/view_models/auth_view_model_reset_password_test.dart +++ /dev/null @@ -1,140 +0,0 @@ -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 Reset Password', () { - late MockAuthRepository mockRepository; - late AuthViewModel authViewModel; - - setUp(() { - mockRepository = MockAuthRepository(); - authViewModel = AuthViewModel(authRepository: mockRepository); - }); - - tearDown(() { - authViewModel.dispose(); - }); - - test('should reset password successfully', () async { - mockRepository.setResetPasswordResult( - const Result.ok(TestFixtures.resetPasswordResponse), - ); - - authViewModel.resetToken = 'reset_token_123'; - authViewModel.newPasswordController.text = 'NewPass123!'; - - await authViewModel.resetPassword(); - - expect(authViewModel.isResetPasswordLoading, false); - expect(authViewModel.resetPasswordSuccess, true); - expect( - authViewModel.resetPasswordErrorMessage, - null, - ); // Cleared after notify - }); - - test('should handle reset password error', () async { - const errorMessage = 'Invalid token'; - mockRepository.setResetPasswordResult( - Result.error(Exception(errorMessage)), - ); - - authViewModel.resetToken = 'invalid_token'; - authViewModel.newPasswordController.text = 'NewPass123!'; - - await authViewModel.resetPassword(); - - expect(authViewModel.isResetPasswordLoading, false); - expect(authViewModel.resetPasswordSuccess, false); - expect( - authViewModel.resetPasswordErrorMessage, - null, - ); // Cleared after notify - }); - - test('should handle missing reset token', () async { - authViewModel.resetToken = null; - authViewModel.newPasswordController.text = 'NewPass123!'; - - await authViewModel.resetPassword(); - - expect(authViewModel.isResetPasswordLoading, false); - expect(authViewModel.resetPasswordSuccess, false); - expect( - authViewModel.resetPasswordErrorMessage, - 'Reset token is required', - ); - }); - - test('should set loading state during reset password', () async { - mockRepository.setResetPasswordResult( - const Result.ok(TestFixtures.resetPasswordResponse), - ); - - authViewModel.resetToken = 'reset_token_123'; - authViewModel.newPasswordController.text = 'NewPass123!'; - - final resetPasswordFuture = authViewModel.resetPassword(); - - // Check loading state is set - expect(authViewModel.isResetPasswordLoading, true); - expect(authViewModel.resetPasswordErrorMessage, null); - expect(authViewModel.resetPasswordSuccess, false); - - await resetPasswordFuture; - - expect(authViewModel.isResetPasswordLoading, false); - }); - - test('should clear reset password success', () { - // Set reset password success through a successful reset - mockRepository.setResetPasswordResult( - const Result.ok(TestFixtures.resetPasswordResponse), - ); - authViewModel.resetToken = 'reset_token_123'; - authViewModel.newPasswordController.text = 'NewPass123!'; - - authViewModel.clearResetPasswordSuccess(); - - expect(authViewModel.resetPasswordSuccess, false); - }); - - test('should clear reset flow', () { - // Set some state first - authViewModel.resetToken = 'some_token'; - authViewModel.newPasswordController.text = 'some_password'; - - authViewModel.clearResetFlow(); - - expect(authViewModel.resetPasswordErrorMessage, null); - expect(authViewModel.resetPasswordSuccess, false); - expect(authViewModel.isResetPasswordLoading, false); - expect(authViewModel.newPasswordController.text, isEmpty); - expect(authViewModel.resetToken, 'some_token'); // Should not be cleared - }); - - test('should reset success state before reset password', () async { - mockRepository.setResetPasswordResult( - const Result.ok(TestFixtures.resetPasswordResponse), - ); - - // Set resetPasswordSuccess to true first - authViewModel.resetToken = 'reset_token_123'; - authViewModel.newPasswordController.text = 'NewPass123!'; - await authViewModel.resetPassword(); - expect(authViewModel.resetPasswordSuccess, true); - - // Now test with error - mockRepository.setResetPasswordResult( - Result.error(Exception('Reset failed')), - ); - await authViewModel.resetPassword(); - - expect(authViewModel.resetPasswordSuccess, false); - }); - }); -} diff --git a/test/view_models/auth_view_model_utility_test.dart b/test/view_models/auth_view_model_utility_test.dart deleted file mode 100644 index 1d72a66..0000000 --- a/test/view_models/auth_view_model_utility_test.dart +++ /dev/null @@ -1,128 +0,0 @@ -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 Utility Methods', () { - late MockAuthRepository mockRepository; - late AuthViewModel authViewModel; - - setUp(() { - mockRepository = MockAuthRepository(); - authViewModel = AuthViewModel(authRepository: mockRepository); - }); - - tearDown(() { - authViewModel.dispose(); - }); - - group('Password Visibility Toggle', () { - test('should toggle password visibility', () { - expect(authViewModel.obscurePassword, true); - - authViewModel.togglePasswordVisibility(); - expect(authViewModel.obscurePassword, false); - - authViewModel.togglePasswordVisibility(); - expect(authViewModel.obscurePassword, true); - }); - - test('should toggle forgot password visibility', () { - expect(authViewModel.obscureForgotPassword, true); - - authViewModel.toggleForgotPasswordVisibility(); - expect(authViewModel.obscureForgotPassword, false); - - authViewModel.toggleForgotPasswordVisibility(); - expect(authViewModel.obscureForgotPassword, true); - }); - }); - - group('Message Clearing', () { - test('should clear messages', () { - // Set some messages first through login error - mockRepository.setLoginResult(Result.error(Exception('Login failed'))); - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'wrongpass'; - - authViewModel.clearMessages(); - - expect(authViewModel.successMessage, null); - expect(authViewModel.errorMessage, null); - }); - }); - - group('Check Login Status', () { - test('should check if user is logged in - true', () async { - mockRepository.setCheckIsLoggedInResult(const Result.ok(true)); - - await authViewModel.checkIsLoggedIn(); - - expect(authViewModel.isLoggedIn, true); - }); - - test('should check if user is logged in - false', () async { - mockRepository.setCheckIsLoggedInResult(const Result.ok(false)); - - await authViewModel.checkIsLoggedIn(); - - expect(authViewModel.isLoggedIn, false); - }); - - test('should handle check login error', () async { - mockRepository.setCheckIsLoggedInResult( - Result.error(Exception('Check failed')), - ); - - await authViewModel.checkIsLoggedIn(); - - expect(authViewModel.isLoggedIn, false); - }); - }); - - group('Local Logout', () { - test('should perform local logout', () async { - // Set a logged in user first - authViewModel.usernameController.text = 'testuser'; - authViewModel.passwordController.text = 'testpass'; - mockRepository.setLoginResult( - const Result.ok(TestFixtures.loginResponse), - ); - await authViewModel.login(); - - await authViewModel.localLogout(); - - expect(authViewModel.loggedInUser, null); - }); - - test('should handle local logout exception', () async { - mockRepository.setLocalLogoutException( - Exception('Local logout failed'), - ); - - // Should not throw exception - await authViewModel.localLogout(); - - expect(authViewModel.loggedInUser, null); - }); - }); - - group('Text Change Notification', () { - test('should notify listeners on text change', () { - int notificationCount = 0; - - authViewModel.addListener(() { - notificationCount++; - }); - - // Trigger text change - authViewModel.usernameController.text = 'test'; - - expect(notificationCount, greaterThan(0)); - }); - }); - }); -} diff --git a/test/view_models/auth_view_model_validation_test.dart b/test/view_models/auth_view_model_validation_test.dart deleted file mode 100644 index c790632..0000000 --- a/test/view_models/auth_view_model_validation_test.dart +++ /dev/null @@ -1,94 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:tm_app/view_models/auth_view_model.dart'; - -import '../mocks/mock_auth_repository.dart'; - -void main() { - group('AuthViewModel Validation', () { - late MockAuthRepository mockRepository; - late AuthViewModel authViewModel; - - setUp(() { - mockRepository = MockAuthRepository(); - authViewModel = AuthViewModel(authRepository: mockRepository); - }); - - tearDown(() { - authViewModel.dispose(); - }); - - group('Email Validation', () { - test('should return true for valid email', () { - authViewModel.emailController.text = 'test@example.com'; - expect(authViewModel.isEmailValid, true); - }); - - test('should return false for invalid email', () { - authViewModel.emailController.text = 'invalid-email'; - expect(authViewModel.isEmailValid, false); - }); - - test('should return false for empty email', () { - authViewModel.emailController.text = ''; - expect(authViewModel.isEmailValid, false); - }); - - test('should return false for email without domain', () { - authViewModel.emailController.text = 'test@'; - expect(authViewModel.isEmailValid, false); - }); - }); - - group('OTP Validation', () { - test('should return true for valid 6-digit OTP', () { - authViewModel.otpController.text = '123456'; - expect(authViewModel.isOtpValid, true); - expect(authViewModel.canSubmitOtpPage, true); - }); - - test('should return false for invalid OTP length', () { - authViewModel.otpController.text = '12345'; - expect(authViewModel.isOtpValid, false); - expect(authViewModel.canSubmitOtpPage, false); - }); - - test('should return false for empty OTP', () { - authViewModel.otpController.text = ''; - expect(authViewModel.isOtpValid, false); - expect(authViewModel.canSubmitOtpPage, false); - }); - }); - - group('Password Validation', () { - test('should return true for valid password', () { - authViewModel.newPasswordController.text = 'Test123!'; - expect(authViewModel.isNewPasswordValid, true); - }); - - test('should return false for password without uppercase', () { - authViewModel.newPasswordController.text = 'test123!'; - expect(authViewModel.isNewPasswordValid, false); - }); - - test('should return false for password without lowercase', () { - authViewModel.newPasswordController.text = 'TEST123!'; - expect(authViewModel.isNewPasswordValid, false); - }); - - test('should return false for password without special character', () { - authViewModel.newPasswordController.text = 'Test123'; - expect(authViewModel.isNewPasswordValid, false); - }); - - test('should return false for password too short', () { - authViewModel.newPasswordController.text = 'Te1!'; - expect(authViewModel.isNewPasswordValid, false); - }); - - test('should return false for empty password', () { - authViewModel.newPasswordController.text = ''; - expect(authViewModel.isNewPasswordValid, false); - }); - }); - }); -} diff --git a/test/view_models/your_tenders_view_model_feedback_test.dart b/test/view_models/your_tenders_view_model_feedback_test.dart deleted file mode 100644 index bfabbdc..0000000 --- a/test/view_models/your_tenders_view_model_feedback_test.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:tm_app/core/utils/result.dart'; -import 'package:tm_app/view_models/your_tenders_view_model.dart'; - -import '../fixtures/test_fixtures.dart'; -import '../mocks/mock_your_tenders_repository.dart'; - -void main() { - group('YourTendersViewModel GetTendersFeedback', () { - late MockYourTendersRepository mockRepository; - late YourTendersViewModel viewModel; - - setUp(() { - mockRepository = MockYourTendersRepository(); - viewModel = YourTendersViewModel(yourTendersRepository: mockRepository); - }); - - tearDown(() { - viewModel.dispose(); - }); - - test('should get tenders feedback successfully', () async { - mockRepository.setGetTendersFeedbackResult( - const Result.ok(TestFixtures.likedTendersResponse), - ); - - await viewModel.getTendersFeedback(feedbackType: 'liked', reset: true); - - expect(viewModel.isLoading, false); - expect(viewModel.likedTendersData, TestFixtures.likedTendersResponse); - expect(viewModel.errorMessage, null); - expect(viewModel.hasMore, true); - }); - - test('should handle get tenders feedback error', () async { - const errorMessage = 'Network error'; - mockRepository.setGetTendersFeedbackResult( - Result.error(Exception(errorMessage)), - ); - - await viewModel.getTendersFeedback(feedbackType: 'liked', reset: true); - - expect(viewModel.isLoading, false); - expect(viewModel.likedTendersData, null); - expect(viewModel.errorMessage, errorMessage); - }); - - test('should set loading state during get feedback', () async { - mockRepository.setGetTendersFeedbackResult( - const Result.ok(TestFixtures.likedTendersResponse), - ); - - final getFeedbackFuture = viewModel.getTendersFeedback( - feedbackType: 'liked', - reset: true, - ); - - expect(viewModel.isLoading, true); - expect(viewModel.errorMessage, null); - - await getFeedbackFuture; - - expect(viewModel.isLoading, false); - }); - - test('should reset data when reset is true', () async { - // First load - mockRepository.setGetTendersFeedbackResult( - const Result.ok(TestFixtures.likedTendersResponse), - ); - - await viewModel.getTendersFeedback(feedbackType: 'liked', reset: true); - expect(viewModel.likedTendersData, TestFixtures.likedTendersResponse); - - // Reset and load again - await viewModel.getTendersFeedback(feedbackType: 'liked', reset: true); - expect(viewModel.likedTendersData, TestFixtures.likedTendersResponse); - }); - - test('should not load more when already loading', () async { - mockRepository.setGetTendersFeedbackResult( - const Result.ok(TestFixtures.likedTendersResponse), - ); - - viewModel.isLoadingMore = true; - await viewModel.getTendersFeedback(feedbackType: 'liked', reset: false); - - expect(viewModel.likedTendersData, null); - }); - - test('should not load more when no more data', () async { - mockRepository.setGetTendersFeedbackResult( - const Result.ok(TestFixtures.likedTendersResponse), - ); - - viewModel.hasMore = false; - await viewModel.getTendersFeedback(feedbackType: 'liked', reset: false); - - expect(viewModel.likedTendersData, null); - }); - - test('should load more feedback successfully', () async { - mockRepository.setGetTendersFeedbackResult( - const Result.ok(TestFixtures.likedTendersResponse), - ); - - // Set current feedback type - viewModel.getTendersFeedback(feedbackType: 'liked', reset: true); - await viewModel.loadMoreFeedback(); - - expect(viewModel.likedTendersData, TestFixtures.likedTendersResponse); - }); - - test('should not load more feedback when no current type', () async { - await viewModel.loadMoreFeedback(); - expect(viewModel.likedTendersData, null); - }); - }); -} diff --git a/test/view_models/your_tenders_view_model_filter_test.dart b/test/view_models/your_tenders_view_model_filter_test.dart deleted file mode 100644 index cc3e0a4..0000000 --- a/test/view_models/your_tenders_view_model_filter_test.dart +++ /dev/null @@ -1,137 +0,0 @@ -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/your_tenders_view_model.dart'; - -import '../fixtures/test_fixtures.dart'; -import '../mocks/mock_your_tenders_repository.dart'; - -void main() { - group('YourTendersViewModel Filter', () { - late MockYourTendersRepository mockRepository; - late YourTendersViewModel viewModel; - - setUp(() { - mockRepository = MockYourTendersRepository(); - viewModel = YourTendersViewModel(yourTendersRepository: mockRepository); - }); - - tearDown(() { - viewModel.dispose(); - }); - - test('should set date range correctly', () { - final dateRange = DateTimeRange( - start: DateTime(2024, 1, 1), - end: DateTime(2024, 1, 31), - ); - - viewModel.setDateRange(dateRange); - - expect(viewModel.selectedDateRange, dateRange); - expect(viewModel.startDateFormatted, '2024/01/01'); - expect(viewModel.endDateFormatted, '2024/01/31'); - expect(viewModel.startDateUnix, '1704067200'); - expect(viewModel.endDateUnix, '1706745600'); - }); - - test('should set status and clear data', () { - // Set some initial data - viewModel.data = TestFixtures.tenderApprovalsResponse; - viewModel.likedTendersData = TestFixtures.likedTendersResponse; - viewModel.isLoading = true; - viewModel.errorMessage = 'Error'; - - viewModel.setStatus('submitted'); - - expect(viewModel.selectedStatus, 'submitted'); - expect(viewModel.data, null); - expect(viewModel.likedTendersData, null); - expect(viewModel.isLoading, false); - expect(viewModel.errorMessage, null); - expect(viewModel.currentPage, 1); - }); - - test('should clear filter and reset state', () { - // Set some initial data - final dateRange = DateTimeRange( - start: DateTime(2024, 1, 1), - end: DateTime(2024, 1, 31), - ); - viewModel.setDateRange(dateRange); - viewModel.setStatus('submitted'); - viewModel.data = TestFixtures.tenderApprovalsResponse; - - viewModel.clearFilter(); - - expect(viewModel.selectedDateRange, null); - expect(viewModel.selectedStatus, 'All'); - expect(viewModel.data, null); - expect(viewModel.likedTendersData, null); - expect(viewModel.isLoading, false); - expect(viewModel.errorMessage, null); - }); - - test('should call with filter for all status', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - viewModel.selectedStatus = 'All'; - await viewModel.callWithFilter(); - - expect(viewModel.data, TestFixtures.tenderApprovalsResponse); - expect(viewModel.isLoading, false); - }); - - test('should call with filter for submitted status', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - viewModel.selectedStatus = 'Tenders Submitted'; - await viewModel.callWithFilter(); - - expect(viewModel.data, TestFixtures.tenderApprovalsResponse); - expect(viewModel.isLoading, false); - }); - - test('should call with filter for liked tenders', () async { - mockRepository.setGetTendersFeedbackResult( - const Result.ok(TestFixtures.likedTendersResponse), - ); - - viewModel.selectedStatus = 'Like Tenders'; - await viewModel.callWithFilter(); - - expect(viewModel.likedTendersData, TestFixtures.likedTendersResponse); - expect(viewModel.isLoading, false); - }); - - test('should call with filter for disliked tenders', () async { - mockRepository.setGetTendersFeedbackResult( - const Result.ok(TestFixtures.likedTendersResponse), - ); - - viewModel.selectedStatus = 'Dislike Tenders'; - await viewModel.callWithFilter(); - - expect(viewModel.likedTendersData, TestFixtures.likedTendersResponse); - expect(viewModel.isLoading, false); - }); - - test('should format dates correctly with date range', () { - final dateRange = DateTimeRange( - start: DateTime(2024, 12, 25), - end: DateTime(2024, 12, 31), - ); - - viewModel.setDateRange(dateRange); - - expect(viewModel.startDateFormatted, '2024/12/25'); - expect(viewModel.endDateFormatted, '2024/12/31'); - expect(viewModel.startDateUnix, '1735084800'); - expect(viewModel.endDateUnix, '1735689600'); - }); - }); -} diff --git a/test/view_models/your_tenders_view_model_get_tenders_test.dart b/test/view_models/your_tenders_view_model_get_tenders_test.dart deleted file mode 100644 index bc2f608..0000000 --- a/test/view_models/your_tenders_view_model_get_tenders_test.dart +++ /dev/null @@ -1,146 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:tm_app/core/utils/result.dart'; -import 'package:tm_app/data/services/model/request_models/get_tenders_request_model/get_tenders_request_model.dart'; -import 'package:tm_app/view_models/your_tenders_view_model.dart'; - -import '../fixtures/test_fixtures.dart'; -import '../mocks/mock_your_tenders_repository.dart'; - -void main() { - group('YourTendersViewModel GetTenders', () { - late MockYourTendersRepository mockRepository; - late YourTendersViewModel viewModel; - - setUp(() { - mockRepository = MockYourTendersRepository(); - viewModel = YourTendersViewModel(yourTendersRepository: mockRepository); - }); - - tearDown(() { - viewModel.dispose(); - }); - - test('should get tenders successfully', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - final requestModel = GetTendersRequestModel( - status: 'submitted', - createdFrom: '1640995200', - createdTo: '1640995200', - limit: 10, - offset: 0, - ); - - await viewModel.getTenders(requestModel: requestModel); - - expect(viewModel.isLoading, false); - expect(viewModel.data, TestFixtures.tenderApprovalsResponse); - expect(viewModel.errorMessage, null); - expect(viewModel.hasMoreTenders, true); - }); - - test('should handle get tenders error', () async { - const errorMessage = 'Network error'; - mockRepository.setGetTendersResult(Result.error(Exception(errorMessage))); - - final requestModel = GetTendersRequestModel( - status: 'submitted', - createdFrom: '1640995200', - createdTo: '1640995200', - limit: 10, - offset: 0, - ); - - await viewModel.getTenders(requestModel: requestModel); - - expect(viewModel.isLoading, false); - expect(viewModel.data, null); - expect(viewModel.errorMessage, errorMessage); - }); - - test('should set loading state during get tenders', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - final requestModel = GetTendersRequestModel( - status: 'submitted', - createdFrom: '1640995200', - createdTo: '1640995200', - limit: 10, - offset: 0, - ); - - final getTendersFuture = viewModel.getTenders(requestModel: requestModel); - - expect(viewModel.isLoading, true); - expect(viewModel.errorMessage, null); - - await getTendersFuture; - - expect(viewModel.isLoading, false); - }); - - test('should reset data when reset is true', () async { - // First load - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - final requestModel = GetTendersRequestModel( - status: 'submitted', - createdFrom: '1640995200', - createdTo: '1640995200', - limit: 10, - offset: 0, - ); - - await viewModel.getTenders(requestModel: requestModel); - expect(viewModel.data, TestFixtures.tenderApprovalsResponse); - - // Reset and load again - await viewModel.getTenders(requestModel: requestModel, reset: true); - expect(viewModel.data, TestFixtures.tenderApprovalsResponse); - }); - - test('should not load more when already loading', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - final requestModel = GetTendersRequestModel( - status: 'submitted', - createdFrom: '1640995200', - createdTo: '1640995200', - limit: 10, - offset: 0, - ); - - viewModel.isLoadingMoreTenders = true; - await viewModel.getTenders(requestModel: requestModel); - - expect(viewModel.data, null); - }); - - test('should not load more when no more data', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - final requestModel = GetTendersRequestModel( - status: 'submitted', - createdFrom: '1640995200', - createdTo: '1640995200', - limit: 10, - offset: 0, - ); - - viewModel.hasMoreTenders = false; - await viewModel.getTenders(requestModel: requestModel); - - expect(viewModel.data, null); - }); - }); -} diff --git a/test/view_models/your_tenders_view_model_initialization_test.dart b/test/view_models/your_tenders_view_model_initialization_test.dart deleted file mode 100644 index b8fdb2c..0000000 --- a/test/view_models/your_tenders_view_model_initialization_test.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:tm_app/view_models/your_tenders_view_model.dart'; - -import '../mocks/mock_your_tenders_repository.dart'; - -void main() { - group('YourTendersViewModel Initialization', () { - late MockYourTendersRepository mockRepository; - late YourTendersViewModel viewModel; - - setUp(() { - mockRepository = MockYourTendersRepository(); - viewModel = YourTendersViewModel(yourTendersRepository: mockRepository); - }); - - tearDown(() { - viewModel.dispose(); - }); - - test('should initialize with default values', () { - expect(viewModel.isLoading, false); - expect(viewModel.errorMessage, null); - expect(viewModel.data, null); - expect(viewModel.likedTendersData, null); - expect(viewModel.isLoadingMore, false); - expect(viewModel.hasMore, true); - expect(viewModel.isLoadingMoreTenders, false); - expect(viewModel.hasMoreTenders, true); - expect(viewModel.selectedDateRange, null); - expect(viewModel.selectedStatus, 'All'); - expect(viewModel.currentPage, 1); - }); - - test('should format dates correctly when no date range is selected', () { - expect(viewModel.startDateFormatted, 'YYYY/MM/DD'); - expect(viewModel.endDateFormatted, 'YYYY/MM/DD'); - expect(viewModel.startDateUnix, ''); - expect(viewModel.endDateUnix, ''); - }); - - test('should calculate total pages correctly when no data', () { - expect(viewModel.totalPages, 1); - }); - }); -} diff --git a/test/view_models/your_tenders_view_model_pagination_test.dart b/test/view_models/your_tenders_view_model_pagination_test.dart deleted file mode 100644 index 34d6ccf..0000000 --- a/test/view_models/your_tenders_view_model_pagination_test.dart +++ /dev/null @@ -1,116 +0,0 @@ -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/your_tenders_view_model.dart'; - -import '../fixtures/test_fixtures.dart'; -import '../mocks/mock_your_tenders_repository.dart'; - -void main() { - group('YourTendersViewModel Pagination', () { - late MockYourTendersRepository mockRepository; - late YourTendersViewModel viewModel; - - setUp(() { - mockRepository = MockYourTendersRepository(); - viewModel = YourTendersViewModel(yourTendersRepository: mockRepository); - }); - - tearDown(() { - viewModel.dispose(); - }); - - test('should calculate total pages from tender data', () { - viewModel.data = TestFixtures.tenderApprovalsResponse; - expect(viewModel.totalPages, 1); - }); - - test('should calculate total pages from feedback data', () { - viewModel.likedTendersData = TestFixtures.likedTendersResponse; - expect(viewModel.totalPages, 1); - }); - - test('should return 1 when no data available', () { - expect(viewModel.totalPages, 1); - }); - - test('should jump to page successfully', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - viewModel.selectedStatus = 'All'; - await viewModel.jumpToPage(2); - - expect(viewModel.currentPage, 2); - expect(viewModel.data, TestFixtures.tenderApprovalsResponse); - expect(viewModel.likedTendersData, null); - expect(viewModel.hasMore, true); - expect(viewModel.hasMoreTenders, true); - }); - - test('should load more tenders for all status', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - viewModel.selectedStatus = 'All'; - await viewModel.loadMoreTenders(); - - expect(viewModel.data, TestFixtures.tenderApprovalsResponse); - }); - - test('should load more tenders for submitted status', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - viewModel.selectedStatus = 'Tenders Submitted'; - await viewModel.loadMoreTenders(); - - expect(viewModel.data, TestFixtures.tenderApprovalsResponse); - }); - - test('should not load more tenders when already loading', () async { - viewModel.isLoadingMoreTenders = true; - await viewModel.loadMoreTenders(); - - expect(viewModel.data, null); - }); - - test('should not load more tenders when no more data', () async { - viewModel.hasMoreTenders = false; - await viewModel.loadMoreTenders(); - - expect(viewModel.data, null); - }); - - test('should handle pagination with date range', () async { - mockRepository.setGetTendersResult( - const Result.ok(TestFixtures.tenderApprovalsResponse), - ); - - viewModel.selectedStatus = 'All'; - viewModel.setDateRange( - DateTimeRange(start: DateTime(2024, 1, 1), end: DateTime(2024, 1, 31)), - ); - - await viewModel.loadMoreTenders(); - - expect(viewModel.data, TestFixtures.tenderApprovalsResponse); - }); - - test('should reset pagination state when clearing data', () { - // Set some pagination state - viewModel.currentPage = 3; - viewModel.data = TestFixtures.tenderApprovalsResponse; - viewModel.likedTendersData = TestFixtures.likedTendersResponse; - - viewModel.clearFilter(); - - expect(viewModel.currentPage, 1); - expect(viewModel.data, null); - expect(viewModel.likedTendersData, null); - }); - }); -} diff --git a/test/view_models/your_tenders_view_model_utility_test.dart b/test/view_models/your_tenders_view_model_utility_test.dart deleted file mode 100644 index daba893..0000000 --- a/test/view_models/your_tenders_view_model_utility_test.dart +++ /dev/null @@ -1,199 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:tm_app/core/constants/assets.dart'; -import 'package:tm_app/core/constants/tender_approval_status.dart'; -import 'package:tm_app/core/constants/tender_feedback.dart'; -import 'package:tm_app/core/theme/colors.dart'; -import 'package:tm_app/view_models/your_tenders_view_model.dart'; - -import '../mocks/mock_your_tenders_repository.dart'; - -void main() { - group('YourTendersViewModel Utility Methods', () { - late MockYourTendersRepository mockRepository; - late YourTendersViewModel viewModel; - - setUp(() { - mockRepository = MockYourTendersRepository(); - viewModel = YourTendersViewModel(yourTendersRepository: mockRepository); - }); - - tearDown(() { - viewModel.dispose(); - }); - - group('getBackGroundColorByStatus', () { - test('should return green for liked status', () { - final color = viewModel.getBackGroundColorByStatus( - TenderFeedback.liked.value, - ); - expect(color, AppColors.green0); - }); - - test('should return green for submitted status', () { - final color = viewModel.getBackGroundColorByStatus( - TenderApprovalStatus.submitted.value, - ); - expect(color, AppColors.green0); - }); - - test('should return red for disliked status', () { - final color = viewModel.getBackGroundColorByStatus( - TenderFeedback.disliked.value, - ); - expect(color, AppColors.red0); - }); - - test('should return red for rejected status', () { - final color = viewModel.getBackGroundColorByStatus( - TenderApprovalStatus.rejected.value, - ); - expect(color, AppColors.red0); - }); - - test('should return grey for unknown status', () { - final color = viewModel.getBackGroundColorByStatus('unknown'); - expect(color, AppColors.grey0); - }); - }); - - group('getBorderColorByStatus', () { - test('should return green for liked status', () { - final color = viewModel.getBorderColorByStatus( - TenderFeedback.liked.value, - ); - expect(color, AppColors.green10); - }); - - test('should return green for submitted status', () { - final color = viewModel.getBorderColorByStatus( - TenderApprovalStatus.submitted.value, - ); - expect(color, AppColors.green10); - }); - - test('should return red for disliked status', () { - final color = viewModel.getBorderColorByStatus( - TenderFeedback.disliked.value, - ); - expect(color, AppColors.red10); - }); - - test('should return red for rejected status', () { - final color = viewModel.getBorderColorByStatus( - TenderApprovalStatus.rejected.value, - ); - expect(color, AppColors.red10); - }); - - test('should return grey for unknown status', () { - final color = viewModel.getBorderColorByStatus('unknown'); - expect(color, AppColors.grey30); - }); - }); - - group('getStatusCardColorByStatus', () { - test('should return green for liked status', () { - final color = viewModel.getStatusCardColorByStatus( - TenderFeedback.liked.value, - ); - expect(color, AppColors.green20); - }); - - test('should return green for submitted status', () { - final color = viewModel.getStatusCardColorByStatus( - TenderApprovalStatus.submitted.value, - ); - expect(color, AppColors.green20); - }); - - test('should return red for disliked status', () { - final color = viewModel.getStatusCardColorByStatus( - TenderFeedback.disliked.value, - ); - expect(color, AppColors.red10); - }); - - test('should return red for rejected status', () { - final color = viewModel.getStatusCardColorByStatus( - TenderApprovalStatus.rejected.value, - ); - expect(color, AppColors.red10); - }); - - test('should return grey for unknown status', () { - final color = viewModel.getStatusCardColorByStatus('unknown'); - expect(color, AppColors.grey0); - }); - }); - - group('getStatusTextColorByStatus', () { - test('should return green for liked status', () { - final color = viewModel.getStatusTextColorByStatus( - TenderFeedback.liked.value, - ); - expect(color, AppColors.green30); - }); - - test('should return green for submitted status', () { - final color = viewModel.getStatusTextColorByStatus( - TenderApprovalStatus.submitted.value, - ); - expect(color, AppColors.green30); - }); - - test('should return red for disliked status', () { - final color = viewModel.getStatusTextColorByStatus( - TenderFeedback.disliked.value, - ); - expect(color, AppColors.red20); - }); - - test('should return red for rejected status', () { - final color = viewModel.getStatusTextColorByStatus( - TenderApprovalStatus.rejected.value, - ); - expect(color, AppColors.red20); - }); - - test('should return grey for unknown status', () { - final color = viewModel.getStatusTextColorByStatus('unknown'); - expect(color, AppColors.grey60); - }); - }); - - group('getStatusIconByStatus', () { - test('should return tick circle for liked status', () { - final icon = viewModel.getStatusIconByStatus( - TenderFeedback.liked.value, - ); - expect(icon, AssetsManager.tickCircle); - }); - - test('should return tick circle for submitted status', () { - final icon = viewModel.getStatusIconByStatus( - TenderApprovalStatus.submitted.value, - ); - expect(icon, AssetsManager.tickCircle); - }); - - test('should return close circle for disliked status', () { - final icon = viewModel.getStatusIconByStatus( - TenderFeedback.disliked.value, - ); - expect(icon, AssetsManager.closeCircle); - }); - - test('should return close circle for rejected status', () { - final icon = viewModel.getStatusIconByStatus( - TenderApprovalStatus.rejected.value, - ); - expect(icon, AssetsManager.closeCircle); - }); - - test('should return null for unknown status', () { - final icon = viewModel.getStatusIconByStatus('unknown'); - expect(icon, null); - }); - }); - }); -}