import 'dart:convert'; import 'dart:io'; final class VersionedSyncFixture { const VersionedSyncFixture({ required this.resourceType, required this.name, required this.schemaVersion, required this.payload, }); final String resourceType; final String name; final int schemaVersion; final Map payload; } VersionedSyncFixture loadExerciseFixture(String name, {String version = 'v1'}) { return _loadFixture( resourceType: 'exercise', path: 'test/fixtures/exercises/$version/$name.json', name: name, ); } VersionedSyncFixture loadProgramFixture(String name, {String version = 'v1'}) { return _loadFixture( resourceType: 'program', path: 'test/fixtures/programs/$version/$name.json', name: name, ); } VersionedSyncFixture loadWorkoutTemplateFixture( String name, { String version = 'v1', }) { return _loadFixture( resourceType: 'workoutTemplate', path: 'test/fixtures/workout_templates/$version/$name.json', name: name, ); } VersionedSyncFixture loadWorkoutHistoryFixture( String name, { String version = 'v1', }) { return _loadFixture( resourceType: 'workoutHistory', path: 'test/fixtures/workout_histories/$version/$name.json', name: name, ); } List loadExerciseFixtures({ String version = 'v1', List names = const [ 'minimal', 'with_steps', 'with_score_chrono', 'with_timers', 'full_combo', ], }) { return [ for (final name in names) loadExerciseFixture(name, version: version), ]; } List loadMinimalResourceFixtures({ String version = 'v1', }) { return [ loadProgramFixture('minimal', version: version), loadWorkoutTemplateFixture('minimal', version: version), loadWorkoutHistoryFixture('minimal', version: version), ]; } VersionedSyncFixture _loadFixture({ required String resourceType, required String path, required String name, }) { final raw = File(path).readAsStringSync(); final decoded = jsonDecode(raw); if (decoded is! Map) { throw StateError('Fixture $path must contain a JSON object.'); } final schemaVersion = decoded['schemaVersion']; if (schemaVersion is! int || schemaVersion <= 0) { throw StateError('Fixture $path must contain a positive schemaVersion.'); } return VersionedSyncFixture( resourceType: resourceType, name: name, schemaVersion: schemaVersion, payload: decoded, ); }