import 'package:eatvio_app/features/consultations/models/consultation_progress.dart'; import 'package:eatvio_app/features/consultations/utils/consultation_progress_mapper.dart'; import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart'; import 'package:flutter_test/flutter_test.dart'; typedef _Expected = ({ Set steps, bool plank, PersonalDietStatus diet, ConsultationPhase phase, }); const _startDate = ConsultationStep.startDate; const _paid = ConsultationStep.paid; const _inProgress = ConsultationStep.inProgress; const _finished = ConsultationStep.finished; final Map _expectations = { ChosenPlanStateEnum.stateInited: ( steps: {}, plank: false, diet: PersonalDietStatus.notProposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateStartDateHasBeenSet: ( steps: {_startDate}, plank: true, diet: PersonalDietStatus.notProposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateInCoordination: ( steps: {}, plank: true, diet: PersonalDietStatus.notProposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateStarted: ( steps: {_startDate, _paid, _inProgress}, plank: true, diet: PersonalDietStatus.proposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateInProgress: ( steps: {_startDate, _paid, _inProgress}, plank: true, diet: PersonalDietStatus.proposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.statePendingPayment: ( steps: {_startDate}, plank: true, diet: PersonalDietStatus.notProposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateConfirmedByConsultant: ( steps: {}, plank: false, diet: PersonalDietStatus.notProposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.statePaid: ( steps: {_startDate, _paid}, plank: true, diet: PersonalDietStatus.notProposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateCanceledByTheInitiator: ( steps: {}, plank: false, diet: PersonalDietStatus.notRequired, phase: ConsultationPhase.canceled, ), ChosenPlanStateEnum.stateLastDayStarted: ( steps: {_startDate, _paid, _inProgress}, plank: true, diet: PersonalDietStatus.proposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateLastDayFinished: ( steps: {_startDate, _paid, _inProgress}, plank: true, diet: PersonalDietStatus.proposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateComplained: ( steps: {_startDate, _paid, _inProgress}, plank: true, diet: PersonalDietStatus.proposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateDone: ( steps: {_startDate, _paid, _inProgress, _finished}, plank: true, diet: PersonalDietStatus.proposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.personalDietSet: ( steps: {_startDate, _paid}, plank: true, diet: PersonalDietStatus.proposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.stateChargeWasCollected: ( steps: {_startDate, _paid, _inProgress, _finished}, plank: false, diet: PersonalDietStatus.proposed, phase: ConsultationPhase.active, ), ChosenPlanStateEnum.statePaymentFailed: ( steps: {_startDate}, plank: false, diet: PersonalDietStatus.notRequired, phase: ConsultationPhase.paymentFailed, ), }; void main() { group('mapConsultationProgress — все состояния', () { test('таблица покрывает ровно все 16 состояний', () { expect(_expectations.length, 16); expect(_expectations.keys.toSet(), ChosenPlanStateEnum.values.toSet()); }); for (final entry in _expectations.entries) { test('${entry.key.name} маппится во все поля ConsultationProgress', () { final progress = mapConsultationProgress( state: entry.key, hasPersonalDiet: true, ); expect(progress.completedSteps, unorderedEquals(entry.value.steps)); expect(progress.showProgressPlank, entry.value.plank); expect(progress.dietStatus, entry.value.diet); expect(progress.phase, entry.value.phase); }); } }); group('mapConsultationProgress — ключевые сценарии', () { test('in_coordination показывает плашку без завершённых шагов', () { final progress = mapConsultationProgress( state: ChosenPlanStateEnum.stateInCoordination, hasPersonalDiet: true, ); expect(progress.showProgressPlank, isTrue); expect(progress.completedSteps, isEmpty); }); test( 'personal_diet_setted показывает плашку и завершает startDate+paid', () { final progress = mapConsultationProgress( state: ChosenPlanStateEnum.personalDietSet, hasPersonalDiet: true, ); expect(progress.showProgressPlank, isTrue); expect(progress.completedSteps, unorderedEquals([_startDate, _paid])); }, ); test( 'started/in_progress/last_day_started/last_day_finished/complained — 3 шага', () { const states = [ ChosenPlanStateEnum.stateStarted, ChosenPlanStateEnum.stateInProgress, ChosenPlanStateEnum.stateLastDayStarted, ChosenPlanStateEnum.stateLastDayFinished, ChosenPlanStateEnum.stateComplained, ]; for (final state in states) { final progress = mapConsultationProgress( state: state, hasPersonalDiet: true, ); expect( progress.completedSteps, unorderedEquals([_startDate, _paid, _inProgress]), reason: 'state=${state.name}', ); } }, ); test('done/charge_was_collected — 4 шага', () { const states = [ ChosenPlanStateEnum.stateDone, ChosenPlanStateEnum.stateChargeWasCollected, ]; for (final state in states) { final progress = mapConsultationProgress( state: state, hasPersonalDiet: true, ); expect( progress.completedSteps, unorderedEquals([_startDate, _paid, _inProgress, _finished]), reason: 'state=${state.name}', ); } }); test( 'canceled — фаза canceled и dietStatus notRequired даже при диете', () { final progress = mapConsultationProgress( state: ChosenPlanStateEnum.stateCanceledByTheInitiator, hasPersonalDiet: true, ); expect(progress.phase, ConsultationPhase.canceled); expect(progress.isCanceled, isTrue); expect(progress.dietStatus, PersonalDietStatus.notRequired); }, ); test('payment_failed — фаза paymentFailed и только startDate', () { final progress = mapConsultationProgress( state: ChosenPlanStateEnum.statePaymentFailed, hasPersonalDiet: true, ); expect(progress.phase, ConsultationPhase.paymentFailed); expect(progress.isPaymentFailed, isTrue); expect(progress.completedSteps, unorderedEquals([_startDate])); }); test('hasPersonalDiet=false даёт notRequired для любого состояния', () { for (final state in ChosenPlanStateEnum.values) { final progress = mapConsultationProgress( state: state, hasPersonalDiet: false, ); expect( progress.dietStatus, PersonalDietStatus.notRequired, reason: 'state=${state.name}', ); expect(progress.hasDietChip, isFalse, reason: 'state=${state.name}'); } }); test('paid с диетой даёт notProposed', () { final progress = mapConsultationProgress( state: ChosenPlanStateEnum.statePaid, hasPersonalDiet: true, ); expect(progress.dietStatus, PersonalDietStatus.notProposed); }); test('personal_diet_setted/started/proposed дают proposed', () { const states = [ ChosenPlanStateEnum.personalDietSet, ChosenPlanStateEnum.stateStarted, ]; for (final state in states) { final progress = mapConsultationProgress( state: state, hasPersonalDiet: true, ); expect( progress.dietStatus, PersonalDietStatus.proposed, reason: 'state=${state.name}', ); } }); }); }