From 25128b614be57d1f2d06d232f290de10a5f6733f Mon Sep 17 00:00:00 2001 From: alestiago Date: Tue, 26 Apr 2022 18:41:01 +0100 Subject: [PATCH] test: tested pinball_components --- lib/game/components/alien_zone.dart | 4 +- lib/game/components/components.dart | 2 +- lib/game/components/flutter_forest.dart | 8 +-- .../google_word_bonus_behaviour.dart | 8 +-- .../components/google_word/google_word.dart | 11 +--- ...g_behaviour.dart => scoring_behavior.dart} | 22 +------ lib/game/components/sparky_fire_zone.dart | 6 +- .../components/alien_bumper/alien_bumper.dart | 15 +++-- ...> alien_bumper_ball_contact_behavior.dart} | 1 - ...rt => alien_bumper_blinking_behavior.dart} | 18 +++-- .../alien_bumper/behaviors/behaviors.dart | 4 +- .../cubit/alien_bumper_cubit.dart | 2 +- .../lib/src/components/dash_nest_bumper.dart | 2 +- .../google_letter/google_letter.dart | 44 +++++-------- .../lib/src/components/signpost.dart | 2 +- .../sparky_bumper/behaviors/behaviors.dart | 4 +- ... sparky_bumper_ball_contact_behavior.dart} | 0 ...t => sparky_bumper_blinking_behavior.dart} | 18 +++-- .../cubit/sparky_bumper_cubit.dart | 5 +- .../sparky_bumper/sparky_bumper.dart | 21 ++++-- packages/pinball_components/pubspec.yaml | 1 + .../test/helpers/mocks.dart | 6 ++ .../alien_bumper/alien_bumper_test.dart | 66 ++++++++++++------- ...ien_bumper_ball_contact_behavior_test.dart | 51 ++++++++++++++ .../alien_bumper_blinking_behavior_test.dart | 45 +++++++++++++ .../cubit/alien_bumper_cubit_test.dart | 24 +++++++ .../src/components/dash_nest_bumper_test.dart | 9 +++ ...gle_letter_ball_contact_behavior_test.dart | 51 ++++++++++++++ .../cubit/google_letter_cubit_test.dart | 24 +++++++ .../google_letter/google_letter_test.dart | 31 +++++++++ .../src/components/layer_sensor_test.dart | 6 +- .../test/src/components/signpost_test.dart | 9 +++ ...rky_bumper_ball_contact_behavior_test.dart | 51 ++++++++++++++ ...sparky_bumper_blinking_behaviour_test.dart | 45 +++++++++++++ .../cubit/sparky_bumper_cubit_test.dart | 24 +++++++ .../sparky_bumper/sparky_bumper_test.dart | 62 ++++++++++++++--- .../lib/src/contact_behavior.dart | 8 +-- .../pinball_flame/lib/src/parent_is_a.dart | 3 +- .../components/scoring_behaviour_test.dart | 6 +- 39 files changed, 561 insertions(+), 158 deletions(-) rename lib/game/components/{scoring_behaviour.dart => scoring_behavior.dart} (57%) rename packages/pinball_components/lib/src/components/alien_bumper/behaviors/{alien_bumper_ball_contact_behaviour.dart => alien_bumper_ball_contact_behavior.dart} (91%) rename packages/pinball_components/lib/src/components/alien_bumper/behaviors/{sprite_behavior.dart => alien_bumper_blinking_behavior.dart} (62%) rename packages/pinball_components/lib/src/components/sparky_bumper/behaviors/{sparky_bumper_ball_contact_behaviour.dart => sparky_bumper_ball_contact_behavior.dart} (100%) rename packages/pinball_components/lib/src/components/sparky_bumper/behaviors/{sprite_behavior.dart => sparky_bumper_blinking_behavior.dart} (62%) create mode 100644 packages/pinball_components/test/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behavior_test.dart create mode 100644 packages/pinball_components/test/src/components/alien_bumper/behaviors/alien_bumper_blinking_behavior_test.dart create mode 100644 packages/pinball_components/test/src/components/alien_bumper/cubit/alien_bumper_cubit_test.dart create mode 100644 packages/pinball_components/test/src/components/google_letter/behaviors/google_letter_ball_contact_behavior_test.dart create mode 100644 packages/pinball_components/test/src/components/google_letter/cubit/google_letter_cubit_test.dart create mode 100644 packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior_test.dart create mode 100644 packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behaviour_test.dart create mode 100644 packages/pinball_components/test/src/components/sparky_bumper/cubit/sparky_bumper_cubit_test.dart diff --git a/lib/game/components/alien_zone.dart b/lib/game/components/alien_zone.dart index 13496c4f..dadc5ba4 100644 --- a/lib/game/components/alien_zone.dart +++ b/lib/game/components/alien_zone.dart @@ -16,12 +16,12 @@ class AlienZone extends Blueprint { components: [ AlienBumper.a( children: [ - ScoringBehaviour(points: 20), + ScoringBehavior(points: 20), ], )..initialPosition = Vector2(-32.52, -9.1), AlienBumper.b( children: [ - ScoringBehaviour(points: 20), + ScoringBehavior(points: 20), ], )..initialPosition = Vector2(-22.89, -17.35), ], diff --git a/lib/game/components/components.dart b/lib/game/components/components.dart index 6672eea7..17dc9ad7 100644 --- a/lib/game/components/components.dart +++ b/lib/game/components/components.dart @@ -8,6 +8,6 @@ export 'flutter_forest.dart'; export 'game_flow_controller.dart'; export 'google_word/google_word.dart'; export 'launcher.dart'; -export 'scoring_behaviour.dart'; +export 'scoring_behavior.dart'; export 'sparky_fire_zone.dart'; export 'wall.dart'; diff --git a/lib/game/components/flutter_forest.dart b/lib/game/components/flutter_forest.dart index f3a0a01a..243fcceb 100644 --- a/lib/game/components/flutter_forest.dart +++ b/lib/game/components/flutter_forest.dart @@ -20,22 +20,22 @@ class FlutterForest extends Component children: [ Signpost( children: [ - ScoringBehaviour(points: 20), + ScoringBehavior(points: 20), ], )..initialPosition = Vector2(8.35, -58.3), DashNestBumper.main( children: [ - ScoringBehaviour(points: 20), + ScoringBehavior(points: 20), ], )..initialPosition = Vector2(18.55, -59.35), DashNestBumper.a( children: [ - ScoringBehaviour(points: 20), + ScoringBehavior(points: 20), ], )..initialPosition = Vector2(8.95, -51.95), DashNestBumper.b( children: [ - ScoringBehaviour(points: 20), + ScoringBehavior(points: 20), ], )..initialPosition = Vector2(23.3, -46.75), DashAnimatronic()..position = Vector2(20, -66), diff --git a/lib/game/components/google_word/behaviors/google_word_bonus_behaviour.dart b/lib/game/components/google_word/behaviors/google_word_bonus_behaviour.dart index 435a0911..b62de944 100644 --- a/lib/game/components/google_word/behaviors/google_word_bonus_behaviour.dart +++ b/lib/game/components/google_word/behaviors/google_word_bonus_behaviour.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:flame/components.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -8,10 +6,10 @@ import 'package:pinball_flame/pinball_flame.dart'; class GoogleWordBonusBehaviour extends Component with HasGameRef, ParentIsA { @override - Future onLoad() async { - await super.onLoad(); - final googleLetters = parent.children.whereType(); + void onMount() { + super.onMount(); + final googleLetters = parent.children.whereType(); for (final letter in googleLetters) { letter.bloc.stream.listen((_) { final achievedBonus = googleLetters diff --git a/lib/game/components/google_word/google_word.dart b/lib/game/components/google_word/google_word.dart index b86d5db6..54d32591 100644 --- a/lib/game/components/google_word/google_word.dart +++ b/lib/game/components/google_word/google_word.dart @@ -1,7 +1,3 @@ -// ignore_for_file: avoid_renaming_method_parameters - -import 'dart:async'; - import 'package:flame/components.dart'; import 'package:pinball/game/components/google_word/behaviors/behaviors.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -21,12 +17,7 @@ class GoogleWord extends Component { GoogleLetter(3)..initialPosition = position + Vector2(2.88, -1.75), GoogleLetter(4)..initialPosition = position + Vector2(8.33, -0.65), GoogleLetter(5)..initialPosition = position + Vector2(12.92, 1.82), + GoogleWordBonusBehaviour(), ], ); - - @override - Future onLoad() async { - await super.onLoad(); - await add(GoogleWordBonusBehaviour()); - } } diff --git a/lib/game/components/scoring_behaviour.dart b/lib/game/components/scoring_behavior.dart similarity index 57% rename from lib/game/components/scoring_behaviour.dart rename to lib/game/components/scoring_behavior.dart index 0f2f497e..0aadd39e 100644 --- a/lib/game/components/scoring_behaviour.dart +++ b/lib/game/components/scoring_behavior.dart @@ -9,32 +9,14 @@ import 'package:pinball_flame/pinball_flame.dart'; /// {@template scoring_behaviour} /// /// {@endtemplate} -class ScoringBehaviour extends Component - with ContactCallbacks, HasGameRef, ParentIsA { +class ScoringBehavior extends ContactBehavior with HasGameRef { /// {@macro scoring_behaviour} - ScoringBehaviour({ + ScoringBehavior({ required int points, }) : _points = points; final int _points; - @override - Future onLoad() async { - await super.onLoad(); - - final userData = parent.body.userData; - if (userData is ContactCallbacksGroup) { - userData.addContactCallbacks(this); - } else if (userData is ContactCallbacks) { - final notifier = ContactCallbacksGroup() - ..addContactCallbacks(userData) - ..addContactCallbacks(this); - parent.body.userData = notifier; - } else { - parent.body.userData = this; - } - } - @override void beginContact(Object other, Contact contact) { super.beginContact(other, contact); diff --git a/lib/game/components/sparky_fire_zone.dart b/lib/game/components/sparky_fire_zone.dart index 07cc2003..a23a4fbc 100644 --- a/lib/game/components/sparky_fire_zone.dart +++ b/lib/game/components/sparky_fire_zone.dart @@ -18,17 +18,17 @@ class SparkyFireZone extends Blueprint { components: [ SparkyBumper.a( children: [ - ScoringBehaviour(points: 20), + ScoringBehavior(points: 20), ], )..initialPosition = Vector2(-22.9, -41.65), SparkyBumper.b( children: [ - ScoringBehaviour(points: 20), + ScoringBehavior(points: 20), ], )..initialPosition = Vector2(-21.25, -57.9), SparkyBumper.c( children: [ - ScoringBehaviour(points: 20), + ScoringBehavior(points: 20), ], )..initialPosition = Vector2(-3.3, -52.55), SparkyComputerSensor()..initialPosition = Vector2(-13, -49.8), diff --git a/packages/pinball_components/lib/src/components/alien_bumper/alien_bumper.dart b/packages/pinball_components/lib/src/components/alien_bumper/alien_bumper.dart index 2be0b71b..d8c75c69 100644 --- a/packages/pinball_components/lib/src/components/alien_bumper/alien_bumper.dart +++ b/packages/pinball_components/lib/src/components/alien_bumper/alien_bumper.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flutter/material.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/src/components/alien_bumper/behaviors/behaviors.dart'; import 'package:pinball_flame/pinball_flame.dart'; @@ -25,14 +26,14 @@ class AlienBumper extends BodyComponent with InitialPosition { super( priority: RenderPriority.alienBumper, children: [ - ContactBehavior(), - SpriteBehavior(), + AlienBumperBallContactBehavior(), + AlienBumperBlinkingBehavior(), _AlienBumperSpriteGroupComponent( offAssetPath: offAssetPath, onAssetPath: onAssetPath, state: bloc.state, ), - if (children != null) ...children, + ...?children, ], renderBody: false, ); @@ -61,11 +62,17 @@ class AlienBumper extends BodyComponent with InitialPosition { children: children, ); + /// {@macro alien_bumper} + @visibleForTesting + AlienBumper.test({ + required this.bloc, + }) : _majorRadius = 3.52, + _minorRadius = 2.97; + final double _majorRadius; final double _minorRadius; - // TODO(alestiago): Evaluate testing this. final AlienBumperCubit bloc; @override diff --git a/packages/pinball_components/lib/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behaviour.dart b/packages/pinball_components/lib/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behavior.dart similarity index 91% rename from packages/pinball_components/lib/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behaviour.dart rename to packages/pinball_components/lib/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behavior.dart index 0d0242fa..9b256813 100644 --- a/packages/pinball_components/lib/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behaviour.dart +++ b/packages/pinball_components/lib/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behavior.dart @@ -1,4 +1,3 @@ -import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; diff --git a/packages/pinball_components/lib/src/components/alien_bumper/behaviors/sprite_behavior.dart b/packages/pinball_components/lib/src/components/alien_bumper/behaviors/alien_bumper_blinking_behavior.dart similarity index 62% rename from packages/pinball_components/lib/src/components/alien_bumper/behaviors/sprite_behavior.dart rename to packages/pinball_components/lib/src/components/alien_bumper/behaviors/alien_bumper_blinking_behavior.dart index 48e570b6..d506445a 100644 --- a/packages/pinball_components/lib/src/components/alien_bumper/behaviors/sprite_behavior.dart +++ b/packages/pinball_components/lib/src/components/alien_bumper/behaviors/alien_bumper_blinking_behavior.dart @@ -2,16 +2,14 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; -/// {@template alien_bumper_sprite_behavior} -/// +/// {@template alien_bumper_blinking_behavior} +/// Makes a [SparkyBumper] blink back to [SparkyBumperState.active] when +/// [SparkyBumperState.inactive]. /// {@endtemplate} -class SpriteBehavior extends TimerComponent with ParentIsA { - /// {@macro alien_bumper_sprite_behavior} - SpriteBehavior() - : super( - period: 0.05, - removeOnFinish: false, - ); +class AlienBumperBlinkingBehavior extends TimerComponent + with ParentIsA { + /// {@macro alien_bumper_blinking_behavior} + AlienBumperBlinkingBehavior() : super(period: 0.05); void _onNewState(AlienBumperState state) { switch (state) { @@ -36,6 +34,6 @@ class SpriteBehavior extends TimerComponent with ParentIsA { @override void onTick() { super.onTick(); - parent.bloc.onAnimated(); + parent.bloc.onBlinked(); } } diff --git a/packages/pinball_components/lib/src/components/alien_bumper/behaviors/behaviors.dart b/packages/pinball_components/lib/src/components/alien_bumper/behaviors/behaviors.dart index b06d1639..14762ea2 100644 --- a/packages/pinball_components/lib/src/components/alien_bumper/behaviors/behaviors.dart +++ b/packages/pinball_components/lib/src/components/alien_bumper/behaviors/behaviors.dart @@ -1,2 +1,2 @@ -export 'alien_bumper_ball_contact_behaviour.dart'; -export 'sprite_behavior.dart'; +export 'alien_bumper_ball_contact_behavior.dart'; +export 'alien_bumper_blinking_behavior.dart'; diff --git a/packages/pinball_components/lib/src/components/alien_bumper/cubit/alien_bumper_cubit.dart b/packages/pinball_components/lib/src/components/alien_bumper/cubit/alien_bumper_cubit.dart index ddcd0e4e..cb9d6873 100644 --- a/packages/pinball_components/lib/src/components/alien_bumper/cubit/alien_bumper_cubit.dart +++ b/packages/pinball_components/lib/src/components/alien_bumper/cubit/alien_bumper_cubit.dart @@ -9,7 +9,7 @@ class AlienBumperCubit extends Cubit { emit(AlienBumperState.inactive); } - void onAnimated() { + void onBlinked() { emit(AlienBumperState.active); } } diff --git a/packages/pinball_components/lib/src/components/dash_nest_bumper.dart b/packages/pinball_components/lib/src/components/dash_nest_bumper.dart index 213ded5d..44402e3d 100644 --- a/packages/pinball_components/lib/src/components/dash_nest_bumper.dart +++ b/packages/pinball_components/lib/src/components/dash_nest_bumper.dart @@ -27,7 +27,7 @@ class DashNestBumper extends BodyComponent with InitialPosition { inactiveAssetPath: inactiveAssetPath, position: spritePosition, ), - if (children != null) ...children, + ...?children, ], renderBody: false, ); diff --git a/packages/pinball_components/lib/src/components/google_letter/google_letter.dart b/packages/pinball_components/lib/src/components/google_letter/google_letter.dart index 70233140..f460031c 100644 --- a/packages/pinball_components/lib/src/components/google_letter/google_letter.dart +++ b/packages/pinball_components/lib/src/components/google_letter/google_letter.dart @@ -13,16 +13,24 @@ export 'cubit/google_letter_cubit.dart'; /// {@endtemplate} class GoogleLetter extends BodyComponent with InitialPosition { /// {@macro google_letter} - GoogleLetter(int index) - : super( + GoogleLetter( + int index, { + GoogleLetterCubit? bloc, + }) : bloc = bloc ?? GoogleLetterCubit(), + super( children: [ - ContactBehavior(), + GoogleLetterBallContactBehavior(), _GoogleLetterSprite(_GoogleLetterSprite.spritePaths[index]) ], ); - // TODO(alestiago): Evaluate testing this. - final GoogleLetterCubit bloc = GoogleLetterCubit(); + final GoogleLetterCubit bloc; + + @override + void onRemove() { + bloc.close(); + super.onRemove(); + } @override Body createBody() { @@ -57,23 +65,11 @@ class _GoogleLetterSprite extends SpriteComponent final String _path; - void _onNewState(GoogleLetterState state) { - switch (state) { - case GoogleLetterState.active: - add(_GoogleLetterColorEffect(color: Colors.green)); - break; - case GoogleLetterState.inactive: - add( - _GoogleLetterColorEffect(color: Colors.red), - ); - break; - } - } - @override Future onLoad() async { await super.onLoad(); - parent.bloc.stream.listen(_onNewState); + // TODO(alisonryan2002): Make SpriteGroupComponent. + // parent.bloc.stream.listen(); // TODO(alestiago): Used cached assets. final sprite = await gameRef.loadSprite(_path); @@ -82,13 +78,3 @@ class _GoogleLetterSprite extends SpriteComponent size = sprite.originalSize / 5; } } - -class _GoogleLetterColorEffect extends ColorEffect { - _GoogleLetterColorEffect({ - required Color color, - }) : super( - color, - const Offset(0, 1), - EffectController(duration: 0.25), - ); -} diff --git a/packages/pinball_components/lib/src/components/signpost.dart b/packages/pinball_components/lib/src/components/signpost.dart index 9bbaea2b..dc45f319 100644 --- a/packages/pinball_components/lib/src/components/signpost.dart +++ b/packages/pinball_components/lib/src/components/signpost.dart @@ -52,7 +52,7 @@ class Signpost extends BodyComponent with InitialPosition { priority: RenderPriority.signpost, children: [ _SignpostSpriteComponent(), - if (children != null) ...children, + ...?children, ], renderBody: false, ); diff --git a/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/behaviors.dart b/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/behaviors.dart index 58b46e41..faaa510b 100644 --- a/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/behaviors.dart +++ b/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/behaviors.dart @@ -1,2 +1,2 @@ -export 'sparky_bumper_ball_contact_behaviour.dart'; -export 'sprite_behavior.dart'; +export 'sparky_bumper_ball_contact_behavior.dart'; +export 'sparky_bumper_blinking_behavior.dart'; diff --git a/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behaviour.dart b/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior.dart similarity index 100% rename from packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behaviour.dart rename to packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior.dart diff --git a/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sprite_behavior.dart b/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behavior.dart similarity index 62% rename from packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sprite_behavior.dart rename to packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behavior.dart index 58fff92c..ab9f4eee 100644 --- a/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sprite_behavior.dart +++ b/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behavior.dart @@ -2,16 +2,14 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; -/// {@template alien_bumper_sprite_behavior} -/// +/// {@template sparky_bumper_blinking_behavior} +/// Makes a [SparkyBumper] blink back to [SparkyBumperState.active] when +/// [SparkyBumperState.inactive]. /// {@endtemplate} -class SpriteBehavior extends TimerComponent with ParentIsA { - /// {@macro alien_bumper_sprite_behavior} - SpriteBehavior() - : super( - period: 0.05, - removeOnFinish: false, - ); +class SparkyBumperBlinkingBehavior extends TimerComponent + with ParentIsA { + /// {@macro sparky_bumper_sprite_behavior} + SparkyBumperBlinkingBehavior() : super(period: 0.05); void _onNewState(SparkyBumperState state) { switch (state) { @@ -36,6 +34,6 @@ class SpriteBehavior extends TimerComponent with ParentIsA { @override void onTick() { super.onTick(); - parent.bloc.onAnimated(); + parent.bloc.onBlinked(); } } diff --git a/packages/pinball_components/lib/src/components/sparky_bumper/cubit/sparky_bumper_cubit.dart b/packages/pinball_components/lib/src/components/sparky_bumper/cubit/sparky_bumper_cubit.dart index 53862a94..59415714 100644 --- a/packages/pinball_components/lib/src/components/sparky_bumper/cubit/sparky_bumper_cubit.dart +++ b/packages/pinball_components/lib/src/components/sparky_bumper/cubit/sparky_bumper_cubit.dart @@ -7,12 +7,9 @@ class SparkyBumperCubit extends Cubit { void onBallContacted() { emit(SparkyBumperState.inactive); - // Future.delayed(const Duration(milliseconds: 500)).whenComplete( - // () => emit(AlienBumperState.active), - // ); } - void onAnimated() { + void onBlinked() { emit(SparkyBumperState.active); } } diff --git a/packages/pinball_components/lib/src/components/sparky_bumper/sparky_bumper.dart b/packages/pinball_components/lib/src/components/sparky_bumper/sparky_bumper.dart index 6592033a..167f2f2c 100644 --- a/packages/pinball_components/lib/src/components/sparky_bumper/sparky_bumper.dart +++ b/packages/pinball_components/lib/src/components/sparky_bumper/sparky_bumper.dart @@ -2,6 +2,7 @@ import 'dart:math' as math; import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flutter/material.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/src/components/sparky_bumper/behaviors/behaviors.dart'; import 'package:pinball_flame/pinball_flame.dart'; @@ -26,15 +27,15 @@ class SparkyBumper extends BodyComponent with InitialPosition { super( priority: RenderPriority.sparkyBumper, children: [ - ContactBehavior(), - SpriteBehavior(), + SparkyBumperBallContactBehavior(), + SparkyBumperBlinkingBehaviour(), _SparkyBumperSpriteGroupComponent( onAssetPath: onAssetPath, offAssetPath: offAssetPath, position: spritePosition, state: bloc.state, ), - if (children != null) ...children, + ...?children, ], renderBody: false, ); @@ -78,12 +79,24 @@ class SparkyBumper extends BodyComponent with InitialPosition { children: children, ); + /// {@macro sparky_bumper} + @visibleForTesting + SparkyBumper.test({ + required this.bloc, + }) : _majorRadius = 3, + _minorRadius = 2.2; + final double _majorRadius; final double _minorRadius; - // TODO(alestiago): Evaluate testing this. final SparkyBumperCubit bloc; + @override + void onRemove() { + bloc.close(); + super.onRemove(); + } + @override Body createBody() { final shape = EllipseShape( diff --git a/packages/pinball_components/pubspec.yaml b/packages/pinball_components/pubspec.yaml index 3821f280..27bf0aec 100644 --- a/packages/pinball_components/pubspec.yaml +++ b/packages/pinball_components/pubspec.yaml @@ -25,6 +25,7 @@ dependencies: path: ../pinball_theme dev_dependencies: + bloc_test: ^9.0.3 flame_test: ^1.3.0 flutter_test: sdk: flutter diff --git a/packages/pinball_components/test/helpers/mocks.dart b/packages/pinball_components/test/helpers/mocks.dart index f8ff494d..d4bd41fd 100644 --- a/packages/pinball_components/test/helpers/mocks.dart +++ b/packages/pinball_components/test/helpers/mocks.dart @@ -16,3 +16,9 @@ class MockGame extends Mock implements Forge2DGame {} class MockContact extends Mock implements Contact {} class MockComponent extends Mock implements Component {} + +class MockAlienBumperCubit extends Mock implements AlienBumperCubit {} + +class MockGoogleLetterCubit extends Mock implements GoogleLetterCubit {} + +class MockSparkyBumperCubit extends Mock implements SparkyBumperCubit {} diff --git a/packages/pinball_components/test/src/components/alien_bumper/alien_bumper_test.dart b/packages/pinball_components/test/src/components/alien_bumper/alien_bumper_test.dart index b92aec09..8b9809fc 100644 --- a/packages/pinball_components/test/src/components/alien_bumper/alien_bumper_test.dart +++ b/packages/pinball_components/test/src/components/alien_bumper/alien_bumper_test.dart @@ -1,9 +1,12 @@ // ignore_for_file: cascade_invocations +import 'package:bloc_test/bloc_test.dart'; 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_components/pinball_components.dart'; +import 'package:pinball_components/src/components/alien_bumper/behaviors/behaviors.dart'; import '../../../helpers/helpers.dart'; @@ -19,39 +22,54 @@ void main() { group('AlienBumper', () { flameTester.test('"a" loads correctly', (game) async { - final bumper = AlienBumper.a(); - await game.ensureAdd(bumper); - - expect(game.contains(bumper), isTrue); + final alienBumper = AlienBumper.a(); + await game.ensureAdd(alienBumper); + expect(game.contains(alienBumper), isTrue); }); flameTester.test('"b" loads correctly', (game) async { - final bumper = AlienBumper.b(); - await game.ensureAdd(bumper); - expect(game.contains(bumper), isTrue); + final alienBumper = AlienBumper.b(); + await game.ensureAdd(alienBumper); + expect(game.contains(alienBumper), isTrue); }); - flameTester.test('animate switches between on and off sprites', - (game) async { - final bumper = AlienBumper.a(); - await game.ensureAdd(bumper); + flameTester.test('closes bloc when removed', (game) async { + final bloc = MockAlienBumperCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: AlienBumperState.active, + ); + when(bloc.close).thenAnswer((_) async {}); + final alienBumper = AlienBumper.test(bloc: bloc); - final spriteGroupComponent = bumper.firstChild()!; + await game.ensureAdd(alienBumper); + game.remove(alienBumper); + await game.ready(); - expect( - spriteGroupComponent.current, - equals(AlienBumperState.active), - ); + verify(bloc.close).called(1); + }); - expect( - spriteGroupComponent.current, - equals(AlienBumperState.inactive), - ); + group('adds', () { + flameTester.test('new children', (game) async { + final component = Component(); + final alienBumper = AlienBumper.a( + children: [component], + ); + await game.ensureAdd(alienBumper); + expect(alienBumper.children, contains(component)); + }); - expect( - spriteGroupComponent.current, - equals(AlienBumperState.active), - ); + flameTester.test('an AlienBumperBallContactBehaviour', (game) async { + final alienBumper = AlienBumper.a(); + await game.ensureAdd(alienBumper); + expect( + alienBumper.children + .whereType() + .single, + isNotNull, + ); + }); }); }); } diff --git a/packages/pinball_components/test/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behavior_test.dart b/packages/pinball_components/test/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behavior_test.dart new file mode 100644 index 00000000..caf577ed --- /dev/null +++ b/packages/pinball_components/test/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behavior_test.dart @@ -0,0 +1,51 @@ +// ignore_for_file: cascade_invocations + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_components/src/components/alien_bumper/behaviors/alien_bumper_ball_contact_behavior.dart'; + +import '../../../../helpers/helpers.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(TestGame.new); + + group( + 'AlienBumperBallContactBehavior', + () { + test('can be instantiated', () { + expect( + AlienBumperBallContactBehavior(), + isA(), + ); + }); + + group( + 'beginContact', + () { + flameTester.test('emits onBallContacted when contacts with a ball', + (game) async { + final behavior = AlienBumperBallContactBehavior(); + final bloc = MockAlienBumperCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: AlienBumperState.active, + ); + + final alienBumper = AlienBumper.test(bloc: bloc); + await alienBumper.add(behavior); + await game.ensureAdd(alienBumper); + + behavior.beginContact(MockBall(), MockContact()); + + verify(alienBumper.bloc.onBallContacted).called(1); + }); + }, + ); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/alien_bumper/behaviors/alien_bumper_blinking_behavior_test.dart b/packages/pinball_components/test/src/components/alien_bumper/behaviors/alien_bumper_blinking_behavior_test.dart new file mode 100644 index 00000000..ea7c53b3 --- /dev/null +++ b/packages/pinball_components/test/src/components/alien_bumper/behaviors/alien_bumper_blinking_behavior_test.dart @@ -0,0 +1,45 @@ +import 'dart:async'; + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_components/src/components/alien_bumper/behaviors/alien_bumper_blinking_behavior.dart'; + +import '../../../../helpers/helpers.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(TestGame.new); + + group( + 'AlienBumperBlinkingBehaviour', + () { + flameTester.test( + 'calls onBlinked after 0.5 seconds when inactive', + (game) async { + // TODO(alestiago): Make this pass. + final behavior = AlienBumperBlinkingBehavior(); + final bloc = MockAlienBumperCubit(); + final streamController = + StreamController.broadcast(); + whenListen( + bloc, + streamController.stream, + initialState: AlienBumperState.active, + ); + + final alienBumper = AlienBumper.test(bloc: bloc); + await alienBumper.add(behavior); + await game.ensureAdd(alienBumper); + + streamController.sink.add(AlienBumperState.inactive); + game.update(0.05); + + verify(bloc.onBlinked).called(1); + }, + ); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/alien_bumper/cubit/alien_bumper_cubit_test.dart b/packages/pinball_components/test/src/components/alien_bumper/cubit/alien_bumper_cubit_test.dart new file mode 100644 index 00000000..140249ea --- /dev/null +++ b/packages/pinball_components/test/src/components/alien_bumper/cubit/alien_bumper_cubit_test.dart @@ -0,0 +1,24 @@ +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball_components/pinball_components.dart'; + +void main() { + group( + 'AlienBumperCubit', + () { + blocTest( + 'onBallContacted emits inactive', + build: AlienBumperCubit.new, + act: (bloc) => bloc.onBallContacted(), + expect: () => [AlienBumperState.inactive], + ); + + blocTest( + 'onBlinked emits active', + build: AlienBumperCubit.new, + act: (bloc) => bloc.onBlinked(), + expect: () => [AlienBumperState.active], + ); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/dash_nest_bumper_test.dart b/packages/pinball_components/test/src/components/dash_nest_bumper_test.dart index ac036ef4..5219a8a6 100644 --- a/packages/pinball_components/test/src/components/dash_nest_bumper_test.dart +++ b/packages/pinball_components/test/src/components/dash_nest_bumper_test.dart @@ -73,5 +73,14 @@ void main() { equals(DashNestBumperSpriteState.inactive), ); }); + + flameTester.test('adds new children', (game) async { + final component = Component(); + final dashNestBumper = DashNestBumper.a( + children: [component], + ); + await game.ensureAdd(dashNestBumper); + expect(dashNestBumper.children, contains(component)); + }); }); } diff --git a/packages/pinball_components/test/src/components/google_letter/behaviors/google_letter_ball_contact_behavior_test.dart b/packages/pinball_components/test/src/components/google_letter/behaviors/google_letter_ball_contact_behavior_test.dart new file mode 100644 index 00000000..a5f2f877 --- /dev/null +++ b/packages/pinball_components/test/src/components/google_letter/behaviors/google_letter_ball_contact_behavior_test.dart @@ -0,0 +1,51 @@ +// ignore_for_file: cascade_invocations + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_components/src/components/google_letter/behaviors/google_letter_ball_contact_behavior.dart'; + +import '../../../../helpers/helpers.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(TestGame.new); + + group( + 'GoogleLetterBallContactBehavior', + () { + test('can be instantiated', () { + expect( + GoogleLetterBallContactBehavior(), + isA(), + ); + }); + + group( + 'beginContact', + () { + flameTester.test('emits onBallContacted when contacts with a ball', + (game) async { + final behavior = GoogleLetterBallContactBehavior(); + final bloc = MockGoogleLetterCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: GoogleLetterState.active, + ); + + final googleLetter = GoogleLetter(0, bloc: bloc); + await googleLetter.add(behavior); + await game.ensureAdd(googleLetter); + + behavior.beginContact(MockBall(), MockContact()); + + verify(googleLetter.bloc.onBallContacted).called(1); + }); + }, + ); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/google_letter/cubit/google_letter_cubit_test.dart b/packages/pinball_components/test/src/components/google_letter/cubit/google_letter_cubit_test.dart new file mode 100644 index 00000000..6296f6b6 --- /dev/null +++ b/packages/pinball_components/test/src/components/google_letter/cubit/google_letter_cubit_test.dart @@ -0,0 +1,24 @@ +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball_components/pinball_components.dart'; + +void main() { + group( + 'GoogleLetterBumperCubit', + () { + blocTest( + 'onBallContacted emits active', + build: GoogleLetterCubit.new, + act: (bloc) => bloc.onBallContacted(), + expect: () => [GoogleLetterState.active], + ); + + blocTest( + 'onReset emits inactive', + build: GoogleLetterCubit.new, + act: (bloc) => bloc.onReset(), + expect: () => [GoogleLetterState.inactive], + ); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/google_letter/google_letter_test.dart b/packages/pinball_components/test/src/components/google_letter/google_letter_test.dart index f6012a35..06e18929 100644 --- a/packages/pinball_components/test/src/components/google_letter/google_letter_test.dart +++ b/packages/pinball_components/test/src/components/google_letter/google_letter_test.dart @@ -1,8 +1,11 @@ // ignore_for_file: cascade_invocations +import 'package:bloc_test/bloc_test.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_components/src/components/google_letter/behaviors/behaviors.dart'; import '../../../helpers/helpers.dart'; @@ -81,5 +84,33 @@ void main() { expect(() => GoogleLetter(-1), throwsA(isA())); expect(() => GoogleLetter(6), throwsA(isA())); }); + + flameTester.test('closes bloc when removed', (game) async { + final bloc = MockGoogleLetterCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: GoogleLetterState.active, + ); + when(bloc.close).thenAnswer((_) async {}); + final googleLetter = GoogleLetter(0, bloc: bloc); + + await game.ensureAdd(googleLetter); + game.remove(googleLetter); + await game.ready(); + + verify(bloc.close).called(1); + }); + + flameTester.test('adds a GoogleLetterBallContactBehaviour', (game) async { + final googleLetter = GoogleLetter(0); + await game.ensureAdd(googleLetter); + expect( + googleLetter.children + .whereType() + .single, + isNotNull, + ); + }); }); } diff --git a/packages/pinball_components/test/src/components/layer_sensor_test.dart b/packages/pinball_components/test/src/components/layer_sensor_test.dart index 3eb2a488..2d1b21be 100644 --- a/packages/pinball_components/test/src/components/layer_sensor_test.dart +++ b/packages/pinball_components/test/src/components/layer_sensor_test.dart @@ -108,7 +108,7 @@ void main() { }); }); - group('LayerSensorBallContactCallback', () { + group('beginContact', () { late Ball ball; late Body body; @@ -133,12 +133,14 @@ void main() { when(() => body.linearVelocity).thenReturn(Vector2(0, -1)); + sensor.beginContact(ball, MockContact()); verify(() => ball.layer = sensor.insideLayer).called(1); verify(() => ball.priority = sensor.insidePriority).called(1); verify(ball.reorderChildren).called(1); when(() => ball.layer).thenReturn(sensor.insideLayer); + sensor.beginContact(ball, MockContact()); verify(() => ball.layer = Layer.board); verify(() => ball.priority = RenderPriority.ballOnBoard).called(1); verify(ball.reorderChildren).called(1); @@ -156,12 +158,14 @@ void main() { when(() => body.linearVelocity).thenReturn(Vector2(0, 1)); + sensor.beginContact(ball, MockContact()); verify(() => ball.layer = sensor.insideLayer).called(1); verify(() => ball.priority = sensor.insidePriority).called(1); verify(ball.reorderChildren).called(1); when(() => ball.layer).thenReturn(sensor.insideLayer); + sensor.beginContact(ball, MockContact()); verify(() => ball.layer = Layer.board); verify(() => ball.priority = RenderPriority.ballOnBoard).called(1); verify(ball.reorderChildren).called(1); diff --git a/packages/pinball_components/test/src/components/signpost_test.dart b/packages/pinball_components/test/src/components/signpost_test.dart index 018c1bee..23aa6bd0 100644 --- a/packages/pinball_components/test/src/components/signpost_test.dart +++ b/packages/pinball_components/test/src/components/signpost_test.dart @@ -151,5 +151,14 @@ void main() { expect(spriteComponent.current, SignpostSpriteState.inactive); }, ); + + flameTester.test('adds new children', (game) async { + final component = Component(); + final signpost = Signpost( + children: [component], + ); + await game.ensureAdd(signpost); + expect(signpost.children, contains(component)); + }); }); } diff --git a/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior_test.dart b/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior_test.dart new file mode 100644 index 00000000..e6108fc7 --- /dev/null +++ b/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior_test.dart @@ -0,0 +1,51 @@ +// ignore_for_file: cascade_invocations + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_components/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior.dart'; + +import '../../../../helpers/helpers.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(TestGame.new); + + group( + 'AlienBumperBallContactBehavior', + () { + test('can be instantiated', () { + expect( + SparkyBumperBallContactBehavior(), + isA(), + ); + }); + + group( + 'beginContact', + () { + flameTester.test('emits onBallContacted when contacts with a ball', + (game) async { + final behavior = SparkyBumperBallContactBehavior(); + final bloc = MockSparkyBumperCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: SparkyBumperState.active, + ); + + final sparkyBumper = SparkyBumper.test(bloc: bloc); + await sparkyBumper.add(behavior); + await game.ensureAdd(sparkyBumper); + + behavior.beginContact(MockBall(), MockContact()); + + verify(sparkyBumper.bloc.onBallContacted).called(1); + }); + }, + ); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behaviour_test.dart b/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behaviour_test.dart new file mode 100644 index 00000000..8995914d --- /dev/null +++ b/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behaviour_test.dart @@ -0,0 +1,45 @@ +import 'dart:async'; + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_components/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behavior.dart'; + +import '../../../../helpers/helpers.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(TestGame.new); + + group( + 'SparkyBumperBlinkingBehaviour', + () { + flameTester.test( + 'calls onBlinked after 0.5 seconds when inactive', + (game) async { + // TODO(alestiago): Make this pass. + final behavior = SparkyBumperBlinkingBehavior(); + final bloc = MockSparkyBumperCubit(); + final streamController = + StreamController.broadcast(); + whenListen( + bloc, + streamController.stream, + initialState: SparkyBumperState.active, + ); + + final sparkyBumper = SparkyBumper.test(bloc: bloc); + await sparkyBumper.add(behavior); + await game.ensureAdd(sparkyBumper); + + streamController.sink.add(SparkyBumperState.inactive); + game.update(0.05); + + verify(bloc.onBlinked).called(1); + }, + ); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/sparky_bumper/cubit/sparky_bumper_cubit_test.dart b/packages/pinball_components/test/src/components/sparky_bumper/cubit/sparky_bumper_cubit_test.dart new file mode 100644 index 00000000..4192f806 --- /dev/null +++ b/packages/pinball_components/test/src/components/sparky_bumper/cubit/sparky_bumper_cubit_test.dart @@ -0,0 +1,24 @@ +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball_components/pinball_components.dart'; + +void main() { + group( + 'SparkyBumperCubit', + () { + blocTest( + 'onBallContacted emits inactive', + build: SparkyBumperCubit.new, + act: (bloc) => bloc.onBallContacted(), + expect: () => [SparkyBumperState.inactive], + ); + + blocTest( + 'onBlinked emits active', + build: SparkyBumperCubit.new, + act: (bloc) => bloc.onBlinked(), + expect: () => [SparkyBumperState.active], + ); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/sparky_bumper/sparky_bumper_test.dart b/packages/pinball_components/test/src/components/sparky_bumper/sparky_bumper_test.dart index d657fc0e..da729c0a 100644 --- a/packages/pinball_components/test/src/components/sparky_bumper/sparky_bumper_test.dart +++ b/packages/pinball_components/test/src/components/sparky_bumper/sparky_bumper_test.dart @@ -1,8 +1,12 @@ // ignore_for_file: cascade_invocations +import 'package:bloc_test/bloc_test.dart'; +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_components/pinball_components.dart'; +import 'package:pinball_components/src/components/sparky_bumper/behaviors/behaviors.dart'; import '../../../helpers/helpers.dart'; @@ -20,22 +24,60 @@ void main() { group('SparkyBumper', () { flameTester.test('"a" loads correctly', (game) async { - final bumper = SparkyBumper.a(); - await game.ensureAdd(bumper); - - expect(game.contains(bumper), isTrue); + final sparkyBumper = SparkyBumper.a(); + await game.ensureAdd(sparkyBumper); + expect(game.contains(sparkyBumper), isTrue); }); flameTester.test('"b" loads correctly', (game) async { - final bumper = SparkyBumper.b(); - await game.ensureAdd(bumper); - expect(game.contains(bumper), isTrue); + final sparkyBumper = SparkyBumper.b(); + await game.ensureAdd(sparkyBumper); + expect(game.contains(sparkyBumper), isTrue); }); flameTester.test('"c" loads correctly', (game) async { - final bumper = SparkyBumper.c(); - await game.ensureAdd(bumper); - expect(game.contains(bumper), isTrue); + final sparkyBumper = SparkyBumper.c(); + await game.ensureAdd(sparkyBumper); + expect(game.contains(sparkyBumper), isTrue); + }); + + flameTester.test('closes bloc when removed', (game) async { + final bloc = MockSparkyBumperCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: SparkyBumperState.active, + ); + when(bloc.close).thenAnswer((_) async {}); + final sparkyBumper = SparkyBumper.test(bloc: bloc); + + await game.ensureAdd(sparkyBumper); + game.remove(sparkyBumper); + await game.ready(); + + verify(bloc.close).called(1); + }); + + group('adds', () { + flameTester.test('new children', (game) async { + final component = Component(); + final sparkyBumper = SparkyBumper.a( + children: [component], + ); + await game.ensureAdd(sparkyBumper); + expect(sparkyBumper.children, contains(component)); + }); + + flameTester.test('an SparkyBumperBallContactBehaviour', (game) async { + final sparkyBumper = SparkyBumper.a(); + await game.ensureAdd(sparkyBumper); + expect( + sparkyBumper.children + .whereType() + .single, + isNotNull, + ); + }); }); }); } diff --git a/packages/pinball_flame/lib/src/contact_behavior.dart b/packages/pinball_flame/lib/src/contact_behavior.dart index a081d3df..f8ad39bf 100644 --- a/packages/pinball_flame/lib/src/contact_behavior.dart +++ b/packages/pinball_flame/lib/src/contact_behavior.dart @@ -3,16 +3,16 @@ import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flutter/material.dart'; import 'package:pinball_flame/pinball_flame.dart'; -class ContactBehavior extends Component +abstract class ContactBehavior extends Component with ContactCallbacks, ParentIsA { @override @mustCallSuper Future onLoad() async { final userData = parent.body.userData; - if (userData is ContactCallbacksGroup) { + if (userData is _ContactCallbacksGroup) { userData.addContactCallbacks(this); } else if (userData is ContactCallbacks) { - final notifier = ContactCallbacksGroup() + final notifier = _ContactCallbacksGroup() ..addContactCallbacks(userData) ..addContactCallbacks(this); parent.body.userData = notifier; @@ -22,7 +22,7 @@ class ContactBehavior extends Component } } -class ContactCallbacksGroup implements ContactCallbacks { +class _ContactCallbacksGroup implements ContactCallbacks { final List _contactCallbacks = []; @override diff --git a/packages/pinball_flame/lib/src/parent_is_a.dart b/packages/pinball_flame/lib/src/parent_is_a.dart index 91866b97..19159c89 100644 --- a/packages/pinball_flame/lib/src/parent_is_a.dart +++ b/packages/pinball_flame/lib/src/parent_is_a.dart @@ -9,8 +9,7 @@ mixin ParentIsA on Component { T get parent => super.parent! as T; @override - Future? addToParent(Component parent) { - assert(parent is T, 'Parent must be of type $T'); + Future? addToParent(covariant T parent) { return super.addToParent(parent); } } diff --git a/test/game/components/scoring_behaviour_test.dart b/test/game/components/scoring_behaviour_test.dart index bea9a3fd..a6f94a13 100644 --- a/test/game/components/scoring_behaviour_test.dart +++ b/test/game/components/scoring_behaviour_test.dart @@ -47,7 +47,7 @@ void main() { 'emits Scored event with points', setUp: (game, tester) async { const points = 20; - final scoringBehaviour = ScoringBehaviour(points: points); + final scoringBehaviour = ScoringBehavior(points: points); await game.ensureAdd(scoringBehaviour); scoringBehaviour.beginContact(ball, MockContact()); @@ -64,7 +64,7 @@ void main() { 'plays score sound', setUp: (game, tester) async { const points = 20; - final scoringBehaviour = ScoringBehaviour(points: points); + final scoringBehaviour = ScoringBehavior(points: points); await game.ensureAdd(scoringBehaviour); scoringBehaviour.beginContact(ball, MockContact()); @@ -77,7 +77,7 @@ void main() { "adds a ScoreText component at Ball's position with points", setUp: (game, tester) async { const points = 20; - final scoringBehaviour = ScoringBehaviour(points: points); + final scoringBehaviour = ScoringBehavior(points: points); await game.ensureAdd(scoringBehaviour); scoringBehaviour.beginContact(ball, MockContact());