fix(core): complete la nullification defensive de sourceExerciseId pour #185

Delta final apres QA vert : renforce la robustesse du pull des programmes quand l'exercice source reference par sourceExerciseId est absent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 18:02:38 +02:00
parent dd882f07ae
commit 933fc1121d
2 changed files with 259 additions and 24 deletions

View File

@ -1750,6 +1750,64 @@ CREATE TABLE pending_share_actions (
expect(programs.single.exercises.single.targetReps, 8);
});
test(
'program list tolerates invalid snapshots after source exercise deletion',
() async {
final now = DateTime.utc(2026, 7, 30, 18);
final exercise = Exercise(
metadata: _metadata('exercise-deleted-invalid-snapshot', now),
name: 'Concours de tirs',
hasTimeMeasure: false,
hasRepsMeasure: false,
hasScoreMeasure: true,
scoreLabel: 'Score',
scoreUnit: 'pts',
);
await exerciseRepository.save(exercise);
await programRepository.save(
Program(
metadata: _metadata('program-invalid-snapshot', now),
name: 'Programme snapshot legacy',
defaultRestSeconds: 30,
exercises: [
ProgramExercise.snapshotFromExercise(
metadata: _metadata('program-exercise-invalid-snapshot', now),
programId: 'program-invalid-snapshot',
exercise: exercise,
position: 0,
setsCount: 2,
enabledMeasures: const {WorkoutMeasure.score},
),
],
),
);
await exerciseRepository.save(
exercise.copyWith(
metadata: exercise.metadata.markDeleted(
now.add(const Duration(minutes: 1)),
),
),
);
await database.customStatement('PRAGMA ignore_check_constraints = ON');
await database.customStatement(
'UPDATE program_exercises '
'SET available_reps_snapshot = 1, available_score_snapshot = 0, '
'score_label_snapshot = NULL, score_unit_snapshot = NULL '
"WHERE id = 'program-exercise-invalid-snapshot'",
);
await database.customStatement('PRAGMA ignore_check_constraints = OFF');
final programs = await programRepository.listActive();
expect(programs, hasLength(1));
final restored = programs.single.exercises.single;
expect(restored.exerciseNameSnapshot, 'Concours de tirs');
expect(restored.sourceExerciseId, exercise.metadata.id);
expect(restored.repsEnabled, isTrue);
expect(restored.scoreEnabled, isFalse);
},
);
test(
'starter program and workout template snapshot exercise steps',
() async {