import 'package:block_seasons/data/save_repository.dart'; import 'package:block_seasons/game/engine/game_engine.dart'; import 'package:block_seasons/game/models/season.dart'; import 'package:block_seasons/l10n/gen/app_localizations.dart'; import 'package:block_seasons/state/providers.dart'; import 'package:block_seasons/ui/screens/game_screen.dart'; import 'package:block_seasons/ui/screens/season_map_screen.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:shared_preferences/shared_preferences.dart'; // The real 60-stage bundled pack is covered by the content repository // tests; the widget test uses a small pack because the bundled one is big // enough that loadString decodes on an isolate, which fake-async test time // never completes. SeasonPack _pack() => SeasonPack.fromJson({ 'schemaVersion': 1, 'seasonId': 'season_001', 'version': 1, 'title': {'en': 'First Bloom', 'ko': '첫 개화'}, 'theme': {'tileSet': 'spring', 'background': 'bg.webp'}, 'stages': [ for (var i = 1; i <= 3; i++) { 'id': 'season_001_00$i', 'seed': 100 + i, 'moveLimit': 20, 'preset': const >[], 'objectives': [ {'type': 'reachScore', 'target': 999999}, ], 'stars': { 'two': {'movesLeft': 5}, 'three': {'movesLeft': 10}, }, 'generatorProfile': 'mid', }, ], }); void main() { testWidgets('map shows stars, locks ahead, and starts unlocked stages', (tester) async { SharedPreferences.setMockInitialValues({}); final repo = SaveRepository(await SharedPreferences.getInstance()); await repo.recordResult( seasonId: 'season_001', stageId: 'season_001_001', stars: 2, score: 300, ); final container = ProviderContainer( overrides: [ saveRepositoryProvider.overrideWithValue(repo), seasonsProvider.overrideWith((ref) async => [_pack()]), ], ); addTearDown(container.dispose); await tester.pumpWidget( UncontrolledProviderScope( container: container, child: const MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, home: SeasonMapScreen(), ), ), ); await tester.pumpAndSettle(); expect(find.text('★ 2/9'), findsOneWidget); expect(find.byIcon(Icons.lock), findsOneWidget); // stage 3 locked expect(find.text('1'), findsOneWidget); expect(find.text('2'), findsOneWidget); // Stage 1 is starred, so stage 2 is unlocked and playable. await tester.tap(find.text('2')); await tester.pumpAndSettle(); expect(find.byType(GameScreen), findsOneWidget); final session = container.read(gameSessionProvider); expect(session, isNotNull); expect(session!.phase, GamePhase.playing); expect(container.read(seasonFlowProvider)!.stage.id, 'season_001_002'); }); }