feat: change screens flow (#195)

pull/211/head
arturplaczek 3 years ago committed by GitHub
parent 12d20b8dbc
commit 35c23140b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

@ -11,8 +11,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:leaderboard_repository/leaderboard_repository.dart'; import 'package:leaderboard_repository/leaderboard_repository.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball/l10n/l10n.dart'; import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/landing/landing.dart'; import 'package:pinball/theme/theme.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
class App extends StatelessWidget { class App extends StatelessWidget {
@ -34,20 +35,17 @@ class App extends StatelessWidget {
RepositoryProvider.value(value: _leaderboardRepository), RepositoryProvider.value(value: _leaderboardRepository),
RepositoryProvider.value(value: _pinballAudio), RepositoryProvider.value(value: _pinballAudio),
], ],
child: MaterialApp( child: BlocProvider(
create: (context) => ThemeCubit(),
child: const MaterialApp(
title: 'I/O Pinball', title: 'I/O Pinball',
theme: ThemeData( localizationsDelegates: [
appBarTheme: const AppBarTheme(color: Color(0xFF13B9FF)),
colorScheme: ColorScheme.fromSwatch(
accentColor: const Color(0xFF13B9FF),
),
),
localizationsDelegates: const [
AppLocalizations.delegate, AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate, GlobalMaterialLocalizations.delegate,
], ],
supportedLocales: AppLocalizations.supportedLocales, supportedLocales: AppLocalizations.supportedLocales,
home: const LandingPage(), home: PinballGamePage(),
),
), ),
); );
} }

@ -5,6 +5,7 @@ import 'package:flame/components.dart';
import 'package:flame/input.dart'; import 'package:flame/input.dart';
import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_bloc/flame_bloc.dart';
import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/gen/assets.gen.dart'; import 'package:pinball/gen/assets.gen.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
@ -28,6 +29,9 @@ class PinballGame extends Forge2DGame
/// Identifier of the play button overlay /// Identifier of the play button overlay
static const playButtonOverlay = 'play_button'; static const playButtonOverlay = 'play_button';
@override
Color backgroundColor() => Colors.transparent;
final PinballTheme theme; final PinballTheme theme;
final PinballAudio audio; final PinballAudio audio;

