diff --git a/packages/pinball_components/lib/src/components/layer_sensor/layer_sensor.dart b/packages/pinball_components/lib/src/components/layer_sensor/layer_sensor.dart index f90ffd79..4b1d6ae3 100644 --- a/packages/pinball_components/lib/src/components/layer_sensor/layer_sensor.dart +++ b/packages/pinball_components/lib/src/components/layer_sensor/layer_sensor.dart @@ -21,8 +21,7 @@ enum LayerEntranceOrientation { /// By default the base [layer] is set to [Layer.board] and the /// [outsideZIndex] is set to [ZIndexes.ballOnBoard]. /// {@endtemplate} -abstract class LayerSensor extends BodyComponent - with InitialPosition, Layered, ContactCallbacks { +abstract class LayerSensor extends BodyComponent with InitialPosition, Layered { /// {@macro layer_sensor} LayerSensor({ required this.insideLayer, @@ -61,9 +60,7 @@ abstract class LayerSensor extends BodyComponent shape, isSensor: true, ); - final bodyDef = BodyDef( - position: initialPosition, - ); + final bodyDef = BodyDef(position: initialPosition); return world.createBody(bodyDef)..createFixture(fixtureDef); } } diff --git a/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart b/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart new file mode 100644 index 00000000..b7bc308b --- /dev/null +++ b/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart @@ -0,0 +1,136 @@ +// 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:mocktail/mocktail.dart'; +import 'package:pinball_components/pinball_components.dart'; +import 'package:pinball_components/src/components/layer_sensor/behaviors/behaviors.dart'; + +import '../../../../helpers/helpers.dart'; + +class _TestLayerSensor extends LayerSensor { + _TestLayerSensor({ + required LayerEntranceOrientation orientation, + required int insideZIndex, + required Layer insideLayer, + }) : super( + insideLayer: insideLayer, + insideZIndex: insideZIndex, + orientation: orientation, + ); + + @override + Shape get shape => PolygonShape()..setAsBoxXY(1, 1); +} + +class _MockBall extends Mock implements Ball {} + +class _MockBody extends Mock implements Body {} + +class _MockContact extends Mock implements Contact {} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + final flameTester = FlameTester(TestGame.new); + + group( + 'LayerSensorBehavior', + () { + test('can be instantiated', () { + expect( + LayerFilteringBehavior(), + isA(), + ); + }); + + flameTester.test( + 'loads', + (game) async { + final behavior = LayerFilteringBehavior(); + final parent = _TestLayerSensor( + orientation: LayerEntranceOrientation.down, + insideZIndex: 1, + insideLayer: Layer.spaceshipEntranceRamp, + ); + + await parent.add(behavior); + await game.ensureAdd(parent); + + expect(game.contains(parent), isTrue); + }, + ); + + group('beginContact', () { + late Ball ball; + late Body body; + late int insideZIndex; + late Layer insideLayer; + + setUp(() { + ball = _MockBall(); + body = _MockBody(); + insideZIndex = 1; + insideLayer = Layer.spaceshipEntranceRamp; + + when(() => ball.body).thenReturn(body); + when(() => ball.layer).thenReturn(Layer.board); + }); + + flameTester.test( + 'changes ball layer and zIndex ' + 'when a ball enters and exits a downward oriented LayerSensor', + (game) async { + final parent = _TestLayerSensor( + orientation: LayerEntranceOrientation.down, + insideZIndex: 1, + insideLayer: insideLayer, + )..initialPosition = Vector2(0, 10); + final behavior = LayerFilteringBehavior(); + + await parent.add(behavior); + await game.ensureAdd(parent); + + when(() => body.linearVelocity).thenReturn(Vector2(0, -1)); + + behavior.beginContact(ball, _MockContact()); + verify(() => ball.layer = insideLayer).called(1); + verify(() => ball.zIndex = insideZIndex).called(1); + + when(() => ball.layer).thenReturn(insideLayer); + + behavior.beginContact(ball, _MockContact()); + verify(() => ball.layer = Layer.board); + verify(() => ball.zIndex = ZIndexes.ballOnBoard).called(1); + }); + + flameTester.test( + 'changes ball layer and zIndex ' + 'when a ball enters and exits an upward oriented LayerSensor', + (game) async { + final parent = _TestLayerSensor( + orientation: LayerEntranceOrientation.up, + insideZIndex: 1, + insideLayer: insideLayer, + )..initialPosition = Vector2(0, 10); + final behavior = LayerFilteringBehavior(); + + await parent.add(behavior); + await game.ensureAdd(parent); + + when(() => body.linearVelocity).thenReturn(Vector2(0, 1)); + + behavior.beginContact(ball, _MockContact()); + verify(() => ball.layer = insideLayer).called(1); + verify(() => ball.zIndex = 1).called(1); + + when(() => ball.layer).thenReturn(insideLayer); + + behavior.beginContact(ball, _MockContact()); + verify(() => ball.layer = Layer.board); + verify(() => ball.zIndex = ZIndexes.ballOnBoard).called(1); + }); + }); + }, + ); +} diff --git a/packages/pinball_components/test/src/components/layer_sensor_test.dart b/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart similarity index 59% rename from packages/pinball_components/test/src/components/layer_sensor_test.dart rename to packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart index cfd19bb0..dd32ad56 100644 --- a/packages/pinball_components/test/src/components/layer_sensor_test.dart +++ b/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart @@ -2,16 +2,10 @@ import 'package:flame_forge2d/flame_forge2d.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/layer_sensor/behaviors/behaviors.dart'; -import '../../helpers/helpers.dart'; - -class _MockBall extends Mock implements Ball {} - -class _MockBody extends Mock implements Body {} - -class _MockContact extends Mock implements Contact {} +import '../../../helpers/helpers.dart'; class TestLayerSensor extends LayerSensor { TestLayerSensor({ @@ -112,68 +106,22 @@ void main() { ); }); }); - }); - - group('beginContact', () { - late Ball ball; - late Body body; - late int insideZIndex; - late Layer insideLayer; - - setUp(() { - ball = _MockBall(); - body = _MockBody(); - insideZIndex = 1; - insideLayer = Layer.spaceshipEntranceRamp; - - when(() => ball.body).thenReturn(body); - when(() => ball.layer).thenReturn(Layer.board); - }); - - flameTester.test( - 'changes ball layer and zIndex ' - 'when a ball enters and exits a downward oriented LayerSensor', - (game) async { - final sensor = TestLayerSensor( - orientation: LayerEntranceOrientation.down, - insideZIndex: insidePriority, - insideLayer: insideLayer, - )..initialPosition = Vector2(0, 10); - - when(() => body.linearVelocity).thenReturn(Vector2(0, -1)); - - sensor.beginContact(ball, _MockContact()); - verify(() => ball.layer = insideLayer).called(1); - verify(() => ball.zIndex = insideZIndex).called(1); - - when(() => ball.layer).thenReturn(insideLayer); - - sensor.beginContact(ball, _MockContact()); - verify(() => ball.layer = Layer.board); - verify(() => ball.zIndex = ZIndexes.ballOnBoard).called(1); - }); flameTester.test( - 'changes ball layer and zIndex ' - 'when a ball enters and exits an upward oriented LayerSensor', - (game) async { - final sensor = TestLayerSensor( - orientation: LayerEntranceOrientation.up, - insideZIndex: insidePriority, - insideLayer: insideLayer, - )..initialPosition = Vector2(0, 10); - - when(() => body.linearVelocity).thenReturn(Vector2(0, 1)); - - sensor.beginContact(ball, _MockContact()); - verify(() => ball.layer = insideLayer).called(1); - verify(() => ball.zIndex = insidePriority).called(1); - - when(() => ball.layer).thenReturn(insideLayer); + 'adds a LayerFilteringBehavior', + (game) async { + final layerSensor = TestLayerSensor( + orientation: LayerEntranceOrientation.down, + insideZIndex: insidePriority, + insideLayer: Layer.spaceshipEntranceRamp, + ); + await game.ensureAdd(layerSensor); - sensor.beginContact(ball, _MockContact()); - verify(() => ball.layer = Layer.board); - verify(() => ball.zIndex = ZIndexes.ballOnBoard).called(1); - }); + expect( + layerSensor.children.whereType().length, + equals(1), + ); + }, + ); }); }