import 'dart:convert'; import 'dart:io'; import 'package:block_seasons/data/content_repository.dart'; import 'package:block_seasons/game/models/season.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); test('loads the bundled Season 1 pack with 60 calibrated stages', () async { final repo = ContentRepository(); final pack = await repo.loadBundledSeason('season_001'); expect(pack.seasonId, 'season_001'); expect(pack.stages, hasLength(60)); expect(pack.titleFor('ko'), '첫 개화'); // Sanity: every stage has a positive budget and at least one objective. for (final stage in pack.stages) { expect(stage.moveLimit, greaterThan(0), reason: stage.id); expect(stage.objectives, isNotEmpty, reason: stage.id); expect(stage.stars.threeMovesLeft, greaterThan(stage.stars.twoMovesLeft), reason: stage.id); } }); test('availableSeasons returns the bundled season', () async { final repo = ContentRepository(); final seasons = await repo.availableSeasons(); expect(seasons.map((s) => s.seasonId), contains('season_001')); }); group('cache merge and fallback', () { late Directory tmp; setUp(() async { tmp = await Directory.systemTemp.createTemp('bs_repo_'); }); tearDown(() async { if (await tmp.exists()) await tmp.delete(recursive: true); }); Map packJson(String id) => { 'schemaVersion': 1, 'seasonId': id, 'version': 1, 'title': {'en': id}, 'theme': const SeasonTheme().toJson(), 'stages': [ { 'id': '${id}_001', 'seed': 1, 'moveLimit': 10, 'preset': [], 'objectives': [ {'type': 'reachScore', 'target': 100} ], 'stars': { 'two': {'movesLeft': 2}, 'three': {'movesLeft': 4} }, 'generatorProfile': 'mid', } ], }; Future putCachedSeason(String id) async { final dir = Directory('${tmp.path}/seasons/$id'); await dir.create(recursive: true); await File('${dir.path}/pack.json') .writeAsString(jsonEncode(packJson(id))); } test('merges cached seasons after bundled ones, sorted by id', () async { TestWidgetsFlutterBinding.ensureInitialized(); await putCachedSeason('season_002'); final repo = ContentRepository(cacheDir: tmp); final seasons = await repo.availableSeasons(); expect(seasons.map((s) => s.seasonId).toList(), ['season_001', 'season_002']); }); test('cached copy of a bundled season wins over the bundle', () async { TestWidgetsFlutterBinding.ensureInitialized(); await putCachedSeason('season_001'); final repo = ContentRepository(cacheDir: tmp); final seasons = await repo.availableSeasons(); // Cached fake has exactly 1 stage; the bundled real one has 60. expect(seasons.single.stages, hasLength(1)); }); test('corrupt cached pack falls back to bundle silently', () async { TestWidgetsFlutterBinding.ensureInitialized(); final dir = Directory('${tmp.path}/seasons/season_001'); await dir.create(recursive: true); await File('${dir.path}/pack.json').writeAsString('{not json'); final repo = ContentRepository(cacheDir: tmp); final seasons = await repo.availableSeasons(); expect(seasons.single.stages, hasLength(60)); }); }); }