merge(develop): clôture lot #91 Wear OS - fréquence cardiaque, notifications, finitions montre

Intègre le commit de clôture du lot #91 resté non fusionné. Conflits
attendus sur entities.dart, workout_execution_screen.dart et
watch_companion_projection_test.dart : arbitrage Architect - garder la
base feature/ticket91-wear-os-watch-sync sur ces 3 fichiers puis réinjecter
uniquement les invariants chronos utiles (Durée / Temps réalisé).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

# Conflicts:
#	lib/domain/entities.dart
#	lib/presentation/workout_execution_screen.dart
#	test/application/watch_companion_projection_test.dart
This commit is contained in:
2026-07-28 11:35:22 +02:00
80 changed files with 12296 additions and 891 deletions

View File

@ -15,6 +15,22 @@ void main() {
name: 'Fondations basket - 45 min',
defaultRestSeconds: 45,
isExample: true,
exercises: [
ProgramExercise(
metadata: _metadata('program-exercise-1'),
programId: 'program-1',
position: 0,
exerciseNameSnapshot: 'Tirs',
availableTimeSnapshot: false,
availableRepsSnapshot: true,
availableScoreSnapshot: false,
setsCount: 3,
timeEnabled: false,
repsEnabled: true,
scoreEnabled: false,
targetReps: 10,
),
],
),
);
final exerciseRepository = _FakeExerciseRepository();
@ -65,6 +81,44 @@ void main() {
);
});
testWidgets('un programme sans exercice ne peut pas être enregistré', (
tester,
) async {
final programRepository = _FakeProgramRepository();
final exerciseRepository = _FakeExerciseRepository();
await tester.pumpWidget(
MaterialApp(
home: ProgramFormScreen(
programUseCases: _programUseCases(
programRepository,
exerciseRepository,
),
exerciseUseCases: _exerciseUseCases(exerciseRepository),
),
),
);
expect(
find.text('Ajoute au moins un exercice pour enregistrer ce programme.'),
findsOneWidget,
);
expect(
tester
.widget<FilledButton>(
find.widgetWithText(FilledButton, 'Enregistrer'),
)
.onPressed,
isNull,
);
await tester.enterText(find.widgetWithText(TextFormField, 'Nom'), 'Vide');
await tester.tap(find.text('Enregistrer'));
await tester.pump();
expect(programRepository.saved, isEmpty);
});
testWidgets('filtre les programmes par tag et peut effacer les filtres', (
tester,
) async {
@ -125,9 +179,36 @@ void main() {
name: 'Jambes',
defaultRestSeconds: 60,
tags: const ['match'],
exercises: [
ProgramExercise(
metadata: _metadata('program-exercise-1'),
programId: 'program-1',
sourceExerciseId: 'exercise-1',
position: 0,
exerciseNameSnapshot: 'Tirs',
availableTimeSnapshot: false,
availableRepsSnapshot: true,
availableScoreSnapshot: false,
setsCount: 3,
timeEnabled: false,
repsEnabled: true,
scoreEnabled: false,
targetReps: 10,
),
],
),
);
final exerciseRepository = _FakeExerciseRepository()
..exercises.add(
Exercise(
metadata: _metadata('exercise-1'),
name: 'Tirs',
hasTimeMeasure: false,
hasRepsMeasure: true,
hasScoreMeasure: false,
defaultTargetReps: 10,
),
);
final exerciseRepository = _FakeExerciseRepository();
await tester.pumpWidget(
MaterialApp(
@ -167,9 +248,36 @@ void main() {
name: 'Fondations basket - 45 min',
defaultRestSeconds: 45,
isExample: true,
exercises: [
ProgramExercise(
metadata: _metadata('program-exercise-1'),
programId: 'program-1',
sourceExerciseId: 'exercise-1',
position: 0,
exerciseNameSnapshot: 'Tirs',
availableTimeSnapshot: false,
availableRepsSnapshot: true,
availableScoreSnapshot: false,
setsCount: 3,
timeEnabled: false,
repsEnabled: true,
scoreEnabled: false,
targetReps: 10,
),
],
),
);
final exerciseRepository = _FakeExerciseRepository()
..exercises.add(
Exercise(
metadata: _metadata('exercise-1'),
name: 'Tirs',
hasTimeMeasure: false,
hasRepsMeasure: true,
hasScoreMeasure: false,
defaultTargetReps: 10,
),
);
final exerciseRepository = _FakeExerciseRepository();
await tester.pumpWidget(
MaterialApp(