import 'package:block_seasons/game/engine/game_engine.dart'; import 'package:block_seasons/ui/widgets/effects_overlay.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; PlacementResult _clearResult() => const PlacementResult( events: [], pointsGained: 250, linesCleared: 1, gemsCleared: 0, clearedRows: [3], clearedCols: [], comboStreak: 2, ); void main() { testWidgets('second batch after drain completes within its own duration', (tester) async { final key = GlobalKey(); await tester.pumpWidget(MaterialApp( home: Stack(children: [Positioned.fill(child: EffectsOverlay(key: key))]), )); const board = Rect.fromLTWH(0, 0, 320, 320); // ── First batch ────────────────────────────────────────────────────────── key.currentState!.onPlacement(_clearResult(), boardRect: board); await tester.pumpAndSettle(); // Ticker must be stopped after the first drain. expect( key.currentState!.ticker.isActive, isFalse, reason: 'ticker should be idle after first batch drains', ); // _now must be Duration.zero after drain (regression for stale-clock bug). // Without the fix, _now stays frozen at the elapsed value from the last // tick of the first batch (~1000 ms). expect( key.currentState!.now, Duration.zero, reason: '_now must be reset to zero when the list drains so the next ' 'batch starts from a clean clock', ); // ── Second batch ───────────────────────────────────────────────────────── // With the stale-clock bug the effects get start: ~1000ms, but the // restarted ticker delivers elapsed from 0, so progress stays 0 forever // and they never drain. We verify the second batch completes via // pumpAndSettle (which would time out if the ticker ran forever). key.currentState!.onPlacement(_clearResult(), boardRect: board); await tester.pump(const Duration(milliseconds: 100)); await tester.pumpAndSettle(); expect( tester.hasRunningAnimations, isFalse, reason: 'second batch must finish; stale clock would keep effects frozen ' 'and the ticker running indefinitely', ); }); }