Merge branch 'fix/spaceship-ramp-logic' of github.com:VGVentures/pinball into fix/spaceship-ramp-logic

pull/416/head
RuiAlonso 3 years ago
commit 83d85b6239

@ -13,7 +13,8 @@ class BallSpawningBehavior extends Component
bool listenWhen(GameState? previousState, GameState newState) { bool listenWhen(GameState? previousState, GameState newState) {
if (!newState.status.isPlaying) return false; if (!newState.status.isPlaying) return false;
final startedGame = previousState?.status.isWaiting ?? true; final startedGame = (previousState?.status.isWaiting ?? true) ||
(previousState?.status.isGameOver ?? true);
final lostRound = final lostRound =
(previousState?.rounds ?? newState.rounds + 1) > newState.rounds; (previousState?.rounds ?? newState.rounds + 1) > newState.rounds;
return startedGame || lostRound; return startedGame || lostRound;

@ -19,7 +19,7 @@ class GameBloc extends Bloc<GameEvent, GameState> {
static const _maxScore = 9999999999; static const _maxScore = 9999999999;
void _onGameStarted(GameStarted _, Emitter emit) { void _onGameStarted(GameStarted _, Emitter emit) {
emit(state.copyWith(status: GameStatus.playing)); emit(const GameState.initial().copyWith(status: GameStatus.playing));
} }
void _onGameOver(GameOver _, Emitter emit) { void _onGameOver(GameOver _, Emitter emit) {

@ -66,7 +66,7 @@ class GameOverInfoDisplay extends Component with HasGameRef {
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
await super.onLoad(); await super.onLoad();
gameRef.overlays.add(PinballGame.playButtonOverlay); gameRef.overlays.add(PinballGame.replayButtonOverlay);
} }
} }

@ -22,6 +22,7 @@ class GameBlocStatusListener extends Component
break; break;
case GameStatus.playing: case GameStatus.playing:
readProvider<PinballAudioPlayer>().play(PinballAudio.backgroundMusic); readProvider<PinballAudioPlayer>().play(PinballAudio.backgroundMusic);
_resetBonuses();
gameRef gameRef
.descendants() .descendants()
.whereType<Flipper>() .whereType<Flipper>()
@ -32,6 +33,7 @@ class GameBlocStatusListener extends Component
.forEach(_addPlungerBehaviors); .forEach(_addPlungerBehaviors);
gameRef.overlays.remove(PinballGame.playButtonOverlay); gameRef.overlays.remove(PinballGame.playButtonOverlay);
gameRef.overlays.remove(PinballGame.replayButtonOverlay);
break; break;
case GameStatus.gameOver: case GameStatus.gameOver:
readProvider<PinballAudioPlayer>().play(PinballAudio.gameOverVoiceOver); readProvider<PinballAudioPlayer>().play(PinballAudio.gameOverVoiceOver);
@ -54,6 +56,15 @@ class GameBlocStatusListener extends Component
} }
} }
void _resetBonuses() {
gameRef
.descendants()
.whereType<FlameBlocProvider<GoogleWordCubit, GoogleWordState>>()
.single
.bloc
.onReset();
}
void _addPlungerBehaviors(Plunger plunger) { void _addPlungerBehaviors(Plunger plunger) {
final platformHelper = readProvider<PlatformHelper>(); final platformHelper = readProvider<PlatformHelper>();
const pullingStrength = 7.0; const pullingStrength = 7.0;

@ -17,7 +17,7 @@ class GoogleWordBonusBehavior extends Component {
onNewState: (state) { onNewState: (state) {
readBloc<GameBloc, GameState>() readBloc<GameBloc, GameState>()
.add(const BonusActivated(GameBonus.googleWord)); .add(const BonusActivated(GameBonus.googleWord));
readBloc<GoogleWordCubit, GoogleWordState>().onBonusAwarded(); readBloc<GoogleWordCubit, GoogleWordState>().onReset();
add(BonusBallSpawningBehavior()); add(BonusBallSpawningBehavior());
add(GoogleWordAnimatingBehavior()); add(GoogleWordAnimatingBehavior());
}, },

@ -38,10 +38,13 @@ class PinballGame extends PinballForge2DGame
images.prefix = ''; images.prefix = '';
} }
/// Identifier of the play button overlay /// Identifier of the play button overlay.
static const playButtonOverlay = 'play_button'; static const playButtonOverlay = 'play_button';
/// Identifier of the mobile controls overlay /// Identifier of the replay button overlay.
static const replayButtonOverlay = 'replay_button';
/// Identifier of the mobile controls overlay.
static const mobileControlsOverlay = 'mobile_controls'; static const mobileControlsOverlay = 'mobile_controls';
@override @override

@ -100,22 +100,25 @@ class PinballGameLoadedView extends StatelessWidget {
focusNode: game.focusNode, focusNode: game.focusNode,
initialActiveOverlays: const [PinballGame.playButtonOverlay], initialActiveOverlays: const [PinballGame.playButtonOverlay],
overlayBuilderMap: { overlayBuilderMap: {
PinballGame.playButtonOverlay: (context, game) { PinballGame.playButtonOverlay: (_, game) => const Positioned(
return const Positioned(
bottom: 20, bottom: 20,
right: 0, right: 0,
left: 0, left: 0,
child: PlayButtonOverlay(), child: PlayButtonOverlay(),
); ),
}, PinballGame.mobileControlsOverlay: (_, game) => Positioned(
PinballGame.mobileControlsOverlay: (context, game) {
return Positioned(
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0,
child: MobileControls(game: game), child: MobileControls(game: game),
); ),
}, PinballGame.replayButtonOverlay: (context, game) =>
const Positioned(
bottom: 20,
right: 0,
left: 0,
child: ReplayButtonOverlay(),
)
}, },
), ),
), ),

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/l10n/l10n.dart'; import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/start_game/start_game.dart'; import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_ui/pinball_ui.dart'; import 'package:pinball_ui/pinball_ui.dart';
@ -18,6 +19,7 @@ class ReplayButtonOverlay extends StatelessWidget {
return PinballButton( return PinballButton(
text: l10n.replay, text: l10n.replay,
onTap: () { onTap: () {
context.read<GameBloc>().add(const GameStarted());
context.read<StartGameBloc>().add(const ReplayTapped()); context.read<StartGameBloc>().add(const ReplayTapped());
}, },
); );

@ -1,6 +1,8 @@
import 'package:flame/components.dart'; import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/android_animatronic/behaviors/behaviors.dart';
import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_flame/pinball_flame.dart';
/// {@template android_animatronic} /// {@template android_animatronic}
@ -13,6 +15,7 @@ class AndroidAnimatronic extends BodyComponent
: super( : super(
children: [ children: [
_AndroidAnimatronicSpriteAnimationComponent(), _AndroidAnimatronicSpriteAnimationComponent(),
AndroidAnimatronicBallContactBehavior(),
...?children, ...?children,
], ],
renderBody: false, renderBody: false,
@ -21,6 +24,13 @@ class AndroidAnimatronic extends BodyComponent
zIndex = ZIndexes.androidHead; zIndex = ZIndexes.androidHead;
} }
/// Creates an [AndroidAnimatronic] without any children.
///
/// This can be used for testing [AndroidAnimatronic]'s behaviors in
/// isolation.
@visibleForTesting
AndroidAnimatronic.test();
@override @override
Body createBody() { Body createBody() {
final shape = EllipseShape( final shape = EllipseShape(

@ -1,18 +1,15 @@
// ignore_for_file: public_member_api_docs // ignore_for_file: public_member_api_docs
import 'package:flame_bloc/flame_bloc.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_flame/pinball_flame.dart';
class AndroidSpaceshipEntranceBallContactBehavior class AndroidAnimatronicBallContactBehavior
extends ContactBehavior<AndroidSpaceshipEntrance> extends ContactBehavior<AndroidAnimatronic> {
with FlameBlocReader<AndroidSpaceshipCubit, AndroidSpaceshipState> {
@override @override
void beginContact(Object other, Contact contact) { void beginContact(Object other, Contact contact) {
super.beginContact(other, contact); super.beginContact(other, contact);
if (other is! Ball) return; if (other is! Ball) return;
readBloc<AndroidSpaceshipCubit, AndroidSpaceshipState>().onBallContacted();
bloc.onBallEntered();
} }
} }

@ -0,0 +1 @@
export 'android_animatronic_ball_contact_behavior.dart.dart';

@ -5,7 +5,6 @@ import 'package:flame/components.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/android_spaceship/behaviors/behaviors.dart';
import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_flame/pinball_flame.dart';
export 'cubit/android_spaceship_cubit.dart'; export 'cubit/android_spaceship_cubit.dart';
@ -17,9 +16,6 @@ class AndroidSpaceship extends Component {
_SpaceshipSaucer()..initialPosition = position, _SpaceshipSaucer()..initialPosition = position,
_SpaceshipSaucerSpriteAnimationComponent()..position = position, _SpaceshipSaucerSpriteAnimationComponent()..position = position,
_LightBeamSpriteComponent()..position = position + Vector2(2.5, 5), _LightBeamSpriteComponent()..position = position + Vector2(2.5, 5),
AndroidSpaceshipEntrance(
children: [AndroidSpaceshipEntranceBallContactBehavior()],
),
_SpaceshipHole( _SpaceshipHole(
outsideLayer: Layer.spaceshipExitRail, outsideLayer: Layer.spaceshipExitRail,
outsidePriority: ZIndexes.ballOnSpaceshipRail, outsidePriority: ZIndexes.ballOnSpaceshipRail,
@ -134,35 +130,6 @@ class _LightBeamSpriteComponent extends SpriteComponent
} }
} }
class AndroidSpaceshipEntrance extends BodyComponent
with ParentIsA<AndroidSpaceship>, Layered {
AndroidSpaceshipEntrance({Iterable<Component>? children})
: super(
children: children,
renderBody: false,
) {
layer = Layer.spaceship;
}
@override
Body createBody() {
final shape = PolygonShape()
..setAsBox(
2,
0.1,
Vector2(-27.4, -37.2),
-0.12,
);
final fixtureDef = FixtureDef(
shape,
isSensor: true,
);
final bodyDef = BodyDef();
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
}
class _SpaceshipHole extends LayerSensor { class _SpaceshipHole extends LayerSensor {
_SpaceshipHole({required Layer outsideLayer, required int outsidePriority}) _SpaceshipHole({required Layer outsideLayer, required int outsidePriority})
: super( : super(

@ -1 +0,0 @@
export 'android_spaceship_entrance_ball_contact_behavior.dart.dart';

@ -5,7 +5,7 @@ part 'android_spaceship_state.dart';
class AndroidSpaceshipCubit extends Cubit<AndroidSpaceshipState> { class AndroidSpaceshipCubit extends Cubit<AndroidSpaceshipState> {
AndroidSpaceshipCubit() : super(AndroidSpaceshipState.withoutBonus); AndroidSpaceshipCubit() : super(AndroidSpaceshipState.withoutBonus);
void onBallEntered() => emit(AndroidSpaceshipState.withBonus); void onBallContacted() => emit(AndroidSpaceshipState.withBonus);
void onBonusAwarded() => emit(AndroidSpaceshipState.withoutBonus); void onBonusAwarded() => emit(AndroidSpaceshipState.withoutBonus);
} }

@ -1,4 +1,4 @@
export 'android_animatronic.dart'; export 'android_animatronic/android_animatronic.dart';
export 'android_bumper/android_bumper.dart'; export 'android_bumper/android_bumper.dart';
export 'android_spaceship/android_spaceship.dart'; export 'android_spaceship/android_spaceship.dart';
export 'arcade_background/arcade_background.dart'; export 'arcade_background/arcade_background.dart';

@ -17,7 +17,7 @@ class GoogleWordAnimatingBehavior extends TimerComponent
_blinks++; _blinks++;
} else { } else {
timer.stop(); timer.stop();
bloc.onAnimationFinished(); bloc.onReset();
shouldRemove = true; shouldRemove = true;
} }
} }

@ -68,7 +68,7 @@ class GoogleWordCubit extends Cubit<GoogleWordState> {
); );
} }
void onAnimationFinished() { void onReset() {
emit(GoogleWordState.initial()); emit(GoogleWordState.initial());
_lastLitLetter = 0; _lastLitLetter = 0;
} }

@ -14,7 +14,6 @@ class SpaceshipRampCubit extends Cubit<SpaceshipRampState> {
void onProgressed() { void onProgressed() {
final index = ArrowLightState.values.indexOf(state.lightState); final index = ArrowLightState.values.indexOf(state.lightState);
emit( emit(
state.copyWith( state.copyWith(
lightState: lightState:

@ -35,7 +35,7 @@ class SpaceshipRampState extends Equatable {
/// Indicates the state of the arrow on the [SpaceshipRamp]. /// Indicates the state of the arrow on the [SpaceshipRamp].
enum ArrowLightState { enum ArrowLightState {
/// Arrow with no dashes lit up. /// Arrow with no lights lit up.
inactive, inactive,
/// Arrow with 1 light lit up. /// Arrow with 1 light lit up.

@ -7,7 +7,7 @@ import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart'; import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/android_spaceship/behaviors/behaviors.dart'; import 'package:pinball_components/src/components/android_animatronic/behaviors/behaviors.dart';
import '../../../../helpers/helpers.dart'; import '../../../../helpers/helpers.dart';
@ -23,19 +23,19 @@ void main() {
final flameTester = FlameTester(TestGame.new); final flameTester = FlameTester(TestGame.new);
group( group(
'AndroidSpaceshipEntranceBallContactBehavior', 'AndroidAnimatronicBallContactBehavior',
() { () {
test('can be instantiated', () { test('can be instantiated', () {
expect( expect(
AndroidSpaceshipEntranceBallContactBehavior(), AndroidAnimatronicBallContactBehavior(),
isA<AndroidSpaceshipEntranceBallContactBehavior>(), isA<AndroidAnimatronicBallContactBehavior>(),
); );
}); });
flameTester.test( flameTester.test(
'beginContact calls onBallEntered when entrance contacts with a ball', 'beginContact calls onBallContacted when in contact with a ball',
(game) async { (game) async {
final behavior = AndroidSpaceshipEntranceBallContactBehavior(); final behavior = AndroidAnimatronicBallContactBehavior();
final bloc = _MockAndroidSpaceshipCubit(); final bloc = _MockAndroidSpaceshipCubit();
whenListen( whenListen(
bloc, bloc,
@ -43,20 +43,20 @@ void main() {
initialState: AndroidSpaceshipState.withoutBonus, initialState: AndroidSpaceshipState.withoutBonus,
); );
final entrance = AndroidSpaceshipEntrance(); final animatronic = AndroidAnimatronic.test();
final androidSpaceship = FlameBlocProvider<AndroidSpaceshipCubit, final androidSpaceship = FlameBlocProvider<AndroidSpaceshipCubit,
AndroidSpaceshipState>.value( AndroidSpaceshipState>.value(
value: bloc, value: bloc,
children: [ children: [
AndroidSpaceship.test(children: [entrance]) AndroidSpaceship.test(children: [animatronic])
], ],
); );
await entrance.add(behavior); await animatronic.add(behavior);
await game.ensureAdd(androidSpaceship); await game.ensureAdd(androidSpaceship);
behavior.beginContact(_MockBall(), _MockContact()); behavior.beginContact(_MockBall(), _MockContact());
verify(bloc.onBallEntered).called(1); verify(bloc.onBallContacted).called(1);
}, },
); );
}, },

@ -4,6 +4,7 @@ import 'package:flame/components.dart';
import 'package:flame_test/flame_test.dart'; import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/android_animatronic/behaviors/behaviors.dart';
import '../../helpers/helpers.dart'; import '../../helpers/helpers.dart';
@ -58,7 +59,8 @@ void main() {
}, },
); );
flameTester.test('adds new children', (game) async { group('adds', () {
flameTester.test('new children', (game) async {
final component = Component(); final component = Component();
final androidAnimatronic = AndroidAnimatronic( final androidAnimatronic = AndroidAnimatronic(
children: [component], children: [component],
@ -66,5 +68,17 @@ void main() {
await game.ensureAdd(androidAnimatronic); await game.ensureAdd(androidAnimatronic);
expect(androidAnimatronic.children, contains(component)); expect(androidAnimatronic.children, contains(component));
}); });
flameTester.test('a AndroidAnimatronicBallContactBehavior', (game) async {
final androidAnimatronic = AndroidAnimatronic();
await game.ensureAdd(androidAnimatronic);
expect(
androidAnimatronic.children
.whereType<AndroidAnimatronicBallContactBehavior>()
.single,
isNotNull,
);
});
});
}); });
} }

@ -6,7 +6,6 @@ import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart'; import 'package:mocktail/mocktail.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_components/src/components/android_spaceship/behaviors/behaviors.dart';
import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_flame/pinball_flame.dart';
import '../../../helpers/helpers.dart'; import '../../../helpers/helpers.dart';
@ -84,26 +83,5 @@ void main() {
); );
}, },
); );
flameTester.test(
'AndroidSpaceshipEntrance has an '
'AndroidSpaceshipEntranceBallContactBehavior', (game) async {
final androidSpaceship = AndroidSpaceship(position: Vector2.zero());
final provider =
FlameBlocProvider<AndroidSpaceshipCubit, AndroidSpaceshipState>.value(
value: bloc,
children: [androidSpaceship],
);
await game.ensureAdd(provider);
final androidSpaceshipEntrance =
androidSpaceship.firstChild<AndroidSpaceshipEntrance>();
expect(
androidSpaceshipEntrance!.children
.whereType<AndroidSpaceshipEntranceBallContactBehavior>()
.single,
isNotNull,
);
});
}); });
} }

