forked from eatvio/eatvio_app
- show diet duration hint and plan duration in suggestion flow - disable diet CTA on duration mismatch with grey visual state - keep progress plank visible for personal_diet_setted - center step labels under their circles
280 lines
8.5 KiB
Dart
280 lines
8.5 KiB
Dart
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<ConsultationStep> 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<ChosenPlanStateEnum, _Expected> _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}',
|
||
);
|
||
}
|
||
});
|
||
});
|
||
}
|