diff --git a/lib/game/components/sparky_fire_zone.dart b/lib/game/components/sparky_fire_zone.dart index bbf3bdc7..0573f976 100644 --- a/lib/game/components/sparky_fire_zone.dart +++ b/lib/game/components/sparky_fire_zone.dart @@ -1,6 +1,7 @@ // ignore_for_file: avoid_renaming_method_parameters import 'package:flame/components.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flutter/material.dart'; import 'package:pinball/flame/flame.dart'; import 'package:pinball/game/game.dart'; @@ -8,27 +9,48 @@ import 'package:pinball_components/pinball_components.dart'; // TODO(ruimiguel): create and add SparkyFireZone component here in other PR. +class ControlledSparkyBumper extends SparkyBumper + with Controls<_SparkyBumperController> { + ControlledSparkyBumper() : super.a() { + controller = _SparkyBumperController(this); + } +} + /// {@template sparky_bumper_controller} /// Controls a [SparkyBumper]. /// {@endtemplate} -@visibleForTesting -class SparkyBumperController extends ComponentController +class _SparkyBumperController extends ComponentController with HasGameRef { /// {@macro sparky_bumper_controller} - SparkyBumperController(SparkyBumper sparkyBumper) : super(sparkyBumper); + _SparkyBumperController(SparkyBumper sparkyBumper) : super(sparkyBumper); /// Flag for activated state of the [SparkyBumper]. /// /// Used to toggle [SparkyBumper]s' state between activated and deactivated. - bool _isActivated = false; + bool isActivated = false; /// Registers when a [SparkyBumper] is hit by a [Ball]. + /// + /// Triggered by [ControlledSparkyBumperBallContactCallback]. void hit() { - if (_isActivated) { + if (isActivated) { component.deactivate(); } else { component.activate(); } - _isActivated = !_isActivated; + isActivated = !isActivated; + } +} + +/// Listens when a [Ball] bounces bounces against a [SparkyBumper]. +class ControlledSparkyBumperBallContactCallback + extends ContactCallback, Ball> { + @override + void begin( + Controls<_SparkyBumperController> controlledSparkyBumper, + Ball _, + Contact __, + ) { + controlledSparkyBumper.controller.hit(); } } diff --git a/test/game/components/sparky_fire_zone_test.dart b/test/game/components/sparky_fire_zone_test.dart index 5188aa59..b59e4a55 100644 --- a/test/game/components/sparky_fire_zone_test.dart +++ b/test/game/components/sparky_fire_zone_test.dart @@ -1,3 +1,8 @@ +// ignore_for_file: cascade_invocations + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:pinball/game/game.dart'; @@ -6,27 +11,57 @@ import 'package:pinball_components/pinball_components.dart'; import '../../helpers/helpers.dart'; void main() { - group('SparkyBumperController', () { - late SparkyBumper sparkyBumper; + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(EmptyPinballGameTest.new); - setUp(() { - sparkyBumper = MockSparkyBumper(); - }); + group('SparkyFireZone', () { + group('bumpers', () { + late ControlledSparkyBumper controlledSparkyBumper; + + flameTester.testGameWidget( + 'activate when deactivated bumper is hit', + setUp: (game, tester) async { + controlledSparkyBumper = ControlledSparkyBumper(); + await game.ensureAdd(controlledSparkyBumper); + + final callback = ControlledSparkyBumperBallContactCallback(); + game.addContactCallback(callback); - test('toggle activated state when bumper is hit', () { - final controller = SparkyBumperController(sparkyBumper); + callback.begin( + controlledSparkyBumper, + MockBall(), + MockContact(), + ); + }, + verify: (game, tester) async { + expect(controlledSparkyBumper.controller.isActivated, isTrue); + }, + ); - when(() => sparkyBumper.activate()).thenReturn(null); - when(() => sparkyBumper.deactivate()).thenReturn(null); + flameTester.testGameWidget( + 'deactivate when activated bumper is hit', + setUp: (game, tester) async { + controlledSparkyBumper = ControlledSparkyBumper(); + await game.ensureAdd(controlledSparkyBumper); - controller - ..hit() - ..hit(); + final callback = ControlledSparkyBumperBallContactCallback(); + game.addContactCallback(callback); - verifyInOrder([ - () => sparkyBumper.activate(), - () => sparkyBumper.deactivate(), - ]); + callback.begin( + controlledSparkyBumper, + MockBall(), + MockContact(), + ); + callback.begin( + controlledSparkyBumper, + MockBall(), + MockContact(), + ); + }, + verify: (game, tester) async { + expect(controlledSparkyBumper.controller.isActivated, isFalse); + }, + ); }); }); } diff --git a/test/helpers/mocks.dart b/test/helpers/mocks.dart index b1ef8ebe..748b48f3 100644 --- a/test/helpers/mocks.dart +++ b/test/helpers/mocks.dart @@ -74,5 +74,3 @@ class MockComponentSet extends Mock implements ComponentSet {} class MockDashNestBumper extends Mock implements DashNestBumper {} class MockPinballAudio extends Mock implements PinballAudio {} - -class MockSparkyBumper extends Mock implements SparkyBumper {}