fix(persistence): correctifs post-QA sur les repositories (ticket #13)

Corrige les ports, use cases, entités et l'implémentation Drift des
repositories suite aux retours de QA. flutter analyze propre, 24/24
tests verts, build APK debug validé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 22:14:07 +02:00
parent 009615c6a5
commit 9f9d0dbe3b
7 changed files with 227 additions and 0 deletions

View File

@ -111,6 +111,104 @@ void main() {
clock.value = clock.value.add(const Duration(seconds: 15));
expect(resumed.elapsedActiveMillisecondsAt(clock.now()), 45000);
});
test('adjustRestSeconds persists adjusted rest duration', () async {
final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12));
final repository = _FakeActiveSessionRepository()
..restStates['rest-1'] = ActiveRestState(
metadata: _metadata('rest-1'),
activeWorkoutSessionId: 'session-1',
afterProgramIndex: 0,
afterExerciseIndex: 0,
afterSetIndex: 0,
plannedRestSeconds: 60,
adjustedRestSeconds: 60,
startedAt: clock.now(),
);
final useCase = _activeUseCase(repository, clock);
final adjusted = await useCase.adjustRestSeconds(
restStateId: 'rest-1',
deltaSeconds: -75,
);
expect(adjusted.adjustedRestSeconds, 0);
expect(repository.restStates['rest-1']!.adjustedRestSeconds, 0);
});
test('skipRest persists skippedAt timestamp', () async {
final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12));
final repository = _FakeActiveSessionRepository()
..restStates['rest-1'] = ActiveRestState(
metadata: _metadata('rest-1'),
activeWorkoutSessionId: 'session-1',
afterProgramIndex: 0,
afterExerciseIndex: 0,
afterSetIndex: 0,
plannedRestSeconds: 60,
adjustedRestSeconds: 60,
startedAt: clock.now(),
);
clock.value = clock.value.add(const Duration(seconds: 10));
final useCase = _activeUseCase(repository, clock);
final skipped = await useCase.skipRest(restStateId: 'rest-1');
expect(skipped.skippedAt, clock.now());
expect(repository.restStates['rest-1']!.skippedAt, clock.now());
});
test('findActiveRest returns latest non-ended non-skipped rest', () async {
final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12));
final repository = _FakeActiveSessionRepository()
..restStates['ended'] = ActiveRestState(
metadata: _metadata('ended'),
activeWorkoutSessionId: 'session-1',
afterProgramIndex: 0,
afterExerciseIndex: 0,
afterSetIndex: 0,
plannedRestSeconds: 60,
adjustedRestSeconds: 60,
startedAt: clock.now(),
endedAt: clock.now().add(const Duration(seconds: 60)),
)
..restStates['older-active'] = ActiveRestState(
metadata: _metadata('older-active'),
activeWorkoutSessionId: 'session-1',
afterProgramIndex: 0,
afterExerciseIndex: 1,
afterSetIndex: 0,
plannedRestSeconds: 60,
adjustedRestSeconds: 60,
startedAt: clock.now().add(const Duration(seconds: 30)),
)
..restStates['latest-active'] = ActiveRestState(
metadata: _metadata('latest-active'),
activeWorkoutSessionId: 'session-1',
afterProgramIndex: 0,
afterExerciseIndex: 2,
afterSetIndex: 0,
plannedRestSeconds: 60,
adjustedRestSeconds: 60,
startedAt: clock.now().add(const Duration(seconds: 90)),
)
..restStates['skipped'] = ActiveRestState(
metadata: _metadata('skipped'),
activeWorkoutSessionId: 'session-1',
afterProgramIndex: 0,
afterExerciseIndex: 3,
afterSetIndex: 0,
plannedRestSeconds: 60,
adjustedRestSeconds: 60,
startedAt: clock.now().add(const Duration(seconds: 120)),
skippedAt: clock.now().add(const Duration(seconds: 125)),
);
final useCase = _activeUseCase(repository, clock);
final active = await useCase.findActiveRest(sessionId: 'session-1');
expect(active?.metadata.id, 'latest-active');
});
}
EntityMetadata _metadata(String id) {
@ -181,3 +279,51 @@ final class _FakeProgramRepository implements ProgramRepository {
@override
Future<void> saveExercise(ProgramExercise exercise) async {}
}
ActiveWorkoutSessionUseCases _activeUseCase(
_FakeActiveSessionRepository repository,
_FakeClock clock,
) {
return ActiveWorkoutSessionUseCases(
sessionRepository: repository,
templateRepository: _FakeWorkoutTemplateRepository(),
clock: clock,
ids: _FakeIds(),
originDeviceId: 'device-1',
);
}
final class _FakeActiveSessionRepository implements ActiveSessionRepository {
final restStates = <String, ActiveRestState>{};
@override
Future<ActiveWorkoutSession?> findById(String id) async => null;
@override
Future<ActiveWorkoutSession?> findOpen() async => null;
@override
Future<ActiveRestState?> findRestStateById(String id) async => restStates[id];
@override
Future<List<ActiveRestState>> listRestStates(String sessionId) async {
return restStates.values
.where((rest) => rest.activeWorkoutSessionId == sessionId)
.toList();
}
@override
Future<List<ActiveSetResult>> listSetResults(String sessionId) async =>
const [];
@override
Future<void> save(ActiveWorkoutSession session) async {}
@override
Future<void> saveRestState(ActiveRestState restState) async {
restStates[restState.metadata.id] = restState;
}
@override
Future<void> saveSetResult(ActiveSetResult result) async {}
}