// Author: fruit.com.cn import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:fruitshorts/pages/player/widgets/player_double_tap_hearts.dart'; void main() { testWidgets('should_show_three_develop_hearts_when_burst_starts', ( tester, ) async { await tester.pumpWidget( const MaterialApp( home: Scaffold( body: PlayerDoubleTapHeartBurst(burstId: 1, onCompleted: _noop), ), ), ); await tester.pump(const Duration(milliseconds: 200)); expect(find.byIcon(Icons.favorite_rounded), findsNWidgets(3)); expect(_size(tester, 0), 48); expect(_size(tester, 1), 36); expect(_size(tester, 2), 40); final elapsedText = tester .widget(find.byKey(const Key('heart-burst-elapsed-debug'))) .data!; final elapsedMs = int.parse(elapsedText.replaceFirst('ms', '')); expect(elapsedMs, inInclusiveRange(180, 220)); expect( tester .widgetList( find.descendant( of: find.byType(PlayerDoubleTapHeartBurst), matching: find.byType(Stack), ), ) .every((stack) => stack.clipBehavior == Clip.none), isTrue, ); }); testWidgets('heart burst keeps opacity then fades after 55 percent', ( tester, ) async { await tester.pumpWidget( const MaterialApp( home: Scaffold( body: PlayerDoubleTapHeartBurst(burstId: 2, onCompleted: _noop), ), ), ); await tester.pump(const Duration(milliseconds: 450)); expect(_opacity(tester, 0), closeTo(1, 1e-9)); await tester.pump(const Duration(milliseconds: 750)); expect(_opacity(tester, 0), lessThan(0.5)); }); testWidgets('heart position is anchored to the overlay origin', ( tester, ) async { const origin = Offset(300, 546); await tester.pumpWidget( const MaterialApp( home: Scaffold( body: Stack( fit: StackFit.expand, children: [ Positioned.fill( child: PlayerDoubleTapHeartBurst( burstId: 4, origin: origin, onCompleted: _noop, ), ), ], ), ), ), ); final firstHeart = find.byKey(const Key('double-tap-heart-0')); expect( (tester.getCenter(firstHeart) - origin).distance, lessThanOrEqualTo(1), ); final debugTopLeft = tester.getTopLeft( find.byKey(const Key('heart-burst-elapsed-debug')), ); expect( (debugTopLeft - const Offset(308, 556)).distance, lessThanOrEqualTo(1), ); await tester.pump(const Duration(milliseconds: 750)); final midpoint = tester.getCenter(firstHeart); expect(midpoint.dy, lessThan(origin.dy)); expect((midpoint.dx - origin.dx).abs(), lessThanOrEqualTo(1)); }); testWidgets('develop heart burst completes after about 1590ms', ( tester, ) async { var completed = false; var elapsedMs = 0; await tester.pumpWidget( MaterialApp( home: Scaffold( body: PlayerDoubleTapHeartBurst( burstId: 3, onCompleted: () => completed = true, ), ), ), ); while (!completed && elapsedMs < 2000) { await tester.pump(const Duration(milliseconds: 16)); elapsedMs += 16; } expect(completed, isTrue); expect(elapsedMs, greaterThanOrEqualTo(1584)); expect(elapsedMs, lessThanOrEqualTo(1616)); }); } double _size(WidgetTester tester, int index) { return tester.widget(find.byKey(Key('double-tap-heart-$index'))).size!; } double _opacity(WidgetTester tester, int index) { final opacity = find .ancestor( of: find.byKey(Key('double-tap-heart-$index')), matching: find.byType(Opacity), ) .first; return tester.widget(opacity).opacity; } void _noop() {}