feat(exercice): icône d'exercice (ticket #38)

Étend le modèle Drift (tables.dart, app_database.dart/.g.dart), les
entités/use cases/repositories et les écrans bibliothèque d'exercices
et programme pour associer une icône à chaque exercice. flutter
analyze propre, 72/72 tests verts, build APK debug validé. Dernier
ticket du backlog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-18 14:25:26 +02:00
parent c92bded211
commit bdd7877ea5
10 changed files with 589 additions and 27 deletions

View File

@ -216,6 +216,72 @@ void main() {
expect(find.text('Aucune image sélectionnée'), findsOneWidget);
});
testWidgets('désigner une image comme icône lindique visuellement', (
tester,
) async {
final exerciseRepository = _FakeExerciseRepository();
final storage = _FakeMediaStorage();
await tester.binding.setSurfaceSize(const Size(400, 1600));
addTearDown(() => tester.binding.setSurfaceSize(null));
await tester.pumpWidget(
MaterialApp(
home: ExerciseFormScreen(
exerciseUseCases: _exerciseUseCases(exerciseRepository),
mediaUseCases: _mediaUseCases(exerciseRepository, storage: storage),
mediaPicker: _FakeMediaPicker(
imagePaths: const [
'/tmp/imports/photo-1.png',
'/tmp/imports/photo-2.png',
],
),
),
),
);
await tester.enterText(find.widgetWithText(TextFormField, 'Nom'), 'Squat');
await tester.enterText(
find.widgetWithText(TextFormField, 'Temps par défaut (s)'),
'45',
);
await tester.tap(find.text('Ajouter une image'));
await tester.pump();
await tester.tap(find.text('Ajouter une image'));
await tester.pump();
await tester.tap(find.byTooltip('Définir comme icône').last);
await tester.pump();
expect(find.byTooltip('Icône choisie'), findsOneWidget);
await tester.tap(find.text('Enregistrer'));
await tester.pumpAndSettle();
expect(exerciseRepository.saved.single.iconMediaId, 'id-2');
});
testWidgets('ExerciseListTile utilise licône choisie', (tester) async {
final exercise = Exercise(
metadata: _metadata('exercise-1'),
name: 'Squat',
imageMediaIds: const ['image-1', 'image-2'],
iconMediaId: 'image-2',
hasTimeMeasure: true,
hasRepsMeasure: false,
hasScoreMeasure: false,
defaultTargetTimeSeconds: 45,
);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(body: ExerciseListTile(exercise: exercise)),
),
);
expect(find.byTooltip('Icône dexercice image-2'), findsOneWidget);
});
testWidgets(
'supprimer un exercice demande confirmation puis le retire de la liste',
(tester) async {