feat(ui): configuration du score chronométré (ticket #26)

Ajoute la configuration du score chronométré sur exercise_library_screen.dart
et program_screen.dart, s'appuyant sur les fondations domain du ticket
#25. flutter analyze propre, 41/41 tests verts, build APK debug validé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-18 09:08:16 +02:00
parent ab6b373a79
commit 2f732aa1b1
4 changed files with 299 additions and 38 deletions

View File

@ -66,6 +66,70 @@ void main() {
expect(find.text('Score (kg)'), findsOneWidget);
});
testWidgets('basculer en chrono intégré masque lunité et affiche le badge', (
tester,
) async {
final exerciseRepository = _FakeExerciseRepository();
await tester.pumpWidget(
MaterialApp(
home: ExerciseFormScreen(
exerciseUseCases: _exerciseUseCases(exerciseRepository),
mediaUseCases: _mediaUseCases(exerciseRepository),
),
),
);
await tester.enterText(find.widgetWithText(TextFormField, 'Nom'), 'Run');
await tester.dragUntilVisible(
find.text('Score'),
find.byType(ListView),
const Offset(0, -200),
);
await tester.tap(find.widgetWithText(SwitchListTile, 'Score'));
await tester.pump();
await tester.dragUntilVisible(
find.text('Unité'),
find.byType(ListView),
const Offset(0, -200),
);
expect(find.widgetWithText(TextFormField, 'Unité'), findsOneWidget);
await tester.dragUntilVisible(
find.text('Chrono intégré'),
find.byType(ListView),
const Offset(0, 200),
);
await tester.tap(find.text('Chrono intégré'));
await tester.pump();
await tester.dragUntilVisible(
find.text('Temps réalisé'),
find.byType(ListView),
const Offset(0, -200),
);
expect(find.text('Temps réalisé'), findsOneWidget);
expect(find.widgetWithText(TextFormField, 'Unité'), findsNothing);
await tester.ensureVisible(find.text('Enregistrer'));
await tester.tap(find.text('Enregistrer'));
await tester.pumpAndSettle();
final saved = exerciseRepository.saved.single;
expect(saved.scoreInputMode, ScoreInputMode.stopwatch);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(body: ExerciseListTile(exercise: saved)),
),
);
await tester.pumpAndSettle();
expect(find.text('Score chrono'), findsOneWidget);
expect(find.text('Score'), findsNothing);
});
testWidgets(
'sélectionner une image déclenche limport et confirme le fichier',
(tester) async {

View File

@ -102,6 +102,73 @@ void main() {
expect(find.widgetWithText(SwitchListTile, 'Score'), findsNothing);
},
);
testWidgets('affiche lobjectif de chrono pour un score en mode chrono', (
tester,
) async {
final exerciseRepository = _FakeExerciseRepository()
..exercises.add(
Exercise(
metadata: _metadata('exercise-1'),
name: 'Suicides',
hasTimeMeasure: true,
hasRepsMeasure: true,
hasScoreMeasure: true,
scoreInputMode: ScoreInputMode.stopwatch,
scoreLabel: 'Temps réalisé',
),
);
await tester.pumpWidget(
MaterialApp(
home: ProgramFormScreen(
programUseCases: _programUseCases(
_FakeProgramRepository(),
exerciseRepository,
),
exerciseUseCases: _exerciseUseCases(exerciseRepository),
),
),
);
await tester.tap(find.text('Ajouter un exercice'));
await tester.pumpAndSettle();
await tester.tap(find.text('Suicides'));
await tester.pumpAndSettle();
await tester.tap(find.byTooltip("Personnaliser l'exercice"));
await tester.pumpAndSettle();
expect(find.text('Score chrono'), findsOneWidget);
await tester.dragUntilVisible(
find.text(
"Temps sert d'objectif de durée ; Score chrono enregistre "
'le temps réalisé.',
),
find.byType(ListView),
const Offset(0, -200),
);
expect(
find.text(
"Temps sert d'objectif de durée ; Score chrono enregistre "
'le temps réalisé.',
),
findsOneWidget,
);
await tester.dragUntilVisible(
find.text('Objectif de chrono'),
find.byType(ListView),
const Offset(0, -200),
);
expect(
find.widgetWithText(TextFormField, 'Objectif de chrono'),
findsOneWidget,
);
expect(find.widgetWithText(TextFormField, 'Cible score'), findsNothing);
expect(
find.text('Le résultat réel sera mesuré pendant la série.'),
findsOneWidget,
);
});
}
ExerciseUseCases _exerciseUseCases(_FakeExerciseRepository repository) {