// Widget tests for the booster bar mounted in the game screen. // // Board-geometry taps (hammer / line-bomb cell selection) are NOT covered here: // the board is laid out inside an Expanded/Center whose pixel geometry is not // deterministic in a widget test, so a pixel-accurate cell tap is unreliable. // Those paths are left to manual QA (see the agent report). What we CAN verify // deterministically is the inventory side-effect: shuffle applies immediately // and spends one booster. import 'package:block_seasons/core/rng.dart'; import 'package:block_seasons/data/save_repository.dart'; import 'package:block_seasons/game/engine/piece_generator.dart'; import 'package:block_seasons/game/models/booster.dart'; import 'package:block_seasons/game/models/stage.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:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:shared_preferences/shared_preferences.dart'; StageConfig _stage() => StageConfig.fromJson({ 'id': 'ui_b', 'seed': 1, 'moveLimit': 20, 'preset': [ {'x': 0, 'y': 0, 't': 'filled', 'c': 3}, ], 'objectives': [ {'type': 'reachScore', 'target': 100000}, ], 'stars': { 'two': {'movesLeft': 5}, 'three': {'movesLeft': 10}, }, }); Widget _wrap(ProviderContainer c) => UncontrolledProviderScope( container: c, child: MaterialApp( debugShowCheckedModeBanner: false, locale: const Locale('en'), localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, home: const GameScreen(), ), ); void main() { TestWidgetsFlutterBinding.ensureInitialized(); Future startedContainer() async { SharedPreferences.setMockInitialValues({}); final repo = SaveRepository(await SharedPreferences.getInstance()); final c = ProviderContainer(overrides: [ saveRepositoryProvider.overrideWithValue(repo), ]); c.read(gameSessionProvider.notifier).startStage( _stage(), generator: PieceGenerator(SeededRng(1)), ); return c; } testWidgets('tapping shuffle applies immediately and spends one booster', (tester) async { final c = await startedContainer(); await c.read(boosterInventoryProvider.notifier).grant(BoosterType.shuffle); expect(c.read(boosterInventoryProvider)[BoosterType.shuffle], 1); await tester.pumpWidget(_wrap(c)); await tester.pump(); await tester.tap(find.byKey(const ValueKey('booster_shuffle'))); await tester.pump(); await tester.pump(); expect(c.read(boosterInventoryProvider)[BoosterType.shuffle], 0); c.dispose(); }); }