feat: social networks `ShareDisplay` (#406)

* feat: share screen and tests

* chore: assets gen

* feat: added share repository

* feature: injecting sharerepository

* feat: share url

* feat: state for showing ShareDisplay at Backbox

* test: tests for sharing links

* test: backbox tests

* Update lib/game/components/backbox/displays/share_display.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

* Update lib/game/components/backbox/displays/share_display.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

* Update lib/game/components/backbox/displays/share_display.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

* Update test/game/components/backbox/backbox_test.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

* Update test/game/components/backbox/displays/share_display_test.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

* Update test/game/components/backbox/displays/share_display_test.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

* Update test/game/components/backbox/backbox_test.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

* Update test/game/components/backbox/backbox_test.dart

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>

* refactor: moved down social networks icons

* refactor: url and text for share

Co-authored-by: Allison Ryan <77211884+allisonryan0002@users.noreply.github.com>
pull/414/head
Rui Miguel Alonso 3 years ago committed by GitHub
parent c3094850fd
commit 80da24b43c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -9,20 +9,24 @@ import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart'; import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
import 'package:pinball_ui/pinball_ui.dart'; import 'package:pinball_ui/pinball_ui.dart';
import 'package:share_repository/share_repository.dart';
class App extends StatelessWidget { class App extends StatelessWidget {
const App({ const App({
Key? key, Key? key,
required AuthenticationRepository authenticationRepository, required AuthenticationRepository authenticationRepository,
required LeaderboardRepository leaderboardRepository, required LeaderboardRepository leaderboardRepository,
required ShareRepository shareRepository,
required PinballAudioPlayer pinballAudioPlayer, required PinballAudioPlayer pinballAudioPlayer,
}) : _authenticationRepository = authenticationRepository, }) : _authenticationRepository = authenticationRepository,
_leaderboardRepository = leaderboardRepository, _leaderboardRepository = leaderboardRepository,
_shareRepository = shareRepository,
_pinballAudioPlayer = pinballAudioPlayer, _pinballAudioPlayer = pinballAudioPlayer,
super(key: key); super(key: key);
final AuthenticationRepository _authenticationRepository; final AuthenticationRepository _authenticationRepository;
final LeaderboardRepository _leaderboardRepository; final LeaderboardRepository _leaderboardRepository;
final ShareRepository _shareRepository;
final PinballAudioPlayer _pinballAudioPlayer; final PinballAudioPlayer _pinballAudioPlayer;
@override @override
@ -31,6 +35,7 @@ class App extends StatelessWidget {
providers: [ providers: [
RepositoryProvider.value(value: _authenticationRepository), RepositoryProvider.value(value: _authenticationRepository),
RepositoryProvider.value(value: _leaderboardRepository), RepositoryProvider.value(value: _leaderboardRepository),
RepositoryProvider.value(value: _shareRepository),
RepositoryProvider.value(value: _pinballAudioPlayer), RepositoryProvider.value(value: _pinballAudioPlayer),
], ],
child: MultiBlocProvider( child: MultiBlocProvider(

@ -6,10 +6,13 @@ import 'package:leaderboard_repository/leaderboard_repository.dart';
import 'package:pinball/game/components/backbox/bloc/backbox_bloc.dart'; import 'package:pinball/game/components/backbox/bloc/backbox_bloc.dart';
import 'package:pinball/game/components/backbox/displays/displays.dart'; import 'package:pinball/game/components/backbox/displays/displays.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball/l10n/l10n.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';
import 'package:pinball_theme/pinball_theme.dart' hide Assets; import 'package:pinball_theme/pinball_theme.dart' hide Assets;
import 'package:pinball_ui/pinball_ui.dart';
import 'package:platform_helper/platform_helper.dart'; import 'package:platform_helper/platform_helper.dart';
import 'package:share_repository/share_repository.dart';
/// {@template backbox} /// {@template backbox}
/// The [Backbox] of the pinball machine. /// The [Backbox] of the pinball machine.
@ -18,21 +21,26 @@ class Backbox extends PositionComponent with ZIndex, HasGameRef {
/// {@macro backbox} /// {@macro backbox}
Backbox({ Backbox({
required LeaderboardRepository leaderboardRepository, required LeaderboardRepository leaderboardRepository,
required ShareRepository shareRepository,
required List<LeaderboardEntryData>? entries, required List<LeaderboardEntryData>? entries,
}) : _bloc = BackboxBloc( }) : _bloc = BackboxBloc(
leaderboardRepository: leaderboardRepository, leaderboardRepository: leaderboardRepository,
initialEntries: entries, initialEntries: entries,
), ),
_shareRepository = shareRepository,
_platformHelper = PlatformHelper(); _platformHelper = PlatformHelper();
/// {@macro backbox} /// {@macro backbox}
@visibleForTesting @visibleForTesting
Backbox.test({ Backbox.test({
required BackboxBloc bloc, required BackboxBloc bloc,
required ShareRepository shareRepository,
required PlatformHelper platformHelper, required PlatformHelper platformHelper,
}) : _bloc = bloc, }) : _bloc = bloc,
_shareRepository = shareRepository,
_platformHelper = platformHelper; _platformHelper = platformHelper;
final ShareRepository _shareRepository;
late final Component _display; late final Component _display;
final BackboxBloc _bloc; final BackboxBloc _bloc;
final PlatformHelper _platformHelper; final PlatformHelper _platformHelper;
@ -87,6 +95,8 @@ class Backbox extends PositionComponent with ZIndex, HasGameRef {
), ),
); );
} else if (state is InitialsSuccessState) { } else if (state is InitialsSuccessState) {
gameRef.overlays.remove(PinballGame.mobileControlsOverlay);
_display.add( _display.add(
GameOverInfoDisplay( GameOverInfoDisplay(
onShare: () { onShare: () {
@ -94,6 +104,20 @@ class Backbox extends PositionComponent with ZIndex, HasGameRef {
}, },
), ),
); );
} else if (state is ShareState) {
_display.add(
ShareDisplay(
onShare: (platform) {
final message = readProvider<AppLocalizations>()
.iGotScoreAtPinball(state.score);
final url = _shareRepository.shareText(
value: message,
platform: platform,
);
openLink(url);
},
),
);
} else if (state is InitialsFailureState) { } else if (state is InitialsFailureState) {
_display.add( _display.add(
InitialsSubmissionFailureDisplay( InitialsSubmissionFailureDisplay(

@ -75,9 +75,7 @@ class BackboxBloc extends Bloc<BackboxEvent, BackboxState> {
Emitter<BackboxState> emit, Emitter<BackboxState> emit,
) async { ) async {
emit( emit(
ShareState( ShareState(score: event.score),
score: event.score,
),
); );
} }

@ -5,3 +5,4 @@ export 'initials_submission_success_display.dart';
export 'leaderboard_display.dart'; export 'leaderboard_display.dart';
export 'leaderboard_failure_display.dart'; export 'leaderboard_failure_display.dart';
export 'loading_display.dart'; export 'loading_display.dart';
export 'share_display.dart';

@ -0,0 +1,189 @@
import 'dart:async';
import 'package:flame/components.dart';
import 'package:flame/input.dart';
import 'package:flutter/material.dart';
import 'package:pinball/l10n/l10n.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
import 'package:pinball_ui/pinball_ui.dart';
import 'package:share_repository/share_repository.dart';
/// Signature for the callback called when the user tries to share their score
/// on the [ShareDisplay].
typedef OnSocialShareTap = void Function(SharePlatform);
final _descriptionTextPaint = TextPaint(
style: const TextStyle(
fontSize: 1.6,
color: PinballColors.white,
fontFamily: PinballFonts.pixeloidSans,
),
);
/// {@template share_display}
/// Display that allows users to share their score to social networks.
/// {@endtemplate}
class ShareDisplay extends Component with HasGameRef {
/// {@macro share_display}
ShareDisplay({
OnSocialShareTap? onShare,
}) : super(
children: [
_ShareInstructionsComponent(
onShare: onShare,
),
],
);
}
class _ShareInstructionsComponent extends PositionComponent with HasGameRef {
_ShareInstructionsComponent({
OnSocialShareTap? onShare,
}) : super(
anchor: Anchor.center,
position: Vector2(0, -25),
children: [
_DescriptionComponent(),
_SocialNetworksComponent(
onShare: onShare,
),
],
);
}
class _DescriptionComponent extends PositionComponent with HasGameRef {
_DescriptionComponent()
: super(
anchor: Anchor.center,
position: Vector2.zero(),
children: [
_LetEveryoneTextComponent(),
_SharingYourScoreTextComponent(),
_SocialMediaTextComponent(),
],
);
}
class _LetEveryoneTextComponent extends TextComponent with HasGameRef {
_LetEveryoneTextComponent()
: super(
anchor: Anchor.center,
position: Vector2.zero(),
textRenderer: _descriptionTextPaint,
);
@override
Future<void> onLoad() async {
await super.onLoad();
text = readProvider<AppLocalizations>().letEveryone;
}
}
class _SharingYourScoreTextComponent extends TextComponent with HasGameRef {
_SharingYourScoreTextComponent()
: super(
anchor: Anchor.center,
position: Vector2(0, 2.5),
textRenderer: _descriptionTextPaint,
);
@override
Future<void> onLoad() async {
await super.onLoad();
text = readProvider<AppLocalizations>().bySharingYourScore;
}
}
class _SocialMediaTextComponent extends TextComponent with HasGameRef {
_SocialMediaTextComponent()
: super(
anchor: Anchor.center,
position: Vector2(0, 5),
textRenderer: _descriptionTextPaint,
);
@override
Future<void> onLoad() async {
await super.onLoad();
text = readProvider<AppLocalizations>().socialMediaAccount;
}
}
class _SocialNetworksComponent extends PositionComponent with HasGameRef {
_SocialNetworksComponent({
OnSocialShareTap? onShare,
}) : super(
anchor: Anchor.center,
position: Vector2(0, 12),
children: [
FacebookButtonComponent(onTap: onShare),
TwitterButtonComponent(onTap: onShare),
],
);
}
/// {@template facebook_button_component}
/// Button for sharing on Facebook.
/// {@endtemplate}
class FacebookButtonComponent extends SpriteComponent
with HasGameRef, Tappable {
/// {@macro facebook_button_component}
FacebookButtonComponent({
OnSocialShareTap? onTap,
}) : _onTap = onTap,
super(
anchor: Anchor.center,
position: Vector2(-5, 0),
);
final OnSocialShareTap? _onTap;
@override
bool onTapDown(TapDownInfo info) {
_onTap?.call(SharePlatform.facebook);
return true;
}
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = Sprite(
gameRef.images.fromCache(Assets.images.backbox.button.facebook.keyName),
);
this.sprite = sprite;
size = sprite.originalSize / 25;
}
}
/// {@template twitter_button_component}
/// Button for sharing on Twitter.
/// {@endtemplate}
class TwitterButtonComponent extends SpriteComponent with HasGameRef, Tappable {
/// {@macro twitter_button_component}
TwitterButtonComponent({
OnSocialShareTap? onTap,
}) : _onTap = onTap,
super(
anchor: Anchor.center,
position: Vector2(5, 0),
);
final OnSocialShareTap? _onTap;
@override
bool onTapDown(TapDownInfo info) {
_onTap?.call(SharePlatform.twitter);
return true;
}
@override
Future<void> onLoad() async {
await super.onLoad();
final sprite = Sprite(
gameRef.images.fromCache(Assets.images.backbox.button.twitter.keyName),
);
this.sprite = sprite;
size = sprite.originalSize / 25;
}
}

@ -101,6 +101,8 @@ extension PinballGameAssetsX on PinballGame {
images.load(components.Assets.images.sparky.bumper.c.dimmed.keyName), images.load(components.Assets.images.sparky.bumper.c.dimmed.keyName),
images.load(components.Assets.images.backbox.marquee.keyName), images.load(components.Assets.images.backbox.marquee.keyName),
images.load(components.Assets.images.backbox.displayDivider.keyName), images.load(components.Assets.images.backbox.displayDivider.keyName),
images.load(components.Assets.images.backbox.button.facebook.keyName),
images.load(components.Assets.images.backbox.button.twitter.keyName),
images.load( images.load(
components.Assets.images.backbox.displayTitleDecoration.keyName, components.Assets.images.backbox.displayTitleDecoration.keyName,
), ),

@ -14,12 +14,14 @@ import 'package:pinball/select_character/select_character.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.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';
import 'package:share_repository/share_repository.dart';
class PinballGame extends PinballForge2DGame class PinballGame extends PinballForge2DGame
with HasKeyboardHandlerComponents, MultiTouchTapDetector, HasTappables { with HasKeyboardHandlerComponents, MultiTouchTapDetector, HasTappables {
PinballGame({ PinballGame({
required CharacterThemeCubit characterThemeBloc, required CharacterThemeCubit characterThemeBloc,
required this.leaderboardRepository, required this.leaderboardRepository,
required this.shareRepository,
required GameBloc gameBloc, required GameBloc gameBloc,
required AppLocalizations l10n, required AppLocalizations l10n,
required PinballAudioPlayer audioPlayer, required PinballAudioPlayer audioPlayer,
@ -51,6 +53,8 @@ class PinballGame extends PinballForge2DGame
final LeaderboardRepository leaderboardRepository; final LeaderboardRepository leaderboardRepository;
final ShareRepository shareRepository;
final AppLocalizations _l10n; final AppLocalizations _l10n;
final GameBloc _gameBloc; final GameBloc _gameBloc;
@ -84,6 +88,7 @@ class PinballGame extends PinballForge2DGame
providers: [ providers: [
FlameProvider<PinballAudioPlayer>.value(_audioPlayer), FlameProvider<PinballAudioPlayer>.value(_audioPlayer),
FlameProvider<LeaderboardRepository>.value(leaderboardRepository), FlameProvider<LeaderboardRepository>.value(leaderboardRepository),
FlameProvider<ShareRepository>.value(shareRepository),
FlameProvider<AppLocalizations>.value(_l10n), FlameProvider<AppLocalizations>.value(_l10n),
], ],
children: [ children: [
@ -106,6 +111,7 @@ class PinballGame extends PinballForge2DGame
Boundaries(), Boundaries(),
Backbox( Backbox(
leaderboardRepository: leaderboardRepository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
entries: _entries, entries: _entries,
), ),
GoogleWord(position: Vector2(-4.45, 1.8)), GoogleWord(position: Vector2(-4.45, 1.8)),
@ -188,6 +194,7 @@ class DebugPinballGame extends PinballGame with FPSCounter, PanDetector {
DebugPinballGame({ DebugPinballGame({
required CharacterThemeCubit characterThemeBloc, required CharacterThemeCubit characterThemeBloc,
required LeaderboardRepository leaderboardRepository, required LeaderboardRepository leaderboardRepository,
required ShareRepository shareRepository,
required AppLocalizations l10n, required AppLocalizations l10n,
required PinballAudioPlayer audioPlayer, required PinballAudioPlayer audioPlayer,
required GameBloc gameBloc, required GameBloc gameBloc,
@ -195,6 +202,7 @@ class DebugPinballGame extends PinballGame with FPSCounter, PanDetector {
characterThemeBloc: characterThemeBloc, characterThemeBloc: characterThemeBloc,
audioPlayer: audioPlayer, audioPlayer: audioPlayer,
leaderboardRepository: leaderboardRepository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
l10n: l10n, l10n: l10n,
gameBloc: gameBloc, gameBloc: gameBloc,
); );

@ -12,6 +12,7 @@ import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart'; import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
import 'package:pinball_ui/pinball_ui.dart'; import 'package:pinball_ui/pinball_ui.dart';
import 'package:share_repository/share_repository.dart';
class PinballGamePage extends StatelessWidget { class PinballGamePage extends StatelessWidget {
const PinballGamePage({ const PinballGamePage({
@ -26,12 +27,14 @@ class PinballGamePage extends StatelessWidget {
final characterThemeBloc = context.read<CharacterThemeCubit>(); final characterThemeBloc = context.read<CharacterThemeCubit>();
final audioPlayer = context.read<PinballAudioPlayer>(); final audioPlayer = context.read<PinballAudioPlayer>();
final leaderboardRepository = context.read<LeaderboardRepository>(); final leaderboardRepository = context.read<LeaderboardRepository>();
final shareRepository = context.read<ShareRepository>();
final gameBloc = context.read<GameBloc>(); final gameBloc = context.read<GameBloc>();
final game = isDebugMode final game = isDebugMode
? DebugPinballGame( ? DebugPinballGame(
characterThemeBloc: characterThemeBloc, characterThemeBloc: characterThemeBloc,
audioPlayer: audioPlayer, audioPlayer: audioPlayer,
leaderboardRepository: leaderboardRepository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
l10n: context.l10n, l10n: context.l10n,
gameBloc: gameBloc, gameBloc: gameBloc,
) )
@ -39,6 +42,7 @@ class PinballGamePage extends StatelessWidget {
characterThemeBloc: characterThemeBloc, characterThemeBloc: characterThemeBloc,
audioPlayer: audioPlayer, audioPlayer: audioPlayer,
leaderboardRepository: leaderboardRepository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
l10n: context.l10n, l10n: context.l10n,
gameBloc: gameBloc, gameBloc: gameBloc,
); );

@ -189,7 +189,7 @@
"description": "Text shown on the mobile controls enter button" "description": "Text shown on the mobile controls enter button"
}, },
"initialsErrorTitle": "Uh-oh... well, that didnt work", "initialsErrorTitle": "Uh-oh... well, that didnt work",
"@enter": { "@initialsErrorTitle": {
"description": "Title shown when the initials submission fails" "description": "Title shown when the initials submission fails"
}, },
"initialsErrorMessage": "Please try a different combination of letters", "initialsErrorMessage": "Please try a different combination of letters",
@ -200,4 +200,26 @@
"@leaderboardErrorMessage": { "@leaderboardErrorMessage": {
"description": "Text shown when the leaderboard had an error while loading" "description": "Text shown when the leaderboard had an error while loading"
} }
,
"letEveryone": "Let everyone know about I/O Pinball",
"@letEveryone": {
"description": "Text displayed on share screen for description"
},
"bySharingYourScore": "by sharing your score to your preferred",
"@bySharingYourScore": {
"description": "Text displayed on share screen for description"
},
"socialMediaAccount": "social media account!",
"@socialMediaAccount": {
"description": "Text displayed on share screen for description"
},
"iGotScoreAtPinball": "I got {score} at the #IOPinball machine, can you beat my score? See you at #GoogleIO!",
"@iGotScoreAtPinball": {
"description": "Text to share score on Social Network",
"placeholders": {
"score": {
"type": "int"
}
}
}
} }

@ -6,10 +6,13 @@ import 'package:leaderboard_repository/leaderboard_repository.dart';
import 'package:pinball/app/app.dart'; import 'package:pinball/app/app.dart';
import 'package:pinball/bootstrap.dart'; import 'package:pinball/bootstrap.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
import 'package:share_repository/share_repository.dart';
void main() { void main() {
bootstrap((firestore, firebaseAuth) async { bootstrap((firestore, firebaseAuth) async {
final leaderboardRepository = LeaderboardRepository(firestore); final leaderboardRepository = LeaderboardRepository(firestore);
const shareRepository =
ShareRepository(appUrl: ShareRepository.pinballGameUrl);
final authenticationRepository = AuthenticationRepository(firebaseAuth); final authenticationRepository = AuthenticationRepository(firebaseAuth);
final pinballAudioPlayer = PinballAudioPlayer(); final pinballAudioPlayer = PinballAudioPlayer();
unawaited( unawaited(
@ -20,6 +23,7 @@ void main() {
return App( return App(
authenticationRepository: authenticationRepository, authenticationRepository: authenticationRepository,
leaderboardRepository: leaderboardRepository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
pinballAudioPlayer: pinballAudioPlayer, pinballAudioPlayer: pinballAudioPlayer,
); );
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

@ -59,6 +59,9 @@ class $AssetsImagesAndroidGen {
class $AssetsImagesBackboxGen { class $AssetsImagesBackboxGen {
const $AssetsImagesBackboxGen(); const $AssetsImagesBackboxGen();
$AssetsImagesBackboxButtonGen get button =>
const $AssetsImagesBackboxButtonGen();
/// File path: assets/images/backbox/display_divider.png /// File path: assets/images/backbox/display_divider.png
AssetGenImage get displayDivider => AssetGenImage get displayDivider =>
const AssetGenImage('assets/images/backbox/display_divider.png'); const AssetGenImage('assets/images/backbox/display_divider.png');
@ -386,6 +389,18 @@ class $AssetsImagesAndroidSpaceshipGen {
const AssetGenImage('assets/images/android/spaceship/saucer.png'); const AssetGenImage('assets/images/android/spaceship/saucer.png');
} }
class $AssetsImagesBackboxButtonGen {
const $AssetsImagesBackboxButtonGen();
/// File path: assets/images/backbox/button/facebook.png
AssetGenImage get facebook =>
const AssetGenImage('assets/images/backbox/button/facebook.png');
/// File path: assets/images/backbox/button/twitter.png
AssetGenImage get twitter =>
const AssetGenImage('assets/images/backbox/button/twitter.png');
}
class $AssetsImagesDashBumperGen { class $AssetsImagesDashBumperGen {
const $AssetsImagesDashBumperGen(); const $AssetsImagesDashBumperGen();

@ -90,6 +90,7 @@ flutter:
- assets/images/multiplier/x6/ - assets/images/multiplier/x6/
- assets/images/score/ - assets/images/score/
- assets/images/backbox/ - assets/images/backbox/
- assets/images/backbox/button/
- assets/images/flapper/ - assets/images/flapper/
- assets/images/skill_shot/ - assets/images/skill_shot/

@ -17,6 +17,9 @@ class ShareRepository {
/// Url to the Google IO Event. /// Url to the Google IO Event.
static const googleIOEvent = 'https://events.google.com/io/'; static const googleIOEvent = 'https://events.google.com/io/';
/// Url to the Pinball game.
static const pinballGameUrl = 'https://ashehwkdkdjruejdnensjsjdne.web.app/#/';
/// Returns a url to share the [value] on the given [platform]. /// Returns a url to share the [value] on the given [platform].
/// ///
/// The returned url can be opened using the [url_launcher](https://pub.dev/packages/url_launcher) package. /// The returned url can be opened using the [url_launcher](https://pub.dev/packages/url_launcher) package.

@ -5,6 +5,7 @@ import 'package:mocktail/mocktail.dart';
import 'package:pinball/app/app.dart'; import 'package:pinball/app/app.dart';
import 'package:pinball/game/game.dart'; import 'package:pinball/game/game.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
import 'package:share_repository/share_repository.dart';
class _MockAuthenticationRepository extends Mock class _MockAuthenticationRepository extends Mock
implements AuthenticationRepository {} implements AuthenticationRepository {}
@ -14,15 +15,19 @@ class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {}
class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { class _MockLeaderboardRepository extends Mock implements LeaderboardRepository {
} }
class _MockShareRepository extends Mock implements ShareRepository {}
void main() { void main() {
group('App', () { group('App', () {
late AuthenticationRepository authenticationRepository; late AuthenticationRepository authenticationRepository;
late LeaderboardRepository leaderboardRepository; late LeaderboardRepository leaderboardRepository;
late ShareRepository shareRepository;
late PinballAudioPlayer pinballAudioPlayer; late PinballAudioPlayer pinballAudioPlayer;
setUp(() { setUp(() {
authenticationRepository = _MockAuthenticationRepository(); authenticationRepository = _MockAuthenticationRepository();
leaderboardRepository = _MockLeaderboardRepository(); leaderboardRepository = _MockLeaderboardRepository();
shareRepository = _MockShareRepository();
pinballAudioPlayer = _MockPinballAudioPlayer(); pinballAudioPlayer = _MockPinballAudioPlayer();
when(pinballAudioPlayer.load).thenAnswer((_) => [Future.value()]); when(pinballAudioPlayer.load).thenAnswer((_) => [Future.value()]);
}); });
@ -32,6 +37,7 @@ void main() {
App( App(
authenticationRepository: authenticationRepository, authenticationRepository: authenticationRepository,
leaderboardRepository: leaderboardRepository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
pinballAudioPlayer: pinballAudioPlayer, pinballAudioPlayer: pinballAudioPlayer,
), ),
); );

@ -20,7 +20,10 @@ import 'package:pinball/l10n/l10n.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';
import 'package:pinball_theme/pinball_theme.dart' as theme; import 'package:pinball_theme/pinball_theme.dart' as theme;
import 'package:pinball_ui/pinball_ui.dart';
import 'package:platform_helper/platform_helper.dart'; import 'package:platform_helper/platform_helper.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:share_repository/share_repository.dart';
class _TestGame extends Forge2DGame class _TestGame extends Forge2DGame
with HasKeyboardHandlerComponents, HasTappables { with HasKeyboardHandlerComponents, HasTappables {
@ -36,6 +39,8 @@ class _TestGame extends Forge2DGame
character.leaderboardIcon.keyName, character.leaderboardIcon.keyName,
Assets.images.backbox.marquee.keyName, Assets.images.backbox.marquee.keyName,
Assets.images.backbox.displayDivider.keyName, Assets.images.backbox.displayDivider.keyName,
Assets.images.backbox.button.facebook.keyName,
Assets.images.backbox.button.twitter.keyName,
Assets.images.backbox.displayTitleDecoration.keyName, Assets.images.backbox.displayTitleDecoration.keyName,
]); ]);
} }
@ -75,8 +80,14 @@ class _MockBackboxBloc extends Mock implements BackboxBloc {}
class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { class _MockLeaderboardRepository extends Mock implements LeaderboardRepository {
} }
class _MockShareRepository extends Mock implements ShareRepository {}
class _MockTapDownInfo extends Mock implements TapDownInfo {} class _MockTapDownInfo extends Mock implements TapDownInfo {}
class _MockUrlLauncher extends Mock
with MockPlatformInterfaceMixin
implements UrlLauncherPlatform {}
class _MockAppLocalizations extends Mock implements AppLocalizations { class _MockAppLocalizations extends Mock implements AppLocalizations {
@override @override
String get score => ''; String get score => '';
@ -105,6 +116,15 @@ class _MockAppLocalizations extends Mock implements AppLocalizations {
@override @override
String get loading => ''; String get loading => '';
@override
String get letEveryone => '';
@override
String get bySharingYourScore => '';
@override
String get socialMediaAccount => '';
@override @override
String get shareYourScore => ''; String get shareYourScore => '';
@ -134,6 +154,9 @@ class _MockAppLocalizations extends Mock implements AppLocalizations {
@override @override
String get leaderboardErrorMessage => ''; String get leaderboardErrorMessage => '';
@override
String iGotScoreAtPinball(int _) => '';
} }
void main() { void main() {
@ -143,6 +166,7 @@ void main() {
late BackboxBloc bloc; late BackboxBloc bloc;
late PlatformHelper platformHelper; late PlatformHelper platformHelper;
late UrlLauncherPlatform urlLauncher;
setUp(() { setUp(() {
bloc = _MockBackboxBloc(); bloc = _MockBackboxBloc();
@ -161,6 +185,7 @@ void main() {
(game) async { (game) async {
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -178,6 +203,7 @@ void main() {
await game.pump( await game.pump(
Backbox.test( Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
), ),
); );
@ -199,6 +225,7 @@ void main() {
leaderboardRepository: _MockLeaderboardRepository(), leaderboardRepository: _MockLeaderboardRepository(),
initialEntries: [LeaderboardEntryData.empty], initialEntries: [LeaderboardEntryData.empty],
), ),
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -230,6 +257,7 @@ void main() {
); );
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -258,6 +286,7 @@ void main() {
); );
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -270,7 +299,8 @@ void main() {
); );
flameTester.test( flameTester.test(
'adds the mobile controls overlay when platform is mobile', 'adds the mobile controls overlay '
'when platform is mobile at InitialsFormState',
(game) async { (game) async {
final bloc = _MockBackboxBloc(); final bloc = _MockBackboxBloc();
final platformHelper = _MockPlatformHelper(); final platformHelper = _MockPlatformHelper();
@ -286,6 +316,7 @@ void main() {
when(() => platformHelper.isMobile).thenReturn(true); when(() => platformHelper.isMobile).thenReturn(true);
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -297,6 +328,33 @@ void main() {
}, },
); );
flameTester.test(
'remove the mobile controls overlay '
'when InitialsSuccessState',
(game) async {
final bloc = _MockBackboxBloc();
final platformHelper = _MockPlatformHelper();
final state = InitialsSuccessState(score: 10);
whenListen(
bloc,
Stream<BackboxState>.empty(),
initialState: state,
);
when(() => platformHelper.isMobile).thenReturn(true);
final backbox = Backbox.test(
bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper,
);
await game.pump(backbox);
expect(
game.overlays.value,
isNot(contains(PinballGame.mobileControlsOverlay)),
);
},
);
flameTester.test( flameTester.test(
'adds InitialsSubmissionSuccessDisplay on InitialsSuccessState', 'adds InitialsSubmissionSuccessDisplay on InitialsSuccessState',
(game) async { (game) async {
@ -308,6 +366,7 @@ void main() {
); );
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -330,6 +389,7 @@ void main() {
); );
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -359,6 +419,7 @@ void main() {
); );
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -373,6 +434,145 @@ void main() {
}, },
); );
group('ShareDisplay', () {
setUp(() async {
urlLauncher = _MockUrlLauncher();
UrlLauncherPlatform.instance = urlLauncher;
});
flameTester.test(
'adds ShareDisplay on ShareState',
(game) async {
final state = ShareState(score: 100);
whenListen(
bloc,
const Stream<InitialsSuccessState>.empty(),
initialState: state,
);
final backbox = Backbox.test(
bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper,
);
await game.pump(backbox);
expect(
game.descendants().whereType<ShareDisplay>().length,
equals(1),
);
},
);
flameTester.test(
'opens Facebook link when sharing with Facebook',
(game) async {
when(() => urlLauncher.canLaunch(any()))
.thenAnswer((_) async => true);
when(
() => urlLauncher.launch(
any(),
useSafariVC: any(named: 'useSafariVC'),
useWebView: any(named: 'useWebView'),
enableJavaScript: any(named: 'enableJavaScript'),
enableDomStorage: any(named: 'enableDomStorage'),
universalLinksOnly: any(named: 'universalLinksOnly'),
headers: any(named: 'headers'),
),
).thenAnswer((_) async => true);
final state = ShareState(score: 100);
whenListen(
bloc,
const Stream<ShareState>.empty(),
initialState: state,
);
final shareRepository = _MockShareRepository();
const fakeUrl = 'http://fakeUrl';
when(
() => shareRepository.shareText(
value: any(named: 'value'),
platform: SharePlatform.facebook,
),
).thenReturn(fakeUrl);
final backbox = Backbox.test(
bloc: bloc,
shareRepository: shareRepository,
platformHelper: platformHelper,
);
await game.pump(backbox);
final facebookButton =
game.descendants().whereType<FacebookButtonComponent>().first;
facebookButton.onTapDown(_MockTapDownInfo());
await game.ready();
verify(
() => shareRepository.shareText(
value: any(named: 'value'),
platform: SharePlatform.facebook,
),
).called(1);
},
);
flameTester.test(
'opens Twitter link when sharing with Twitter',
(game) async {
final state = ShareState(score: 100);
whenListen(
bloc,
Stream.value(state),
initialState: state,
);
final shareRepository = _MockShareRepository();
const fakeUrl = 'http://fakeUrl';
when(
() => shareRepository.shareText(
value: any(named: 'value'),
platform: SharePlatform.twitter,
),
).thenReturn(fakeUrl);
when(() => urlLauncher.canLaunch(any()))
.thenAnswer((_) async => true);
when(
() => urlLauncher.launch(
any(),
useSafariVC: any(named: 'useSafariVC'),
useWebView: any(named: 'useWebView'),
enableJavaScript: any(named: 'enableJavaScript'),
enableDomStorage: any(named: 'enableDomStorage'),
universalLinksOnly: any(named: 'universalLinksOnly'),
headers: any(named: 'headers'),
),
).thenAnswer((_) async => true);
final backbox = Backbox.test(
bloc: bloc,
shareRepository: shareRepository,
platformHelper: platformHelper,
);
await game.pump(backbox);
final facebookButton =
game.descendants().whereType<TwitterButtonComponent>().first;
facebookButton.onTapDown(_MockTapDownInfo());
await game.ready();
verify(
() => shareRepository.shareText(
value: any(named: 'value'),
platform: SharePlatform.twitter,
),
).called(1);
},
);
});
flameTester.test( flameTester.test(
'adds LeaderboardDisplay on LeaderboardSuccessState', 'adds LeaderboardDisplay on LeaderboardSuccessState',
(game) async { (game) async {
@ -384,6 +584,7 @@ void main() {
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -406,6 +607,7 @@ void main() {
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -429,6 +631,7 @@ void main() {
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);
@ -469,6 +672,7 @@ void main() {
final backbox = Backbox.test( final backbox = Backbox.test(
bloc: bloc, bloc: bloc,
shareRepository: _MockShareRepository(),
platformHelper: platformHelper, platformHelper: platformHelper,
); );
await game.pump(backbox); await game.pump(backbox);

@ -137,6 +137,25 @@ void main() {
); );
}); });
group('ShareScoreRequested', () {
blocTest<BackboxBloc, BackboxState>(
'emits ShareState',
setUp: () {
leaderboardRepository = _MockLeaderboardRepository();
},
build: () => BackboxBloc(
leaderboardRepository: leaderboardRepository,
initialEntries: emptyEntries,
),
act: (bloc) => bloc.add(
ShareScoreRequested(score: 100),
),
expect: () => [
ShareState(score: 100),
],
);
});
group('LeaderboardRequested', () { group('LeaderboardRequested', () {
blocTest<BackboxBloc, BackboxState>( blocTest<BackboxBloc, BackboxState>(
'adds [LoadingState, LeaderboardSuccessState] when request succeeds', 'adds [LoadingState, LeaderboardSuccessState] when request succeeds',

@ -203,5 +203,23 @@ void main() {
}); });
}); });
}); });
group('ShareState', () {
test('can be instantiated', () {
expect(
ShareState(score: 0),
isNotNull,
);
});
test('supports value comparison', () {
expect(
ShareState(score: 0),
equals(
ShareState(score: 0),
),
);
});
});
}); });
} }

@ -0,0 +1,112 @@
// ignore_for_file: cascade_invocations
import 'package:flame/game.dart';
import 'package:flame/input.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/bloc/game_bloc.dart';
import 'package:pinball/game/components/backbox/displays/share_display.dart';
import 'package:pinball/l10n/l10n.dart';
import 'package:pinball_components/pinball_components.dart';
import 'package:pinball_flame/pinball_flame.dart';
class _TestGame extends Forge2DGame with HasTappables {
@override
Future<void> onLoad() async {
await super.onLoad();
images.prefix = '';
await images.loadAll(
[
Assets.images.backbox.button.facebook.keyName,
Assets.images.backbox.button.twitter.keyName,
],
);
}
Future<void> pump(ShareDisplay component) {
return ensureAdd(
FlameBlocProvider<GameBloc, GameState>.value(
value: GameBloc(),
children: [
FlameProvider.value(
_MockAppLocalizations(),
children: [component],
),
],
),
);
}
}
class _MockAppLocalizations extends Mock implements AppLocalizations {
@override
String get letEveryone => '';
@override
String get bySharingYourScore => '';
@override
String get socialMediaAccount => '';
}
class _MockTapDownInfo extends Mock implements TapDownInfo {}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
final flameTester = FlameTester(_TestGame.new);
group('ShareDisplay', () {
flameTester.test(
'loads correctly',
(game) async {
final component = ShareDisplay();
await game.pump(component);
expect(game.descendants(), contains(component));
},
);
flameTester.test(
'calls onShare when Facebook button is tapped',
(game) async {
var tapped = false;
final tapDownInfo = _MockTapDownInfo();
final component = ShareDisplay(
onShare: (_) => tapped = true,
);
await game.pump(component);
final facebookButton =
component.descendants().whereType<FacebookButtonComponent>().first;
facebookButton.onTapDown(tapDownInfo);
expect(tapped, isTrue);
},
);
flameTester.test(
'calls onShare when Twitter button is tapped',
(game) async {
var tapped = false;
final tapDownInfo = _MockTapDownInfo();
final component = ShareDisplay(
onShare: (_) => tapped = true,
);
await game.pump(component);
final twitterButton =
component.descendants().whereType<TwitterButtonComponent>().first;
twitterButton.onTapDown(tapDownInfo);
expect(tapped, isTrue);
},
);
});
}

@ -14,6 +14,7 @@ import 'package:pinball_audio/pinball_audio.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';
import 'package:pinball_theme/pinball_theme.dart' as theme; import 'package:pinball_theme/pinball_theme.dart' as theme;
import 'package:share_repository/share_repository.dart';
class _TestGame extends Forge2DGame { class _TestGame extends Forge2DGame {
@override @override
@ -65,6 +66,8 @@ class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {}
class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { class _MockLeaderboardRepository extends Mock implements LeaderboardRepository {
} }
class _MockShareRepository extends Mock implements ShareRepository {}
class _MockAppLocalizations extends Mock implements AppLocalizations { class _MockAppLocalizations extends Mock implements AppLocalizations {
@override @override
String get score => ''; String get score => '';
@ -149,9 +152,11 @@ void main() {
'changes the backbox display', 'changes the backbox display',
(game) async { (game) async {
final component = GameBlocStatusListener(); final component = GameBlocStatusListener();
final repository = _MockLeaderboardRepository(); final leaderboardRepository = _MockLeaderboardRepository();
final shareRepository = _MockShareRepository();
final backbox = Backbox( final backbox = Backbox(
leaderboardRepository: repository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
entries: const [], entries: const [],
); );
@ -165,9 +170,11 @@ void main() {
'removes FlipperKeyControllingBehavior from Flipper', 'removes FlipperKeyControllingBehavior from Flipper',
(game) async { (game) async {
final component = GameBlocStatusListener(); final component = GameBlocStatusListener();
final repository = _MockLeaderboardRepository(); final leaderboardRepository = _MockLeaderboardRepository();
final shareRepository = _MockShareRepository();
final backbox = Backbox( final backbox = Backbox(
leaderboardRepository: repository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
entries: const [], entries: const [],
); );
final flipper = Flipper.test(side: BoardSide.left); final flipper = Flipper.test(side: BoardSide.left);
@ -193,9 +200,11 @@ void main() {
(game) async { (game) async {
final audioPlayer = _MockPinballAudioPlayer(); final audioPlayer = _MockPinballAudioPlayer();
final component = GameBlocStatusListener(); final component = GameBlocStatusListener();
final repository = _MockLeaderboardRepository(); final leaderboardRepository = _MockLeaderboardRepository();
final shareRepository = _MockShareRepository();
final backbox = Backbox( final backbox = Backbox(
leaderboardRepository: repository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
entries: const [], entries: const [],
); );
await game.pump( await game.pump(
@ -245,9 +254,11 @@ void main() {
'adds key controlling behavior to Flippers when the game is started', 'adds key controlling behavior to Flippers when the game is started',
(game) async { (game) async {
final component = GameBlocStatusListener(); final component = GameBlocStatusListener();
final repository = _MockLeaderboardRepository(); final leaderboardRepository = _MockLeaderboardRepository();
final shareRepository = _MockShareRepository();
final backbox = Backbox( final backbox = Backbox(
leaderboardRepository: repository, leaderboardRepository: leaderboardRepository,
shareRepository: shareRepository,
entries: const [], entries: const [],
); );
final flipper = Flipper.test(side: BoardSide.left); final flipper = Flipper.test(side: BoardSide.left);

@ -16,12 +16,14 @@ import 'package:pinball/game/game.dart';
import 'package:pinball/select_character/select_character.dart'; import 'package:pinball/select_character/select_character.dart';
import 'package:pinball_audio/src/pinball_audio.dart'; import 'package:pinball_audio/src/pinball_audio.dart';
import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/pinball_components.dart';
import 'package:share_repository/share_repository.dart';
class _TestPinballGame extends PinballGame { class _TestPinballGame extends PinballGame {
_TestPinballGame() _TestPinballGame()
: super( : super(
characterThemeBloc: CharacterThemeCubit(), characterThemeBloc: CharacterThemeCubit(),
leaderboardRepository: _MockLeaderboardRepository(), leaderboardRepository: _MockLeaderboardRepository(),
shareRepository: _MockShareRepository(),
gameBloc: GameBloc(), gameBloc: GameBloc(),
l10n: _MockAppLocalizations(), l10n: _MockAppLocalizations(),
audioPlayer: _MockPinballAudioPlayer(), audioPlayer: _MockPinballAudioPlayer(),
@ -41,6 +43,7 @@ class _TestDebugPinballGame extends DebugPinballGame {
: super( : super(
characterThemeBloc: CharacterThemeCubit(), characterThemeBloc: CharacterThemeCubit(),
leaderboardRepository: _MockLeaderboardRepository(), leaderboardRepository: _MockLeaderboardRepository(),
shareRepository: _MockShareRepository(),
gameBloc: GameBloc(), gameBloc: GameBloc(),
l10n: _MockAppLocalizations(), l10n: _MockAppLocalizations(),
audioPlayer: _MockPinballAudioPlayer(), audioPlayer: _MockPinballAudioPlayer(),
@ -81,6 +84,8 @@ class _MockDragEndInfo extends Mock implements DragEndInfo {}
class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { class _MockLeaderboardRepository extends Mock implements LeaderboardRepository {
} }
class _MockShareRepository extends Mock implements ShareRepository {}
class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {}
void main() { void main() {

@ -16,6 +16,7 @@ import 'package:pinball/more_information/more_information.dart';
import 'package:pinball/select_character/select_character.dart'; import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart'; import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
import 'package:share_repository/share_repository.dart';
import '../../helpers/helpers.dart'; import '../../helpers/helpers.dart';
@ -24,6 +25,7 @@ class _TestPinballGame extends PinballGame {
: super( : super(
characterThemeBloc: CharacterThemeCubit(), characterThemeBloc: CharacterThemeCubit(),
leaderboardRepository: _MockLeaderboardRepository(), leaderboardRepository: _MockLeaderboardRepository(),
shareRepository: _MockShareRepository(),
gameBloc: GameBloc(), gameBloc: GameBloc(),
l10n: _MockAppLocalizations(), l10n: _MockAppLocalizations(),
audioPlayer: _MockPinballAudioPlayer(), audioPlayer: _MockPinballAudioPlayer(),
@ -60,6 +62,8 @@ class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {}
class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { class _MockLeaderboardRepository extends Mock implements LeaderboardRepository {
} }
class _MockShareRepository extends Mock implements ShareRepository {}
void main() { void main() {
final game = _TestPinballGame(); final game = _TestPinballGame();

@ -12,12 +12,15 @@ import 'package:pinball/select_character/select_character.dart';
import 'package:pinball/start_game/start_game.dart'; import 'package:pinball/start_game/start_game.dart';
import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_audio/pinball_audio.dart';
import 'package:pinball_ui/pinball_ui.dart'; import 'package:pinball_ui/pinball_ui.dart';
import 'package:share_repository/share_repository.dart';
class _MockAssetsManagerCubit extends Mock implements AssetsManagerCubit {} class _MockAssetsManagerCubit extends Mock implements AssetsManagerCubit {}
class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { class _MockLeaderboardRepository extends Mock implements LeaderboardRepository {
} }
class _MockShareRepository extends Mock implements ShareRepository {}
class _MockCharacterThemeCubit extends Mock implements CharacterThemeCubit {} class _MockCharacterThemeCubit extends Mock implements CharacterThemeCubit {}
class _MockGameBloc extends Mock implements GameBloc {} class _MockGameBloc extends Mock implements GameBloc {}
@ -55,6 +58,7 @@ extension PumpApp on WidgetTester {
AssetsManagerCubit? assetsManagerCubit, AssetsManagerCubit? assetsManagerCubit,
CharacterThemeCubit? characterThemeCubit, CharacterThemeCubit? characterThemeCubit,
LeaderboardRepository? leaderboardRepository, LeaderboardRepository? leaderboardRepository,
ShareRepository? shareRepository,
PinballAudioPlayer? pinballAudioPlayer, PinballAudioPlayer? pinballAudioPlayer,
}) { }) {
return runAsync(() { return runAsync(() {
@ -64,6 +68,9 @@ extension PumpApp on WidgetTester {
RepositoryProvider.value( RepositoryProvider.value(
value: leaderboardRepository ?? _MockLeaderboardRepository(), value: leaderboardRepository ?? _MockLeaderboardRepository(),
), ),
RepositoryProvider.value(
value: shareRepository ?? _MockShareRepository(),
),
RepositoryProvider.value( RepositoryProvider.value(
value: pinballAudioPlayer ?? _buildDefaultPinballAudioPlayer(), value: pinballAudioPlayer ?? _buildDefaultPinballAudioPlayer(),
), ),

Loading…
Cancel
Save