import 'package:eatvio_app/features/notifications/models/notification_model.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { group('NotificationType.getTypeFromString', () { test('returns correct type for new string-based keys', () { final cases = { 'diet-cancelled': NotificationType.dietCancelled, 'entity-commented': NotificationType.entityCommented, 'comment-replied': NotificationType.commentReplied, 'phone-changed': NotificationType.phoneChanged, 'diet-started': NotificationType.dietStarted, 'personal-diet-creation-needed-to-author': NotificationType.personalDietCreationNeeded, 'chosen-plan-client-last-day-finished': NotificationType.chosenPlanClientLastDayFinished, 'chosen-plan-consultant-last-day-started': NotificationType.chosenPlanConsultantLastDayStarted, 'chosen-plan-client-last-day-started': NotificationType.chosenPlanClientLastDayStarted, 'subscription': NotificationType.subscription, 'badge-awarded': NotificationType.badgeAwarded, 'badge-revoked': NotificationType.badgeRevoked, 'diet-expired': NotificationType.dietExpired, 'consultant-request-started': NotificationType.consultantRequestStarted, 'diet-will-started-in': NotificationType.dietWillStartedIn, 'client-close-complaint-success': NotificationType.clientCloseComplaintSuccess, 'complaint-to-moderation-for-user': NotificationType.complaintToModerationForUser, 'client-refund-success': NotificationType.clientRefundSuccess, 'consultant-refund-success': NotificationType.consultantRefundSuccess, 'client-reject-success': NotificationType.clientRejectSuccess, 'consultant-reject-success': NotificationType.consultantRejectSuccess, 'score-added': NotificationType.scoreAdded, 'score-substracted': NotificationType.scoreSubstracted, 'product-status-updated-for-author': NotificationType.productStatusUpdatedForAuthor, 'diet-can-not-started': NotificationType.dietCanNotBeStarted, 'stay-on-track-to-author': NotificationType.stayOnTrackToAuthor, 'chosen-plan-started-to-client': NotificationType.chosenPlanStartedToClient, 'client-start-plan-subscription-to-subscriber': NotificationType.clientStartPlanSubscriptionToSubscriber, 'consultant-confirm-plan-subscription-to-subscriber': NotificationType.consultantConfirmPlanSubscriptionToSubscriber, 'client-paid-plan-subscription-to-author': NotificationType.clientPaidPlanSubscriptionToAuthor, 'chosen-plan-tomorrow-reminder-to-client': NotificationType.chosenPlanTomorrowReminderToClient, 'chosen-plan-tomorrow-reminder-to-consultant': NotificationType.chosenPlanTomorrowReminderToConsultant, 'chosen-plan-started-to-consultant': NotificationType.chosenPlanStartedToConsultant, 'consultant-left-diary-comment': NotificationType.consultantLeftDiaryComment, 'chosen-plan-finished-to-client': NotificationType.chosenPlanFinishedToClient, 'consultant-confirm-plan-subscription-to-author': NotificationType.consultantConfirmPlanSubscriptionToAuthor, 'client-paid-plan-subscription-to-subscriber': NotificationType.clientPaidPlanSubscriptionToSubscriber, 'client-start-plan-subscription-to-author': NotificationType.clientStartPlanSubscriptionToAuthor, 'client-cancel-plan-subscription-to-author': NotificationType.clientCancelPlanSubscriptionToAuthor, 'client-cancel-plan-subscription-to-subscriber': NotificationType.clientCancelPlanSubscriptionToSubscriber, 'user-daily-report-completed': NotificationType.userDailyReportCompleted, 'chosen-plan-finished-to-consultant': NotificationType.chosenPlanFinishedToConsultant, 'stay-on-track-to-customer': NotificationType.stayOnTrackToCustomer, 'diary-reminder-for-users': NotificationType.diaryReminderForUsers, 'personal-diet-is-defined-to-customer': NotificationType.personalDietIsDefinedToCustomer, }; cases.forEach((key, expected) { expect(NotificationType.getTypeFromString(key), expected, reason: key); }); }); test('returns correct type for legacy FQCN values', () { final cases = { 'App\\Notifications\\Plan\\PlanSubscriptionStartedToAuthor': NotificationType.planSubscriptionStartedToAuthor, 'App\\Notifications\\Plan\\PlanSubscriptionCanceledToAuthor': NotificationType.planSubscriptionCanceledToAuthor, 'App\\Notifications\\Plan\\ChosenPlanStartedToClientNotification': NotificationType.chosenPlanStartedToClientNotification, 'App\\Notifications\\Plan\\ChosenPlanTomorrowReminderToClientNotification': NotificationType.chosenPlanTomorrowReminderToClientNotification, 'App\\Notifications\\DiaryReminderNotification': NotificationType.diaryReminderNotification, 'App\\Notifications\\Plan\\ConsultantLeftComment': NotificationType.consultantLeftComment, 'App\\Notifications\\Plan\\PersonalizedDietIsDefined': NotificationType.personalizedDietIsDefined, 'App\\Notifications\\Plan\\ChosenPlanFinishedToClient': NotificationType.chosenPlanFinishedToClient, 'App\\Notifications\\Plan\\PlanSubscriptionCanceledToCustomer': NotificationType.planSubscriptionCanceledToCustomer, 'App\\Notifications\\Plan\\ChosenPlanStartedToConsultantNotification': NotificationType.chosenPlanStartedToConsultantNotification, 'App\\Notifications\\Plan\\ChosenPlanTomorrowReminderToConsultantNotification': NotificationType.chosenPlanTomorrowReminderToConsultantNotification, 'App\\Notifications\\Plan\\PlanSubscriptionPaidToAuthor': NotificationType.planSubscriptionPaidToAuthor, 'App\\Notifications\\Plan\\ChosenPlanFinishedToConsultant': NotificationType.chosenPlanFinishedToConsultant, 'App\\Notifications\\ChosenPlan\\LastDayFinishedForUser': NotificationType.chosenPlanLastDayFinishedForUser, 'App\\Notifications\\ChosenPlan\\LastDayStartedForConsultant': NotificationType.chosenPlanConsultantLastDayStarted, 'App\\Notifications\\ComplaintToModerationNotify': NotificationType.complaintToModerationForUser, 'App\\Notifications\\Comment\\Replied': NotificationType.commentReplied, 'App\\Notifications\\Score\\ScoreAdded': NotificationType.scoreAdded, 'App\\Notifications\\Comment\\EntityCommented': NotificationType.entityCommented, 'App\\Notifications\\Plan\\PlanSubscriptionExpired': NotificationType.planSubscriptionExpired, 'App\\Notifications\\Plan\\PlanSubscriptionRenewed': NotificationType.planSubscriptionRenewed, 'App\\Notifications\\Plan\\ConsultantAssigned': NotificationType.consultantAssigned, 'App\\Notifications\\Plan\\ConsultantUnassigned': NotificationType.consultantUnassigned, 'App\\Notifications\\Payment\\PaymentFailed': NotificationType.paymentFailed, 'App\\Notifications\\Payment\\PaymentSuccessful': NotificationType.paymentSuccessful, 'App\\Notifications\\Goal\\GoalAchieved': NotificationType.goalAchieved, 'App\\Notifications\\Workout\\WorkoutReminder': NotificationType.workoutReminder, 'App\\Notifications\\Meal\\MealReminder': NotificationType.mealReminder, }; cases.forEach((key, expected) { expect(NotificationType.getTypeFromString(key), expected, reason: key); }); }); test('returns unknown for unexpected type', () { expect(NotificationType.getTypeFromString('some-unknown-type'), NotificationType.unknown); }); }); group('Notification model factories', () { test('PlanSubscriptionStartedToAuthorNotification.fromJson parses basic fields', () { final json = {'plan_name': 'Plan', 'user_name': 'User', 'chat_id': 'chat-1', 'created_at': '2024-01-01T12:00:00Z'}; final notification = PlanSubscriptionStartedToAuthorNotification.fromJson(json, NotificationType.planSubscriptionStartedToAuthor, isRead: true); expect(notification.planName, 'Plan'); expect(notification.customerName, 'User'); expect(notification.chatId, 'chat-1'); expect(notification.isRead, true); expect(notification.type, NotificationType.planSubscriptionStartedToAuthor); }); test('ChosenPlanStartedToClientNotification.fromJson with default isRead', () { final json = {'plan_name': 'Plan', 'plan_id': 10, 'created_at': '2024-01-01T12:00:00Z'}; final notification = ChosenPlanStartedToClientNotification.fromJson(json, NotificationType.chosenPlanStartedToClient); expect(notification.planName, 'Plan'); expect(notification.planId, 10); expect(notification.isRead, false); expect(notification.type, NotificationType.chosenPlanStartedToClient); }); test('UnknownNotification uses default createdAt when not provided', () { final notification = UnknownNotification(type: NotificationType.unknown, createdAt: DateTime.now()); expect(notification.type, NotificationType.unknown); expect(notification.isRead, true); // createdAt is initialized with epoch when not provided expect(notification.createdAt.isBefore(DateTime.now()), isTrue); }); test('ConsultantAssignedNotification.fromJson parses all fields', () { final json = { 'consultant_name': 'John Doe', 'plan_name': 'Test Plan', 'plan_id': 123, 'created_at': '2024-01-01T12:00:00Z', }; final notification = ConsultantAssignedNotification.fromJson( json, NotificationType.consultantAssigned, isRead: true, ); expect(notification.consultantName, 'John Doe'); expect(notification.planName, 'Test Plan'); expect(notification.planId, 123); expect(notification.isRead, true); expect(notification.type, NotificationType.consultantAssigned); }); test('ConsultantUnassignedNotification.fromJson parses all fields', () { final json = { 'consultant_name': 'Jane Smith', 'plan_name': 'Another Plan', 'plan_id': 456, 'created_at': '2024-01-02T12:00:00Z', }; final notification = ConsultantUnassignedNotification.fromJson( json, NotificationType.consultantUnassigned, isRead: false, ); expect(notification.consultantName, 'Jane Smith'); expect(notification.planName, 'Another Plan'); expect(notification.planId, 456); expect(notification.isRead, false); expect(notification.type, NotificationType.consultantUnassigned); }); test('PaymentFailedNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Premium Plan', 'error_message': 'Insufficient funds', 'payment_method': 'credit_card', 'created_at': '2024-01-03T12:00:00Z', }; final notification = PaymentFailedNotification.fromJson( json, NotificationType.paymentFailed, isRead: true, ); expect(notification.planName, 'Premium Plan'); expect(notification.errorMessage, 'Insufficient funds'); expect(notification.paymentMethod, 'credit_card'); expect(notification.isRead, true); expect(notification.type, NotificationType.paymentFailed); }); test('PaymentSuccessfulNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Premium Plan', 'amount': 99.99, 'currency': 'USD', 'transaction_id': 'txn_123456', 'created_at': '2024-01-04T12:00:00Z', }; final notification = PaymentSuccessfulNotification.fromJson( json, NotificationType.paymentSuccessful, isRead: false, ); expect(notification.planName, 'Premium Plan'); expect(notification.amount, 99.99); expect(notification.currency, 'USD'); expect(notification.transactionId, 'txn_123456'); expect(notification.isRead, false); expect(notification.type, NotificationType.paymentSuccessful); }); test('PaymentSuccessfulNotification.fromJson handles int amount', () { final json = { 'plan_name': 'Basic Plan', 'amount': 50, 'currency': 'EUR', 'transaction_id': 'txn_789', 'created_at': '2024-01-05T12:00:00Z', }; final notification = PaymentSuccessfulNotification.fromJson( json, NotificationType.paymentSuccessful, ); expect(notification.amount, 50.0); }); test('GoalAchievedNotification.fromJson parses all fields', () { final json = { 'goal_name': 'Weight Loss', 'goal_type': 'weight', 'achieved_value': 70.5, 'target_value': 75.0, 'created_at': '2024-01-06T12:00:00Z', }; final notification = GoalAchievedNotification.fromJson( json, NotificationType.goalAchieved, isRead: true, ); expect(notification.goalName, 'Weight Loss'); expect(notification.goalType, 'weight'); expect(notification.achievedValue, 70.5); expect(notification.targetValue, 75.0); expect(notification.isRead, true); expect(notification.type, NotificationType.goalAchieved); }); test('GoalAchievedNotification.fromJson handles int values', () { final json = { 'goal_name': 'Steps', 'goal_type': 'steps', 'achieved_value': 10000, 'target_value': 8000, 'created_at': '2024-01-07T12:00:00Z', }; final notification = GoalAchievedNotification.fromJson( json, NotificationType.goalAchieved, ); expect(notification.achievedValue, 10000.0); expect(notification.targetValue, 8000.0); }); test('WorkoutReminderNotification.fromJson parses all fields', () { final json = { 'workout_name': 'Morning Run', 'workout_type': 'running', 'duration': 30, 'created_at': '2024-01-08T12:00:00Z', }; final notification = WorkoutReminderNotification.fromJson( json, NotificationType.workoutReminder, isRead: false, ); expect(notification.workoutName, 'Morning Run'); expect(notification.workoutType, 'running'); expect(notification.duration, 30); expect(notification.isRead, false); expect(notification.type, NotificationType.workoutReminder); }); test('MealReminderNotification.fromJson parses all fields', () { final json = { 'meal_name': 'Breakfast', 'meal_type': 'breakfast', 'calories': 500, 'created_at': '2024-01-09T12:00:00Z', }; final notification = MealReminderNotification.fromJson( json, NotificationType.mealReminder, isRead: true, ); expect(notification.mealName, 'Breakfast'); expect(notification.mealType, 'breakfast'); expect(notification.calories, 500); expect(notification.isRead, true); expect(notification.type, NotificationType.mealReminder); }); test('DietCancelledNotification.fromJson parses all fields', () { final json = { 'diet_name': 'Keto Diet', 'created_at': '2024-01-10T12:00:00Z', }; final notification = DietCancelledNotification.fromJson( json, NotificationType.dietCancelled, isRead: false, ); expect(notification.dietName, 'Keto Diet'); expect(notification.isRead, false); expect(notification.type, NotificationType.dietCancelled); }); test('DietCancelledNotification.fromJson handles missing diet_name', () { final json = { 'created_at': '2024-01-11T12:00:00Z', }; final notification = DietCancelledNotification.fromJson( json, NotificationType.dietCancelled, ); expect(notification.dietName, ''); }); test('DietStartedNotification.fromJson parses all fields', () { final json = { 'diet_name': 'Mediterranean Diet', 'created_at': '2024-01-12T12:00:00Z', }; final notification = DietStartedNotification.fromJson( json, NotificationType.dietStarted, isRead: true, ); expect(notification.dietName, 'Mediterranean Diet'); expect(notification.isRead, true); expect(notification.type, NotificationType.dietStarted); }); test('DietStartedNotification.fromJson handles missing diet_name', () { final json = { 'created_at': '2024-01-13T12:00:00Z', }; final notification = DietStartedNotification.fromJson( json, NotificationType.dietStarted, ); expect(notification.dietName, ''); }); test('DietExpiredNotification.fromJson parses all fields', () { final json = { 'diet_name': 'Vegan Diet', 'created_at': '2024-01-14T12:00:00Z', }; final notification = DietExpiredNotification.fromJson( json, NotificationType.dietExpired, isRead: false, ); expect(notification.dietName, 'Vegan Diet'); expect(notification.isRead, false); expect(notification.type, NotificationType.dietExpired); }); test('DietExpiredNotification.fromJson handles missing diet_name', () { final json = { 'created_at': '2024-01-15T12:00:00Z', }; final notification = DietExpiredNotification.fromJson( json, NotificationType.dietExpired, ); expect(notification.dietName, ''); }); test('Notification models use custom createdAt when provided', () { final customDate = DateTime(2024, 6, 15, 10, 30); final json = {'plan_name': 'Test Plan', 'plan_id': 1}; final notification = ChosenPlanStartedToClientNotification.fromJson( json, NotificationType.chosenPlanStartedToClient, createdAt: customDate.toIso8601String(), ); expect(notification.createdAt, customDate); }); test('DietWillStartedInNotification.fromJson parses all fields', () { final json = { 'diet_name': 'Summer Diet', 'start_date': '2024-06-01', 'created_at': '2024-01-16T12:00:00Z', }; final notification = DietWillStartedInNotification.fromJson( json, NotificationType.dietWillStartedIn, isRead: true, ); expect(notification.dietName, 'Summer Diet'); expect(notification.startDate, '2024-06-01'); expect(notification.isRead, true); expect(notification.type, NotificationType.dietWillStartedIn); }); test('DietWillStartedInNotification.fromJson handles missing fields', () { final json = {'created_at': '2024-01-17T12:00:00Z'}; final notification = DietWillStartedInNotification.fromJson( json, NotificationType.dietWillStartedIn, ); expect(notification.dietName, ''); expect(notification.startDate, ''); }); test('DietCanNotBeStartedNotification.fromJson parses all fields', () { final json = { 'diet_name': 'Winter Diet', 'reason': 'Not enough products', 'created_at': '2024-01-18T12:00:00Z', }; final notification = DietCanNotBeStartedNotification.fromJson( json, NotificationType.dietCanNotBeStarted, isRead: false, ); expect(notification.dietName, 'Winter Diet'); expect(notification.reason, 'Not enough products'); expect(notification.isRead, false); expect(notification.type, NotificationType.dietCanNotBeStarted); }); test('DietCanNotBeStartedNotification.fromJson handles missing fields', () { final json = {'created_at': '2024-01-19T12:00:00Z'}; final notification = DietCanNotBeStartedNotification.fromJson( json, NotificationType.dietCanNotBeStarted, ); expect(notification.dietName, ''); expect(notification.reason, ''); }); test('PersonalDietCreationNeededNotification.fromJson parses all fields', () { final json = { 'user_name': 'John Doe', 'consultant_name': 'Consultant', 'my_diets_url': 'https://example.com/diets', 'created_at': '2024-01-20T12:00:00Z', }; final notification = PersonalDietCreationNeededNotification.fromJson( json, NotificationType.personalDietCreationNeeded, isRead: true, ); expect(notification.userName, 'John Doe'); expect(notification.consultantName, 'Consultant'); expect(notification.myDietsUrl, 'https://example.com/diets'); expect(notification.isRead, true); expect(notification.type, NotificationType.personalDietCreationNeeded); }); test('PersonalDietCreationNeededNotification.fromJson handles missing fields', () { final json = {'created_at': '2024-01-21T12:00:00Z'}; final notification = PersonalDietCreationNeededNotification.fromJson( json, NotificationType.personalDietCreationNeeded, ); expect(notification.userName, ''); expect(notification.consultantName, ''); }); test('ChosenPlanClientLastDayFinishedNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Final Plan', 'created_at': '2024-01-22T12:00:00Z', }; final notification = ChosenPlanClientLastDayFinishedNotification.fromJson( json, NotificationType.chosenPlanClientLastDayFinished, isRead: false, ); expect(notification.planName, 'Final Plan'); expect(notification.isRead, false); expect(notification.type, NotificationType.chosenPlanClientLastDayFinished); }); test('ChosenPlanClientLastDayStartedNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Starting Plan', 'created_at': '2024-01-23T12:00:00Z', }; final notification = ChosenPlanClientLastDayStartedNotification.fromJson( json, NotificationType.chosenPlanClientLastDayStarted, isRead: true, ); expect(notification.planName, 'Starting Plan'); expect(notification.isRead, true); expect(notification.type, NotificationType.chosenPlanClientLastDayStarted); }); test('StayOnTrackToAuthorNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Track Plan', 'user_name': 'Jane Smith', 'day_num': 1, 'diary_day_id': 10, 'created_at': '2024-01-24T12:00:00Z', }; final notification = StayOnTrackToAuthorNotification.fromJson( json, NotificationType.stayOnTrackToAuthor, isRead: false, ); expect(notification.planName, 'Track Plan'); expect(notification.userName, 'Jane Smith'); expect(notification.isRead, false); expect(notification.type, NotificationType.stayOnTrackToAuthor); }); test('ClientStartPlanSubscriptionToSubscriberNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Subscriber Plan', 'created_at': '2024-01-25T12:00:00Z', }; final notification = ClientStartPlanSubscriptionToSubscriberNotification.fromJson( json, NotificationType.clientStartPlanSubscriptionToSubscriber, isRead: true, ); expect(notification.planName, 'Subscriber Plan'); expect(notification.isRead, true); expect(notification.type, NotificationType.clientStartPlanSubscriptionToSubscriber); }); test('PlanSubscriptionCanceledToAuthorNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Canceled Plan', 'user_name': 'User Name', 'created_at': '2024-01-26T12:00:00Z', }; final notification = PlanSubscriptionCanceledToAuthorNotification.fromJson( json, NotificationType.planSubscriptionCanceledToAuthor, isRead: false, ); expect(notification.planName, 'Canceled Plan'); expect(notification.customerName, 'User Name'); expect(notification.isRead, false); expect(notification.type, NotificationType.planSubscriptionCanceledToAuthor); }); test('ChosenPlanTomorrowReminderToClientNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Reminder Plan', 'created_at': '2024-01-27T12:00:00Z', }; final notification = ChosenPlanTomorrowReminderToClientNotification.fromJson( json, NotificationType.chosenPlanTomorrowReminderToClientNotification, isRead: true, ); expect(notification.planName, 'Reminder Plan'); expect(notification.isRead, true); expect(notification.type, NotificationType.chosenPlanTomorrowReminderToClientNotification); }); test('DiaryReminderNotification.fromJson parses all fields', () { final json = { 'created_at': '2024-01-28T12:00:00Z', }; final notification = DiaryReminderNotification.fromJson( json, NotificationType.diaryReminderNotification, isRead: false, ); expect(notification.isRead, false); expect(notification.type, NotificationType.diaryReminderNotification); }); test('ConsultantLeftCommentNotification.fromJson parses all fields', () { final json = { 'diary_date': '2024-01-29T12:00:00Z', 'created_at': '2024-01-29T12:00:00Z', }; final notification = ConsultantLeftCommentNotification.fromJson( json, NotificationType.consultantLeftComment, isRead: true, ); expect(notification.date, isA()); expect(notification.isRead, true); expect(notification.type, NotificationType.consultantLeftComment); }); test('PersonalizedDietIsDefinedNotification.fromJson parses all fields', () { final json = { 'created_at': '2024-01-30T12:00:00Z', }; final notification = PersonalizedDietIsDefinedNotification.fromJson( json, NotificationType.personalizedDietIsDefined, isRead: false, ); expect(notification.isRead, false); expect(notification.type, NotificationType.personalizedDietIsDefined); }); test('ChosenPlanFinishedToClientNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Finished Plan', 'created_at': '2024-01-31T12:00:00Z', }; final notification = ChosenPlanFinishedToClientNotification.fromJson( json, NotificationType.chosenPlanFinishedToClient, isRead: true, ); expect(notification.planName, 'Finished Plan'); expect(notification.isRead, true); expect(notification.type, NotificationType.chosenPlanFinishedToClient); }); test('PlanSubscriptionCanceledToCustomerNotification.fromJson parses all fields', () { final json = { 'plan_name': 'Customer Canceled Plan', 'created_at': '2024-02-01T12:00:00Z', }; final notification = PlanSubscriptionCanceledToCustomerNotification.fromJson( json, NotificationType.planSubscriptionCanceledToCustomer, isRead: false, ); expect(notification.planName, 'Customer Canceled Plan'); expect(notification.isRead, false); expect(notification.type, NotificationType.planSubscriptionCanceledToCustomer); }); }); }