diff --git a/packages/pinball_components/lib/src/components/flipper/behaviors/behaviors.dart b/packages/pinball_components/lib/src/components/flipper/behaviors/behaviors.dart index 8f3d1d55..ef3630e7 100644 --- a/packages/pinball_components/lib/src/components/flipper/behaviors/behaviors.dart +++ b/packages/pinball_components/lib/src/components/flipper/behaviors/behaviors.dart @@ -1,2 +1,2 @@ export 'flipper_jointing_behavior.dart'; -export 'flipper_key_listening_behavior.dart'; +export 'flipper_key_controlling_behavior.dart'; diff --git a/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_listening_behavior.dart b/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_controlling_behavior.dart similarity index 95% rename from packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_listening_behavior.dart rename to packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_controlling_behavior.dart index e171b371..95566e75 100644 --- a/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_listening_behavior.dart +++ b/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_controlling_behavior.dart @@ -4,7 +4,7 @@ import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; /// Allows controlling the [Flipper]'s movement with keyboard input. -class FlipperKeyListeningBehavior extends Component +class FlipperKeyControllingBehavior extends Component with KeyboardHandler, ParentIsA { /// The [LogicalKeyboardKey]s that will control the [Flipper]. /// diff --git a/packages/pinball_components/lib/src/components/flipper/flipper.dart b/packages/pinball_components/lib/src/components/flipper/flipper.dart index 36455d15..37a03fc1 100644 --- a/packages/pinball_components/lib/src/components/flipper/flipper.dart +++ b/packages/pinball_components/lib/src/components/flipper/flipper.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flutter/foundation.dart'; import 'package:pinball_components/pinball_components.dart'; export 'behaviors/behaviors.dart'; @@ -20,10 +21,16 @@ class Flipper extends BodyComponent with KeyboardHandler, InitialPosition { children: [ _FlipperSpriteComponent(side: side), FlipperJointingBehavior(), - FlipperKeyListeningBehavior(), + FlipperKeyControllingBehavior(), ], ); + /// Creates a [Flipper] without any children. + /// + /// This can be used for testing [Flipper]'s behaviors in isolation. + @visibleForTesting + Flipper.test({required this.side}); + /// The size of the [Flipper]. static final size = Vector2(13.5, 4.3); diff --git a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_jointing_behavior_test.dart b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_jointing_behavior_test.dart index 8b137891..e489e8d9 100644 --- a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_jointing_behavior_test.dart +++ b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_jointing_behavior_test.dart @@ -1 +1,38 @@ +// ignore_for_file: cascade_invocations +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball_components/src/components/components.dart'; + +import '../../../../helpers/helpers.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + group('FlipperJointingBehavior', () { + final flameTester = FlameTester(TestGame.new); + + test('can be instantiated', () { + expect( + FlipperJointingBehavior(), + isA(), + ); + }); + + flameTester.test('can be loaded', (game) async { + final behavior = FlipperJointingBehavior(); + final parent = Flipper.test(side: BoardSide.left); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + expect(parent.contains(behavior), isTrue); + }); + + flameTester.test('joints', (game) async { + final behavior = FlipperJointingBehavior(); + final parent = Flipper.test(side: BoardSide.left); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + + expect(parent.body.joints, isNotEmpty); + }); + }); +} diff --git a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_key_controlling_behavior_test.dart b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_key_controlling_behavior_test.dart index e69de29b..11d4354f 100644 --- a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_key_controlling_behavior_test.dart +++ b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_key_controlling_behavior_test.dart @@ -0,0 +1,359 @@ +// ignore_for_file: cascade_invocations + +import 'dart:collection'; + +import 'package:flame_test/flame_test.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball_components/pinball_components.dart'; + +import '../../../../helpers/helpers.dart'; + +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(); + } +} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + group('FlipperKeyControllingBehavior', () { + final flameTester = FlameTester(TestGame.new); + + group( + 'onKeyEvent', + () { + late Flipper rightFlipper; + late Flipper leftFlipper; + + setUp(() { + rightFlipper = Flipper.test(side: BoardSide.right); + leftFlipper = Flipper.test(side: BoardSide.left); + }); + + group('on right Flipper', () { + flameTester.test( + 'moves upwards when right arrow is pressed', + (game) async { + await game.ensureAdd(rightFlipper); + final behavior = FlipperKeyControllingBehavior(); + await rightFlipper.ensureAdd(behavior); + + final event = _MockRawKeyDownEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.arrowRight, + ); + + behavior.onKeyEvent(event, {}); + + expect(rightFlipper.body.linearVelocity.y, isNegative); + expect(rightFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'moves downwards when right arrow is released', + (game) async { + await game.ensureAdd(rightFlipper); + final behavior = FlipperKeyControllingBehavior(); + await rightFlipper.ensureAdd(behavior); + + final event = _MockRawKeyUpEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.arrowRight, + ); + + behavior.onKeyEvent(event, {}); + + expect(rightFlipper.body.linearVelocity.y, isPositive); + expect(rightFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'moves upwards when D is pressed', + (game) async { + await game.ensureAdd(rightFlipper); + final behavior = FlipperKeyControllingBehavior(); + await rightFlipper.ensureAdd(behavior); + + final event = _MockRawKeyDownEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyD, + ); + + behavior.onKeyEvent(event, {}); + + expect(rightFlipper.body.linearVelocity.y, isNegative); + expect(rightFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'moves downwards when D is released', + (game) async { + await game.ensureAdd(rightFlipper); + final behavior = FlipperKeyControllingBehavior(); + await rightFlipper.ensureAdd(behavior); + + final event = _MockRawKeyUpEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyD, + ); + + behavior.onKeyEvent(event, {}); + + expect(rightFlipper.body.linearVelocity.y, isPositive); + expect(rightFlipper.body.linearVelocity.x, isZero); + }, + ); + + group("doesn't move when", () { + flameTester.test( + 'left awrrow is pressed', + (game) async { + await game.ensureAdd(rightFlipper); + final behavior = FlipperKeyControllingBehavior(); + await rightFlipper.ensureAdd(behavior); + + final event = _MockRawKeyDownEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.arrowLeft, + ); + + behavior.onKeyEvent(event, {}); + + expect(rightFlipper.body.linearVelocity.y, isZero); + expect(rightFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'left arrow is released', + (game) async { + await game.ensureAdd(rightFlipper); + final behavior = FlipperKeyControllingBehavior(); + await rightFlipper.ensureAdd(behavior); + + final event = _MockRawKeyUpEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.arrowLeft, + ); + + behavior.onKeyEvent(event, {}); + + expect(rightFlipper.body.linearVelocity.y, isZero); + expect(rightFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'A is pressed', + (game) async { + await game.ensureAdd(rightFlipper); + final behavior = FlipperKeyControllingBehavior(); + await rightFlipper.ensureAdd(behavior); + + final event = _MockRawKeyDownEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyA, + ); + + behavior.onKeyEvent(event, {}); + + expect(rightFlipper.body.linearVelocity.y, isZero); + expect(rightFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'A is released', + (game) async { + await game.ensureAdd(rightFlipper); + final behavior = FlipperKeyControllingBehavior(); + await rightFlipper.ensureAdd(behavior); + + final event = _MockRawKeyUpEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyA, + ); + + behavior.onKeyEvent(event, {}); + + expect(rightFlipper.body.linearVelocity.y, isZero); + expect(rightFlipper.body.linearVelocity.x, isZero); + }, + ); + }); + }); + + group('on left Flipper', () { + flameTester.test( + 'moves upwards when left arrow is pressed', + (game) async { + await game.ensureAdd(leftFlipper); + final behavior = FlipperKeyControllingBehavior(); + await leftFlipper.ensureAdd(behavior); + + final event = _MockRawKeyDownEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.arrowLeft, + ); + + behavior.onKeyEvent(event, {}); + + expect(leftFlipper.body.linearVelocity.y, isNegative); + expect(leftFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'moves downwards when left arrow is released', + (game) async { + await game.ensureAdd(leftFlipper); + final behavior = FlipperKeyControllingBehavior(); + await leftFlipper.ensureAdd(behavior); + + final event = _MockRawKeyUpEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.arrowLeft, + ); + + behavior.onKeyEvent(event, {}); + + expect(leftFlipper.body.linearVelocity.y, isPositive); + expect(leftFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'moves upwards when A is pressed', + (game) async { + await game.ensureAdd(leftFlipper); + final behavior = FlipperKeyControllingBehavior(); + await leftFlipper.ensureAdd(behavior); + + final event = _MockRawKeyDownEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyA, + ); + + behavior.onKeyEvent(event, {}); + + expect(leftFlipper.body.linearVelocity.y, isNegative); + expect(leftFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'moves downwards when A is released', + (game) async { + await game.ensureAdd(leftFlipper); + final behavior = FlipperKeyControllingBehavior(); + await leftFlipper.ensureAdd(behavior); + + final event = _MockRawKeyUpEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyA, + ); + + behavior.onKeyEvent(event, {}); + + expect(leftFlipper.body.linearVelocity.y, isPositive); + expect(leftFlipper.body.linearVelocity.x, isZero); + }, + ); + + group("doesn't move when", () { + flameTester.test( + 'right awrrow is pressed', + (game) async { + await game.ensureAdd(leftFlipper); + final behavior = FlipperKeyControllingBehavior(); + await leftFlipper.ensureAdd(behavior); + + final event = _MockRawKeyDownEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.arrowRight, + ); + + behavior.onKeyEvent(event, {}); + + expect(leftFlipper.body.linearVelocity.y, isZero); + expect(leftFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'right arrow is released', + (game) async { + await game.ensureAdd(leftFlipper); + final behavior = FlipperKeyControllingBehavior(); + await leftFlipper.ensureAdd(behavior); + + final event = _MockRawKeyUpEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.arrowRight, + ); + + behavior.onKeyEvent(event, {}); + + expect(leftFlipper.body.linearVelocity.y, isZero); + expect(leftFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'D is pressed', + (game) async { + await game.ensureAdd(leftFlipper); + final behavior = FlipperKeyControllingBehavior(); + await leftFlipper.ensureAdd(behavior); + + final event = _MockRawKeyDownEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyD, + ); + + behavior.onKeyEvent(event, {}); + + expect(leftFlipper.body.linearVelocity.y, isZero); + expect(leftFlipper.body.linearVelocity.x, isZero); + }, + ); + + flameTester.test( + 'D is released', + (game) async { + await game.ensureAdd(leftFlipper); + final behavior = FlipperKeyControllingBehavior(); + await leftFlipper.ensureAdd(behavior); + + final event = _MockRawKeyUpEvent(); + when(() => event.logicalKey).thenReturn( + LogicalKeyboardKey.keyD, + ); + + behavior.onKeyEvent(event, {}); + + expect(leftFlipper.body.linearVelocity.y, isZero); + expect(leftFlipper.body.linearVelocity.x, isZero); + }, + ); + }); + }); + }, + ); + }); +} diff --git a/test/game/components/controlled_flipper_test.dart b/test/game/components/controlled_flipper_test.dart deleted file mode 100644 index f9561b60..00000000 --- a/test/game/components/controlled_flipper_test.dart +++ /dev/null @@ -1,194 +0,0 @@ -import 'dart:collection'; - -import 'package:bloc_test/bloc_test.dart'; -import 'package:flame_test/flame_test.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:pinball/game/game.dart'; -import 'package:pinball_components/pinball_components.dart'; - -import '../../helpers/helpers.dart'; - -class _MockGameBloc extends Mock implements GameBloc {} - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - final assets = [ - Assets.images.flipper.left.keyName, - Assets.images.flipper.right.keyName, - ]; - final flameTester = FlameTester( - () => EmptyPinballTestGame(assets: assets), - ); - - final flameBlocTester = FlameBlocTester( - gameBuilder: EmptyPinballTestGame.new, - blocBuilder: () { - final bloc = _MockGameBloc(); - const state = GameState( - totalScore: 0, - roundScore: 0, - multiplier: 1, - rounds: 0, - bonusHistory: [], - ); - whenListen(bloc, Stream.value(state), initialState: state); - return bloc; - }, - assets: assets, - ); - - group('FlipperController', () { - group('onKeyEvent', () { - final leftKeys = UnmodifiableListView([ - LogicalKeyboardKey.arrowLeft, - LogicalKeyboardKey.keyA, - ]); - final rightKeys = UnmodifiableListView([ - LogicalKeyboardKey.arrowRight, - LogicalKeyboardKey.keyD, - ]); - - group('and Flipper is left', () { - late Flipper flipper; - late FlipperController controller; - - setUp(() { - flipper = Flipper(side: BoardSide.left); - controller = FlipperController(flipper); - flipper.add(controller); - }); - - testRawKeyDownEvents(leftKeys, (event) { - flameTester.test( - 'moves upwards ' - 'when ${event.logicalKey.keyLabel} is pressed', - (game) async { - await game.ready(); - await game.add(flipper); - controller.onKeyEvent(event, {}); - - expect(flipper.body.linearVelocity.y, isNegative); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); - }); - - testRawKeyDownEvents(leftKeys, (event) { - flameBlocTester.testGameWidget( - 'does nothing when is game over', - setUp: (game, tester) async { - await game.ensureAdd(flipper); - controller.onKeyEvent(event, {}); - }, - verify: (game, tester) async { - expect(flipper.body.linearVelocity.y, isZero); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); - }); - - testRawKeyUpEvents(leftKeys, (event) { - flameTester.test( - 'moves downwards ' - 'when ${event.logicalKey.keyLabel} is released', - (game) async { - await game.ready(); - await game.add(flipper); - controller.onKeyEvent(event, {}); - - expect(flipper.body.linearVelocity.y, isPositive); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); - }); - - testRawKeyUpEvents(rightKeys, (event) { - flameTester.test( - 'does nothing ' - 'when ${event.logicalKey.keyLabel} is released', - (game) async { - await game.ready(); - await game.add(flipper); - controller.onKeyEvent(event, {}); - - expect(flipper.body.linearVelocity.y, isZero); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); - }); - }); - - group('and Flipper is right', () { - late Flipper flipper; - late FlipperController controller; - - setUp(() { - flipper = Flipper(side: BoardSide.right); - controller = FlipperController(flipper); - flipper.add(controller); - }); - - testRawKeyDownEvents(rightKeys, (event) { - flameTester.test( - 'moves upwards ' - 'when ${event.logicalKey.keyLabel} is pressed', - (game) async { - await game.ready(); - await game.add(flipper); - controller.onKeyEvent(event, {}); - - expect(flipper.body.linearVelocity.y, isNegative); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); - }); - - testRawKeyUpEvents(rightKeys, (event) { - flameTester.test( - 'moves downwards ' - 'when ${event.logicalKey.keyLabel} is released', - (game) async { - await game.ready(); - await game.add(flipper); - controller.onKeyEvent(event, {}); - - expect(flipper.body.linearVelocity.y, isPositive); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); - }); - - testRawKeyDownEvents(rightKeys, (event) { - flameBlocTester.testGameWidget( - 'does nothing when is game over', - setUp: (game, tester) async { - await game.ensureAdd(flipper); - controller.onKeyEvent(event, {}); - }, - verify: (game, tester) async { - expect(flipper.body.linearVelocity.y, isZero); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); - }); - - testRawKeyUpEvents(leftKeys, (event) { - flameTester.test( - 'does nothing ' - 'when ${event.logicalKey.keyLabel} is released', - (game) async { - await game.ready(); - await game.add(flipper); - controller.onKeyEvent(event, {}); - - expect(flipper.body.linearVelocity.y, isZero); - expect(flipper.body.linearVelocity.x, isZero); - }, - ); - }); - }); - }); - }); -}