@ -9,7 +9,7 @@ void main() {
blocTest<AndroidSpaceshipCubit, AndroidSpaceshipState>( blocTest<AndroidSpaceshipCubit, AndroidSpaceshipState>(
'onBallEntered emits withBonus', 'onBallEntered emits withBonus',
build: AndroidSpaceshipCubit.new, build: AndroidSpaceshipCubit.new,
act: (bloc) => bloc.onBallEntered(), act: (bloc) => bloc.onBallContacted(),
expect: () => [AndroidSpaceshipState.withBonus], expect: () => [AndroidSpaceshipState.withBonus],
); );

@ -41,7 +41,7 @@ void main() {
); );
flameTester.testGameWidget( flameTester.testGameWidget(
'calls onAnimationFinished and removes itself ' 'calls onReset and removes itself '
'after all blinks complete', 'after all blinks complete',
setUp: (game, tester) async { setUp: (game, tester) async {
final behavior = GoogleWordAnimatingBehavior(); final behavior = GoogleWordAnimatingBehavior();
@ -53,7 +53,7 @@ void main() {
} }
await game.ready(); await game.ready();
verify(bloc.onAnimationFinished).called(1); verify(bloc.onReset).called(1);
expect( expect(
game.descendants().whereType<GoogleWordAnimatingBehavior>().isEmpty, game.descendants().whereType<GoogleWordAnimatingBehavior>().isEmpty,
isTrue, isTrue,

@ -62,9 +62,9 @@ void main() {
); );
blocTest<GoogleWordCubit, GoogleWordState>( blocTest<GoogleWordCubit, GoogleWordState>(
'onAnimationFinished emits initial state', 'onReset emits initial state',
build: GoogleWordCubit.new, build: GoogleWordCubit.new,
act: (bloc) => bloc.onAnimationFinished(), act: (bloc) => bloc.onReset(),
expect: () => [GoogleWordState.initial()], expect: () => [GoogleWordState.initial()],
); );
}, },

@ -37,6 +37,7 @@ class _TestGame extends Forge2DGame with HasTappables {
Iterable<Component> children, { Iterable<Component> children, {
PinballAudioPlayer? pinballAudioPlayer, PinballAudioPlayer? pinballAudioPlayer,
PlatformHelper? platformHelper, PlatformHelper? platformHelper,
GoogleWordCubit? googleWordBloc,
}) async { }) async {
return ensureAdd( return ensureAdd(
FlameMultiBlocProvider( FlameMultiBlocProvider(
@ -47,6 +48,9 @@ class _TestGame extends Forge2DGame with HasTappables {
FlameBlocProvider<CharacterThemeCubit, CharacterThemeState>.value( FlameBlocProvider<CharacterThemeCubit, CharacterThemeState>.value(
value: CharacterThemeCubit(), value: CharacterThemeCubit(),
), ),
FlameBlocProvider<GoogleWordCubit, GoogleWordState>.value(
value: googleWordBloc ?? GoogleWordCubit(),
),
], ],
children: [ children: [
MultiFlameProvider( MultiFlameProvider(
@ -80,6 +84,8 @@ class _MockPlatformHelper extends Mock implements PlatformHelper {}
class _MockPlungerCubit extends Mock implements PlungerCubit {} class _MockPlungerCubit extends Mock implements PlungerCubit {}
class _MockGoogleWordCubit extends Mock implements GoogleWordCubit {}
class _MockAppLocalizations extends Mock implements AppLocalizations { class _MockAppLocalizations extends Mock implements AppLocalizations {
@override @override
String get score => ''; String get score => '';
@ -332,6 +338,20 @@ void main() {
}, },
); );
flameTester.test(
'resets the GoogleWordCubit',
(game) async {
final googleWordBloc = _MockGoogleWordCubit();
final component = GameBlocStatusListener();
await game.pump([component], googleWordBloc: googleWordBloc);
expect(state.status, equals(GameStatus.playing));
component.onNewState(state);
verify(googleWordBloc.onReset).called(1);
},
);
flameTester.test( flameTester.test(
'adds FlipperKeyControllingBehavior to Flippers', 'adds FlipperKeyControllingBehavior to Flippers',
(game) async { (game) async {

@ -75,7 +75,7 @@ void main() {
flameTester.testGameWidget( flameTester.testGameWidget(
'adds GameBonus.googleWord to the game when all letters ' 'adds GameBonus.googleWord to the game when all letters '
'in google word are activated and calls onBonusAwarded', 'in google word are activated and calls onReset',
setUp: (game, tester) async { setUp: (game, tester) async {
final behavior = GoogleWordBonusBehavior(); final behavior = GoogleWordBonusBehavior();
final parent = GoogleGallery.test(); final parent = GoogleGallery.test();
@ -114,7 +114,7 @@ void main() {
verify( verify(
() => gameBloc.add(const BonusActivated(GameBonus.googleWord)), () => gameBloc.add(const BonusActivated(GameBonus.googleWord)),
).called(1); ).called(1);
verify(googleWordBloc.onBonusAwarded).called(1); verify(googleWordBloc.onReset).called(1);
}, },
); );

@ -307,6 +307,23 @@ void main() {
expect(find.byType(MobileControls), findsOneWidget); expect(find.byType(MobileControls), findsOneWidget);
}); });
testWidgets(
'ReplayButtonOverlay when the overlay is added',
(tester) async {
await tester.pumpApp(
PinballGameView(game),
gameBloc: gameBloc,
startGameBloc: startGameBloc,
);
game.overlays.add(PinballGame.replayButtonOverlay);
await tester.pump();
expect(find.byType(ReplayButtonOverlay), findsOneWidget);
},
);
group('info icon', () { group('info icon', () {
testWidgets('renders on game over', (tester) async { testWidgets('renders on game over', (tester) async {
final gameState = GameState.initial().copyWith( final gameState = GameState.initial().copyWith(

@ -8,24 +8,32 @@ import '../../../helpers/helpers.dart';
class _MockStartGameBloc extends Mock implements StartGameBloc {} class _MockStartGameBloc extends Mock implements StartGameBloc {}
class _MockGameBloc extends Mock implements GameBloc {}
void main() { void main() {
group('ReplayButtonOverlay', () { group('ReplayButtonOverlay', () {
late StartGameBloc startGameBloc; late StartGameBloc startGameBloc;
late _MockGameBloc gameBloc;
setUp(() async { setUp(() async {
await mockFlameImages(); await mockFlameImages();
startGameBloc = _MockStartGameBloc(); startGameBloc = _MockStartGameBloc();
gameBloc = _MockGameBloc();
whenListen( whenListen(
startGameBloc, startGameBloc,
Stream.value(const StartGameState.initial()), Stream.value(const StartGameState.initial()),
initialState: const StartGameState.initial(), initialState: const StartGameState.initial(),
); );
whenListen(
gameBloc,
Stream.value(const GameState.initial()),
initialState: const GameState.initial(),
);
}); });
testWidgets('renders correctly', (tester) async { testWidgets('renders correctly', (tester) async {
await tester.pumpApp(const ReplayButtonOverlay()); await tester.pumpApp(const ReplayButtonOverlay());
expect(find.text('Replay'), findsOneWidget); expect(find.text('Replay'), findsOneWidget);
}); });
@ -33,6 +41,7 @@ void main() {
(tester) async { (tester) async {
await tester.pumpApp( await tester.pumpApp(
const ReplayButtonOverlay(), const ReplayButtonOverlay(),
gameBloc: gameBloc,
startGameBloc: startGameBloc, startGameBloc: startGameBloc,
); );
@ -41,5 +50,19 @@ void main() {
verify(() => startGameBloc.add(const ReplayTapped())).called(1); verify(() => startGameBloc.add(const ReplayTapped())).called(1);
}); });
testWidgets('adds GameStarted event to GameBloc when tapped',
(tester) async {
await tester.pumpApp(
const ReplayButtonOverlay(),
gameBloc: gameBloc,
startGameBloc: startGameBloc,
);
await tester.tap(find.text('Replay'));
await tester.pump();
verify(() => gameBloc.add(const GameStarted())).called(1);
});
}); });
} }

Loading…
Cancel
Save