Files
GameTime/test/application/use_cases_test.dart
Blomios 7b6d21450b fix(qa): corrections issues de la passe QA fonctionnelle
Corrige les bugs identifiés lors de la QA finale sur use_cases.dart et
drift_repositories.dart, ajoute la couverture de tests d'infrastructure
manquante (test/infrastructure/drift_repositories_test.dart).
flutter analyze propre, 21/21 tests verts, build APK debug validé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:28:38 +02:00

184 lines
5.1 KiB
Dart

import 'dart:convert';
import 'package:flutter_test/flutter_test.dart';
import 'package:gametime/application/application.dart';
import 'package:gametime/domain/domain.dart';
void main() {
test('Exercise requires at least one active measure', () {
expect(
() => Exercise(
metadata: _metadata('exercise-1'),
name: 'Push up',
hasTimeMeasure: false,
hasRepsMeasure: false,
hasScoreMeasure: false,
),
throwsA(isA<DomainException>()),
);
});
test('Workout template use case rejects active measure overrides', () async {
final useCase = WorkoutTemplateUseCases(
templateRepository: _FakeWorkoutTemplateRepository(),
programRepository: _FakeProgramRepository(),
clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
ids: _FakeIds(),
originDeviceId: 'device-1',
);
await expectLater(
useCase.overrideExerciseTargets(
workoutTemplateProgramId: 'template-program-1',
snapshotProgramExerciseId: 'exercise-snapshot-1',
attemptedMeasureOverride: {WorkoutMeasure.reps},
),
throwsA(isA<DomainException>()),
);
});
test(
'Workout template use case rejects target overrides for inactive measures',
() async {
final useCase = WorkoutTemplateUseCases(
templateRepository: _FakeWorkoutTemplateRepository(),
programRepository: _FakeProgramRepository(),
clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
ids: _FakeIds(),
originDeviceId: 'device-1',
);
await expectLater(
useCase.saveConfigured(
name: 'Séance tir',
programs: [
WorkoutTemplateProgramConfig(
clientKey: 'program-1',
programNameSnapshot: 'Programme tir',
defaultRestSecondsSnapshot: 30,
programSnapshotJson: jsonEncode({
'exercises': [
{
'id': 'exercise-snapshot-1',
'exerciseNameSnapshot': 'Lancers francs',
'setsCount': 3,
'timeEnabled': true,
'repsEnabled': false,
'scoreEnabled': false,
'targetTimeSeconds': 60,
'targetReps': null,
'targetScore': null,
},
],
}),
),
],
overrides: const [
WorkoutTemplateExerciseOverrideConfig(
workoutTemplateProgramClientKey: 'program-1',
snapshotProgramExerciseId: 'exercise-snapshot-1',
targetRepsOverride: 10,
),
],
),
throwsA(isA<DomainException>()),
);
},
);
test('Active session elapsed time is based on persisted timestamps', () {
final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12));
final session = ActiveWorkoutSession(
metadata: _metadata('session-1'),
status: ActiveWorkoutStatus.running,
startedAt: clock.now(),
lastPersistedAt: clock.now(),
elapsedActiveMs: 0,
currentProgramIndex: 0,
currentExerciseIndex: 0,
currentSetIndex: 0,
resolvedTemplateSnapshotJson: '{}',
);
clock.value = clock.value.add(const Duration(seconds: 30));
final paused = session.pause(clock.now());
expect(paused.elapsedActiveMs, 30000);
clock.value = clock.value.add(const Duration(minutes: 5));
final resumed = paused.resume(clock.now());
expect(resumed.elapsedActiveMillisecondsAt(clock.now()), 30000);
clock.value = clock.value.add(const Duration(seconds: 15));
expect(resumed.elapsedActiveMillisecondsAt(clock.now()), 45000);
});
}
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 {
_FakeClock(this.value);
DateTime value;
@override
DateTime now() => value;
}
final class _FakeIds implements IdGenerator {
var _next = 0;
@override
String newId() {
_next += 1;
return 'id-$_next';
}
}
final class _FakeWorkoutTemplateRepository
implements WorkoutTemplateRepository {
@override
Future<WorkoutTemplate?> findById(String id) async => null;
@override
Future<List<WorkoutTemplate>> listActive() async => const [];
@override
Future<void> replaceComposition(
WorkoutTemplate template,
DateTime deletedAt,
) async {}
@override
Future<void> save(WorkoutTemplate template) async {}
@override
Future<void> saveOverride(WorkoutTemplateExerciseOverride override) async {}
@override
Future<void> saveProgram(WorkoutTemplateProgram program) async {}
}
final class _FakeProgramRepository implements ProgramRepository {
@override
Future<Program?> findById(String id) async => null;
@override
Future<List<Program>> listActive() async => const [];
@override
Future<void> replaceExercises(Program program, DateTime deletedAt) async {}
@override
Future<void> save(Program program) async {}
@override
Future<void> saveExercise(ProgramExercise exercise) async {}
}