import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:gametime/application/application.dart'; import 'package:gametime/domain/domain.dart'; import 'package:gametime/presentation/presentation.dart'; void main() { testWidgets( 'ajoute un exercice au programme avec sa configuration par défaut', (tester) async { final programRepository = _FakeProgramRepository(); final exerciseRepository = _FakeExerciseRepository() ..exercises.add( Exercise( metadata: _metadata('exercise-1'), name: 'Squat', hasTimeMeasure: true, hasRepsMeasure: true, hasScoreMeasure: false, ), ); await tester.pumpWidget( MaterialApp( home: ProgramFormScreen( programUseCases: _programUseCases( programRepository, exerciseRepository, ), exerciseUseCases: _exerciseUseCases(exerciseRepository), ), ), ); await tester.enterText( find.widgetWithText(TextFormField, 'Nom'), 'Jambes', ); await tester.tap(find.text('Ajouter un exercice')); await tester.pumpAndSettle(); await tester.tap(find.text('Squat')); await tester.pumpAndSettle(); expect(find.text('Squat'), findsOneWidget); expect(find.text('Repos 60 s'), findsOneWidget); expect(find.text('Exercice ajouté'), findsOneWidget); expect(find.byTooltip("Personnaliser l'exercice"), findsOneWidget); expect(find.byType(CheckboxListTile), findsNothing); await tester.tap(find.text('Enregistrer')); await tester.pumpAndSettle(); final savedExercise = programRepository.programs.single.exercises.single; expect(savedExercise.setsCount, 3); expect(savedExercise.timeEnabled, isTrue); expect(savedExercise.repsEnabled, isTrue); expect(savedExercise.scoreEnabled, isFalse); expect(savedExercise.restSecondsOverride, 60); }, ); testWidgets( 'limite les mesures aux mesures autorisées par l’exercice source', (tester) async { final exerciseRepository = _FakeExerciseRepository() ..exercises.add( Exercise( metadata: _metadata('exercise-1'), name: 'Pompes', hasTimeMeasure: false, hasRepsMeasure: true, hasScoreMeasure: false, ), ); 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('Pompes')); await tester.pumpAndSettle(); await tester.tap(find.byTooltip("Personnaliser l'exercice")); await tester.pumpAndSettle(); expect(find.text("Personnaliser l'exercice"), findsOneWidget); expect( find.widgetWithText(SwitchListTile, 'Répétitions'), findsOneWidget, ); expect(find.widgetWithText(SwitchListTile, 'Temps'), findsNothing); expect(find.widgetWithText(SwitchListTile, 'Score'), findsNothing); }, ); testWidgets('affiche l’objectif 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) { return ExerciseUseCases( repository: repository, clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)), ids: _FakeIds(), originDeviceId: 'device-1', ); } ProgramUseCases _programUseCases( _FakeProgramRepository programRepository, _FakeExerciseRepository exerciseRepository, ) { return ProgramUseCases( programRepository: programRepository, exerciseRepository: exerciseRepository, clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)), ids: _FakeIds(), originDeviceId: 'device-1', ); } EntityMetadata _metadata(String id) { return EntityMetadata( id: id, createdAt: DateTime.utc(2026, 7, 17), updatedAt: DateTime.utc(2026, 7, 17), originDeviceId: 'device-1', ); } final class _FakeClock implements Clock { const _FakeClock(this.value); final DateTime value; @override DateTime now() => value; } final class _FakeIds implements IdGenerator { var _next = 0; @override String newId() { _next += 1; return 'id-$_next'; } } final class _FakeExerciseRepository implements ExerciseRepository { final exercises = []; final saved = []; @override Future findById(String id) async { for (final exercise in exercises) { if (exercise.metadata.id == id) { return exercise; } } return null; } @override Future isReferencedByProgram(String id) async => false; @override Future> listActive() async => exercises; @override Future save(Exercise exercise) async { saved.add(exercise); } } final class _FakeProgramRepository implements ProgramRepository { final programs = []; @override Future findById(String id) async { for (final program in programs) { if (program.metadata.id == id) { return program; } } return null; } @override Future> listActive() async => programs; @override Future replaceExercises(Program program, DateTime deletedAt) async { programs.removeWhere((item) => item.metadata.id == program.metadata.id); programs.add(program); } @override Future save(Program program) async { programs.add(program); } @override Future saveExercise(ProgramExercise exercise) async {} }