chore: restore GameHud visibility and control game flow (#247)

pull/336/head
arturplaczek 2 years ago committed by GitHub
parent d729a9ac69
commit 03f60fbffe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -8,6 +8,7 @@ import 'package:leaderboard_repository/leaderboard_repository.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_audio/pinball_audio.dart';
import 'package:pinball_ui/pinball_ui.dart';
@ -34,8 +35,11 @@ class App extends StatelessWidget {
RepositoryProvider.value(value: _leaderboardRepository),
RepositoryProvider.value(value: _pinballAudio),
],
child: BlocProvider(
create: (context) => CharacterThemeCubit(),
child: MultiBlocProvider(
providers: [
BlocProvider(create: (_) => CharacterThemeCubit()),
BlocProvider(create: (_) => StartGameBloc()),
],
child: MaterialApp(
title: 'I/O Pinball',
theme: PinballTheme.standard,

@ -60,7 +60,6 @@ class PinballGamePage extends StatelessWidget {
return MultiBlocProvider(
providers: [
BlocProvider(create: (_) => StartGameBloc(game: game)),
BlocProvider(create: (_) => GameBloc()),
BlocProvider(create: (_) => AssetsManagerCubit(loadables)..load()),
],
@ -105,36 +104,43 @@ class PinballGameLoadedView extends StatelessWidget {
@override
Widget build(BuildContext context) {
final isPlaying = context.select(
(StartGameBloc bloc) => bloc.state.status == StartGameStatus.play,
);
final gameWidgetWidth = MediaQuery.of(context).size.height * 9 / 16;
final screenWidth = MediaQuery.of(context).size.width;
final leftMargin = (screenWidth / 2) - (gameWidgetWidth / 1.8);
return Stack(
children: [
Positioned.fill(
child: GameWidget<PinballGame>(
game: game,
initialActiveOverlays: const [PinballGame.playButtonOverlay],
overlayBuilderMap: {
PinballGame.playButtonOverlay: (context, game) {
return Positioned(
bottom: 20,
right: 0,
left: 0,
child: PlayButtonOverlay(game: game),
);
return StartGameListener(
game: game,
child: Stack(
children: [
Positioned.fill(
child: GameWidget<PinballGame>(
game: game,
initialActiveOverlays: const [PinballGame.playButtonOverlay],
overlayBuilderMap: {
PinballGame.playButtonOverlay: (context, game) {
return const Positioned(
bottom: 20,
right: 0,
left: 0,
child: PlayButtonOverlay(),
);
},
},
},
),
),
),
// TODO(arturplaczek): add Visibility to GameHud based on StartGameBloc
// status
Positioned(
top: 16,
left: leftMargin,
child: const GameHud(),
),
],
Positioned(
top: 16,
left: leftMargin,
child: Visibility(
visible: isPlaying,
child: const GameHud(),
),
),
],
),
);
}
}

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:pinball/game/pinball_game.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_ui/pinball_ui.dart';
/// {@template play_button_overlay}
@ -9,13 +9,7 @@ import 'package:pinball_ui/pinball_ui.dart';
/// {@endtemplate}
class PlayButtonOverlay extends StatelessWidget {
/// {@macro play_button_overlay}
const PlayButtonOverlay({
Key? key,
required PinballGame game,
}) : _game = game,
super(key: key);
final PinballGame _game;
const PlayButtonOverlay({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -23,9 +17,8 @@ class PlayButtonOverlay extends StatelessWidget {
return PinballButton(
text: l10n.play,
onTap: () async {
_game.gameFlowController.start();
await showCharacterSelectionDialog(context);
onTap: () {
context.read<StartGameBloc>().add(const PlayTapped());
},
);
}

@ -3,10 +3,8 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pinball/gen/gen.dart';
import 'package:pinball/l10n/l10n.dart';
import 'package:pinball_audio/pinball_audio.dart';
import 'package:pinball_ui/pinball_ui.dart';
import 'package:platform_helper/platform_helper.dart';
@ -51,24 +49,16 @@ extension on Control {
}
}
Future<void> showHowToPlayDialog(BuildContext context) {
final audio = context.read<PinballAudio>();
return showDialog<void>(
context: context,
builder: (_) => HowToPlayDialog(),
).then((_) {
audio.ioPinballVoiceOver();
});
}
class HowToPlayDialog extends StatefulWidget {
HowToPlayDialog({
Key? key,
required this.onDismissCallback,
@visibleForTesting PlatformHelper? platformHelper,
}) : platformHelper = platformHelper ?? PlatformHelper(),
super(key: key);
final PlatformHelper platformHelper;
final VoidCallback onDismissCallback;
@override
State<HowToPlayDialog> createState() => _HowToPlayDialogState();
@ -82,6 +72,7 @@ class _HowToPlayDialogState extends State<HowToPlayDialog> {
closeTimer = Timer(const Duration(seconds: 3), () {
if (mounted) {
Navigator.of(context).pop();
widget.onDismissCallback.call();
}
});
}
@ -96,10 +87,17 @@ class _HowToPlayDialogState extends State<HowToPlayDialog> {
Widget build(BuildContext context) {
final isMobile = widget.platformHelper.isMobile;
final l10n = context.l10n;
return PinballDialog(
title: l10n.howToPlay,
subtitle: l10n.tipsForFlips,
child: isMobile ? const _MobileBody() : const _DesktopBody(),
return WillPopScope(
onWillPop: () {
widget.onDismissCallback.call();
return Future.value(true);
},
child: PinballDialog(
title: l10n.howToPlay,
subtitle: l10n.tipsForFlips,
child: isMobile ? const _MobileBody() : const _DesktopBody(),
),
);
}
}

@ -1,20 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pinball/how_to_play/how_to_play.dart';
import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_theme/pinball_theme.dart';
import 'package:pinball_ui/pinball_ui.dart';
/// Inflates [CharacterSelectionDialog] using [showDialog].
Future<void> showCharacterSelectionDialog(BuildContext context) {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (_) => const CharacterSelectionDialog(),
);
}
/// {@template character_selection_dialog}
/// Dialog used to select the playing character of the game.
/// {@endtemplate character_selection_dialog}
@ -59,7 +50,7 @@ class _SelectCharacterButton extends StatelessWidget {
return PinballButton(
onTap: () async {
Navigator.of(context).pop();
await showHowToPlayDialog(context);
context.read<StartGameBloc>().add(const CharacterSelected());
},
text: l10n.select,
);

@ -1,6 +1,5 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:pinball/game/game.dart';
part 'start_game_event.dart';
part 'start_game_state.dart';
@ -10,23 +9,16 @@ part 'start_game_state.dart';
/// {@endtemplate}
class StartGameBloc extends Bloc<StartGameEvent, StartGameState> {
/// {@macro start_game_bloc}
StartGameBloc({
required PinballGame game,
}) : _game = game,
super(const StartGameState.initial()) {
StartGameBloc() : super(const StartGameState.initial()) {
on<PlayTapped>(_onPlayTapped);
on<CharacterSelected>(_onCharacterSelected);
on<HowToPlayFinished>(_onHowToPlayFinished);
}
final PinballGame _game;
void _onPlayTapped(
PlayTapped event,
Emitter<StartGameState> emit,
) {
_game.gameFlowController.start();
emit(
state.copyWith(
status: StartGameStatus.selectCharacter,

@ -1 +1,2 @@
export 'bloc/start_game_bloc.dart';
export 'widgets/start_game_listener.dart';

@ -0,0 +1,95 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/how_to_play/how_to_play.dart';
import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_audio/pinball_audio.dart';
import 'package:pinball_ui/pinball_ui.dart';
/// {@template start_game_listener}
/// Listener that manages the display of dialogs for [StartGameStatus].
///
/// It's responsible for starting the game after pressing play button
/// and playing a sound after the 'how to play' dialog.
/// {@endtemplate}
class StartGameListener extends StatelessWidget {
/// {@macro start_game_listener}
const StartGameListener({
Key? key,
required Widget child,
required PinballGame game,
}) : _child = child,
_game = game,
super(key: key);
final Widget _child;
final PinballGame _game;
@override
Widget build(BuildContext context) {
return BlocListener<StartGameBloc, StartGameState>(
listener: (context, state) {
switch (state.status) {
case StartGameStatus.initial:
break;
case StartGameStatus.selectCharacter:
_onSelectCharacter(context);
_game.gameFlowController.start();
break;
case StartGameStatus.howToPlay:
_onHowToPlay(context);
break;
case StartGameStatus.play:
break;
}
},
child: _child,
);
}
void _onSelectCharacter(BuildContext context) {
_showPinballDialog(
context: context,
child: const CharacterSelectionDialog(),
barrierDismissible: false,
);
}
void _onHowToPlay(BuildContext context) {
final audio = context.read<PinballAudio>();
_showPinballDialog(
context: context,
child: HowToPlayDialog(
onDismissCallback: () {
context.read<StartGameBloc>().add(const HowToPlayFinished());
audio.ioPinballVoiceOver();
},
),
);
}
void _showPinballDialog({
required BuildContext context,
required Widget child,
bool barrierDismissible = true,
}) {
final gameWidgetWidth = MediaQuery.of(context).size.height * 9 / 16;
showDialog<void>(
context: context,
barrierColor: PinballColors.transparent,
barrierDismissible: barrierDismissible,
builder: (_) {
return Center(
child: SizedBox(
height: gameWidgetWidth * 0.87,
width: gameWidgetWidth,
child: child,
),
);
},
);
}
}

@ -200,12 +200,11 @@ void main() {
find.byWidgetPredicate((w) => w is GameWidget<PinballGame>),
findsOneWidget,
);
// TODO(arturplaczek): add Visibility to GameHud based on StartGameBloc
// status
// expect(
// find.byType(GameHud),
// findsNothing,
// );
expect(
find.byType(GameHud),
findsNothing,
);
});
testWidgets('renders a hud on play state', (tester) async {

@ -2,64 +2,44 @@ import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/bloc/start_game_bloc.dart';
import '../../../helpers/helpers.dart';
class _MockPinballGame extends Mock implements PinballGame {}
class _MockGameFlowController extends Mock implements GameFlowController {}
class _MockCharacterThemeCubit extends Mock implements CharacterThemeCubit {}
class _MockStartGameBloc extends Mock implements StartGameBloc {}
void main() {
group('PlayButtonOverlay', () {
late PinballGame game;
late GameFlowController gameFlowController;
late CharacterThemeCubit characterThemeCubit;
late StartGameBloc startGameBloc;
setUp(() async {
await mockFlameImages();
game = _MockPinballGame();
gameFlowController = _MockGameFlowController();
characterThemeCubit = _MockCharacterThemeCubit();
startGameBloc = _MockStartGameBloc();
whenListen(
characterThemeCubit,
const Stream<CharacterThemeState>.empty(),
initialState: const CharacterThemeState.initial(),
startGameBloc,
Stream.value(const StartGameState.initial()),
initialState: const StartGameState.initial(),
);
when(() => characterThemeCubit.state)
.thenReturn(const CharacterThemeState.initial());
when(() => game.gameFlowController).thenReturn(gameFlowController);
when(gameFlowController.start).thenAnswer((_) {});
});
testWidgets('renders correctly', (tester) async {
await tester.pumpApp(PlayButtonOverlay(game: game));
expect(find.text('Play'), findsOneWidget);
});
await tester.pumpApp(const PlayButtonOverlay());
testWidgets('calls gameFlowController.start when tapped', (tester) async {
await tester.pumpApp(
PlayButtonOverlay(game: game),
characterThemeCubit: characterThemeCubit,
);
await tester.tap(find.text('Play'));
await tester.pump();
verify(gameFlowController.start).called(1);
expect(find.text('Play'), findsOneWidget);
});
testWidgets('displays CharacterSelectionDialog when tapped',
testWidgets('adds PlayTapped event to StartGameBloc when taped',
(tester) async {
await tester.pumpApp(
PlayButtonOverlay(game: game),
characterThemeCubit: characterThemeCubit,
const PlayButtonOverlay(),
startGameBloc: startGameBloc,
);
await tester.tap(find.text('Play'));
await tester.pump();
expect(find.byType(CharacterSelectionDialog), findsOneWidget);
verify(() => startGameBloc.add(const PlayTapped())).called(1);
});
});
}

@ -3,13 +3,10 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/how_to_play/how_to_play.dart';
import 'package:pinball/l10n/l10n.dart';
import 'package:pinball_audio/pinball_audio.dart';
import 'package:platform_helper/platform_helper.dart';
import '../helpers/helpers.dart';
class _MockPinballAudio extends Mock implements PinballAudio {}
class _MockPlatformHelper extends Mock implements PlatformHelper {}
void main() {
@ -25,7 +22,11 @@ void main() {
testWidgets(
'can be instantiated without passing in a platform helper',
(tester) async {
await tester.pumpApp(HowToPlayDialog());
await tester.pumpApp(
HowToPlayDialog(
onDismissCallback: () {},
),
);
expect(find.byType(HowToPlayDialog), findsOneWidget);
},
);
@ -35,6 +36,7 @@ void main() {
await tester.pumpApp(
HowToPlayDialog(
platformHelper: platformHelper,
onDismissCallback: () {},
),
);
expect(find.text(l10n.howToPlay), findsOneWidget);
@ -49,6 +51,7 @@ void main() {
await tester.pumpApp(
HowToPlayDialog(
platformHelper: platformHelper,
onDismissCallback: () {},
),
);
expect(find.text(l10n.howToPlay), findsOneWidget);
@ -62,7 +65,12 @@ void main() {
Builder(
builder: (context) {
return TextButton(
onPressed: () => showHowToPlayDialog(context),
onPressed: () => showDialog<void>(
context: context,
builder: (_) => HowToPlayDialog(
onDismissCallback: () {},
),
),
child: const Text('test'),
);
},
@ -82,7 +90,12 @@ void main() {
Builder(
builder: (context) {
return TextButton(
onPressed: () => showHowToPlayDialog(context),
onPressed: () => showDialog<void>(
context: context,
builder: (_) => HowToPlayDialog(
onDismissCallback: () {},
),
),
child: const Text('test'),
);
},
@ -96,30 +109,5 @@ void main() {
await tester.pumpAndSettle();
expect(find.byType(HowToPlayDialog), findsNothing);
});
testWidgets(
'plays the I/O Pinball voice over audio on dismiss',
(tester) async {
final audio = _MockPinballAudio();
await tester.pumpApp(
Builder(
builder: (context) {
return TextButton(
onPressed: () => showHowToPlayDialog(context),
child: const Text('test'),
);
},
),
pinballAudio: audio,
);
expect(find.byType(HowToPlayDialog), findsNothing);
await tester.tap(find.text('test'));
await tester.pumpAndSettle();
await tester.tapAt(Offset.zero);
await tester.pumpAndSettle();
verify(audio.ioPinballVoiceOver).called(1);
},
);
});
}

@ -2,8 +2,8 @@ import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/how_to_play/how_to_play.dart';
import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_theme/pinball_theme.dart';
import 'package:pinball_ui/pinball_ui.dart';
@ -11,14 +11,19 @@ import '../../helpers/helpers.dart';
class _MockCharacterThemeCubit extends Mock implements CharacterThemeCubit {}
class _MockStartGameBloc extends Mock implements StartGameBloc {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
late CharacterThemeCubit characterThemeCubit;
late StartGameBloc startGameBloc;
setUp(() async {
await mockFlameImages();
characterThemeCubit = _MockCharacterThemeCubit();
startGameBloc = _MockStartGameBloc();
whenListen(
characterThemeCubit,
const Stream<CharacterThemeState>.empty(),
@ -29,25 +34,6 @@ void main() {
});
group('CharacterSelectionDialog', () {
group('showCharacterSelectionDialog', () {
testWidgets('inflates the dialog', (tester) async {
await tester.pumpApp(
Builder(
builder: (context) {
return TextButton(
onPressed: () => showCharacterSelectionDialog(context),
child: const Text('test'),
);
},
),
characterThemeCubit: characterThemeCubit,
);
await tester.tap(find.text('test'));
await tester.pump();
expect(find.byType(CharacterSelectionDialog), findsOneWidget);
});
});
testWidgets('selecting a new character calls characterSelected on cubit',
(tester) async {
await tester.pumpApp(
@ -63,15 +49,22 @@ void main() {
testWidgets(
'tapping the select button dismisses the character '
'dialog and shows the how to play dialog', (tester) async {
'dialog and calls CharacterSelected event to the bloc', (tester) async {
whenListen(
startGameBloc,
const Stream<StartGameState>.empty(),
initialState: const StartGameState.initial(),
);
await tester.pumpApp(
const CharacterSelectionDialog(),
characterThemeCubit: characterThemeCubit,
startGameBloc: startGameBloc,
);
await tester.tap(find.byType(PinballButton));
await tester.pumpAndSettle();
expect(find.byType(CharacterSelectionDialog), findsNothing);
expect(find.byType(HowToPlayDialog), findsOneWidget);
verify(() => startGameBloc.add(const CharacterSelected())).called(1);
});
testWidgets('updating the selected character updates the preview',

@ -24,9 +24,7 @@ void main() {
group('StartGameBloc', () {
blocTest<StartGameBloc, StartGameState>(
'on PlayTapped changes status to selectCharacter',
build: () => StartGameBloc(
game: pinballGame,
),
build: StartGameBloc.new,
act: (bloc) => bloc.add(const PlayTapped()),
expect: () => [
const StartGameState(
@ -37,9 +35,7 @@ void main() {
blocTest<StartGameBloc, StartGameState>(
'on CharacterSelected changes status to howToPlay',
build: () => StartGameBloc(
game: pinballGame,
),
build: StartGameBloc.new,
act: (bloc) => bloc.add(const CharacterSelected()),
expect: () => [
const StartGameState(
@ -50,9 +46,7 @@ void main() {
blocTest<StartGameBloc, StartGameState>(
'on HowToPlayFinished changes status to play',
build: () => StartGameBloc(
game: pinballGame,
),
build: StartGameBloc.new,
act: (bloc) => bloc.add(const HowToPlayFinished()),
expect: () => [
const StartGameState(

@ -0,0 +1,269 @@
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/how_to_play/how_to_play.dart';
import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_audio/pinball_audio.dart';
import '../../helpers/helpers.dart';
class _MockStartGameBloc extends Mock implements StartGameBloc {}
class _MockCharacterThemeCubit extends Mock implements CharacterThemeCubit {}
class _MockPinballGame extends Mock implements PinballGame {}
class _MockGameFlowController extends Mock implements GameFlowController {}
class _MockPinballAudio extends Mock implements PinballAudio {}
void main() {
late StartGameBloc startGameBloc;
late PinballGame pinballGame;
late PinballAudio pinballAudio;
late CharacterThemeCubit characterThemeCubit;
group('StartGameListener', () {
setUp(() async {
await mockFlameImages();
startGameBloc = _MockStartGameBloc();
pinballGame = _MockPinballGame();
pinballAudio = _MockPinballAudio();
characterThemeCubit = _MockCharacterThemeCubit();
});
group('on selectCharacter status', () {
testWidgets(
'calls start on the game controller',
(tester) async {
whenListen(
startGameBloc,
Stream.value(
const StartGameState(status: StartGameStatus.selectCharacter),
),
initialState: const StartGameState.initial(),
);
final gameController = _MockGameFlowController();
when(() => pinballGame.gameFlowController)
.thenAnswer((_) => gameController);
await tester.pumpApp(
StartGameListener(
game: pinballGame,
child: const SizedBox.shrink(),
),
startGameBloc: startGameBloc,
);
verify(gameController.start).called(1);
},
);
testWidgets(
'shows SelectCharacter dialog',
(tester) async {
whenListen(
startGameBloc,
Stream.value(
const StartGameState(status: StartGameStatus.selectCharacter),
),
initialState: const StartGameState.initial(),
);
whenListen(
characterThemeCubit,
Stream.value(const CharacterThemeState.initial()),
initialState: const CharacterThemeState.initial(),
);
final gameController = _MockGameFlowController();
when(() => pinballGame.gameFlowController)
.thenAnswer((_) => gameController);
await tester.pumpApp(
StartGameListener(
game: pinballGame,
child: const SizedBox.shrink(),
),
startGameBloc: startGameBloc,
characterThemeCubit: characterThemeCubit,
);
await tester.pump(kThemeAnimationDuration);
expect(
find.byType(CharacterSelectionDialog),
findsOneWidget,
);
},
);
});
testWidgets(
'on howToPlay status shows HowToPlay dialog',
(tester) async {
whenListen(
startGameBloc,
Stream.value(
const StartGameState(status: StartGameStatus.howToPlay),
),
initialState: const StartGameState.initial(),
);
await tester.pumpApp(
StartGameListener(
game: pinballGame,
child: const SizedBox.shrink(),
),
startGameBloc: startGameBloc,
);
await tester.pumpAndSettle();
expect(
find.byType(HowToPlayDialog),
findsOneWidget,
);
},
);
testWidgets(
'do nothing on play status',
(tester) async {
whenListen(
startGameBloc,
Stream.value(
const StartGameState(status: StartGameStatus.play),
),
initialState: const StartGameState.initial(),
);
await tester.pumpApp(
StartGameListener(
game: pinballGame,
child: const SizedBox.shrink(),
),
startGameBloc: startGameBloc,
);
await tester.pumpAndSettle();
expect(
find.byType(HowToPlayDialog),
findsNothing,
);
expect(
find.byType(CharacterSelectionDialog),
findsNothing,
);
},
);
testWidgets(
'do nothing on initial status',
(tester) async {
whenListen(
startGameBloc,
Stream.value(
const StartGameState(status: StartGameStatus.initial),
),
initialState: const StartGameState.initial(),
);
await tester.pumpApp(
StartGameListener(
game: pinballGame,
child: const SizedBox.shrink(),
),
startGameBloc: startGameBloc,
);
await tester.pumpAndSettle();
expect(
find.byType(HowToPlayDialog),
findsNothing,
);
expect(
find.byType(CharacterSelectionDialog),
findsNothing,
);
},
);
group('on dismiss HowToPlayDialog', () {
setUp(() {
whenListen(
startGameBloc,
Stream.value(
const StartGameState(status: StartGameStatus.howToPlay),
),
initialState: const StartGameState.initial(),
);
});
testWidgets(
'adds HowToPlayFinished event',
(tester) async {
await tester.pumpApp(
StartGameListener(
game: pinballGame,
child: const SizedBox.shrink(),
),
startGameBloc: startGameBloc,
);
await tester.pumpAndSettle();
expect(
find.byType(HowToPlayDialog),
findsOneWidget,
);
await tester.tapAt(const Offset(1, 1));
await tester.pumpAndSettle();
expect(
find.byType(HowToPlayDialog),
findsNothing,
);
await tester.pumpAndSettle();
verify(
() => startGameBloc.add(const HowToPlayFinished()),
).called(1);
},
);
testWidgets(
'plays the I/O Pinball voice over audio',
(tester) async {
await tester.pumpApp(
StartGameListener(
game: pinballGame,
child: const SizedBox.shrink(),
),
startGameBloc: startGameBloc,
pinballAudio: pinballAudio,
);
await tester.pumpAndSettle();
expect(
find.byType(HowToPlayDialog),
findsOneWidget,
);
await tester.tapAt(const Offset(1, 1));
await tester.pumpAndSettle();
expect(
find.byType(HowToPlayDialog),
findsNothing,
);
await tester.pumpAndSettle();
verify(pinballAudio.ioPinballVoiceOver).called(1);
},
);
});
});
}
Loading…
Cancel
Save