From 0a01e3b5fb14070d9e0006cb4d8bcf00fc045589 Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 2 Mar 2022 06:10:50 -0300 Subject: [PATCH 1/5] chore: updating flame, flame_forge2d and flame_bloc versions (#4) * chore: updating flame, flame_forge2d and flame_bloc versions * adding FlameBloc to the PinballGame * refactor: sorted pub dependencies Co-authored-by: alestiago --- lib/game/pinball_game.dart | 3 ++- pubspec.lock | 11 +++++++++-- pubspec.yaml | 5 +++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index 306d03f0..6bf24a20 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -1,3 +1,4 @@ +import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_forge2d/forge2d_game.dart'; -class PinballGame extends Forge2DGame {} +class PinballGame extends Forge2DGame with FlameBloc {} diff --git a/pubspec.lock b/pubspec.lock index 86f1fbe5..55901a4e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -133,14 +133,21 @@ packages: name: flame url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0-releasecandidate.1" + flame_bloc: + dependency: "direct main" + description: + name: flame_bloc + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0-releasecandidate.1" flame_forge2d: dependency: "direct main" description: name: flame_forge2d url: "https://pub.dartlang.org" source: hosted - version: "0.8.3" + version: "0.9.0-releasecandidate.1" flutter: dependency: "direct main" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index f703cd22..2bd5be03 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,8 +8,9 @@ environment: dependencies: bloc: ^8.0.2 - flame: ^1.0.0 - flame_forge2d: ^0.8.3 + flame: ^1.1.0-releasecandidate.1 + flame_bloc: ^1.2.0-releasecandidate.1 + flame_forge2d: ^0.9.0-releasecandidate.1 flutter: sdk: flutter flutter_bloc: ^8.0.1 From be299bcd51a68d3993e814be39519a71aef84f61 Mon Sep 17 00:00:00 2001 From: Alejandro Santiago Date: Wed, 2 Mar 2022 09:40:37 +0000 Subject: [PATCH 2/5] chore: included dependecy on flame_test (#5) --- pubspec.lock | 7 +++++++ pubspec.yaml | 1 + 2 files changed, 8 insertions(+) diff --git a/pubspec.lock b/pubspec.lock index 55901a4e..cff109ca 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -148,6 +148,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.9.0-releasecandidate.1" + flame_test: + dependency: "direct dev" + description: + name: flame_test + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 2bd5be03..3730daa3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,6 +20,7 @@ dependencies: dev_dependencies: bloc_test: ^9.0.2 + flame_test: ^1.1.0 flutter_test: sdk: flutter mockingjay: ^0.2.0 From 0d27b7f762955f9f7738e095a048fe7362e3e443 Mon Sep 17 00:00:00 2001 From: Alejandro Santiago Date: Wed, 2 Mar 2022 13:47:46 +0000 Subject: [PATCH 3/5] feat: included initial Ball body component (#6) * feat: included initial ball body component * feat: included loads correctly test * chore: moved test to correct directory * refactor: replaced vector instances * refactor: modified exists test * refactor: reused flameTester --- lib/game/components/ball.dart | 28 ++++++++++ lib/game/components/components.dart | 1 + lib/game/game.dart | 1 + test/game/components/ball_test.dart | 83 +++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 lib/game/components/ball.dart create mode 100644 lib/game/components/components.dart create mode 100644 test/game/components/ball_test.dart diff --git a/lib/game/components/ball.dart b/lib/game/components/ball.dart new file mode 100644 index 00000000..ce2e4335 --- /dev/null +++ b/lib/game/components/ball.dart @@ -0,0 +1,28 @@ +import 'package:flame_forge2d/body_component.dart'; +import 'package:flutter/material.dart'; +import 'package:forge2d/forge2d.dart'; + +class Ball extends BodyComponent { + Ball({ + required Vector2 position, + }) : _position = position { + // TODO(alestiago): Use asset instead of color when provided. + paint = Paint()..color = const Color(0xFFFFFFFF); + } + + final Vector2 _position; + + @override + Body createBody() { + final shape = CircleShape()..radius = 2; + + final fixtureDef = FixtureDef(shape)..density = 1; + + final bodyDef = BodyDef() + ..userData = this + ..position = _position + ..type = BodyType.dynamic; + + return world.createBody(bodyDef)..createFixture(fixtureDef); + } +} diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart new file mode 100644 index 00000000..6a26208c --- /dev/null +++ b/lib/game/components/components.dart @@ -0,0 +1 @@ +export 'ball.dart'; diff --git a/lib/game/game.dart b/lib/game/game.dart index ec8e0824..0a8dac1b 100644 --- a/lib/game/game.dart +++ b/lib/game/game.dart @@ -1,2 +1,3 @@ +export 'components/components.dart'; export 'pinball_game.dart'; export 'view/pinball_game_page.dart'; diff --git a/test/game/components/ball_test.dart b/test/game/components/ball_test.dart new file mode 100644 index 00000000..c4576c68 --- /dev/null +++ b/test/game/components/ball_test.dart @@ -0,0 +1,83 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball/game/game.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('Ball', () { + final flameTester = FlameTester(PinballGame.new); + + flameTester.test( + 'loads correctly', + (game) async { + final ball = Ball(position: Vector2.zero()); + await game.ensureAdd(ball); + + expect(game.contains(ball), isTrue); + }, + ); + + group('body', () { + flameTester.test( + 'positions correctly', + (game) async { + final position = Vector2.all(10); + final ball = Ball(position: position); + await game.ensureAdd(ball); + game.contains(ball); + + expect(ball.body.position, position); + }, + ); + + flameTester.test( + 'is dynamic', + (game) async { + final ball = Ball(position: Vector2.zero()); + await game.ensureAdd(ball); + + expect(ball.body.bodyType, equals(BodyType.dynamic)); + }, + ); + }); + + group('first fixture', () { + flameTester.test( + 'exists', + (game) async { + final ball = Ball(position: Vector2.zero()); + await game.ensureAdd(ball); + + expect(ball.body.fixtures[0], isA()); + }, + ); + + flameTester.test( + 'is dense', + (game) async { + final ball = Ball(position: Vector2.zero()); + await game.ensureAdd(ball); + + final fixture = ball.body.fixtures[0]; + expect(fixture.density, greaterThan(0)); + }, + ); + + flameTester.test( + 'shape is circular', + (game) async { + final ball = Ball(position: Vector2.zero()); + await game.ensureAdd(ball); + + final fixture = ball.body.fixtures[0]; + expect(fixture.shape.shapeType, equals(ShapeType.circle)); + expect(fixture.shape.radius, equals(2)); + }, + ); + }); + }); +} From 18e1f950ad0e7547f11eb9a2738c9c714fff620e Mon Sep 17 00:00:00 2001 From: Alejandro Santiago Date: Wed, 2 Mar 2022 14:37:50 +0000 Subject: [PATCH 4/5] feat: implement GameBloc (#3) * chore: generated bloc using VS extension * chore: included equatable dependency * feat: implemented BallLost and Scored events * refactor: renamed ballsLeft to balls * chore: exported bloc in barrel file * feat: tested and improved GameState * feat: tested and improved GameState * feat: tested and improved GameEvent * feat: tested GameBloc * refactor: modified redundant test message * refactor: included initial factory constructor * refactor: corrected class doc comment * feat: made GameEvent support value equality * refactor: adapted equality test to pick coverage * refactor: moved linter ignore comment * refactor: removed const from equality comparison * refactor: changed factory constructor for named constructor * refactor: added trailing commas --- lib/game/bloc/game_bloc.dart | 25 ++++++ lib/game/bloc/game_event.dart | 26 ++++++ lib/game/bloc/game_state.dart | 49 +++++++++++ lib/game/game.dart | 1 + pubspec.lock | 7 ++ pubspec.yaml | 1 + test/game/bloc/game_bloc_test.dart | 63 +++++++++++++++ test/game/bloc/game_event_test.dart | 44 ++++++++++ test/game/bloc/game_state_test.dart | 121 ++++++++++++++++++++++++++++ 9 files changed, 337 insertions(+) create mode 100644 lib/game/bloc/game_bloc.dart create mode 100644 lib/game/bloc/game_event.dart create mode 100644 lib/game/bloc/game_state.dart create mode 100644 test/game/bloc/game_bloc_test.dart create mode 100644 test/game/bloc/game_event_test.dart create mode 100644 test/game/bloc/game_state_test.dart diff --git a/lib/game/bloc/game_bloc.dart b/lib/game/bloc/game_bloc.dart new file mode 100644 index 00000000..71c527a8 --- /dev/null +++ b/lib/game/bloc/game_bloc.dart @@ -0,0 +1,25 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:meta/meta.dart'; + +part 'game_event.dart'; +part 'game_state.dart'; + +class GameBloc extends Bloc { + GameBloc() : super(const GameState.initial()) { + on(_onBallLost); + on(_onScored); + } + + void _onBallLost(BallLost event, Emitter emit) { + if (state.balls > 0) { + emit(state.copyWith(balls: state.balls - 1)); + } + } + + void _onScored(Scored event, Emitter emit) { + if (!state.isGameOver) { + emit(state.copyWith(score: state.score + event.points)); + } + } +} diff --git a/lib/game/bloc/game_event.dart b/lib/game/bloc/game_event.dart new file mode 100644 index 00000000..88ef265b --- /dev/null +++ b/lib/game/bloc/game_event.dart @@ -0,0 +1,26 @@ +part of 'game_bloc.dart'; + +@immutable +abstract class GameEvent extends Equatable { + const GameEvent(); +} + +/// Event added when a user drops a ball off the screen. +class BallLost extends GameEvent { + const BallLost(); + + @override + List get props => []; +} + +/// Event added when a user increases their score. +class Scored extends GameEvent { + const Scored({ + required this.points, + }) : assert(points > 0, 'Points must be greater than 0'); + + final int points; + + @override + List get props => [points]; +} diff --git a/lib/game/bloc/game_state.dart b/lib/game/bloc/game_state.dart new file mode 100644 index 00000000..235e264d --- /dev/null +++ b/lib/game/bloc/game_state.dart @@ -0,0 +1,49 @@ +part of 'game_bloc.dart'; + +/// {@template game_state} +/// Represents the state of the pinball game. +/// {@endtemplate} +class GameState extends Equatable { + /// {@macro game_state} + const GameState({ + required this.score, + required this.balls, + }) : assert(score >= 0, "Score can't be negative"), + assert(balls >= 0, "Number of balls can't be negative"); + + const GameState.initial() + : score = 0, + balls = 3; + + /// The current score of the game. + final int score; + + /// The number of balls left in the game. + /// + /// When the number of balls is 0, the game is over. + final int balls; + + /// Determines when the game is over. + bool get isGameOver => balls == 0; + + GameState copyWith({ + int? score, + int? balls, + }) { + assert( + score == null || score >= this.score, + "Score can't be decreased", + ); + + return GameState( + score: score ?? this.score, + balls: balls ?? this.balls, + ); + } + + @override + List get props => [ + score, + balls, + ]; +} diff --git a/lib/game/game.dart b/lib/game/game.dart index 0a8dac1b..e2e5361f 100644 --- a/lib/game/game.dart +++ b/lib/game/game.dart @@ -1,3 +1,4 @@ +export 'bloc/game_bloc.dart'; export 'components/components.dart'; export 'pinball_game.dart'; export 'view/pinball_game_page.dart'; diff --git a/pubspec.lock b/pubspec.lock index cff109ca..e218776d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -113,6 +113,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.1" + equatable: + dependency: "direct main" + description: + name: equatable + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" fake_async: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3730daa3..5d708073 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: bloc: ^8.0.2 + equatable: ^2.0.3 flame: ^1.1.0-releasecandidate.1 flame_bloc: ^1.2.0-releasecandidate.1 flame_forge2d: ^0.9.0-releasecandidate.1 diff --git a/test/game/bloc/game_bloc_test.dart b/test/game/bloc/game_bloc_test.dart new file mode 100644 index 00000000..2676a286 --- /dev/null +++ b/test/game/bloc/game_bloc_test.dart @@ -0,0 +1,63 @@ +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball/game/game.dart'; + +void main() { + group('GameBloc', () { + test('initial state has 3 balls and empty score', () { + final gameBloc = GameBloc(); + expect(gameBloc.state.score, equals(0)); + expect(gameBloc.state.balls, equals(3)); + }); + + group('LostBall', () { + blocTest( + "doesn't decrease ball " + 'when no balls left', + build: GameBloc.new, + act: (bloc) { + for (var i = 0; i <= bloc.state.balls; i++) { + bloc.add(const BallLost()); + } + }, + expect: () => [ + const GameState(score: 0, balls: 2), + const GameState(score: 0, balls: 1), + const GameState(score: 0, balls: 0), + ], + ); + }); + + group('Scored', () { + blocTest( + 'increases score ' + 'when game is not over', + build: GameBloc.new, + act: (bloc) => bloc + ..add(const Scored(points: 2)) + ..add(const Scored(points: 3)), + expect: () => [ + const GameState(score: 2, balls: 3), + const GameState(score: 5, balls: 3), + ], + ); + + blocTest( + "doesn't increase score " + 'when game is over', + build: GameBloc.new, + act: (bloc) { + for (var i = 0; i < bloc.state.balls; i++) { + bloc.add(const BallLost()); + } + bloc.add(const Scored(points: 2)); + }, + expect: () => [ + const GameState(score: 0, balls: 2), + const GameState(score: 0, balls: 1), + const GameState(score: 0, balls: 0), + ], + ); + }); + }); +} diff --git a/test/game/bloc/game_event_test.dart b/test/game/bloc/game_event_test.dart new file mode 100644 index 00000000..e839ab56 --- /dev/null +++ b/test/game/bloc/game_event_test.dart @@ -0,0 +1,44 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball/game/game.dart'; + +void main() { + group('GameEvent', () { + group('BallLost', () { + test('can be instantiated', () { + expect(const BallLost(), isNotNull); + }); + + test('supports value equality', () { + expect( + BallLost(), + equals(const BallLost()), + ); + }); + }); + + group('Scored', () { + test('can be instantiated', () { + expect(const Scored(points: 1), isNotNull); + }); + + test('supports value equality', () { + expect( + Scored(points: 1), + equals(const Scored(points: 1)), + ); + expect( + const Scored(points: 1), + isNot(equals(const Scored(points: 2))), + ); + }); + + test( + 'throws AssertionError ' + 'when score is smaller than 1', () { + expect(() => Scored(points: 0), throwsAssertionError); + }); + }); + }); +} diff --git a/test/game/bloc/game_state_test.dart b/test/game/bloc/game_state_test.dart new file mode 100644 index 00000000..f62bae67 --- /dev/null +++ b/test/game/bloc/game_state_test.dart @@ -0,0 +1,121 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball/game/game.dart'; + +void main() { + group('GameState', () { + test('supports value equality', () { + expect( + GameState(score: 0, balls: 0), + equals(const GameState(score: 0, balls: 0)), + ); + }); + + group('constructor', () { + test('can be instantiated', () { + expect(const GameState(score: 0, balls: 0), isNotNull); + }); + }); + + test( + 'throws AssertionError ' + 'when balls are negative', + () { + expect( + () => GameState(balls: -1, score: 0), + throwsAssertionError, + ); + }, + ); + + test( + 'throws AssertionError ' + 'when score is negative', + () { + expect( + () => GameState(balls: 0, score: -1), + throwsAssertionError, + ); + }, + ); + + group('isGameOver', () { + test( + 'is true ' + 'when no balls are left', () { + const gameState = GameState( + balls: 0, + score: 0, + ); + expect(gameState.isGameOver, isTrue); + }); + + test( + 'is false ' + 'when one 1 ball left', () { + const gameState = GameState( + balls: 1, + score: 0, + ); + expect(gameState.isGameOver, isFalse); + }); + }); + + group('copyWith', () { + test( + 'throws AssertionError ' + 'when scored is decreased', + () { + const gameState = GameState( + balls: 0, + score: 2, + ); + expect( + () => gameState.copyWith(score: gameState.score - 1), + throwsAssertionError, + ); + }, + ); + + test( + 'copies correctly ' + 'when no arguement specified', + () { + const gameState = GameState( + balls: 0, + score: 2, + ); + expect( + gameState.copyWith(), + equals(gameState), + ); + }, + ); + + test( + 'copies correctly ' + 'when all arguements specified', + () { + const gameState = GameState( + score: 2, + balls: 0, + ); + final otherGameState = GameState( + score: gameState.score + 1, + balls: gameState.balls + 1, + ); + expect(gameState, isNot(equals(otherGameState))); + + expect( + gameState.copyWith( + score: otherGameState.score, + balls: otherGameState.balls, + ), + equals(otherGameState), + ); + }, + ); + }); + }); +} From afeaf4a058818720c37389cabad5da3307ab6761 Mon Sep 17 00:00:00 2001 From: Alejandro Santiago Date: Wed, 2 Mar 2022 19:59:43 +0000 Subject: [PATCH 5/5] feat: implemented `ScorePoints` mixin and callback (#7) * feat: implemented ScorePoints mixin * refactor: renamed BallHasScoreCallback to BallScorePointsCallback * feat: included test for end method * chore: included TODO comment * docs: included doc comments * feat: set ScorePoints mixin on BodyComponent * feat: rewrote test for mixin only extending BodyComponent * feat: registered BallScorePointsCallback in PinballGame * docs: improved BallScorePointsCallback doc comment * docs: changed PR url to issue url * refactor: fixed analyzer warnings * refactor: used real class names instead of Mock class names Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com> --- lib/game/components/ball.dart | 5 +- lib/game/components/components.dart | 1 + lib/game/components/score_points.dart | 30 ++++++++ lib/game/pinball_game.dart | 8 ++- test/game/components/score_points_test.dart | 80 +++++++++++++++++++++ test/game/pinball_game_test.dart | 9 +++ 6 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 lib/game/components/score_points.dart create mode 100644 test/game/components/score_points_test.dart create mode 100644 test/game/pinball_game_test.dart diff --git a/lib/game/components/ball.dart b/lib/game/components/ball.dart index ce2e4335..8ff24094 100644 --- a/lib/game/components/ball.dart +++ b/lib/game/components/ball.dart @@ -1,8 +1,11 @@ +import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_forge2d/body_component.dart'; import 'package:flutter/material.dart'; import 'package:forge2d/forge2d.dart'; +import 'package:pinball/game/game.dart'; -class Ball extends BodyComponent { +class Ball extends BodyComponent + with BlocComponent { Ball({ required Vector2 position, }) : _position = position { diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart index 6a26208c..e3d2c6ce 100644 --- a/lib/game/components/components.dart +++ b/lib/game/components/components.dart @@ -1 +1,2 @@ export 'ball.dart'; +export 'score_points.dart'; diff --git a/lib/game/components/score_points.dart b/lib/game/components/score_points.dart new file mode 100644 index 00000000..02506c8c --- /dev/null +++ b/lib/game/components/score_points.dart @@ -0,0 +1,30 @@ +// ignore_for_file: avoid_renaming_method_parameters + +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:pinball/game/game.dart'; + +/// {@template score_points} +/// Specifies the amount of points received on [Ball] collision. +/// {@endtemplate} +mixin ScorePoints on BodyComponent { + /// {@macro score_points} + int get points; +} + +/// Adds points to the score when a [Ball] collides with a [BodyComponent] that +/// implements [ScorePoints]. +class BallScorePointsCallback extends ContactCallback { + @override + void begin( + Ball ball, + ScorePoints hasPoints, + Contact _, + ) { + ball.gameRef.read().add(Scored(points: hasPoints.points)); + } + + // TODO(alestiago): remove once this issue is closed. + // https://github.com/flame-engine/flame/issues/1414 + @override + void end(Ball _, ScorePoints __, Contact ___) {} +} diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index 6bf24a20..c4977435 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -1,4 +1,10 @@ import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_forge2d/forge2d_game.dart'; +import 'package:pinball/game/game.dart'; -class PinballGame extends Forge2DGame with FlameBloc {} +class PinballGame extends Forge2DGame with FlameBloc { + @override + Future onLoad() async { + addContactCallback(BallScorePointsCallback()); + } +} diff --git a/test/game/components/score_points_test.dart b/test/game/components/score_points_test.dart new file mode 100644 index 00000000..9a93c078 --- /dev/null +++ b/test/game/components/score_points_test.dart @@ -0,0 +1,80 @@ +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball/game/game.dart'; + +class MockBall extends Mock implements Ball {} + +class MockGameBloc extends Mock implements GameBloc {} + +class MockPinballGame extends Mock implements PinballGame {} + +class FakeContact extends Fake implements Contact {} + +class FakeGameEvent extends Fake implements GameEvent {} + +class FakeScorePoints extends BodyComponent with ScorePoints { + @override + Body createBody() { + throw UnimplementedError(); + } + + @override + int get points => 2; +} + +void main() { + group('BallScorePointsCallback', () { + late PinballGame game; + late GameBloc bloc; + late Ball ball; + late FakeScorePoints fakeScorePoints; + + setUp(() { + game = MockPinballGame(); + bloc = MockGameBloc(); + ball = MockBall(); + fakeScorePoints = FakeScorePoints(); + }); + + setUpAll(() { + registerFallbackValue(FakeGameEvent()); + }); + + group('begin', () { + test( + 'emits Scored event with points', + () { + when(() => ball.gameRef).thenReturn(game); + when(game.read).thenReturn(bloc); + + BallScorePointsCallback().begin( + ball, + fakeScorePoints, + FakeContact(), + ); + + verify( + () => bloc.add( + Scored(points: fakeScorePoints.points), + ), + ).called(1); + }, + ); + }); + + group('end', () { + test("doesn't add events to GameBloc", () { + BallScorePointsCallback().end( + ball, + fakeScorePoints, + FakeContact(), + ); + + verifyNever( + () => bloc.add(any()), + ); + }); + }); + }); +} diff --git a/test/game/pinball_game_test.dart b/test/game/pinball_game_test.dart new file mode 100644 index 00000000..75a77aa9 --- /dev/null +++ b/test/game/pinball_game_test.dart @@ -0,0 +1,9 @@ +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('PinballGame', () { + // TODO(alestiago): test if [PinballGame] registers + // [BallScorePointsCallback] once the following issue is resolved: + // https://github.com/flame-engine/flame/issues/1416 + }); +}