@ -1,8 +1,11 @@
/ / ignore_for_file: cascade_invocations
import ' dart:collection ' ;
import ' package:bloc_test/bloc_test.dart ' ;
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 ' ;
@ -13,11 +16,16 @@ void main() {
final flameTester = FlameTester ( PinballGameTest . create ) ;
group ( ' Plunger ' , ( ) {
const compressionDistance = 0.0 ;
flameTester . test (
' loads correctly ' ,
( game ) async {
await game . ready ( ) ;
final plunger = Plunger ( position: Vector2 . zero ( ) ) ;
final plunger = Plunger (
position: Vector2 . zero ( ) ,
compressionDistance: compressionDistance ,
) ;
await game . ensureAdd ( plunger ) ;
expect ( game . contains ( plunger ) , isTrue ) ;
@ -29,7 +37,10 @@ void main() {
' positions correctly ' ,
( game ) async {
final position = Vector2 . all ( 10 ) ;
final plunger = Plunger ( position: position ) ;
final plunger = Plunger (
position: position ,
compressionDistance: compressionDistance ,
) ;
await game . ensureAdd ( plunger ) ;
game . contains ( plunger ) ;
@ -40,7 +51,10 @@ void main() {
flameTester . test (
' is dynamic ' ,
( game ) async {
final plunger = Plunger ( position: Vector2 . zero ( ) ) ;
final plunger = Plunger (
position: Vector2 . zero ( ) ,
compressionDistance: compressionDistance ,
) ;
await game . ensureAdd ( plunger ) ;
expect ( plunger . body . bodyType , equals ( BodyType . dynamic ) ) ;
@ -50,7 +64,10 @@ void main() {
flameTester . test (
' ignores gravity ' ,
( game ) async {
final plunger = Plunger ( position: Vector2 . zero ( ) ) ;
final plunger = Plunger (
position: Vector2 . zero ( ) ,
compressionDistance: compressionDistance ,
) ;
await game . ensureAdd ( plunger ) ;
expect ( plunger . body . gravityScale , isZero ) ;
@ -58,11 +75,14 @@ void main() {
) ;
} ) ;
group ( ' fi rst fi xture' , ( ) {
group ( ' fi xture' , ( ) {
flameTester . test (
' exists ' ,
( game ) async {
final plunger = Plunger ( position: Vector2 . zero ( ) ) ;
final plunger = Plunger (
position: Vector2 . zero ( ) ,
compressionDistance: compressionDistance ,
) ;
await game . ensureAdd ( plunger ) ;
expect ( plunger . body . fixtures [ 0 ] , isA < Fixture > ( ) ) ;
@ -72,65 +92,128 @@ void main() {
flameTester . test (
' shape is a polygon ' ,
( game ) async {
final plunger = Plunger ( position: Vector2 . zero ( ) ) ;
final plunger = Plunger (
position: Vector2 . zero ( ) ,
compressionDistance: compressionDistance ,
) ;
await game . ensureAdd ( plunger ) ;
final fixture = plunger . body . fixtures [ 0 ] ;
expect ( fixture . shape . shapeType , equals ( ShapeType . polygon ) ) ;
} ,
) ;
} ) ;
flameTester . test (
' pull sets a negative linear velocity ' ,
( game ) async {
final plunger = Plunger ( position: Vector2 . zero ( ) ) ;
await game . ensureAdd ( plunger ) ;
plunger . pull ( ) ;
expect ( plunger . body . linearVelocity . y , isNegative ) ;
expect ( plunger . body . linearVelocity . x , isZero ) ;
} ,
) ;
group ( ' release ' , ( ) {
flameTester . test (
' does not set a linear velocity '
' when plunger is in starting position ' ,
' has density ' ,
( game ) async {
final plunger = Plunger ( position: Vector2 . zero ( ) ) ;
final plunger = Plunger (
position: Vector2 . zero ( ) ,
compressionDistance: compressionDistance ,
) ;
await game . ensureAdd ( plunger ) ;
plunger . release ( ) ;
expect ( plunger . body . linearVelocity . y , isZero ) ;
expect ( plunger . body . linearVelocity . x , isZero ) ;
final fixture = plunger . body . fixtures [ 0 ] ;
expect ( fixture . density , greaterThan ( 0 ) ) ;
} ,
) ;
} ) ;
flameTester . test (
' sets a positive linear velocity '
' when plunger is below starting position ' ,
( game ) async {
final plunger = Plunger ( position: Vector2 . zero ( ) ) ;
await game . ensureAdd ( plunger ) ;
group ( ' onKeyEvent ' , ( ) {
final keys = UnmodifiableListView ( [
LogicalKeyboardKey . space ,
LogicalKeyboardKey . arrowDown ,
LogicalKeyboardKey . keyS ,
] ) ;
plunger . body . setTransform ( Vector2 ( 0 , - 1 ) , 0 ) ;
plunger . release ( ) ;
late Plunger plunger ;
expect ( plunger . body . linearVelocity . y , isPositive ) ;
expect ( plunger . body . linearVelocity . x , isZero ) ;
} ,
) ;
setUp ( ( ) {
plunger = Plunger (
position: Vector2 . zero ( ) ,
compressionDistance: compressionDistance ,
) ;
} ) ;
testRawKeyUpEvents ( keys , ( event ) {
final keyLabel = ( event . logicalKey ! = LogicalKeyboardKey . space )
? event . logicalKey . keyLabel
: ' Space ' ;
flameTester . test (
' moves upwards when $ keyLabel is released '
' and plunger is below its starting position ' ,
( game ) async {
await game . ensureAdd ( plunger ) ;
plunger . body . setTransform ( Vector2 ( 0 , - 1 ) , 0 ) ;
plunger . onKeyEvent ( event , { } ) ;
expect ( plunger . body . linearVelocity . y , isPositive ) ;
expect ( plunger . body . linearVelocity . x , isZero ) ;
} ,
) ;
} ) ;
testRawKeyUpEvents ( keys , ( event ) {
final keyLabel = ( event . logicalKey ! = LogicalKeyboardKey . space )
? event . logicalKey . keyLabel
: ' Space ' ;
flameTester . test (
' does not move when $ keyLabel is released '
' and plunger is in its starting position ' ,
( game ) async {
await game . ensureAdd ( plunger ) ;
plunger . onKeyEvent ( event , { } ) ;
expect ( plunger . body . linearVelocity . y , isZero ) ;
expect ( plunger . body . linearVelocity . x , isZero ) ;
} ,
) ;
} ) ;
testRawKeyDownEvents ( keys , ( event ) {
final keyLabel = ( event . logicalKey ! = LogicalKeyboardKey . space )
? event . logicalKey . keyLabel
: ' Space ' ;
flameTester . test (
' moves downwards when $ keyLabel is pressed ' ,
( game ) async {
await game . ensureAdd ( plunger ) ;
plunger . onKeyEvent ( event , { } ) ;
expect ( plunger . body . linearVelocity . y , isNegative ) ;
expect ( plunger . body . linearVelocity . x , isZero ) ;
} ,
) ;
} ) ;
} ) ;
} ) ;
group ( ' PlungerAnchorPrismaticJointDef ' , ( ) {
late Plunger plunger ;
late Anchor anchor ;
group ( ' PlungerAnchor ' , ( ) {
const compressionDistance = 10.0 ;
flameTester . test (
' position is a compression distance below the Plunger ' ,
( game ) async {
final plunger = Plunger (
position: Vector2 . zero ( ) ,
compressionDistance: compressionDistance ,
) ;
await game . ensureAdd ( plunger ) ;
final plungerAnchor = PlungerAnchor ( plunger: plunger ) ;
await game . ensureAdd ( plungerAnchor ) ;
expect (
plungerAnchor . body . position . y ,
equals ( plunger . body . position . y - compressionDistance ) ,
) ;
} ,
) ;
} ) ;
group ( ' PlungerAnchorPrismaticJointDef ' , ( ) {
const compressionDistance = 10.0 ;
final gameBloc = MockGameBloc ( ) ;
late Plunger plunger ;
setUp ( ( ) {
whenListen (
@ -138,51 +221,21 @@ void main() {
const Stream < GameState > . empty ( ) ,
initialState: const GameState . initial ( ) ,
) ;
plunger = Plunger ( position: Vector2 . zero ( ) ) ;
anchor = Anchor ( position: Vector2 ( 0 , - 1 ) ) ;
plunger = Plunger (
position: Vector2 . zero ( ) ,
compressionDistance: compressionDistance ,
) ;
} ) ;
final flameTester = flameBlocTester ( gameBloc: gameBloc ) ;
flameTester . test (
' throws AssertionError '
' when anchor is above plunger ' ,
( game ) async {
final anchor = Anchor ( position: Vector2 ( 0 , 1 ) ) ;
await game . ensureAddAll ( [ plunger , anchor ] ) ;
expect (
( ) = > PlungerAnchorPrismaticJointDef (
plunger: plunger ,
anchor: anchor ,
) ,
throwsAssertionError ,
) ;
} ,
) ;
flameTester . test (
' throws AssertionError '
' when anchor is in same position as plunger ' ,
( game ) async {
final anchor = Anchor ( position: Vector2 . zero ( ) ) ;
await game . ensureAddAll ( [ plunger , anchor ] ) ;
expect (
( ) = > PlungerAnchorPrismaticJointDef (
plunger: plunger ,
anchor: anchor ,
) ,
throwsAssertionError ,
) ;
} ,
) ;
group ( ' initializes with ' , ( ) {
flameTester . test (
' plunger body as bodyA ' ,
( game ) async {
await game . ensureAddAll ( [ plunger , anchor ] ) ;
await game . ensureAdd ( plunger ) ;
final anchor = PlungerAnchor ( plunger: plunger ) ;
await game . ensureAdd ( anchor ) ;
final jointDef = PlungerAnchorPrismaticJointDef (
plunger: plunger ,
@ -196,7 +249,9 @@ void main() {
flameTester . test (
' anchor body as bodyB ' ,
( game ) async {
await game . ensureAddAll ( [ plunger , anchor ] ) ;
await game . ensureAdd ( plunger ) ;
final anchor = PlungerAnchor ( plunger: plunger ) ;
await game . ensureAdd ( anchor ) ;
final jointDef = PlungerAnchorPrismaticJointDef (
plunger: plunger ,
@ -211,7 +266,9 @@ void main() {
flameTester . test (
' limits enabled ' ,
( game ) async {
await game . ensureAddAll ( [ plunger , anchor ] ) ;
await game . ensureAdd ( plunger ) ;
final anchor = PlungerAnchor ( plunger: plunger ) ;
await game . ensureAdd ( anchor ) ;
final jointDef = PlungerAnchorPrismaticJointDef (
plunger: plunger ,
@ -226,7 +283,9 @@ void main() {
flameTester . test (
' lower translation limit as negative infinity ' ,
( game ) async {
await game . ensureAddAll ( [ plunger , anchor ] ) ;
await game . ensureAdd ( plunger ) ;
final anchor = PlungerAnchor ( plunger: plunger ) ;
await game . ensureAdd ( anchor ) ;
final jointDef = PlungerAnchorPrismaticJointDef (
plunger: plunger ,
@ -241,7 +300,9 @@ void main() {
flameTester . test (
' connected body collison enabled ' ,
( game ) async {
await game . ensureAddAll ( [ plunger , anchor ] ) ;
await game . ensureAdd ( plunger ) ;
final anchor = PlungerAnchor ( plunger: plunger ) ;
await game . ensureAdd ( anchor ) ;
final jointDef = PlungerAnchorPrismaticJointDef (
plunger: plunger ,
@ -254,46 +315,51 @@ void main() {
) ;
} ) ;
flameTester . widgetTest (
' plunger cannot go below anchor ' ,
( game , tester ) async {
await game . ensureAddAll ( [ plunger , anchor ] ) ;
testRawKeyUpEvents ( [ LogicalKeyboardKey . space ] , ( event ) {
flameTester . widgetTest (
' plunger cannot go below anchor ' ,
( game , tester ) async {
await game . ensureAdd ( plunger ) ;
final anchor = PlungerAnchor ( plunger: plunger ) ;
await game . ensureAdd ( anchor ) ;
/ / Giving anchor a shape for the plunger to collide with .
anchor . body . createFixtureFromShape ( PolygonShape ( ) . . setAsBoxXY ( 2 , 1 ) ) ;
/ / Giving anchor a shape for the plunger to collide with .
anchor . body . createFixtureFromShape ( PolygonShape ( ) . . setAsBoxXY ( 2 , 1 ) ) ;
final jointDef = PlungerAnchorPrismaticJointDef (
plunger: plunger ,
anchor: anchor ,
) ;
game . world . createJoint ( jointDef ) ;
final jointDef = PlungerAnchorPrismaticJointDef (
plunger: plunger ,
anchor: anchor ,
) ;
game . world . createJoint ( jointDef ) ;
plunger . pull ( ) ;
await tester . pump ( const Duration ( seconds: 1 ) ) ;
await tester . pump ( const Duration ( seconds: 1 ) ) ;
expect ( plunger . body . position . y > anchor . body . position . y , isTrue ) ;
} ,
) ;
expect ( plunger . body . position . y > anchor . body . position . y , isTrue ) ;
} ,
) ;
} ) ;
flameTester . widgetTest (
' plunger cannot excessively exceed starting position ' ,
( game , tester ) async {
await game . ensureAddAll ( [ plunger , anchor ] ) ;
testRawKeyUpEvents ( [ LogicalKeyboardKey . space ] , ( event ) {
flameTester . widgetTest (
' plunger cannot excessively exceed starting position ' ,
( game , tester ) async {
await game . ensureAdd ( plunger ) ;
final anchor = PlungerAnchor ( plunger: plunger ) ;
await game . ensureAdd ( anchor ) ;
final jointDef = PlungerAnchorPrismaticJointDef (
plunger: plunger ,
anchor: anchor ,
) ;
game . world . createJoint ( jointDef ) ;
final jointDef = PlungerAnchorPrismaticJointDef (
plunger: plunger ,
anchor: anchor ,
) ;
game . world . createJoint ( jointDef ) ;
plunger . pull ( ) ;
await tester . pump ( const Duration ( seconds: 1 ) ) ;
plunger . body . setTransform ( Vector2 ( 0 , - 1 ) , 0 ) ;
plunger . release ( ) ;
await tester . pump ( const Duration ( seconds: 1 ) ) ;
await tester . pump ( const Duration ( seconds: 1 ) ) ;
expect ( plunger . body . position . y < 1 , isTrue ) ;
} ,
) ;
expect ( plunger . body . position . y < 1 , isTrue ) ;
} ,
) ;
} ) ;
} ) ;
}