From d0756e0b60058583cfa0d49ae7e22b7a62dc5d5b Mon Sep 17 00:00:00 2001 From: Erick Date: Fri, 11 Mar 2022 09:09:37 -0300 Subject: [PATCH] feat: adding ball spawning upon click on debug mode (#28) * feat: adding ball spawming upon click on debug mode * PR suggestions * fix: coverage * fix: rebase * feat: rebase fixes --- lib/game/components/ball.dart | 2 +- lib/game/pinball_game.dart | 9 +++++ lib/game/view/pinball_game_page.dart | 14 ++++++- test/game/pinball_game_test.dart | 20 +++++++++ test/game/view/pinball_game_page_test.dart | 47 +++++++++++++++++++++- test/helpers/extensions.dart | 10 +++++ test/helpers/mocks.dart | 5 +++ 7 files changed, 102 insertions(+), 5 deletions(-) diff --git a/lib/game/components/ball.dart b/lib/game/components/ball.dart index 20aa924e..d1721927 100644 --- a/lib/game/components/ball.dart +++ b/lib/game/components/ball.dart @@ -53,7 +53,7 @@ class Ball extends PositionBodyComponent { final bloc = gameRef.read()..add(const BallLost()); - final shouldBallRespwan = !bloc.state.isLastBall; + final shouldBallRespwan = !bloc.state.isLastBall && !bloc.state.isGameOver; if (shouldBallRespwan) { gameRef.spawnBall(); } diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index 5854422c..7d6fba41 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -105,3 +105,12 @@ class PinballGame extends Forge2DGame ); } } + +class DebugPinballGame extends PinballGame with TapDetector { + DebugPinballGame({required PinballTheme theme}) : super(theme: theme); + + @override + void onTapUp(TapUpInfo info) { + add(Ball(position: info.eventPosition.game)); + } +} diff --git a/lib/game/view/pinball_game_page.dart b/lib/game/view/pinball_game_page.dart index 95997832..4af2168e 100644 --- a/lib/game/view/pinball_game_page.dart +++ b/lib/game/view/pinball_game_page.dart @@ -1,6 +1,7 @@ // ignore_for_file: public_member_api_docs import 'package:flame/game.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:pinball/game/game.dart'; @@ -29,9 +30,15 @@ class PinballGamePage extends StatelessWidget { } class PinballGameView extends StatefulWidget { - const PinballGameView({Key? key, required this.theme}) : super(key: key); + const PinballGameView({ + Key? key, + required this.theme, + bool isDebugMode = kDebugMode, + }) : _isDebugMode = isDebugMode, + super(key: key); final PinballTheme theme; + final bool _isDebugMode; @override State createState() => _PinballGameViewState(); @@ -47,7 +54,10 @@ class _PinballGameViewState extends State { // TODO(erickzanardo): Revisit this when we start to have more assets // this could expose a Stream (maybe even a cubit?) so we could show the // the loading progress with some fancy widgets. - _game = PinballGame(theme: widget.theme)..preLoadAssets(); + _game = (widget._isDebugMode + ? DebugPinballGame(theme: widget.theme) + : PinballGame(theme: widget.theme)) + ..preLoadAssets(); } @override diff --git a/test/game/pinball_game_test.dart b/test/game/pinball_game_test.dart index 3048308b..f1d6bb32 100644 --- a/test/game/pinball_game_test.dart +++ b/test/game/pinball_game_test.dart @@ -3,6 +3,7 @@ import 'package:flame/components.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; import 'package:pinball/game/game.dart'; import '../helpers/helpers.dart'; @@ -11,6 +12,7 @@ void main() { group('PinballGame', () { TestWidgetsFlutterBinding.ensureInitialized(); final flameTester = FlameTester(PinballGameTest.create); + final debugModeFlameTester = FlameTester(DebugPinballGameTest.create); // TODO(alestiago): test if [PinballGame] registers // [BallScorePointsCallback] once the following issue is resolved: @@ -49,6 +51,24 @@ void main() { ); }, ); + + debugModeFlameTester.test('adds a ball on tap up', (game) async { + await game.ready(); + + final eventPosition = MockEventPosition(); + when(() => eventPosition.game).thenReturn(Vector2.all(10)); + + final tapUpEvent = MockTapUpInfo(); + when(() => tapUpEvent.eventPosition).thenReturn(eventPosition); + + game.onTapUp(tapUpEvent); + await game.ready(); + + expect( + game.children.whereType().length, + equals(1), + ); + }); }); }, ); diff --git a/test/game/view/pinball_game_page_test.dart b/test/game/view/pinball_game_page_test.dart index fcfbe149..0e3ee963 100644 --- a/test/game/view/pinball_game_page_test.dart +++ b/test/game/view/pinball_game_page_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: prefer_const_constructors + import 'package:bloc_test/bloc_test.dart'; import 'package:flame/game.dart'; import 'package:flutter/material.dart'; @@ -20,7 +22,7 @@ void main() { ); await tester.pumpApp( - const PinballGamePage(theme: theme), + PinballGamePage(theme: theme), gameBloc: gameBloc, ); expect(find.byType(PinballGameView), findsOneWidget); @@ -64,9 +66,10 @@ void main() { ); await tester.pumpApp( - const PinballGameView(theme: theme), + PinballGameView(theme: theme), gameBloc: gameBloc, ); + expect( find.byWidgetPredicate((w) => w is GameWidget), findsOneWidget, @@ -100,5 +103,45 @@ void main() { ); }, ); + + testWidgets('renders the real game when not in debug mode', (tester) async { + final gameBloc = MockGameBloc(); + whenListen( + gameBloc, + Stream.value(const GameState.initial()), + initialState: const GameState.initial(), + ); + + await tester.pumpApp( + const PinballGameView(theme: theme, isDebugMode: false), + gameBloc: gameBloc, + ); + expect( + find.byWidgetPredicate( + (w) => w is GameWidget && w.game is! DebugPinballGame, + ), + findsOneWidget, + ); + }); + + testWidgets('renders the debug game when on debug mode', (tester) async { + final gameBloc = MockGameBloc(); + whenListen( + gameBloc, + Stream.value(const GameState.initial()), + initialState: const GameState.initial(), + ); + + await tester.pumpApp( + const PinballGameView(theme: theme), + gameBloc: gameBloc, + ); + expect( + find.byWidgetPredicate( + (w) => w is GameWidget && w.game is DebugPinballGame, + ), + findsOneWidget, + ); + }); }); } diff --git a/test/helpers/extensions.dart b/test/helpers/extensions.dart index a976abd9..2a0a7e59 100644 --- a/test/helpers/extensions.dart +++ b/test/helpers/extensions.dart @@ -10,3 +10,13 @@ extension PinballGameTest on PinballGame { ), ); } + +/// [DebugPinballGame] extension to reduce boilerplate in tests. +extension DebugPinballGameTest on DebugPinballGame { + /// Create [PinballGame] with default [PinballTheme]. + static DebugPinballGame create() => DebugPinballGame( + theme: const PinballTheme( + characterTheme: DashTheme(), + ), + ); +} diff --git a/test/helpers/mocks.dart b/test/helpers/mocks.dart index 44e78afe..46886752 100644 --- a/test/helpers/mocks.dart +++ b/test/helpers/mocks.dart @@ -1,3 +1,4 @@ +import 'package:flame/input.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; @@ -32,3 +33,7 @@ class MockRawKeyUpEvent extends Mock implements RawKeyUpEvent { return super.toString(); } } + +class MockTapUpInfo extends Mock implements TapUpInfo {} + +class MockEventPosition extends Mock implements EventPosition {}