Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: board not loading when playing through the tutorial #578

Merged
merged 2 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 26 additions & 22 deletions lib/how_to_play/view/how_to_play_page.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:authentication_repository/authentication_repository.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:game_domain/game_domain.dart';
import 'package:io_crossword/assets/assets.dart';
import 'package:io_crossword/audio/audio.dart';
import 'package:io_crossword/crossword/crossword.dart';
Expand Down Expand Up @@ -108,17 +110,7 @@ class _HowToPlaySmall extends StatelessWidget {
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 375),
child: SingleChildScrollView(
child: HowToPlayContent(
mascot: mascot,
onDonePressed: () {
context
.read<AudioController>()
.playSfx(Assets.music.startButton1);
context
.read<HowToPlayCubit>()
.updateStatus(HowToPlayStatus.pickingUp);
},
),
child: HowToPlayPageContent(mascot: mascot),
),
),
),
Expand Down Expand Up @@ -172,17 +164,7 @@ class _HowToPlayLarge extends StatelessWidget {
child: SingleChildScrollView(
child: Column(
children: [
HowToPlayContent(
mascot: mascot,
onDonePressed: () {
context
.read<AudioController>()
.playSfx(Assets.music.startButton1);
context
.read<HowToPlayCubit>()
.updateStatus(HowToPlayStatus.pickingUp);
},
),
HowToPlayPageContent(mascot: mascot),
const SizedBox(height: 40),
const PlayNowButton(),
],
Expand All @@ -196,6 +178,28 @@ class _HowToPlayLarge extends StatelessWidget {
}
}

@visibleForTesting
class HowToPlayPageContent extends StatelessWidget {
@visibleForTesting
const HowToPlayPageContent({required this.mascot, super.key});

final Mascot mascot;

@override
Widget build(BuildContext context) {
return HowToPlayContent(
mascot: mascot,
onDonePressed: () {
context.read<AudioController>().playSfx(Assets.music.startButton1);
context
.read<PlayerBloc>()
.add(PlayerCreateScoreRequested(context.read<User>().id));
context.read<HowToPlayCubit>().updateStatus(HowToPlayStatus.pickingUp);
},
);
}
}

class _MascotAnimation extends StatefulWidget {
const _MascotAnimation();

Expand Down
8 changes: 4 additions & 4 deletions lib/how_to_play/widgets/how_to_play_content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ class _TabSelector extends StatelessWidget {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: index > 0
TextButton(
onPressed: index > 0
? () {
context
.read<AudioController>()
Expand All @@ -163,8 +163,8 @@ class _TabSelector extends StatelessWidget {
TabPageSelector(
controller: tabController,
),
GestureDetector(
onTap: () {
TextButton(
onPressed: () {
if (index == tabController.length - 1) {
onDonePressed();
} else {
Expand Down
211 changes: 116 additions & 95 deletions test/how_to_play/view/how_to_play_page_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// ignore_for_file: prefer_const_constructors

import 'package:authentication_repository/authentication_repository.dart';
import 'package:bloc_test/bloc_test.dart';
import 'package:flame/cache.dart';
import 'package:flame/flame.dart';
Expand Down Expand Up @@ -117,44 +118,90 @@ void main() {
late HowToPlayCubit howToPlayCubit;
late PlayerBloc playerBloc;
late Widget widget;
late AppLocalizations l10n;

setUpAll(() async {
l10n = await AppLocalizations.delegate.load(Locale('en'));
});

setUp(() {
howToPlayCubit = _MockHowToPlayCubit();
playerBloc = _MockPlayerBloc();

when(() => howToPlayCubit.loadAssets(any())).thenAnswer((_) async {});

when(() => howToPlayCubit.state).thenReturn(
HowToPlayState(
assetsStatus: AssetsLoadingStatus.success,
),
HowToPlayState(assetsStatus: AssetsLoadingStatus.success),
);

when(() => playerBloc.state).thenReturn(PlayerState());

widget = MultiBlocProvider(
providers: [
BlocProvider.value(
value: howToPlayCubit,
),
BlocProvider.value(
value: playerBloc,
),
BlocProvider.value(value: howToPlayCubit),
BlocProvider.value(value: playerBloc),
],
child: HowToPlayView(),
);
});

for (final layout in IoLayoutData.values) {
testWidgets('displays IoAppBar with $layout', (tester) async {
await tester.pumpApp(
widget,
layout: layout,
);
group('displays', () {
for (final layout in IoLayoutData.values) {
testWidgets('$IoAppBar with $layout', (tester) async {
await tester.pumpApp(widget, layout: layout);

expect(find.byType(IoAppBar), findsOneWidget);
});
}
expect(find.byType(IoAppBar), findsOneWidget);
});

testWidgets('$HowToPlayPageContent with $layout', (tester) async {
await tester.pumpApp(widget, layout: layout);

expect(find.byType(HowToPlayPageContent), findsOneWidget);
});

testWidgets('a $PlayNowButton with $layout', (tester) async {
await tester.pumpApp(widget, layout: layout);

expect(find.byType(PlayNowButton), findsOneWidget);
});

testWidgets('localized playNow text with $layout', (tester) async {
await tester.pumpApp(widget, layout: layout);

expect(find.text(l10n.playNow), findsOneWidget);
});

testWidgets('LookUp animation for dash with $layout', (tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.android;

await tester.pumpApp(
MultiBlocProvider(
providers: [
BlocProvider.value(value: howToPlayCubit),
BlocProvider.value(value: playerBloc),
],
child: HowToPlayView(),
),
layout: layout,
);

final widget = find
.byType(SpriteAnimationList)
.evaluate()
.single
.widget as SpriteAnimationList;

expect(
widget.animationItems.first,
isA<AnimationItem>().having(
(item) => item.spriteData,
'spriteData',
Mascot.dash.teamMascot.lookUpSpriteMobileData,
),
);

debugDefaultTargetPlatformOverride = null;
});
}
});

for (final layout in IoLayoutData.values) {
testWidgets(
Expand Down Expand Up @@ -229,98 +276,72 @@ void main() {
expect(capturedPredicate(secondRoute), isFalse);
},
);
}
});

testWidgets(
'verify status is updated to pickingUp '
'when done button is pressed', (tester) async {
final l10n = await AppLocalizations.delegate.load(Locale('en'));
group('$HowToPlayPageContent', () {
late HowToPlayCubit howToPlayCubit;
late PlayerBloc playerBloc;
late Widget widget;
late AppLocalizations l10n;

setUpAll(() async {
l10n = await AppLocalizations.delegate.load(Locale('en'));
});

setUp(() {
howToPlayCubit = _MockHowToPlayCubit();
playerBloc = _MockPlayerBloc();

when(() => howToPlayCubit.loadAssets(any())).thenAnswer((_) async {});
when(() => howToPlayCubit.state).thenReturn(
HowToPlayState(assetsStatus: AssetsLoadingStatus.success),
);
when(() => playerBloc.state).thenReturn(PlayerState());

widget = MultiBlocProvider(
providers: [
BlocProvider.value(value: howToPlayCubit),
BlocProvider.value(value: playerBloc),
],
child: HowToPlayView(),
);
});

testWidgets(
'verify status is updated to pickingUp when done button is pressed',
(tester) async {
when(() => howToPlayCubit.state).thenReturn(
HowToPlayState(
index: 4,
assetsStatus: AssetsLoadingStatus.success,
),
);

await tester.pumpApp(
widget,
layout: layout,
);
await tester.pumpApp(widget);

await tester.tap(find.text(l10n.doneButtonLabel));

verify(() => howToPlayCubit.updateStatus(HowToPlayStatus.pickingUp))
.called(1);
});
}

group('displays', () {
testWidgets('a $PlayNowButton when small layout', (tester) async {
await tester.pumpApp(
widget,
layout: IoLayoutData.small,
);
},
);

expect(find.byType(PlayNowButton), findsOneWidget);
});

testWidgets('a $PlayNowButton when large layout', (tester) async {
await tester.pumpApp(
widget,
layout: IoLayoutData.large,
);

expect(find.byType(PlayNowButton), findsOneWidget);
});

testWidgets('localized playNow text', (tester) async {
late final AppLocalizations l10n;

await tester.pumpApp(
Builder(
builder: (context) {
l10n = context.l10n;
return widget;
},
),
layout: IoLayoutData.small,
);

expect(find.text(l10n.playNow), findsOneWidget);
});

testWidgets('renders LookUp animation for dash', (tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.android;

await tester.pumpApp(
MultiBlocProvider(
providers: [
BlocProvider.value(
value: howToPlayCubit,
),
BlocProvider.value(
value: playerBloc,
),
],
child: HowToPlayView(),
testWidgets(
'verify $PlayerCreateScoreRequested is added when done button is pressed',
(tester) async {
when(() => howToPlayCubit.state).thenReturn(
HowToPlayState(
index: 4,
assetsStatus: AssetsLoadingStatus.success,
),
layout: IoLayoutData.small,
);
await tester.pumpApp(widget, user: User(id: 'userId'));

final widget = find.byType(SpriteAnimationList).evaluate().single.widget
as SpriteAnimationList;

expect(
widget.animationItems.first,
isA<AnimationItem>().having(
(item) => item.spriteData,
'spriteData',
Mascot.dash.teamMascot.lookUpSpriteMobileData,
),
);
await tester.tap(find.text(l10n.doneButtonLabel));

debugDefaultTargetPlatformOverride = null;
});
});
verify(() => playerBloc.add(PlayerCreateScoreRequested('userId')))
.called(1);
},
);
});
}