feat(server): implemente synchronisation et serveur avec fixtures (#187)

- Implémente la couche de synchronisation avec le serveur
- Ajoute les fixtures versionnées pour les tests
- Met à jour Drift database et repositories pour le support sync
- Améliore les tests de synchronisation
- Corrige et améliore le watch companion pour la collecte de métriques

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-04 23:07:31 +02:00
parent d1edb2397e
commit fe3608cc4a
31 changed files with 5056 additions and 394 deletions

View File

@ -237,6 +237,67 @@ void main() {
expect(find.text('186 kcal'), findsOneWidget);
});
testWidgets(
'affiche la distance indisponible quand la dernière mesure live la coupe',
(tester) async {
final now = DateTime.now().toUtc();
final clock = _FakeClock(now);
final repository = _FakeActiveSessionRepository();
final sensorUseCases = ActiveWorkoutSensorUseCases(clock: clock)
..recordTelemetrySample(
WatchSensorSample(
sessionId: 'session-1',
capturedAtEpochMs: now
.subtract(const Duration(seconds: 1))
.millisecondsSinceEpoch,
heartRateBpm: 124,
distanceMeters: 840,
caloriesKcal: 186,
),
)
..recordTelemetrySample(
WatchSensorSample(
sessionId: 'session-1',
capturedAtEpochMs: now.millisecondsSinceEpoch,
heartRateBpm: 126,
caloriesKcal: 188,
),
);
addTearDown(sensorUseCases.dispose);
final session = ActiveWorkoutSession(
metadata: _metadata('session-1'),
sourceWorkoutTemplateId: 'template-1',
status: ActiveWorkoutStatus.running,
startedAt: now,
lastPersistedAt: now,
elapsedActiveMs: 0,
currentProgramIndex: 0,
currentExerciseIndex: 0,
currentSetIndex: 0,
resolvedTemplateSnapshotJson: _sessionSnapshot(),
);
repository.session = session;
await tester.pumpWidget(
MaterialApp(
home: WorkoutExecutionScreen(
initialSession: session,
activeUseCases: _activeUseCases(repository, clock),
closeUseCase: _closeUseCase(repository, clock),
historyUseCases: _historyUseCases(clock),
workoutTemplateUseCases: _workoutTemplateUseCases(),
sensorUseCases: sensorUseCases,
),
),
);
expect(find.text('FC 126 bpm'), findsOneWidget);
expect(find.text('840 m'), findsNothing);
expect(find.text('Donnée indisponible'), findsOneWidget);
expect(find.text('188 kcal'), findsOneWidget);
},
);
testWidgets('affiche les états capteur explicites avant la première mesure', (
tester,
) async {