@ -5,32 +5,40 @@ import 'package:flutter/foundation.dart';
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/game/game.dart';
import 'package:pinball/start_game/start_game.dart';
import 'package:pinball/theme/theme.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
import 'package:pinball_theme/pinball_theme.dart';
class PinballGamePage extends StatelessWidget { class PinballGamePage extends StatelessWidget {
const PinballGamePage({ const PinballGamePage({
Key? key, Key? key,
required this.theme, this.isDebugMode = kDebugMode,
required this.game,
}) : super(key: key); }) : super(key: key);
final PinballTheme theme; final bool isDebugMode;
final PinballGame game;
static Route route({ static Route route({
required PinballTheme theme,
bool isDebugMode = kDebugMode, bool isDebugMode = kDebugMode,
}) { }) {
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
builder: (context) { builder: (context) {
return PinballGamePage(
isDebugMode: isDebugMode,
);
},
);
}
@override
Widget build(BuildContext context) {
final theme = context.read<ThemeCubit>().state.theme;
final audio = context.read<PinballAudio>(); final audio = context.read<PinballAudio>();
final pinballAudio = context.read<PinballAudio>();
final game = isDebugMode final game = isDebugMode
? DebugPinballGame(theme: theme, audio: audio) ? DebugPinballGame(theme: theme, audio: audio)
: PinballGame(theme: theme, audio: audio); : PinballGame(theme: theme, audio: audio);
final pinballAudio = context.read<PinballAudio>();
final loadables = [ final loadables = [
...game.preLoadAssets(), ...game.preLoadAssets(),
pinballAudio.load(), pinballAudio.load(),
@ -38,21 +46,15 @@ class PinballGamePage extends StatelessWidget {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider(create: (_) => StartGameBloc(game: game)),
BlocProvider(create: (_) => GameBloc()), BlocProvider(create: (_) => GameBloc()),
BlocProvider( BlocProvider(
create: (_) => AssetsManagerCubit(loadables)..load(), create: (_) => AssetsManagerCubit(loadables)..load(),
), ),
], ],
child: PinballGamePage(theme: theme, game: game), child: PinballGameView(game: game),
);
},
); );
} }
@override
Widget build(BuildContext context) {
return PinballGameView(game: game);
}
} }
class PinballGameView extends StatelessWidget { class PinballGameView extends StatelessWidget {
@ -65,18 +67,51 @@ class PinballGameView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final loadingProgress = context.watch<AssetsManagerCubit>().state.progress; final isLoading = context.select(
(AssetsManagerCubit bloc) => bloc.state.progress != 1,
);
if (loadingProgress != 1) {
return Scaffold( return Scaffold(
body: Center( backgroundColor: Colors.blue,
child: Text( body: isLoading
loadingProgress.toString(), ? const _PinballGameLoadingView()
: PinballGameLoadedView(game: game),
);
}
}
class _PinballGameLoadingView extends StatelessWidget {
const _PinballGameLoadingView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final loadingProgress = context.select(
(AssetsManagerCubit bloc) => bloc.state.progress,
);
return Padding(
padding: const EdgeInsets.all(24),
child: Center(
child: LinearProgressIndicator(
color: Colors.white,
value: loadingProgress,
), ),
), ),
); );
} }
}
@visibleForTesting
class PinballGameLoadedView extends StatelessWidget {
const PinballGameLoadedView({
Key? key,
required this.game,
}) : super(key: key);
final PinballGame game;
@override
Widget build(BuildContext context) {
return Stack( return Stack(
children: [ children: [
Positioned.fill( Positioned.fill(

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pinball/game/pinball_game.dart'; import 'package:pinball/game/pinball_game.dart';
import 'package:pinball/l10n/l10n.dart'; import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/theme/theme.dart';
/// {@template play_button_overlay} /// {@template play_button_overlay}
/// [Widget] that renders the button responsible to starting the game /// [Widget] that renders the button responsible to starting the game
@ -18,9 +19,27 @@ class PlayButtonOverlay extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final l10n = context.l10n; final l10n = context.l10n;
return Center( return Center(
child: ElevatedButton( child: ElevatedButton(
onPressed: _game.gameFlowController.start, onPressed: () {
_game.gameFlowController.start();
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (_) {
final height = MediaQuery.of(context).size.height * 0.5;
return Center(
child: SizedBox(
height: height,
width: height * 1.4,
child: const CharacterSelectionDialog(),
),
);
},
);
},
child: Text(l10n.play), child: Text(l10n.play),
), ),
); );

@ -1 +0,0 @@
export 'view/landing_page.dart';

@ -69,7 +69,7 @@ class LeaderboardView extends StatelessWidget {
const SizedBox(height: 20), const SizedBox(height: 20),
TextButton( TextButton(
onPressed: () => Navigator.of(context).push<void>( onPressed: () => Navigator.of(context).push<void>(
CharacterSelectionPage.route(), CharacterSelectionDialog.route(),
), ),
child: Text(l10n.retry), child: Text(l10n.retry),
), ),

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

@ -2,42 +2,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pinball/l10n/l10n.dart'; import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/theme/theme.dart';
class LandingPage extends StatelessWidget { class HowToPlayDialog extends StatelessWidget {
const LandingPage({Key? key}) : super(key: key); const HowToPlayDialog({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () => Navigator.of(context).push<void>(
CharacterSelectionPage.route(),
),
child: Text(l10n.play),
),
TextButton(
onPressed: () => showDialog<void>(
context: context,
builder: (_) => const _HowToPlayDialog(),
),
child: Text(l10n.howToPlay),
),
],
),
),
);
}
}
class _HowToPlayDialog extends StatelessWidget {
const _HowToPlayDialog({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

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

@ -2,17 +2,17 @@
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/theme/theme.dart'; import 'package:pinball/theme/theme.dart';
import 'package:pinball_theme/pinball_theme.dart'; import 'package:pinball_theme/pinball_theme.dart';
class CharacterSelectionPage extends StatelessWidget { class CharacterSelectionDialog extends StatelessWidget {
const CharacterSelectionPage({Key? key}) : super(key: key); const CharacterSelectionDialog({Key? key}) : super(key: key);
static Route route() { static Route route() {
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
builder: (_) => const CharacterSelectionPage(), builder: (_) => const CharacterSelectionDialog(),
); );
} }
@ -46,11 +46,13 @@ class CharacterSelectionView extends StatelessWidget {
const _CharacterSelectionGridView(), const _CharacterSelectionGridView(),
const SizedBox(height: 20), const SizedBox(height: 20),
TextButton( TextButton(
onPressed: () => Navigator.of(context).push<void>( onPressed: () {
PinballGamePage.route( Navigator.of(context).pop();
theme: context.read<ThemeCubit>().state.theme, showDialog<void>(
), context: context,
), builder: (_) => const HowToPlayDialog(),
);
},
child: Text(l10n.start), child: Text(l10n.start),
), ),
], ],

@ -7,8 +7,9 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leaderboard_repository/leaderboard_repository.dart'; import 'package:leaderboard_repository/leaderboard_repository.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/app/app.dart'; import 'package:pinball/app/app.dart';
import 'package:pinball/landing/landing.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
import '../../helpers/mocks.dart'; import '../../helpers/mocks.dart';
@ -21,16 +22,18 @@ void main() {
setUp(() { setUp(() {
leaderboardRepository = MockLeaderboardRepository(); leaderboardRepository = MockLeaderboardRepository();
pinballAudio = MockPinballAudio(); pinballAudio = MockPinballAudio();
when(pinballAudio.load).thenAnswer((_) => Future.value());
}); });
testWidgets('renders LandingPage', (tester) async { testWidgets('renders PinballGamePage', (tester) async {
await tester.pumpWidget( await tester.pumpWidget(
App( App(
leaderboardRepository: leaderboardRepository, leaderboardRepository: leaderboardRepository,
pinballAudio: pinballAudio, pinballAudio: pinballAudio,
), ),
); );
expect(find.byType(LandingPage), findsOneWidget); expect(find.byType(PinballGamePage), findsOneWidget);
}); });
}); });
} }

@ -5,40 +5,46 @@ import 'package:flame/game.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball_theme/pinball_theme.dart'; import 'package:pinball/theme/theme.dart';
import '../../helpers/helpers.dart'; import '../../helpers/helpers.dart';
void main() { void main() {
const theme = PinballTheme(characterTheme: DashTheme());
final game = PinballTestGame(); final game = PinballTestGame();
group('PinballGamePage', () { group('PinballGamePage', () {
testWidgets('renders PinballGameView', (tester) async { late ThemeCubit themeCubit;
final gameBloc = MockGameBloc(); late GameBloc gameBloc;
setUp(() {
themeCubit = MockThemeCubit();
gameBloc = MockGameBloc();
whenListen(
themeCubit,
const Stream<ThemeState>.empty(),
initialState: const ThemeState.initial(),
);
whenListen( whenListen(
gameBloc, gameBloc,
Stream.value(const GameState.initial()), Stream.value(const GameState.initial()),
initialState: const GameState.initial(), initialState: const GameState.initial(),
); );
});
testWidgets('renders PinballGameView', (tester) async {
await tester.pumpApp( await tester.pumpApp(
PinballGamePage(theme: theme, game: game), PinballGamePage(),
gameBloc: gameBloc, themeCubit: themeCubit,
); );
expect(find.byType(PinballGameView), findsOneWidget); expect(find.byType(PinballGameView), findsOneWidget);
}); });
testWidgets( testWidgets(
'renders the loading indicator while the assets load', 'renders the loading indicator while the assets load',
(tester) async { (tester) async {
final gameBloc = MockGameBloc();
whenListen(
gameBloc,
Stream.value(const GameState.initial()),
initialState: const GameState.initial(),
);
final assetsManagerCubit = MockAssetsManagerCubit(); final assetsManagerCubit = MockAssetsManagerCubit();
final initialAssetsState = AssetsManagerState( final initialAssetsState = AssetsManagerState(
loadables: [Future<void>.value()], loadables: [Future<void>.value()],
@ -51,11 +57,27 @@ void main() {
); );
await tester.pumpApp( await tester.pumpApp(
PinballGamePage(theme: theme, game: game), PinballGameView(
gameBloc: gameBloc, game: game,
),
assetsManagerCubit: assetsManagerCubit, assetsManagerCubit: assetsManagerCubit,
themeCubit: themeCubit,
); );
expect(find.text('0.0'), findsOneWidget);
expect(
find.byWidgetPredicate(
(widget) =>
widget is LinearProgressIndicator && widget.value == 0.0,
),
findsOneWidget,
);
},
);
testWidgets(
'renders PinballGameLoadedView after resources have been loaded',
(tester) async {
final assetsManagerCubit = MockAssetsManagerCubit();
final loadedAssetsState = AssetsManagerState( final loadedAssetsState = AssetsManagerState(
loadables: [Future<void>.value()], loadables: [Future<void>.value()],
@ -67,11 +89,20 @@ void main() {
initialState: loadedAssetsState, initialState: loadedAssetsState,
); );
await tester.pump(); await tester.pumpApp(
expect(find.byType(PinballGameView), findsOneWidget); PinballGameView(
}, game: game,
),
assetsManagerCubit: assetsManagerCubit,
themeCubit: themeCubit,
gameBloc: gameBloc,
); );
await tester.pump();
expect(find.byType(PinballGameLoadedView), findsOneWidget);
});
group('route', () { group('route', () {
Future<void> pumpRoute({ Future<void> pumpRoute({
required WidgetTester tester, required WidgetTester tester,
@ -85,7 +116,6 @@ void main() {
onPressed: () { onPressed: () {
Navigator.of(context).push<void>( Navigator.of(context).push<void>(
PinballGamePage.route( PinballGamePage.route(
theme: theme,
isDebugMode: isDebugMode, isDebugMode: isDebugMode,
), ),
); );
@ -95,6 +125,7 @@ void main() {
}, },
), ),
), ),
themeCubit: themeCubit,
); );
await tester.tap(find.text('Tap me')); await tester.tap(find.text('Tap me'));

@ -1,8 +1,9 @@
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/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/theme/theme.dart';
import '../../helpers/helpers.dart'; import '../../../helpers/helpers.dart';
void main() { void main() {
group('PlayButtonOverlay', () { group('PlayButtonOverlay', () {
@ -31,5 +32,15 @@ void main() {
verify(gameFlowController.start).called(1); verify(gameFlowController.start).called(1);
}); });
testWidgets('displays CharacterSelectionDialog when tapped',
(tester) async {
await tester.pumpApp(PlayButtonOverlay(game: game));
await tester.tap(find.text('Play'));
await tester.pump();
expect(find.byType(CharacterSelectionDialog), findsOneWidget);
});
}); });
} }

@ -1,71 +0,0 @@
// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockingjay/mockingjay.dart';
import 'package:pinball/l10n/l10n.dart';
import 'package:pinball/landing/landing.dart';
import '../../helpers/helpers.dart';
void main() {
group('LandingPage', () {
testWidgets('renders correctly', (tester) async {
final l10n = await AppLocalizations.delegate.load(Locale('en'));
await tester.pumpApp(LandingPage());
expect(find.byType(TextButton), findsNWidgets(2));
expect(find.text(l10n.play), findsOneWidget);
expect(find.text(l10n.howToPlay), findsOneWidget);
});
testWidgets('tapping on play button navigates to CharacterSelectionPage',
(tester) async {
final l10n = await AppLocalizations.delegate.load(Locale('en'));
final navigator = MockNavigator();
when(() => navigator.push<void>(any())).thenAnswer((_) async {});
await tester.pumpApp(
LandingPage(),
navigator: navigator,
);
await tester.tap(find.widgetWithText(TextButton, l10n.play));
verify(() => navigator.push<void>(any())).called(1);
});
testWidgets('tapping on how to play button displays dialog with controls',
(tester) async {
final l10n = await AppLocalizations.delegate.load(Locale('en'));
await tester.pumpApp(LandingPage());
await tester.tap(find.widgetWithText(TextButton, l10n.howToPlay));
await tester.pump();
expect(find.byType(Dialog), findsOneWidget);
});
});
group('KeyIndicator', () {
testWidgets('fromKeyName renders correctly', (tester) async {
const keyName = 'A';
await tester.pumpApp(
KeyIndicator.fromKeyName(keyName: keyName),
);
expect(find.text(keyName), findsOneWidget);
});
testWidgets('fromIcon renders correctly', (tester) async {
const keyIcon = Icons.keyboard_arrow_down;
await tester.pumpApp(
KeyIndicator.fromIcon(keyIcon: keyIcon),
);
expect(find.byIcon(keyIcon), findsOneWidget);
});
});
}

@ -0,0 +1,39 @@
// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pinball/start_game/start_game.dart';
import '../../helpers/helpers.dart';
void main() {
group('HowToPlayDialog', () {
testWidgets('displays dialog', (tester) async {
await tester.pumpApp(HowToPlayDialog());
expect(find.byType(Dialog), findsOneWidget);
});
});
group('KeyIndicator', () {
testWidgets('fromKeyName renders correctly', (tester) async {
const keyName = 'A';
await tester.pumpApp(
KeyIndicator.fromKeyName(keyName: keyName),
);
expect(find.text(keyName), findsOneWidget);
});
testWidgets('fromIcon renders correctly', (tester) async {
const keyIcon = Icons.keyboard_arrow_down;
await tester.pumpApp(
KeyIndicator.fromIcon(keyIcon: keyIcon),
);
expect(find.byIcon(keyIcon), findsOneWidget);
});
});
}

@ -4,6 +4,7 @@ import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockingjay/mockingjay.dart'; import 'package:mockingjay/mockingjay.dart';
import 'package:pinball/start_game/start_game.dart';
import 'package:pinball/theme/theme.dart'; import 'package:pinball/theme/theme.dart';
import 'package:pinball_theme/pinball_theme.dart'; import 'package:pinball_theme/pinball_theme.dart';
@ -24,7 +25,7 @@ void main() {
group('CharacterSelectionPage', () { group('CharacterSelectionPage', () {
testWidgets('renders CharacterSelectionView', (tester) async { testWidgets('renders CharacterSelectionView', (tester) async {
await tester.pumpApp( await tester.pumpApp(
CharacterSelectionPage(), CharacterSelectionDialog(),
themeCubit: themeCubit, themeCubit: themeCubit,
); );
expect(find.byType(CharacterSelectionView), findsOneWidget); expect(find.byType(CharacterSelectionView), findsOneWidget);
@ -38,7 +39,7 @@ void main() {
return ElevatedButton( return ElevatedButton(
onPressed: () { onPressed: () {
Navigator.of(context) Navigator.of(context)
.push<void>(CharacterSelectionPage.route()); .push<void>(CharacterSelectionDialog.route());
}, },
child: Text('Tap me'), child: Text('Tap me'),
); );
@ -51,7 +52,7 @@ void main() {
await tester.tap(find.text('Tap me')); await tester.tap(find.text('Tap me'));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.byType(CharacterSelectionPage), findsOneWidget); expect(find.byType(CharacterSelectionDialog), findsOneWidget);
}); });
}); });
@ -82,20 +83,17 @@ void main() {
verify(() => themeCubit.characterSelected(SparkyTheme())).called(1); verify(() => themeCubit.characterSelected(SparkyTheme())).called(1);
}); });
testWidgets('navigates to PinballGamePage when start is tapped', testWidgets('displays how to play dialog when start is tapped',
(tester) async { (tester) async {
final navigator = MockNavigator();
when(() => navigator.push<void>(any())).thenAnswer((_) async {});
await tester.pumpApp( await tester.pumpApp(
CharacterSelectionView(), CharacterSelectionView(),
themeCubit: themeCubit, themeCubit: themeCubit,
navigator: navigator,
); );
await tester.ensureVisible(find.byType(TextButton)); await tester.ensureVisible(find.byType(TextButton));
await tester.tap(find.byType(TextButton)); await tester.tap(find.byType(TextButton));
await tester.pumpAndSettle();
verify(() => navigator.push<void>(any())).called(1); expect(find.byType(HowToPlayDialog), findsOneWidget);
}); });
}); });

Loading…
Cancel
Save