From 421ad272cb363b0b222d000807a262d7f7fa535f Mon Sep 17 00:00:00 2001 From: alestiago Date: Tue, 8 Mar 2022 16:15:38 +0000 Subject: [PATCH] feat: including test and refactor --- lib/game/components/flipper.dart | 37 +++-- lib/game/pinball_game.dart | 6 +- test/game/components/flipper_test.dart | 216 +++++++++++++------------ test/game/pinball_game_test.dart | 45 ++++++ test/helpers/helpers.dart | 1 + test/helpers/key_testers.dart | 50 ++++++ test/helpers/mocks.dart | 16 ++ 7 files changed, 250 insertions(+), 121 deletions(-) create mode 100644 test/helpers/key_testers.dart diff --git a/lib/game/components/flipper.dart b/lib/game/components/flipper.dart index 0264c5f6..d391106d 100644 --- a/lib/game/components/flipper.dart +++ b/lib/game/components/flipper.dart @@ -14,25 +14,42 @@ import 'package:pinball/game/game.dart'; /// {@endtemplate flipper} class Flipper extends BodyComponent with KeyboardHandler { /// {@macro flipper} - Flipper({ + Flipper._({ required Vector2 position, required this.side, + required List keys, }) : _position = position, - _keys = side.isLeft - ? [ - LogicalKeyboardKey.arrowLeft, - LogicalKeyboardKey.keyA, - ] - : [ - LogicalKeyboardKey.arrowRight, - LogicalKeyboardKey.keyD, - ] { + _keys = keys { // TODO(alestiago): Use sprite instead of color when provided. paint = Paint() ..color = const Color(0xFF00FF00) ..style = PaintingStyle.fill; } + /// A left positioned [Flipper]. + Flipper.left({ + required Vector2 position, + }) : this._( + position: position, + side: BoardSide.left, + keys: [ + LogicalKeyboardKey.arrowLeft, + LogicalKeyboardKey.keyA, + ], + ); + + /// A right positioned [Flipper]. + Flipper.right({ + required Vector2 position, + }) : this._( + position: position, + side: BoardSide.right, + keys: [ + LogicalKeyboardKey.arrowRight, + LogicalKeyboardKey.keyD, + ], + ); + /// The width of the [Flipper]. static const width = 12.0; diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index e8c7c129..8846a8b0 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -28,12 +28,11 @@ class PinballGame extends Forge2DGame Future _addFlippers() async { const spaceBetweenFlippers = 2; - final leftFlipper = Flipper( + final leftFlipper = Flipper.left( position: Vector2( flippersPosition.x - (Flipper.width / 2) - (spaceBetweenFlippers / 2), flippersPosition.y, ), - side: BoardSide.left, ); await add(leftFlipper); final leftFlipperAnchor = FlipperAnchor(flipper: leftFlipper); @@ -47,12 +46,11 @@ class PinballGame extends Forge2DGame _leftFlipperRevoluteJoint = world.createJoint(leftFlipperRevoluteJointDef) as RevoluteJoint; - final rightFlipper = Flipper( + final rightFlipper = Flipper.right( position: Vector2( flippersPosition.x + (Flipper.width / 2) + (spaceBetweenFlippers / 2), flippersPosition.y, ), - side: BoardSide.right, ); await add(rightFlipper); final rightFlipperAnchor = FlipperAnchor(flipper: rightFlipper); diff --git a/test/game/components/flipper_test.dart b/test/game/components/flipper_test.dart index 70cbf75e..6bedece2 100644 --- a/test/game/components/flipper_test.dart +++ b/test/game/components/flipper_test.dart @@ -2,9 +2,12 @@ import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinball/game/game.dart'; +import '../../helpers/helpers.dart'; + void main() { TestWidgetsFlutterBinding.ensureInitialized(); final flameTester = FlameTester(PinballGame.new); @@ -14,28 +17,20 @@ void main() { flameTester.test( 'loads correctly', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); - await game.ensureAdd(flipper); + final leftFlipper = Flipper.left(position: Vector2.zero()); + final rightFlipper = Flipper.right(position: Vector2.zero()); + await game.ensureAddAll([leftFlipper, rightFlipper]); - expect(game.contains(flipper), isTrue); + expect(game.contains(leftFlipper), isTrue); }, ); group('constructor', () { test('sets BoardSide', () { - final leftFlipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); + final leftFlipper = Flipper.left(position: Vector2.zero()); expect(leftFlipper.side, equals(leftFlipper.side)); - final rightFlipper = Flipper( - position: Vector2.zero(), - side: BoardSide.right, - ); + final rightFlipper = Flipper.right(position: Vector2.zero()); expect(rightFlipper.side, equals(rightFlipper.side)); }); }); @@ -45,7 +40,7 @@ void main() { 'positions correctly', (game) async { final position = Vector2.all(10); - final flipper = Flipper(position: position, side: BoardSide.left); + final flipper = Flipper.left(position: position); await game.ensureAdd(flipper); game.contains(flipper); @@ -56,10 +51,7 @@ void main() { flameTester.test( 'is dynamic', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); + final flipper = Flipper.left(position: Vector2.zero()); await game.ensureAdd(flipper); expect(flipper.body.bodyType, equals(BodyType.dynamic)); @@ -69,10 +61,7 @@ void main() { flameTester.test( 'ignores gravity', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); + final flipper = Flipper.left(position: Vector2.zero()); await game.ensureAdd(flipper); expect(flipper.body.gravityScale, isZero); @@ -82,10 +71,7 @@ void main() { flameTester.test( 'has greater mass than Ball', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); + final flipper = Flipper.left(position: Vector2.zero()); final ball = Ball(position: Vector2.zero()); await game.ensureAdd(flipper); @@ -103,10 +89,7 @@ void main() { flameTester.test( 'has three', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); + final flipper = Flipper.left(position: Vector2.zero()); await game.ensureAdd(flipper); expect(flipper.body.fixtures.length, equals(3)); @@ -116,10 +99,7 @@ void main() { flameTester.test( 'has density', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); + final flipper = Flipper.left(position: Vector2.zero()); await game.ensureAdd(flipper); final fixtures = flipper.body.fixtures; @@ -133,40 +113,90 @@ void main() { ); }); - group('moveDown', () { - flameTester.test( - 'sets a negative vertical linear velocity', - (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, + group('onKeyEvent', () { + group('and Flipper is left', () { + late Flipper flipper; + + setUp(() { + flipper = Flipper.left(position: Vector2.zero()); + }); + + testRawKeyDownEvents([ + LogicalKeyboardKey.arrowLeft, + LogicalKeyboardKey.keyA, + ], (event) { + flameTester.test( + 'moves upwards ' + 'when ${event.logicalKey.keyLabel} is pressed', + (game) async { + await game.ensureAdd(flipper); + flipper.onKeyEvent(event, {}); + + expect(flipper.body.linearVelocity.y, isPositive); + expect(flipper.body.linearVelocity.x, isZero); + }, ); - await game.ensureAdd(flipper); - - flipper.moveDown(); - - expect(flipper.body.linearVelocity.y, isNegative); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); - }); - - group('moveUp', () { - flameTester.test( - 'sets a positive vertical linear velocity', - (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, + }); + + testRawKeyUpEvents([ + LogicalKeyboardKey.arrowLeft, + LogicalKeyboardKey.keyA, + ], (event) { + flameTester.test( + 'moves downwards ' + 'when ${event.logicalKey.keyLabel} is released', + (game) async { + await game.ensureAdd(flipper); + flipper.onKeyEvent(event, {}); + + expect(flipper.body.linearVelocity.y, isNegative); + expect(flipper.body.linearVelocity.x, isZero); + }, ); - await game.ensureAdd(flipper); - - flipper.moveUp(); + }); + }); - expect(flipper.body.linearVelocity.y, isPositive); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); + group('and Flipper is right', () { + late Flipper flipper; + + setUp(() { + flipper = Flipper.right(position: Vector2.zero()); + }); + + testRawKeyDownEvents([ + LogicalKeyboardKey.arrowRight, + LogicalKeyboardKey.keyD, + ], (event) { + flameTester.test( + 'moves upwards ' + 'when ${event.logicalKey.keyLabel} is pressed', + (game) async { + await game.ensureAdd(flipper); + flipper.onKeyEvent(event, {}); + + expect(flipper.body.linearVelocity.y, isPositive); + expect(flipper.body.linearVelocity.x, isZero); + }, + ); + }); + + testRawKeyUpEvents([ + LogicalKeyboardKey.arrowRight, + LogicalKeyboardKey.keyD, + ], (event) { + flameTester.test( + 'moves downwards ' + 'when ${event.logicalKey.keyLabel} is released', + (game) async { + await game.ensureAdd(flipper); + flipper.onKeyEvent(event, {}); + + expect(flipper.body.linearVelocity.y, isNegative); + expect(flipper.body.linearVelocity.x, isZero); + }, + ); + }); + }); }); }, ); @@ -175,13 +205,9 @@ void main() { 'FlipperAnchor', () { flameTester.test( - 'position is at the left of the flipper ' - 'when BoardSide is left', + 'position is at the left of the left Flipper', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); + final flipper = Flipper.left(position: Vector2.zero()); await game.ensureAdd(flipper); final flipperAnchor = FlipperAnchor(flipper: flipper); @@ -192,13 +218,9 @@ void main() { ); flameTester.test( - 'position is at the right of the flipper ' - 'when BoardSide is right', + 'position is at the right of the right Flipper', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.right, - ); + final flipper = Flipper.right(position: Vector2.zero()); await game.ensureAdd(flipper); final flipperAnchor = FlipperAnchor(flipper: flipper); @@ -215,11 +237,7 @@ void main() { flameTester.test( 'limits enabled', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); - expect(flipper.side, equals(BoardSide.left)); + final flipper = Flipper.left(position: Vector2.zero()); await game.ensureAdd(flipper); final flipperAnchor = FlipperAnchor(flipper: flipper); @@ -236,13 +254,9 @@ void main() { group('equal upper and lower limits', () { flameTester.test( - 'when BoardSide is left', + 'when Flipper is left', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); - expect(flipper.side, equals(BoardSide.left)); + final flipper = Flipper.left(position: Vector2.zero()); await game.ensureAdd(flipper); final flipperAnchor = FlipperAnchor(flipper: flipper); @@ -258,13 +272,9 @@ void main() { ); flameTester.test( - 'when BoardSide is right', + 'when Flipper is right', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.right, - ); - expect(flipper.side, equals(BoardSide.right)); + final flipper = Flipper.right(position: Vector2.zero()); await game.ensureAdd(flipper); final flipperAnchor = FlipperAnchor(flipper: flipper); @@ -285,13 +295,9 @@ void main() { 'unlocks', () { flameTester.test( - 'when BoardSide is left', + 'when Flipper is left', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.left, - ); - expect(flipper.side, equals(BoardSide.left)); + final flipper = Flipper.left(position: Vector2.zero()); await game.ensureAdd(flipper); final flipperAnchor = FlipperAnchor(flipper: flipper); @@ -313,13 +319,9 @@ void main() { ); flameTester.test( - 'when BoardSide is right', + 'when Flipper is right', (game) async { - final flipper = Flipper( - position: Vector2.zero(), - side: BoardSide.right, - ); - expect(flipper.side, equals(BoardSide.right)); + final flipper = Flipper.right(position: Vector2.zero()); await game.ensureAdd(flipper); final flipperAnchor = FlipperAnchor(flipper: flipper); diff --git a/test/game/pinball_game_test.dart b/test/game/pinball_game_test.dart index 75a77aa9..5490fad6 100644 --- a/test/game/pinball_game_test.dart +++ b/test/game/pinball_game_test.dart @@ -1,9 +1,54 @@ +// ignore_for_file: cascade_invocations + +import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball/game/game.dart'; void main() { group('PinballGame', () { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(PinballGame.new); + // TODO(alestiago): test if [PinballGame] registers // [BallScorePointsCallback] once the following issue is resolved: // https://github.com/flame-engine/flame/issues/1416 + group( + 'components', + () { + group('Flippers', () { + flameTester.test( + 'has only one left flipper', + (game) { + final flipper = game.children.firstWhere( + (e) => e is Flipper && e.side == BoardSide.left, + ) as Flipper; + + final anotherFlipper = game.children.lastWhere( + (e) => e is Flipper && e.side == BoardSide.left, + ) as Flipper; + + expect(flipper, equals(anotherFlipper)); + expect(flipper.side, equals(BoardSide.left)); + }, + ); + + flameTester.test( + 'has only one right flipper', + (game) { + final flipper = game.children.firstWhere( + (e) => e is Flipper && e.side == BoardSide.right, + ) as Flipper; + + final anotherFlipper = game.children.lastWhere( + (e) => e is Flipper && e.side == BoardSide.right, + ) as Flipper; + + expect(flipper, equals(anotherFlipper)); + expect(flipper.side, equals(BoardSide.right)); + }, + ); + }); + }, + ); }); } diff --git a/test/helpers/helpers.dart b/test/helpers/helpers.dart index 97bc22be..c2c1cd36 100644 --- a/test/helpers/helpers.dart +++ b/test/helpers/helpers.dart @@ -6,5 +6,6 @@ // https://opensource.org/licenses/MIT. export 'builders.dart'; +export 'key_testers.dart'; export 'mocks.dart'; export 'pump_app.dart'; diff --git a/test/helpers/key_testers.dart b/test/helpers/key_testers.dart new file mode 100644 index 00000000..1545b3f5 --- /dev/null +++ b/test/helpers/key_testers.dart @@ -0,0 +1,50 @@ +import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; +import 'package:mocktail/mocktail.dart'; + +import 'helpers.dart'; + +@isTest +void testRawKeyUpEvents( + List keys, + Function(RawKeyUpEvent) test, +) { + for (final key in keys) { + test(_mockKeyUpEvent(key)); + } +} + +RawKeyUpEvent _mockKeyUpEvent(LogicalKeyboardKey key) { + final event = MockRawKeyUpEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyA, + ); + return event; +} + +@isTest +void testRawKeyDownEvents( + List keys, + Function(RawKeyDownEvent) test, +) { + for (final key in keys) { + test(_mockKeyDownEvent(key)); + } +} + +RawKeyDownEvent _mockKeyDownEvent(LogicalKeyboardKey key) { + final event = MockRawKeyDownEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyA, + ); + return event; +} + +@isTest +void testRawKeyEvents( + List keys, + Function(RawKeyEvent) test, +) { + testRawKeyDownEvents(keys, test); + testRawKeyUpEvents(keys, test); +} diff --git a/test/helpers/mocks.dart b/test/helpers/mocks.dart index b46e2c5c..da9fd537 100644 --- a/test/helpers/mocks.dart +++ b/test/helpers/mocks.dart @@ -1,4 +1,6 @@ import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'package:mocktail/mocktail.dart'; import 'package:pinball/game/game.dart'; @@ -13,3 +15,17 @@ class MockBall extends Mock implements Ball {} class MockContact extends Mock implements Contact {} class MockGameBloc extends Mock implements GameBloc {} + +class MockRawKeyDownEvent extends Mock implements RawKeyDownEvent { + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return super.toString(); + } +} + +class MockRawKeyUpEvent extends Mock implements RawKeyUpEvent { + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return super.toString(); + } +}