import 'package:flutter_test/flutter_test.dart'; import 'package:gametime/application/application.dart'; import 'package:watch_bridge_contract/watch_bridge_contract.dart'; void main() { test('builds active timer notification content', () { final content = buildSessionNotificationContent( _projection( exerciseName: 'Squats bulgares', dominantTimer: _timer(label: 'Chrono étape', accumulatedMs: 134000), ), ); expect(content.title, 'Squats bulgares'); expect(content.primaryLine, '02:14'); expect(content.secondaryLine, 'Série 2/4'); }); test('builds manual score notification content', () { final content = buildSessionNotificationContent( _projection( exerciseName: 'Lancers francs', hasManualScore: true, currentManualScoreValue: 8, ), ); expect(content.title, 'Lancers francs'); expect(content.primaryLine, 'Série 2/4 · 8'); }); test('builds rest notification content with next exercise', () { final now = DateTime.utc(2026, 7, 26, 10); final content = buildSessionNotificationContent( _projection( phase: WatchSessionPhase.restRunning, exerciseName: 'Squats', nextExerciseName: 'Fentes', dominantTimer: _timer( kind: WatchTimerKind.rest, displayMode: WatchTimerDisplayMode.countdown, runState: WatchTimerRunState.running, accumulatedMs: 10000, targetMs: 60000, startedAtEpochMs: now.millisecondsSinceEpoch, ), ), now: now.add(const Duration(seconds: 5)), ); expect(content.title, 'Repos'); expect(content.primaryLine, '00:45 restant · Ensuite : Fentes'); }); test('prefixes paused content without ticking', () { final content = buildSessionNotificationContent( _projection( phase: WatchSessionPhase.paused, dominantTimer: _timer( runState: WatchTimerRunState.paused, accumulatedMs: 42000, ), ), now: DateTime.utc(2026, 7, 26, 10), ); expect(content.primaryLine, 'En pause · 00:42'); }); test('falls back to current step name without timer or score', () { final content = buildSessionNotificationContent( _projection(stepName: 'Gainage'), ); expect(content.primaryLine, 'Gainage'); }); } WatchSessionProjection _projection({ WatchSessionPhase phase = WatchSessionPhase.running, String exerciseName = 'Pompes', String? stepName, WatchTimerProjection? dominantTimer, bool hasManualScore = false, double? currentManualScoreValue, String? nextExerciseName, }) { return WatchSessionProjection( deviceSessionId: 'session-1', revision: 1, projectedAtEpochMs: DateTime.utc(2026, 7, 26, 10).millisecondsSinceEpoch, phase: phase, phoneReachable: true, seriesIndex: 2, seriesTotal: 4, exerciseName: exerciseName, stepName: stepName, dominantTimer: dominantTimer, primaryAction: WatchPrimaryAction.pauseSession, nextExerciseName: nextExerciseName, hasManualScore: hasManualScore, currentManualScoreValue: currentManualScoreValue, canDecrementScore: (currentManualScoreValue ?? 0) > 0, ); } WatchTimerProjection _timer({ WatchTimerKind kind = WatchTimerKind.step, String label = 'Chrono', WatchTimerDisplayMode displayMode = WatchTimerDisplayMode.elapsed, WatchTimerRunState runState = WatchTimerRunState.stopped, int accumulatedMs = 0, int? startedAtEpochMs, int? targetMs, }) { return WatchTimerProjection( kind: kind, label: label, displayMode: displayMode, runState: runState, referenceEpochMs: DateTime.utc(2026, 7, 26, 10).millisecondsSinceEpoch, accumulatedMs: accumulatedMs, startedAtEpochMs: startedAtEpochMs, targetMs: targetMs, ); }