diff --git a/.firebaserc b/.firebaserc deleted file mode 100644 index 46b92aeb..00000000 --- a/.firebaserc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "projects": { - "default": "pinball-dev" - } -} diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 37ec09f9..00000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,3 +0,0 @@ -# Every request must be reviewed and accepted by: - -* @erickzanardo @alestiago @RuiMiguel @allisonryan0002 \ No newline at end of file diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 48ad112c..2a0776dd 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -11,7 +11,7 @@ jobs: uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1 with: flutter_channel: stable - flutter_version: 2.10.5 + flutter_version: 3.22.2 coverage_excludes: "lib/gen/*.dart" test_optimization: false diff --git a/.gitignore b/.gitignore index 2d9c4dbe..f4cd76ff 100644 --- a/.gitignore +++ b/.gitignore @@ -100,12 +100,14 @@ unlinked_spec.ds # Coverage coverage/ +# Golden tests related +**/failures + # Submodules !pubspec.lock packages/**/pubspec.lock # Web related -lib/generated_plugin_registrant.dart # Symbolication related app.*.symbols @@ -128,6 +130,8 @@ app.*.map.json # Firebase related .firebase +firebase.json +lib/firebase_options.dart test/.test_runner.dart web/__/firebase/init.js diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 71c54903..3d0f5d0d 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -15,6 +15,7 @@ "dpad", "endtemplate", "firestore", + "flutterfire", "gapless", "genhtml", "goldens", @@ -22,6 +23,7 @@ "leaderboard", "loadables", "localizable", + "macos", "mixins", "mocktail", "mostrado", @@ -47,4 +49,4 @@ "ignorePaths": [ ".github/workflows/**" ] -} +} \ No newline at end of file diff --git a/README.md b/README.md index 957cb05b..a7b88223 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,17 @@ _Created using [Very Good CLI][very_good_cli_link] 🤖_ ## Getting Started 🚀 +### Firebase +First, please create a Firebase project for development. +After you create your project, remember to activate the following features: + - **Authentication** with the **anonymous** option + - **Firestore** with the rules in firestore.rules. + +Next, use the instructions on [Firebase website](https://firebase.google.com/docs/flutter/setup?platform=web) to set up the **flutterfire_cli**. + +Allow it to override the **lib/firebase_options.dart** file with your project settings. + +### Running locally To run the desired project either use the launch configuration in VSCode/Android Studio or use the following commands: ```sh diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 00000000..e627acdd --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,4 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: + - flame: true \ No newline at end of file diff --git a/firebase.json b/firebase.json deleted file mode 100644 index d2e803bf..00000000 --- a/firebase.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "firestore": { - "rules": "firestore.rules" - }, - "hosting": { - "public": "build/web", - "site": "", - "ignore": ["firebase.json", "**/.*", "**/node_modules/**"], - "headers": [ - { - "source": "**/*.@(jpg|jpeg|gif|png)", - "headers": [ - { - "key": "Cache-Control", - "value": "max-age=3600" - } - ] - }, - { - "source": "**", - "headers": [ - { - "key": "Cache-Control", - "value": "no-cache, no-store, must-revalidate" - } - ] - } - ] - }, - "storage": { - "rules": "storage.rules" - } -} diff --git a/lib/assets_manager/cubit/assets_manager_cubit.dart b/lib/assets_manager/cubit/assets_manager_cubit.dart index 7932f194..f204dc48 100644 --- a/lib/assets_manager/cubit/assets_manager_cubit.dart +++ b/lib/assets_manager/cubit/assets_manager_cubit.dart @@ -19,6 +19,7 @@ class AssetsManagerCubit extends Cubit { /// do its job without adding too much delay for the user, we are letting /// the UI paint first, and then we start loading the assets. await Future.delayed(const Duration(seconds: 1)); + if (isClosed) return; final loadables = Function()>[ _game.preFetchLeaderboard, ..._game.preLoadAssets(), diff --git a/lib/assets_manager/views/assets_loading_page.dart b/lib/assets_manager/views/assets_loading_page.dart index 72476064..114fd3f3 100644 --- a/lib/assets_manager/views/assets_loading_page.dart +++ b/lib/assets_manager/views/assets_loading_page.dart @@ -16,7 +16,7 @@ class AssetsLoadingPage extends StatelessWidget { @override Widget build(BuildContext context) { final l10n = context.l10n; - final headline1 = Theme.of(context).textTheme.headline1; + final displayLarge = Theme.of(context).textTheme.displayLarge; return Container( decoration: const CrtBackground(), child: Center( @@ -30,7 +30,7 @@ class AssetsLoadingPage extends StatelessWidget { const SizedBox(height: 40), AnimatedEllipsisText( l10n.loading, - style: headline1, + style: displayLarge, ), const SizedBox(height: 40), FractionallySizedBox( diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart index f4028ee1..e74b2ac6 100644 --- a/lib/bootstrap.dart +++ b/lib/bootstrap.dart @@ -1,10 +1,6 @@ -import 'dart:async'; import 'dart:developer'; import 'package:bloc/bloc.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/widgets.dart'; class AppBlocObserver extends BlocObserver { @override @@ -19,30 +15,3 @@ class AppBlocObserver extends BlocObserver { super.onError(bloc, error, stackTrace); } } - -typedef BootstrapBuilder = Future Function( - FirebaseFirestore firestore, - FirebaseAuth firebaseAuth, -); - -Future bootstrap(BootstrapBuilder builder) async { - WidgetsFlutterBinding.ensureInitialized(); - FlutterError.onError = (details) { - log(details.exceptionAsString(), stackTrace: details.stack); - }; - - await runZonedGuarded( - () async { - await BlocOverrides.runZoned( - () async => runApp( - await builder( - FirebaseFirestore.instance, - FirebaseAuth.instance, - ), - ), - blocObserver: AppBlocObserver(), - ); - }, - (error, stackTrace) => log(error.toString(), stackTrace: stackTrace), - ); -} diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 00000000..8e0d3e4b --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,63 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + return web; + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for android - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.iOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for ios - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.macOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for macos - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions web = FirebaseOptions( + apiKey: '', + appId: '', + messagingSenderId: '', + projectId: '', + authDomain: '', + storageBucket: '', + ); +} diff --git a/lib/game/behaviors/animatronic_looping_behavior.dart b/lib/game/behaviors/animatronic_looping_behavior.dart index ec741608..61aff738 100644 --- a/lib/game/behaviors/animatronic_looping_behavior.dart +++ b/lib/game/behaviors/animatronic_looping_behavior.dart @@ -1,5 +1,4 @@ import 'package:flame/components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; class AnimatronicLoopingBehavior extends TimerComponent with ParentIsA { @@ -10,8 +9,8 @@ class AnimatronicLoopingBehavior extends TimerComponent @override Future onLoad() async { await super.onLoad(); - parent.animation?.onComplete = () { - parent.animation?.reset(); + parent.animationTicker?.onComplete = () { + parent.animationTicker?.reset(); parent.playing = false; timer ..reset() diff --git a/lib/game/behaviors/camera_focusing_behavior.dart b/lib/game/behaviors/camera_focusing_behavior.dart index 6279f30e..bcf1fa68 100644 --- a/lib/game/behaviors/camera_focusing_behavior.dart +++ b/lib/game/behaviors/camera_focusing_behavior.dart @@ -1,11 +1,10 @@ import 'package:flame/components.dart'; -import 'package:flame/game.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; /// {@template focus_data} -/// Defines a [Camera] focus point. +/// Defines a [CameraComponent] focus point. /// {@endtemplate} class _FocusData { /// {@macro focus_data} @@ -69,16 +68,14 @@ class CameraFocusingBehavior extends Component @override Future onLoad() async { await super.onLoad(); + onGameResize(gameRef.camera.viewport.size); _snap(GameStatus.waiting); } void _snap(GameStatus focusKey) { final focusData = _foci[_activeFocus = focusKey]!; - - gameRef.camera - ..speed = 100 - ..followVector2(focusData.position) - ..zoom = focusData.zoom; + gameRef.camera.moveTo(focusData.position, speed: 100); + gameRef.camera.viewfinder.zoom = focusData.zoom; } void _zoomTo(GameStatus focusKey) { diff --git a/lib/game/components/backbox/backbox.dart b/lib/game/components/backbox/backbox.dart index 4ce44348..070a7190 100644 --- a/lib/game/components/backbox/backbox.dart +++ b/lib/game/components/backbox/backbox.dart @@ -53,7 +53,11 @@ class Backbox extends PositionComponent with ZIndex, HasGameRef { _build(_bloc.state); _subscription = _bloc.stream.listen((state) { - _display.children.removeWhere((_) => true); + final removals = _display.children.map((child) { + _display.remove(child); + return child.removed; + }); + Future.wait(removals); _build(state); }); } diff --git a/lib/game/components/backbox/bloc/backbox_state.dart b/lib/game/components/backbox/bloc/backbox_state.dart index d1025a09..e378c2e8 100644 --- a/lib/game/components/backbox/bloc/backbox_state.dart +++ b/lib/game/components/backbox/bloc/backbox_state.dart @@ -2,7 +2,7 @@ part of 'backbox_bloc.dart'; /// {@template backbox_state} /// The base state for all [BackboxState]. -/// {@endtemplate backbox_state} +/// {@endtemplate} abstract class BackboxState extends Equatable { /// {@macro backbox_state} const BackboxState(); diff --git a/lib/game/components/backbox/displays/game_over_info_display.dart b/lib/game/components/backbox/displays/game_over_info_display.dart index 2db7e20b..57d5d43f 100644 --- a/lib/game/components/backbox/displays/game_over_info_display.dart +++ b/lib/game/components/backbox/displays/game_over_info_display.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flame/components.dart'; -import 'package:flame/input.dart'; +import 'package:flame/events.dart'; import 'package:flutter/material.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball/l10n/l10n.dart'; @@ -164,7 +164,7 @@ class _LinksComponent extends PositionComponent with HasGameRef { /// {@template share_link_component} /// Link button to navigate to sharing score display. /// {@endtemplate} -class ShareLinkComponent extends TextComponent with HasGameRef, Tappable { +class ShareLinkComponent extends TextComponent with HasGameRef, TapCallbacks { /// {@macro share_link_component} ShareLinkComponent({ OnShareTap? onTap, @@ -178,7 +178,7 @@ class ShareLinkComponent extends TextComponent with HasGameRef, Tappable { final OnShareTap? _onTap; @override - bool onTapDown(TapDownInfo info) { + bool onTapDown(TapDownEvent event) { _onTap?.call(); return true; } @@ -202,7 +202,8 @@ class ShareLinkComponent extends TextComponent with HasGameRef, Tappable { /// {@template google_io_link_component} /// Link button to navigate to Google I/O site. /// {@endtemplate} -class GoogleIOLinkComponent extends TextComponent with HasGameRef, Tappable { +class GoogleIOLinkComponent extends TextComponent + with HasGameRef, TapCallbacks { /// {@macro google_io_link_component} GoogleIOLinkComponent() : super( @@ -212,7 +213,7 @@ class GoogleIOLinkComponent extends TextComponent with HasGameRef, Tappable { ); @override - bool onTapUp(TapUpInfo info) { + bool onTapUp(TapUpEvent event) { openLink(ShareRepository.googleIOEvent); return true; } @@ -280,7 +281,8 @@ class _FirebaseTextComponent extends TextComponent with HasGameRef { /// Link text to navigate to Open Source site. /// {@endtemplate} @visibleForTesting -class OpenSourceTextComponent extends TextComponent with HasGameRef, Tappable { +class OpenSourceTextComponent extends TextComponent + with HasGameRef, TapCallbacks { /// {@macro open_source_link_component} OpenSourceTextComponent() : super( @@ -290,7 +292,7 @@ class OpenSourceTextComponent extends TextComponent with HasGameRef, Tappable { ); @override - bool onTapUp(TapUpInfo info) { + bool onTapUp(TapUpEvent event) { openLink(ShareRepository.openSourceCode); return true; } diff --git a/lib/game/components/backbox/displays/leaderboard_display.dart b/lib/game/components/backbox/displays/leaderboard_display.dart index ab418ccc..d2fe584e 100644 --- a/lib/game/components/backbox/displays/leaderboard_display.dart +++ b/lib/game/components/backbox/displays/leaderboard_display.dart @@ -72,7 +72,7 @@ class LeaderboardDisplay extends PositionComponent with HasGameRef { duration: 0.5, curve: Curves.easeIn, ), - )..onFinishCallback = () { + )..onComplete = () { current.removeFromParent(); inactiveArrow.active = true; firstChild()?.add( diff --git a/lib/game/components/backbox/displays/loading_display.dart b/lib/game/components/backbox/displays/loading_display.dart index 6178b940..a720ba48 100644 --- a/lib/game/components/backbox/displays/loading_display.dart +++ b/lib/game/components/backbox/displays/loading_display.dart @@ -18,6 +18,7 @@ final _bodyTextPaint = TextPaint( /// {@endtemplate} class LoadingDisplay extends TextComponent { /// {@template loading_display} + /// {@endtemplate} LoadingDisplay(); late final String _label; diff --git a/lib/game/components/backbox/displays/share_display.dart b/lib/game/components/backbox/displays/share_display.dart index 0bf61e7d..984d877b 100644 --- a/lib/game/components/backbox/displays/share_display.dart +++ b/lib/game/components/backbox/displays/share_display.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flame/components.dart'; -import 'package:flame/input.dart'; +import 'package:flame/events.dart'; import 'package:flutter/material.dart'; import 'package:pinball/l10n/l10n.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -127,7 +127,7 @@ class _SocialNetworksComponent extends PositionComponent with HasGameRef { /// Button for sharing on Facebook. /// {@endtemplate} class FacebookButtonComponent extends SpriteComponent - with HasGameRef, Tappable { + with HasGameRef, TapCallbacks { /// {@macro facebook_button_component} FacebookButtonComponent({ OnSocialShareTap? onTap, @@ -140,7 +140,7 @@ class FacebookButtonComponent extends SpriteComponent final OnSocialShareTap? _onTap; @override - bool onTapUp(TapUpInfo info) { + bool onTapUp(TapUpEvent event) { _onTap?.call(SharePlatform.facebook); return true; } @@ -159,7 +159,8 @@ class FacebookButtonComponent extends SpriteComponent /// {@template twitter_button_component} /// Button for sharing on Twitter. /// {@endtemplate} -class TwitterButtonComponent extends SpriteComponent with HasGameRef, Tappable { +class TwitterButtonComponent extends SpriteComponent + with HasGameRef, TapCallbacks { /// {@macro twitter_button_component} TwitterButtonComponent({ OnSocialShareTap? onTap, @@ -172,7 +173,7 @@ class TwitterButtonComponent extends SpriteComponent with HasGameRef, Tappable { final OnSocialShareTap? _onTap; @override - bool onTapUp(TapUpInfo info) { + bool onTapUp(TapUpEvent event) { _onTap?.call(SharePlatform.twitter); return true; } diff --git a/lib/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior.dart b/lib/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior.dart index 60cd1857..11ccd88a 100644 --- a/lib/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior.dart +++ b/lib/game/components/dino_desert/behaviors/chrome_dino_bonus_behavior.dart @@ -2,7 +2,6 @@ import 'package:flame/components.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// Adds a [GameBonus.dinoChomp] when a [Ball] is chomped by the [ChromeDino]. class ChromeDinoBonusBehavior extends Component diff --git a/lib/game/components/game_bloc_status_listener.dart b/lib/game/components/game_bloc_status_listener.dart index 701c6f48..10bdeead 100644 --- a/lib/game/components/game_bloc_status_listener.dart +++ b/lib/game/components/game_bloc_status_listener.dart @@ -80,21 +80,18 @@ class GameBlocStatusListener extends Component [ PlungerPullingBehavior(strength: 7), PlungerAutoPullingBehavior(), - PlungerKeyControllingBehavior() + PlungerKeyControllingBehavior(), ], ); void _removePlungerBehaviors(Plunger plunger) { - plunger - .descendants() + plunger.children .whereType() .forEach(plunger.remove); - plunger - .descendants() + plunger.children .whereType() .forEach(plunger.remove); - plunger - .descendants() + plunger.children .whereType() .forEach(plunger.remove); } @@ -103,8 +100,7 @@ class GameBlocStatusListener extends Component .firstChild>()! .add(FlipperKeyControllingBehavior()); - void _removeFlipperBehaviors(Flipper flipper) => flipper - .descendants() + void _removeFlipperBehaviors(Flipper flipper) => flipper.children .whereType() .forEach(flipper.remove); } diff --git a/lib/game/components/multiballs/behaviors/multiballs_behavior.dart b/lib/game/components/multiballs/behaviors/multiballs_behavior.dart index 1d3aa16c..8cf7f03a 100644 --- a/lib/game/components/multiballs/behaviors/multiballs_behavior.dart +++ b/lib/game/components/multiballs/behaviors/multiballs_behavior.dart @@ -2,7 +2,6 @@ import 'package:flame/components.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// Toggle each [Multiball] when there is a bonus ball. class MultiballsBehavior extends Component diff --git a/lib/game/components/multipliers/behaviors/multipliers_behavior.dart b/lib/game/components/multipliers/behaviors/multipliers_behavior.dart index ce58a8eb..fbea6c3c 100644 --- a/lib/game/components/multipliers/behaviors/multipliers_behavior.dart +++ b/lib/game/components/multipliers/behaviors/multipliers_behavior.dart @@ -2,7 +2,6 @@ import 'package:flame/components.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// Toggle each [Multiplier] when GameState.multiplier changes. class MultipliersBehavior extends Component diff --git a/lib/game/components/sparky_scorch/behaviors/sparky_computer_bonus_behavior.dart b/lib/game/components/sparky_scorch/behaviors/sparky_computer_bonus_behavior.dart index 3cd2fc0b..15fbf068 100644 --- a/lib/game/components/sparky_scorch/behaviors/sparky_computer_bonus_behavior.dart +++ b/lib/game/components/sparky_scorch/behaviors/sparky_computer_bonus_behavior.dart @@ -2,7 +2,6 @@ import 'package:flame/components.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// Adds a [GameBonus.sparkyTurboCharge] when a [Ball] enters the /// [SparkyComputer]. diff --git a/lib/game/pinball_game.dart b/lib/game/pinball_game.dart index 2b003207..d6b43702 100644 --- a/lib/game/pinball_game.dart +++ b/lib/game/pinball_game.dart @@ -1,9 +1,10 @@ import 'dart:async'; import 'package:flame/components.dart'; -import 'package:flame/game.dart'; +import 'package:flame/events.dart'; import 'package:flame/input.dart'; import 'package:flame_bloc/flame_bloc.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:leaderboard_repository/leaderboard_repository.dart'; @@ -17,8 +18,8 @@ import 'package:pinball_flame/pinball_flame.dart'; import 'package:platform_helper/platform_helper.dart'; import 'package:share_repository/share_repository.dart'; -class PinballGame extends PinballForge2DGame - with HasKeyboardHandlerComponents, MultiTouchTapDetector, HasTappables { +class PinballGame extends Forge2DGame + with HasKeyboardHandlerComponents, MultiTouchTapDetector { PinballGame({ required CharacterThemeCubit characterThemeBloc, required this.leaderboardRepository, @@ -32,9 +33,7 @@ class PinballGame extends PinballForge2DGame _audioPlayer = audioPlayer, _characterThemeBloc = characterThemeBloc, _l10n = l10n, - super( - gravity: Vector2(0, 30), - ) { + super(gravity: Vector2(0, 30)) { images.prefix = ''; } @@ -80,7 +79,7 @@ class PinballGame extends PinballForge2DGame @override Future onLoad() async { - await add( + await world.add( FlameMultiBlocProvider( providers: [ FlameBlocProvider.value( @@ -147,7 +146,6 @@ class PinballGame extends PinballForge2DGame ], ), ); - await super.onLoad(); } @@ -160,7 +158,8 @@ class PinballGame extends PinballForge2DGame final rocket = descendants().whereType().first; final bounds = rocket.topLeftPosition & rocket.size; - final tappedRocket = bounds.contains(info.eventPosition.game.toOffset()); + final tappedRocket = + bounds.contains(screenToWorld(info.eventPosition.widget).toOffset()); if (tappedRocket) { descendants() .whereType>() @@ -213,7 +212,7 @@ class PinballGame extends PinballForge2DGame } } -class DebugPinballGame extends PinballGame with FPSCounter, PanDetector { +class DebugPinballGame extends PinballGame with PanDetector { DebugPinballGame({ required CharacterThemeCubit characterThemeBloc, required LeaderboardRepository leaderboardRepository, @@ -239,6 +238,7 @@ class DebugPinballGame extends PinballGame with FPSCounter, PanDetector { Future onLoad() async { await super.onLoad(); await addAll([PreviewLine(), _DebugInformation()]); + camera.viewfinder.zoom = 50; } @override @@ -247,16 +247,21 @@ class DebugPinballGame extends PinballGame with FPSCounter, PanDetector { if (info.raw.kind == PointerDeviceKind.mouse) { final canvas = descendants().whereType().single; - final ball = Ball()..initialPosition = info.eventPosition.game; + final ball = Ball() + ..initialPosition = screenToWorld(info.eventPosition.widget) + ..zIndex = ZIndexes.ballOnBoard; canvas.add(ball); + world.add(ball); } } @override - void onPanStart(DragStartInfo info) => lineStart = info.eventPosition.game; + void onPanStart(DragStartInfo info) => + lineStart = screenToWorld(info.eventPosition.widget); @override - void onPanUpdate(DragUpdateInfo info) => lineEnd = info.eventPosition.game; + void onPanUpdate(DragUpdateInfo info) => + lineEnd = screenToWorld(info.eventPosition.widget); @override void onPanEnd(DragEndInfo info) { @@ -274,6 +279,8 @@ class DebugPinballGame extends PinballGame with FPSCounter, PanDetector { final impulse = line * -1 * 10; ball.add(BallTurboChargingBehavior(impulse: impulse)); canvas.add(ball); + add(ball); + world.add(ball); } } @@ -299,9 +306,6 @@ class PreviewLine extends PositionComponent with HasGameRef { } class _DebugInformation extends Component with HasGameRef { - @override - PositionType get positionType => PositionType.widget; - final _debugTextPaint = TextPaint( style: const TextStyle( color: Colors.green, @@ -314,14 +318,14 @@ class _DebugInformation extends Component with HasGameRef { @override void render(Canvas canvas) { final debugText = [ - 'FPS: ${gameRef.fps().toStringAsFixed(1)}', + // 'FPS: ${gameRef.fps().toStringAsFixed(1)}', 'BALLS: ${gameRef.descendants().whereType().length}', ].join(' | '); - final height = _debugTextPaint.measureTextHeight(debugText); - final position = Vector2(0, gameRef.camera.canvasSize.y - height); + final height = _debugTextPaint.getLineMetrics(debugText).height; + final position = Vector2(0, gameRef.camera.viewport.size.y - height); canvas.drawRect( - position & Vector2(gameRef.camera.canvasSize.x, height), + position & Vector2(gameRef.camera.viewport.size.x, height), _debugBackgroundPaint, ); _debugTextPaint.render(canvas, debugText, position); diff --git a/lib/game/view/pinball_game_page.dart b/lib/game/view/pinball_game_page.dart index 06fde72d..2db6bdd1 100644 --- a/lib/game/view/pinball_game_page.dart +++ b/lib/game/view/pinball_game_page.dart @@ -118,7 +118,7 @@ class PinballGameLoadedView extends StatelessWidget { right: 0, left: 0, child: ReplayButtonOverlay(), - ) + ), }, ), ), diff --git a/lib/game/view/widgets/bonus_animation.dart b/lib/game/view/widgets/bonus_animation.dart index a52aafc0..bfb9c439 100644 --- a/lib/game/view/widgets/bonus_animation.dart +++ b/lib/game/view/widgets/bonus_animation.dart @@ -93,6 +93,7 @@ class _BonusAnimationState extends State with TickerProviderStateMixin { late SpriteAnimationController controller; late SpriteAnimation animation; + late SpriteAnimationTicker animationTicker; bool shouldRunBuildCallback = true; @override @@ -110,7 +111,7 @@ class _BonusAnimationState extends State shouldRunBuildCallback = oldWidget._imagePath == widget._imagePath; Future.delayed( - Duration(seconds: animation.totalDuration().ceil()), + Duration(seconds: duration()), () { widget._onCompleted?.call(); }, @@ -119,6 +120,10 @@ class _BonusAnimationState extends State super.didUpdateWidget(oldWidget); } + int duration() { + return animationTicker.totalDuration().ceil(); + } + @override Widget build(BuildContext context) { final spriteSheet = SpriteSheet.fromColumnsAndRows( @@ -132,9 +137,10 @@ class _BonusAnimationState extends State to: spriteSheet.rows * spriteSheet.columns, loop: false, ); + animationTicker = animation.createTicker(); Future.delayed( - Duration(seconds: animation.totalDuration().ceil()), + Duration(seconds: duration()), () { if (shouldRunBuildCallback) { widget._onCompleted?.call(); @@ -144,6 +150,7 @@ class _BonusAnimationState extends State controller = SpriteAnimationController( animation: animation, + animationTicker: animationTicker, vsync: this, )..forward(); diff --git a/lib/game/view/widgets/game_hud.dart b/lib/game/view/widgets/game_hud.dart index 5f651a60..f65d1449 100644 --- a/lib/game/view/widgets/game_hud.dart +++ b/lib/game/view/widgets/game_hud.dart @@ -22,7 +22,7 @@ class _GameHudState extends State { bool showAnimation = false; /// Ratio from sprite frame (width 500, height 144) w / h = ratio - static const _ratio = 3.47; + static const _ratio = 3.47222222222; @override Widget build(BuildContext context) { @@ -34,7 +34,7 @@ class _GameHudState extends State { return _ScoreViewDecoration( child: SizedBox( height: height, - width: height * _ratio, + width: (height * _ratio) + 16, child: BlocListener( listenWhen: (previous, current) => previous.bonusHistory.length != current.bonusHistory.length, diff --git a/lib/game/view/widgets/mobile_dpad.dart b/lib/game/view/widgets/mobile_dpad.dart index abad496b..e7d3a29b 100644 --- a/lib/game/view/widgets/mobile_dpad.dart +++ b/lib/game/view/widgets/mobile_dpad.dart @@ -6,6 +6,7 @@ import 'package:pinball_ui/pinball_ui.dart'; /// {@endtemplate} class MobileDpad extends StatelessWidget { /// {@template mobile_dpad} + /// {@endtemplate} const MobileDpad({ Key? key, required this.onTapUp, diff --git a/lib/game/view/widgets/round_count_display.dart b/lib/game/view/widgets/round_count_display.dart index 63e1fa43..8e899edf 100644 --- a/lib/game/view/widgets/round_count_display.dart +++ b/lib/game/view/widgets/round_count_display.dart @@ -20,7 +20,7 @@ class RoundCountDisplay extends StatelessWidget { children: [ Text( l10n.rounds, - style: Theme.of(context).textTheme.subtitle1, + style: Theme.of(context).textTheme.displayLarge, ), const SizedBox(width: 8), Row( diff --git a/lib/game/view/widgets/score_view.dart b/lib/game/view/widgets/score_view.dart index 2d6c72d0..f8207ebb 100644 --- a/lib/game/view/widgets/score_view.dart +++ b/lib/game/view/widgets/score_view.dart @@ -39,7 +39,7 @@ class _GameOver extends StatelessWidget { return Text( l10n.gameOver, - style: Theme.of(context).textTheme.headline1, + style: Theme.of(context).textTheme.displayLarge, ); } } @@ -60,7 +60,7 @@ class _ScoreDisplay extends StatelessWidget { children: [ Text( l10n.score.toLowerCase(), - style: Theme.of(context).textTheme.subtitle1, + style: Theme.of(context).textTheme.titleMedium, ), const _ScoreText(), const RoundCountDisplay(), @@ -81,7 +81,7 @@ class _ScoreText extends StatelessWidget { return Text( score.formatScore(), - style: Theme.of(context).textTheme.headline1, + style: Theme.of(context).textTheme.displayLarge, ); } } diff --git a/lib/how_to_play/widgets/how_to_play_dialog.dart b/lib/how_to_play/widgets/how_to_play_dialog.dart index 6c8c3f13..2a2bfe81 100644 --- a/lib/how_to_play/widgets/how_to_play_dialog.dart +++ b/lib/how_to_play/widgets/how_to_play_dialog.dart @@ -85,13 +85,12 @@ class _HowToPlayDialogState extends State { final isMobile = context.read().isMobile; final l10n = context.l10n; - return WillPopScope( - onWillPop: () { + return PopScope( + onPopInvoked: (_) { widget.onDismissCallback.call(); context .read() .play(PinballAudio.ioPinballVoiceOver); - return Future.value(true); }, child: PinballDialog( title: l10n.howToPlay, @@ -132,20 +131,20 @@ class _MobileLaunchControls extends StatelessWidget { @override Widget build(BuildContext context) { final l10n = context.l10n; - final headline3 = Theme.of(context) + final displaySmall = Theme.of(context) .textTheme - .headline3! + .displaySmall! .copyWith(color: PinballColors.white); return Column( children: [ - Text(l10n.tapAndHoldRocket, style: headline3), + Text(l10n.tapAndHoldRocket, style: displaySmall), Text.rich( TextSpan( children: [ - TextSpan(text: '${l10n.to} ', style: headline3), + TextSpan(text: '${l10n.to} ', style: displaySmall), TextSpan( text: l10n.launch, - style: headline3.copyWith(color: PinballColors.blue), + style: displaySmall.copyWith(color: PinballColors.blue), ), ], ), @@ -163,7 +162,7 @@ class _MobileFlipperControls extends StatelessWidget { final l10n = context.l10n; final headline3 = Theme.of(context) .textTheme - .headline3! + .displaySmall! .copyWith(color: PinballColors.white); return Column( children: [ @@ -189,10 +188,10 @@ class _DesktopBody extends StatelessWidget { @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(16), + return const Padding( + padding: EdgeInsets.all(16), child: Column( - children: const [ + children: [ _DesktopLaunchControls(), SizedBox(height: 16), _DesktopFlipperControls(), @@ -212,18 +211,18 @@ class _DesktopLaunchControls extends StatelessWidget { children: [ Text( l10n.launchControls, - style: Theme.of(context).textTheme.headline4, + style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox(height: 10), - Wrap( - children: const [ + const Wrap( + children: [ _KeyButton(control: Control.down), SizedBox(width: 10), _KeyButton(control: Control.space), SizedBox(width: 10), _KeyButton(control: Control.s), ], - ) + ), ], ); } @@ -239,30 +238,30 @@ class _DesktopFlipperControls extends StatelessWidget { children: [ Text( l10n.flipperControls, - style: Theme.of(context).textTheme.headline4, + style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox(height: 10), - Column( + const Column( children: [ Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, - children: const [ + children: [ _KeyButton(control: Control.left), SizedBox(width: 20), _KeyButton(control: Control.right), ], ), - const SizedBox(height: 8), + SizedBox(height: 8), Wrap( - children: const [ + children: [ _KeyButton(control: Control.a), SizedBox(width: 20), _KeyButton(control: Control.d), ], - ) + ), ], - ) + ), ], ); } @@ -277,7 +276,7 @@ class _KeyButton extends StatelessWidget { Widget build(BuildContext context) { final textTheme = Theme.of(context).textTheme; final textStyle = - control.isArrow ? textTheme.headline1 : textTheme.headline3; + control.isArrow ? textTheme.displayLarge : textTheme.displaySmall; const height = 60.0; final width = control.isSpace ? height * 2.83 : height; return DecoratedBox( diff --git a/lib/main.dart b/lib/main.dart index 11bf35aa..3e8643da 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,28 +1,41 @@ +import 'dart:async'; + import 'package:authentication_repository/authentication_repository.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:leaderboard_repository/leaderboard_repository.dart'; import 'package:pinball/app/app.dart'; import 'package:pinball/bootstrap.dart'; +import 'package:pinball/firebase_options.dart'; import 'package:pinball_audio/pinball_audio.dart'; import 'package:platform_helper/platform_helper.dart'; import 'package:share_repository/share_repository.dart'; -void main() { - bootstrap((firestore, firebaseAuth) async { - final leaderboardRepository = LeaderboardRepository(firestore); - const shareRepository = - ShareRepository(appUrl: ShareRepository.pinballGameUrl); - final authenticationRepository = AuthenticationRepository(firebaseAuth); - final pinballAudioPlayer = PinballAudioPlayer(); - final platformHelper = PlatformHelper(); - await Firebase.initializeApp(); - await authenticationRepository.authenticateAnonymously(); - return App( - authenticationRepository: authenticationRepository, - leaderboardRepository: leaderboardRepository, - shareRepository: shareRepository, - pinballAudioPlayer: pinballAudioPlayer, - platformHelper: platformHelper, - ); - }); +Future bootstrap() async { + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + final leaderboardRepository = + LeaderboardRepository(FirebaseFirestore.instance); + const shareRepository = + ShareRepository(appUrl: ShareRepository.pinballGameUrl); + final authenticationRepository = + AuthenticationRepository(FirebaseAuth.instance); + final pinballAudioPlayer = PinballAudioPlayer(); + final platformHelper = PlatformHelper(); + await authenticationRepository.authenticateAnonymously(); + return App( + authenticationRepository: authenticationRepository, + leaderboardRepository: leaderboardRepository, + shareRepository: shareRepository, + pinballAudioPlayer: pinballAudioPlayer, + platformHelper: platformHelper, + ); +} + +void main() async { + Bloc.observer = AppBlocObserver(); + runApp(await bootstrap()); } diff --git a/lib/more_information/more_information_dialog.dart b/lib/more_information/more_information_dialog.dart index ca04db4e..e45b9cd5 100644 --- a/lib/more_information/more_information_dialog.dart +++ b/lib/more_information/more_information_dialog.dart @@ -10,7 +10,6 @@ Future showMoreInformationDialog(BuildContext context) { return showDialog( context: context, barrierColor: PinballColors.transparent, - barrierDismissible: true, builder: (_) { return Center( child: SizedBox( @@ -32,11 +31,11 @@ class MoreInformationDialog extends StatelessWidget { @override Widget build(BuildContext context) { - return Material( + return const Material( color: PinballColors.transparent, child: _LinkBoxDecoration( child: Column( - children: const [ + children: [ SizedBox(height: 16), _LinkBoxHeader(), Expanded( @@ -59,7 +58,7 @@ class _LinkBoxHeader extends StatelessWidget { children: [ Text( l10n.linkBoxTitle, - style: Theme.of(context).textTheme.headline3!.copyWith( + style: Theme.of(context).textTheme.displaySmall!.copyWith( color: PinballColors.blue, fontWeight: FontWeight.bold, ), @@ -77,9 +76,8 @@ class _LinkBoxHeader extends StatelessWidget { class _LinkBoxDecoration extends StatelessWidget { const _LinkBoxDecoration({ - Key? key, required this.child, - }) : super(key: key); + }); final Widget child; @@ -156,7 +154,7 @@ class _TextLink extends StatelessWidget { onTap: () => openLink(link), child: Text( text, - style: theme.textTheme.headline5!.copyWith( + style: theme.textTheme.headlineSmall!.copyWith( color: PinballColors.white, ), overflow: TextOverflow.ellipsis, @@ -176,7 +174,8 @@ class _MadeWithFlutterAndFirebase extends StatelessWidget { textAlign: TextAlign.center, text: TextSpan( text: l10n.linkBoxMadeWithText, - style: theme.textTheme.headline5!.copyWith(color: PinballColors.white), + style: + theme.textTheme.headlineSmall!.copyWith(color: PinballColors.white), children: [ TextSpan( text: l10n.linkBoxFlutterLinkText, @@ -191,7 +190,7 @@ class _MadeWithFlutterAndFirebase extends StatelessWidget { text: l10n.linkBoxFirebaseLinkText, recognizer: TapGestureRecognizer() ..onTap = () => openLink(_MoreInformationUrl.firebaseWebsite), - style: theme.textTheme.headline5!.copyWith( + style: theme.textTheme.headlineSmall!.copyWith( decoration: TextDecoration.underline, ), ), diff --git a/lib/select_character/view/character_selection_page.dart b/lib/select_character/view/character_selection_page.dart index 5504459f..c6e9da26 100644 --- a/lib/select_character/view/character_selection_page.dart +++ b/lib/select_character/view/character_selection_page.dart @@ -8,7 +8,7 @@ import 'package:pinball_ui/pinball_ui.dart'; /// {@template character_selection_dialog} /// Dialog used to select the playing character of the game. -/// {@endtemplate character_selection_dialog} +/// {@endtemplate} class CharacterSelectionDialog extends StatelessWidget { /// {@macro character_selection_dialog} const CharacterSelectionDialog({Key? key}) : super(key: key); @@ -137,7 +137,7 @@ class _Character extends StatelessWidget { onPressed: () => context.read().characterSelected(character), style: ButtonStyle( - overlayColor: MaterialStateProperty.all( + overlayColor: WidgetStateProperty.all( PinballColors.transparent, ), ), diff --git a/lib/select_character/view/selected_character.dart b/lib/select_character/view/selected_character.dart index ed95297f..5e3107b4 100644 --- a/lib/select_character/view/selected_character.dart +++ b/lib/select_character/view/selected_character.dart @@ -60,7 +60,7 @@ class _SelectedCharacterState extends State children: [ Text( widget.currentCharacter.name, - style: Theme.of(context).textTheme.headline2, + style: Theme.of(context).textTheme.displayMedium, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, ), @@ -95,7 +95,11 @@ class _SelectedCharacterState extends State to: spriteSheet.rows * spriteSheet.columns, ); if (_controller != null) _controller?.dispose(); - _controller = SpriteAnimationController(vsync: this, animation: animation) + _controller = SpriteAnimationController( + vsync: this, + animation: animation, + animationTicker: animation.createTicker(), + ) ..forward() ..repeat(); } diff --git a/packages/authentication_repository/pubspec.yaml b/packages/authentication_repository/pubspec.yaml index bac20507..ff5c6de4 100644 --- a/packages/authentication_repository/pubspec.yaml +++ b/packages/authentication_repository/pubspec.yaml @@ -4,15 +4,17 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dependencies: - firebase_auth: ^3.3.16 + firebase_auth: ^5.1.1 + firebase_core: ^3.1.1 flutter: sdk: flutter + intl: ^0.19.0 dev_dependencies: flutter_test: sdk: flutter - mocktail: ^0.2.0 - very_good_analysis: ^2.4.0 \ No newline at end of file + mocktail: ^1.0.4 + very_good_analysis: ^6.0.0 \ No newline at end of file diff --git a/packages/geometry/pubspec.yaml b/packages/geometry/pubspec.yaml index da305129..47f031c8 100644 --- a/packages/geometry/pubspec.yaml +++ b/packages/geometry/pubspec.yaml @@ -4,12 +4,12 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dependencies: vector_math: ^2.1.1 dev_dependencies: - mocktail: ^0.2.0 + mocktail: ^1.0.3 test: ^1.19.2 - very_good_analysis: ^2.4.0 + very_good_analysis: ^6.0.0 diff --git a/packages/leaderboard_repository/pubspec.yaml b/packages/leaderboard_repository/pubspec.yaml index 1d3869f4..b0aff1d6 100644 --- a/packages/leaderboard_repository/pubspec.yaml +++ b/packages/leaderboard_repository/pubspec.yaml @@ -4,20 +4,20 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dependencies: - cloud_firestore: ^3.1.10 + cloud_firestore: ^5.0.2 equatable: ^2.0.3 flutter: sdk: flutter json_annotation: ^4.4.0 dev_dependencies: - build_runner: ^2.1.8 + build_runner: ^2.4.11 flutter_test: sdk: flutter json_serializable: ^6.1.5 - mocktail: ^0.2.0 - test: ^1.19.2 - very_good_analysis: ^2.4.0 \ No newline at end of file + mocktail: ^1.0.4 + test: ^1.25.2 + very_good_analysis: ^6.0.0 \ No newline at end of file diff --git a/packages/leaderboard_repository/test/src/leaderboard_repository_test.dart b/packages/leaderboard_repository/test/src/leaderboard_repository_test.dart index 89984c5b..8214da1d 100644 --- a/packages/leaderboard_repository/test/src/leaderboard_repository_test.dart +++ b/packages/leaderboard_repository/test/src/leaderboard_repository_test.dart @@ -75,7 +75,7 @@ void main() { when(queryDocumentSnapshot.data).thenReturn({ 'character': 'dash', 'playerInitials': 'user$score', - 'score': score + 'score': score, }); return queryDocumentSnapshot; }).toList(); @@ -162,7 +162,7 @@ void main() { when(queryDocumentSnapshot.data).thenReturn({ 'character': 'dash', 'playerInitials': 'AAA', - 'score': score + 'score': score, }); when(() => queryDocumentSnapshot.id).thenReturn('id$score'); return queryDocumentSnapshot; @@ -222,14 +222,14 @@ void main() { 6500, 6000, 5500, - 5000 + 5000, ]; final queryDocumentSnapshots = leaderboardScores.map((score) { final queryDocumentSnapshot = _MockQueryDocumentSnapshot(); when(queryDocumentSnapshot.data).thenReturn({ 'character': 'dash', 'playerInitials': 'AAA', - 'score': score + 'score': score, }); when(() => queryDocumentSnapshot.id).thenReturn('id$score'); return queryDocumentSnapshot; @@ -269,7 +269,7 @@ void main() { when(queryDocumentSnapshot.data).thenReturn({ 'character': 'dash', 'playerInitials': 'AAA', - 'score': score + 'score': score, }); when(() => queryDocumentSnapshot.id).thenReturn('id$score'); when(() => queryDocumentSnapshot.reference) diff --git a/packages/pinball_audio/lib/src/pinball_audio.dart b/packages/pinball_audio/lib/src/pinball_audio.dart index 4a3d04d8..34933c3a 100644 --- a/packages/pinball_audio/lib/src/pinball_audio.dart +++ b/packages/pinball_audio/lib/src/pinball_audio.dart @@ -1,8 +1,6 @@ import 'dart:math'; -import 'package:audioplayers/audioplayers.dart'; import 'package:clock/clock.dart'; -import 'package:flame_audio/audio_pool.dart'; import 'package:flame_audio/flame_audio.dart'; import 'package:flutter/material.dart'; import 'package:pinball_audio/gen/assets.gen.dart'; @@ -53,12 +51,11 @@ enum PinballAudio { } /// Defines the contract of the creation of an [AudioPool]. -typedef CreateAudioPool = Future Function( - String sound, { - bool? repeating, - int? maxPlayers, - int? minPlayers, - String? prefix, +typedef CreateAudioPool = Future Function({ + required Source source, + required int maxPlayers, + AudioCache? audioCache, + int minPlayers, }); /// Defines the contract for playing a single audio. @@ -165,9 +162,8 @@ class _SingleAudioPool extends _Audio { @override Future load() async { pool = await createAudioPool( - prefixFile(path), + source: DeviceFileSource(prefixFile(path), mimeType: 'audio/mpeg'), maxPlayers: maxPlayers, - prefix: '', ); } @@ -198,14 +194,14 @@ class _RandomABAudio extends _Audio { await Future.wait( [ createAudioPool( - prefixFile(audioAssetA), + source: + DeviceFileSource(prefixFile(audioAssetA), mimeType: 'audio/mpeg'), maxPlayers: 4, - prefix: '', ).then((pool) => audioA = pool), createAudioPool( - prefixFile(audioAssetB), + source: + DeviceFileSource(prefixFile(audioAssetB), mimeType: 'audio/mpeg'), maxPlayers: 4, - prefix: '', ).then((pool) => audioB = pool), ], ); @@ -259,8 +255,8 @@ class PinballAudioPlayer { ConfigureAudioCache? configureAudioCache, Random? seed, }) : _createAudioPool = createAudioPool ?? AudioPool.create, - _playSingleAudio = playSingleAudio ?? FlameAudio.audioCache.play, - _loopSingleAudio = loopSingleAudio ?? FlameAudio.audioCache.loop, + _playSingleAudio = playSingleAudio ?? FlameAudio.play, + _loopSingleAudio = loopSingleAudio ?? FlameAudio.loop, _preCacheSingleAudio = preCacheSingleAudio ?? FlameAudio.audioCache.load, _configureAudioCache = configureAudioCache ?? diff --git a/packages/pinball_audio/pubspec.yaml b/packages/pinball_audio/pubspec.yaml index 8c99d1fc..da444297 100644 --- a/packages/pinball_audio/pubspec.yaml +++ b/packages/pinball_audio/pubspec.yaml @@ -4,20 +4,21 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dependencies: - audioplayers: ^0.20.1 + audioplayers: ^6.0.0 clock: ^1.1.0 - flame_audio: ^1.0.1 + equatable: ^2.0.3 + flame_audio: ^2.10.2 flutter: sdk: flutter dev_dependencies: flutter_test: sdk: flutter - mocktail: ^0.3.0 - very_good_analysis: ^2.4.0 + mocktail: ^1.0.4 + very_good_analysis: ^6.0.0 flutter_gen: line_length: 80 diff --git a/packages/pinball_audio/test/src/pinball_audio_test.dart b/packages/pinball_audio/test/src/pinball_audio_test.dart index 1c82815d..25fb5f9a 100644 --- a/packages/pinball_audio/test/src/pinball_audio_test.dart +++ b/packages/pinball_audio/test/src/pinball_audio_test.dart @@ -1,9 +1,7 @@ // ignore_for_file: prefer_const_constructors, one_member_abstracts import 'dart:math'; -import 'package:audioplayers/audioplayers.dart'; import 'package:clock/clock.dart'; -import 'package:flame_audio/audio_pool.dart'; import 'package:flame_audio/flame_audio.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -15,12 +13,11 @@ class _MockAudioPool extends Mock implements AudioPool {} class _MockAudioCache extends Mock implements AudioCache {} class _MockCreateAudioPool extends Mock { - Future onCall( - String sound, { - bool? repeating, - int? maxPlayers, + Future onCall({ + Source source, + int maxPlayers, + AudioCache? audioCache, int? minPlayers, - String? prefix, }); } @@ -46,6 +43,20 @@ class _MockRandom extends Mock implements Random {} class _MockClock extends Mock implements Clock {} +class SourceMatcher extends Matcher { + SourceMatcher(this.path); + + final String path; + + @override + bool matches(dynamic item, Map matchState) => + (item as DeviceFileSource).path == path; + + @override + Description describe(Description description) => + description.add('Expected: $path'); +} + void main() { group('PinballAudio', () { late _MockCreateAudioPool createAudioPool; @@ -58,15 +69,15 @@ void main() { setUpAll(() { registerFallbackValue(_MockAudioCache()); + registerFallbackValue(DeviceFileSource('/packages/pinball_audio')); }); setUp(() { createAudioPool = _MockCreateAudioPool(); when( () => createAudioPool.onCall( - any(), + source: any(named: 'source'), maxPlayers: any(named: 'maxPlayers'), - prefix: any(named: 'prefix'), ), ).thenAnswer((_) async => _MockAudioPool()); @@ -108,17 +119,23 @@ void main() { verify( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.bumperA}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.kickerA}'), + ), maxPlayers: 4, - prefix: '', ), ).called(1); verify( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.bumperB}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.kickerB}'), + ), maxPlayers: 4, - prefix: '', ), ).called(1); }); @@ -130,17 +147,23 @@ void main() { verify( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.kickerA}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.kickerA}'), + ), maxPlayers: 4, - prefix: '', ), ).called(1); verify( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.kickerB}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.kickerB}'), + ), maxPlayers: 4, - prefix: '', ), ).called(1); }); @@ -152,9 +175,12 @@ void main() { verify( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.flipper}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.flipper}'), + ), maxPlayers: 2, - prefix: '', ), ).called(1); }); @@ -242,23 +268,29 @@ void main() { setUp(() { bumperAPool = _MockAudioPool(); when(() => bumperAPool.start(volume: any(named: 'volume'))) - .thenAnswer((_) async => () {}); + .thenAnswer((_) async => () => Future.new(() {})); when( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.bumperA}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.bumperA}'), + ), maxPlayers: any(named: 'maxPlayers'), - prefix: any(named: 'prefix'), ), ).thenAnswer((_) async => bumperAPool); bumperBPool = _MockAudioPool(); when(() => bumperBPool.start(volume: any(named: 'volume'))) - .thenAnswer((_) async => () {}); + .thenAnswer((_) async => () => Future.new(() {})); when( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.bumperB}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.bumperB}'), + ), maxPlayers: any(named: 'maxPlayers'), - prefix: any(named: 'prefix'), ), ).thenAnswer((_) async => bumperBPool); }); @@ -295,23 +327,29 @@ void main() { setUp(() { kickerAPool = _MockAudioPool(); when(() => kickerAPool.start(volume: any(named: 'volume'))) - .thenAnswer((_) async => () {}); + .thenAnswer((_) async => () => Future.new(() {})); when( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.kickerA}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.kickerA}'), + ), maxPlayers: any(named: 'maxPlayers'), - prefix: any(named: 'prefix'), ), ).thenAnswer((_) async => kickerAPool); kickerBPool = _MockAudioPool(); when(() => kickerBPool.start(volume: any(named: 'volume'))) - .thenAnswer((_) async => () {}); + .thenAnswer((_) async => () => Future.new(() {})); when( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.kickerB}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.kickerB}'), + ), maxPlayers: any(named: 'maxPlayers'), - prefix: any(named: 'prefix'), ), ).thenAnswer((_) async => kickerBPool); }); @@ -347,12 +385,15 @@ void main() { setUp(() { pool = _MockAudioPool(); when(() => pool.start(volume: any(named: 'volume'))) - .thenAnswer((_) async => () {}); + .thenAnswer((_) async => () => Future.new(() {})); when( () => createAudioPool.onCall( - 'packages/pinball_audio/${Assets.sfx.flipper}', + source: any( + named: 'source', + that: + SourceMatcher('packages/pinball_audio/${Assets.sfx.flipper}'), + ), maxPlayers: any(named: 'maxPlayers'), - prefix: any(named: 'prefix'), ), ).thenAnswer((_) async => pool); }); diff --git a/packages/pinball_components/lib/src/components/android_bumper/behaviors/android_bumper_blinking_behavior.dart b/packages/pinball_components/lib/src/components/android_bumper/behaviors/android_bumper_blinking_behavior.dart index 4f7dc135..4c5068bc 100644 --- a/packages/pinball_components/lib/src/components/android_bumper/behaviors/android_bumper_blinking_behavior.dart +++ b/packages/pinball_components/lib/src/components/android_bumper/behaviors/android_bumper_blinking_behavior.dart @@ -1,6 +1,5 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// {@template android_bumper_blinking_behavior} /// Makes an [AndroidBumper] blink back to [AndroidBumperState.lit] when diff --git a/packages/pinball_components/lib/src/components/arcade_background/arcade_background.dart b/packages/pinball_components/lib/src/components/arcade_background/arcade_background.dart index e9936367..9dd37bbc 100644 --- a/packages/pinball_components/lib/src/components/arcade_background/arcade_background.dart +++ b/packages/pinball_components/lib/src/components/arcade_background/arcade_background.dart @@ -25,7 +25,7 @@ class ArcadeBackground extends Component with ZIndex { ArcadeBackgroundState>.value( value: bloc, children: [ArcadeBackgroundSpriteComponent(assetPath: assetPath)], - ) + ), ], ) { zIndex = ZIndexes.arcadeBackground; @@ -45,7 +45,7 @@ class ArcadeBackground extends Component with ZIndex { ArcadeBackgroundState>.value( value: bloc ?? ArcadeBackgroundCubit(), children: [ArcadeBackgroundSpriteComponent(assetPath: assetPath)], - ) + ), ], ); diff --git a/packages/pinball_components/lib/src/components/arrow_icon.dart b/packages/pinball_components/lib/src/components/arrow_icon.dart index 0dc33b10..0dcc9e22 100644 --- a/packages/pinball_components/lib/src/components/arrow_icon.dart +++ b/packages/pinball_components/lib/src/components/arrow_icon.dart @@ -1,5 +1,5 @@ import 'package:flame/components.dart'; -import 'package:flame/input.dart'; +import 'package:flame/events.dart'; import 'package:flutter/material.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -15,7 +15,7 @@ enum ArrowIconDirection { /// {@template arrow_icon} /// A [SpriteComponent] that renders a simple arrow icon. /// {@endtemplate} -class ArrowIcon extends SpriteComponent with Tappable, HasGameRef { +class ArrowIcon extends SpriteComponent with TapCallbacks, HasGameRef { /// {@macro arrow_icon} ArrowIcon({ required Vector2 position, @@ -42,7 +42,7 @@ class ArrowIcon extends SpriteComponent with Tappable, HasGameRef { } @override - bool onTapUp(TapUpInfo info) { + bool onTapUp(TapUpEvent event) { onTap(); return true; } diff --git a/packages/pinball_components/lib/src/components/ball/ball.dart b/packages/pinball_components/lib/src/components/ball/ball.dart index e9c0e628..8eedaf4e 100644 --- a/packages/pinball_components/lib/src/components/ball/ball.dart +++ b/packages/pinball_components/lib/src/components/ball/ball.dart @@ -46,7 +46,7 @@ class Ball extends BodyComponent with Layered, InitialPosition, ZIndex { FlameBlocProvider.value( value: bloc ?? BallCubit(), children: [BallSpriteComponent(assetPath: assetPath)], - ) + ), ], ); @@ -66,7 +66,7 @@ class Ball extends BodyComponent with Layered, InitialPosition, ZIndex { bullet: true, ); - return world.createBody(bodyDef)..createFixtureFromShape(shape, 1); + return world.createBody(bodyDef)..createFixtureFromShape(shape); } /// Immediately and completely [stop]s the ball. diff --git a/packages/pinball_components/lib/src/components/ball/behaviors/ball_gravitating_behavior.dart b/packages/pinball_components/lib/src/components/ball/behaviors/ball_gravitating_behavior.dart index bad129a6..5b4192aa 100644 --- a/packages/pinball_components/lib/src/components/ball/behaviors/ball_gravitating_behavior.dart +++ b/packages/pinball_components/lib/src/components/ball/behaviors/ball_gravitating_behavior.dart @@ -3,7 +3,6 @@ import 'dart:math' as math; import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// Scales the ball's gravity according to its position on the board. class BallGravitatingBehavior extends Component diff --git a/packages/pinball_components/lib/src/components/ball/behaviors/ball_impulsing_behavior.dart b/packages/pinball_components/lib/src/components/ball/behaviors/ball_impulsing_behavior.dart index d875ef7c..21113309 100644 --- a/packages/pinball_components/lib/src/components/ball/behaviors/ball_impulsing_behavior.dart +++ b/packages/pinball_components/lib/src/components/ball/behaviors/ball_impulsing_behavior.dart @@ -1,6 +1,5 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// {@template ball_impulsing_behavior} /// Impulses the [Ball] in a given direction. @@ -17,6 +16,11 @@ class BallImpulsingBehavior extends Component with ParentIsA { Future onLoad() async { await super.onLoad(); parent.body.linearVelocity = _impulse; - shouldRemove = true; + } + + @override + void onMount() { + super.onMount(); + parent.remove(this); } } diff --git a/packages/pinball_components/lib/src/components/ball/behaviors/ball_scaling_behavior.dart b/packages/pinball_components/lib/src/components/ball/behaviors/ball_scaling_behavior.dart index e1e7c405..aa2c5bf7 100644 --- a/packages/pinball_components/lib/src/components/ball/behaviors/ball_scaling_behavior.dart +++ b/packages/pinball_components/lib/src/components/ball/behaviors/ball_scaling_behavior.dart @@ -1,6 +1,5 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// Scales the ball's body and sprite according to its position on the board. class BallScalingBehavior extends Component with ParentIsA { diff --git a/packages/pinball_components/lib/src/components/boundaries.dart b/packages/pinball_components/lib/src/components/boundaries.dart index d1ad34e0..49837454 100644 --- a/packages/pinball_components/lib/src/components/boundaries.dart +++ b/packages/pinball_components/lib/src/components/boundaries.dart @@ -21,7 +21,7 @@ class Boundaries extends Component { /// {@template bottom_boundary} /// Curved boundary at the bottom of the board where the [Ball] exits the field /// of play. -/// {@endtemplate bottom_boundary} +/// {@endtemplate} class _BottomBoundary extends BodyComponent with InitialPosition, ZIndex { /// {@macro bottom_boundary} _BottomBoundary() @@ -89,7 +89,7 @@ class _BottomBoundarySpriteComponent extends SpriteComponent with HasGameRef { /// /// The right side of the board is closed by the barrier the [LaunchRamp] /// creates. -/// {@endtemplate outer_boundary} +/// {@endtemplate} class _OuterBoundary extends BodyComponent with InitialPosition, ZIndex { /// {@macro outer_boundary} _OuterBoundary() diff --git a/packages/pinball_components/lib/src/components/camera_zoom.dart b/packages/pinball_components/lib/src/components/camera_zoom.dart index a3da382e..17f41461 100644 --- a/packages/pinball_components/lib/src/components/camera_zoom.dart +++ b/packages/pinball_components/lib/src/components/camera_zoom.dart @@ -28,17 +28,18 @@ class CameraZoom extends Effect with HasGameRef { @override Future onLoad() async { _tween = Tween( - begin: gameRef.camera.zoom, + begin: gameRef.camera.viewfinder.zoom, end: value, ); } @override void apply(double progress) { - gameRef.camera.zoom = _tween.transform(progress); + gameRef.camera.viewfinder.zoom = _tween.transform(progress); } /// Returns a [Future] that completes once the zoom is finished + @override Future get completed { if (controller.completed) { return Future.value(); diff --git a/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_mouth_opening_behavior.dart b/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_mouth_opening_behavior.dart index 6779a5d8..3ff9a682 100644 --- a/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_mouth_opening_behavior.dart +++ b/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_mouth_opening_behavior.dart @@ -12,7 +12,7 @@ class ChromeDinoMouthOpeningBehavior extends ContactBehavior { if (other is! Ball) return; if (parent.bloc.state.isMouthOpen && parent.firstChild() == null) { - contact.setEnabled(false); + contact.isEnabled = false; } } } diff --git a/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_spitting_behavior.dart b/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_spitting_behavior.dart index 876dd4d6..4c25b6eb 100644 --- a/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_spitting_behavior.dart +++ b/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_spitting_behavior.dart @@ -1,7 +1,6 @@ import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// {@template chrome_dino_spitting_behavior} /// Spits the [Ball] from the [ChromeDino] the next time the mouth opens. diff --git a/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_swiveling_behavior.dart b/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_swiveling_behavior.dart index ab98c6a8..e875a268 100644 --- a/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_swiveling_behavior.dart +++ b/packages/pinball_components/lib/src/components/chrome_dino/behaviors/chrome_dino_swiveling_behavior.dart @@ -1,7 +1,6 @@ import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// {@template chrome_dino_swivel_behavior} /// Swivels the [ChromeDino] up and down periodically to match its animation @@ -51,7 +50,7 @@ class ChromeDinoSwivelingBehavior extends TimerComponent @override void onTick() { super.onTick(); - _joint.setMotorSpeed(-_joint.motorSpeed); + _joint.motorSpeed = -_joint.motorSpeed; } } @@ -63,8 +62,8 @@ class _ChromeDinoAnchor extends JointAnchor parent.parent.children .whereType() .forEach((sprite) { - sprite.animation!.currentIndex = 45; - sprite.changeParent(this); + sprite.animationTicker!.currentIndex = 45; + sprite.parent = this; }); } } diff --git a/packages/pinball_components/lib/src/components/chrome_dino/chrome_dino.dart b/packages/pinball_components/lib/src/components/chrome_dino/chrome_dino.dart index 1de7b684..278c5bd9 100644 --- a/packages/pinball_components/lib/src/components/chrome_dino/chrome_dino.dart +++ b/packages/pinball_components/lib/src/components/chrome_dino/chrome_dino.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flame/components.dart'; -import 'package:flame_forge2d/flame_forge2d.dart' hide Timer; +import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flutter/material.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_components/src/components/chrome_dino/behaviors/behaviors.dart'; diff --git a/packages/pinball_components/lib/src/components/dash_bumper/cubit/dash_bumpers_state.dart b/packages/pinball_components/lib/src/components/dash_bumper/cubit/dash_bumpers_state.dart index 7620a2e2..568a96a4 100644 --- a/packages/pinball_components/lib/src/components/dash_bumper/cubit/dash_bumpers_state.dart +++ b/packages/pinball_components/lib/src/components/dash_bumper/cubit/dash_bumpers_state.dart @@ -7,7 +7,7 @@ class DashBumpersState extends Equatable { : this( bumperSpriteStates: { for (var id in DashBumperId.values) - id: DashBumperSpriteState.inactive + id: DashBumperSpriteState.inactive, }, ); diff --git a/packages/pinball_components/lib/src/components/error_component.dart b/packages/pinball_components/lib/src/components/error_component.dart index 49be8069..243bfe1a 100644 --- a/packages/pinball_components/lib/src/components/error_component.dart +++ b/packages/pinball_components/lib/src/components/error_component.dart @@ -51,7 +51,7 @@ class ErrorComponent extends SpriteComponent with HasGameRef { while (words.isNotEmpty) { final word = words.removeAt(0); - if (_textPaint.measureTextWidth('$currentLine $word') <= maxWidth) { + if (_textPaint.getLineMetrics('$currentLine $word').width <= maxWidth) { currentLine = '$currentLine $word'.trim(); } else { lines.add(currentLine); diff --git a/packages/pinball_components/lib/src/components/flapper/flapper.dart b/packages/pinball_components/lib/src/components/flapper/flapper.dart index 11852934..b98e020e 100644 --- a/packages/pinball_components/lib/src/components/flapper/flapper.dart +++ b/packages/pinball_components/lib/src/components/flapper/flapper.dart @@ -161,10 +161,11 @@ class FlapSpriteAnimationComponent extends SpriteAnimationComponent textureSize: textureSize, loop: false, ), - )..onComplete = () { - animation?.reset(); - playing = false; - }; + ); + animationTicker?.onComplete = () { + animationTicker?.reset(); + playing = false; + }; } } diff --git a/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_jointing_behavior.dart b/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_jointing_behavior.dart index 8e487141..062d8946 100644 --- a/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_jointing_behavior.dart +++ b/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_jointing_behavior.dart @@ -1,7 +1,6 @@ import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// Joints the [Flipper] to allow pivoting around one end. class FlipperJointingBehavior extends Component diff --git a/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_controlling_behavior.dart b/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_controlling_behavior.dart index b002420a..05bab08b 100644 --- a/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_controlling_behavior.dart +++ b/packages/pinball_components/lib/src/components/flipper/behaviors/flipper_key_controlling_behavior.dart @@ -33,14 +33,14 @@ class FlipperKeyControllingBehavior extends Component @override bool onKeyEvent( - RawKeyEvent event, + KeyEvent event, Set keysPressed, ) { if (!_keys.contains(event.logicalKey)) return true; - if (event is RawKeyDownEvent) { + if (event is KeyDownEvent) { bloc.moveUp(); - } else if (event is RawKeyUpEvent) { + } else if (event is KeyUpEvent) { bloc.moveDown(); } diff --git a/packages/pinball_components/lib/src/components/flipper/flipper.dart b/packages/pinball_components/lib/src/components/flipper/flipper.dart index cc6ef13a..9f040deb 100644 --- a/packages/pinball_components/lib/src/components/flipper/flipper.dart +++ b/packages/pinball_components/lib/src/components/flipper/flipper.dart @@ -13,7 +13,7 @@ export 'cubit/flipper_cubit.dart'; /// A bat, typically found in pairs at the bottom of the board. /// /// [Flipper] can be controlled by the player in an arc motion. -/// {@endtemplate flipper} +/// {@endtemplate} class Flipper extends BodyComponent with KeyboardHandler, InitialPosition { /// {@macro flipper} Flipper({ diff --git a/packages/pinball_components/lib/src/components/google_rollover/google_rollover.dart b/packages/pinball_components/lib/src/components/google_rollover/google_rollover.dart index e04e9778..7181fec7 100644 --- a/packages/pinball_components/lib/src/components/google_rollover/google_rollover.dart +++ b/packages/pinball_components/lib/src/components/google_rollover/google_rollover.dart @@ -105,9 +105,10 @@ class _PinSpriteAnimationComponent extends SpriteAnimationComponent textureSize: textureSize, loop: false, ), - )..onComplete = () { - animation?.reset(); - playing = false; - }; + ); + animationTicker?.onComplete = () { + animationTicker?.reset(); + playing = false; + }; } } diff --git a/packages/pinball_components/lib/src/components/google_word/behaviors/google_word_animating_behavior.dart b/packages/pinball_components/lib/src/components/google_word/behaviors/google_word_animating_behavior.dart index 2119c2f8..6e6aded9 100644 --- a/packages/pinball_components/lib/src/components/google_word/behaviors/google_word_animating_behavior.dart +++ b/packages/pinball_components/lib/src/components/google_word/behaviors/google_word_animating_behavior.dart @@ -18,7 +18,7 @@ class GoogleWordAnimatingBehavior extends TimerComponent } else { timer.stop(); bloc.onReset(); - shouldRemove = true; + parent?.remove(this); } } } diff --git a/packages/pinball_components/lib/src/components/google_word/cubit/google_word_cubit.dart b/packages/pinball_components/lib/src/components/google_word/cubit/google_word_cubit.dart index cd69fc9d..0d3fe209 100644 --- a/packages/pinball_components/lib/src/components/google_word/cubit/google_word_cubit.dart +++ b/packages/pinball_components/lib/src/components/google_word/cubit/google_word_cubit.dart @@ -33,7 +33,7 @@ class GoogleWordCubit extends Cubit { if (i.isEven) i: GoogleLetterSpriteState.dimmed else - i: GoogleLetterSpriteState.lit + i: GoogleLetterSpriteState.lit, }, ), ); @@ -46,7 +46,7 @@ class GoogleWordCubit extends Cubit { if (i.isEven) i: GoogleLetterSpriteState.lit else - i: GoogleLetterSpriteState.dimmed + i: GoogleLetterSpriteState.dimmed, }, ), ); @@ -62,7 +62,7 @@ class GoogleWordCubit extends Cubit { if (i.isEven) i: GoogleLetterSpriteState.lit else - i: GoogleLetterSpriteState.dimmed + i: GoogleLetterSpriteState.dimmed, }, ), ); diff --git a/packages/pinball_components/lib/src/components/google_word/cubit/google_word_state.dart b/packages/pinball_components/lib/src/components/google_word/cubit/google_word_state.dart index a1ee2786..d1075880 100644 --- a/packages/pinball_components/lib/src/components/google_word/cubit/google_word_state.dart +++ b/packages/pinball_components/lib/src/components/google_word/cubit/google_word_state.dart @@ -6,7 +6,7 @@ class GoogleWordState extends Equatable { GoogleWordState.initial() : this( letterSpriteStates: { - for (var i = 0; i <= 5; i++) i: GoogleLetterSpriteState.dimmed + for (var i = 0; i <= 5; i++) i: GoogleLetterSpriteState.dimmed, }, ); diff --git a/packages/pinball_components/lib/src/components/kicker/behaviors/kicker_blinking_behavior.dart b/packages/pinball_components/lib/src/components/kicker/behaviors/kicker_blinking_behavior.dart index 569d461f..490f566a 100644 --- a/packages/pinball_components/lib/src/components/kicker/behaviors/kicker_blinking_behavior.dart +++ b/packages/pinball_components/lib/src/components/kicker/behaviors/kicker_blinking_behavior.dart @@ -1,6 +1,5 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// {@template kicker_blinking_behavior} /// Makes a [Kicker] blink back to [KickerState.lit] when [KickerState.dimmed]. diff --git a/packages/pinball_components/lib/src/components/kicker/kicker.dart b/packages/pinball_components/lib/src/components/kicker/kicker.dart index 611f6032..d384255e 100644 --- a/packages/pinball_components/lib/src/components/kicker/kicker.dart +++ b/packages/pinball_components/lib/src/components/kicker/kicker.dart @@ -8,7 +8,6 @@ import 'package:pinball_components/gen/assets.gen.dart'; import 'package:pinball_components/pinball_components.dart' hide Assets; import 'package:pinball_components/src/components/bumping_behavior.dart'; import 'package:pinball_components/src/components/kicker/behaviors/behaviors.dart'; -import 'package:pinball_flame/pinball_flame.dart'; export 'cubit/kicker_cubit.dart'; @@ -17,7 +16,7 @@ export 'cubit/kicker_cubit.dart'; /// opposite side. /// /// [Kicker]s are usually positioned above each [Flipper]. -/// {@endtemplate kicker} +/// {@endtemplate} class Kicker extends BodyComponent with InitialPosition { /// {@macro kicker} Kicker({ diff --git a/packages/pinball_components/lib/src/components/multiball/behaviors/multiball_blinking_behavior.dart b/packages/pinball_components/lib/src/components/multiball/behaviors/multiball_blinking_behavior.dart index b974f33c..e16cdb09 100644 --- a/packages/pinball_components/lib/src/components/multiball/behaviors/multiball_blinking_behavior.dart +++ b/packages/pinball_components/lib/src/components/multiball/behaviors/multiball_blinking_behavior.dart @@ -1,6 +1,5 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// {@template multiball_blinking_behavior} /// Makes a [Multiball] blink back to [MultiballLightState.lit] when diff --git a/packages/pinball_components/lib/src/components/multiball/multiball.dart b/packages/pinball_components/lib/src/components/multiball/multiball.dart index 38150aea..6ebb6271 100644 --- a/packages/pinball_components/lib/src/components/multiball/multiball.dart +++ b/packages/pinball_components/lib/src/components/multiball/multiball.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:pinball_components/gen/assets.gen.dart'; import 'package:pinball_components/src/components/multiball/behaviors/behaviors.dart'; import 'package:pinball_components/src/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; export 'cubit/multiball_cubit.dart'; diff --git a/packages/pinball_components/lib/src/components/multiplier/multiplier.dart b/packages/pinball_components/lib/src/components/multiplier/multiplier.dart index 64e64375..0d9e53db 100644 --- a/packages/pinball_components/lib/src/components/multiplier/multiplier.dart +++ b/packages/pinball_components/lib/src/components/multiplier/multiplier.dart @@ -2,7 +2,6 @@ import 'package:flame/components.dart'; import 'package:flutter/material.dart'; import 'package:pinball_components/gen/assets.gen.dart'; import 'package:pinball_components/src/components/multiplier/cubit/multiplier_cubit.dart'; -import 'package:pinball_flame/pinball_flame.dart'; export 'cubit/multiplier_cubit.dart'; diff --git a/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_jointing_behavior.dart b/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_jointing_behavior.dart index 06332bef..8c0f3574 100644 --- a/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_jointing_behavior.dart +++ b/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_jointing_behavior.dart @@ -1,7 +1,6 @@ import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; class PlungerJointingBehavior extends Component with ParentIsA { PlungerJointingBehavior({required double compressionDistance}) diff --git a/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_key_controlling_behavior.dart b/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_key_controlling_behavior.dart index fcff816a..6846719e 100644 --- a/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_key_controlling_behavior.dart +++ b/packages/pinball_components/lib/src/components/plunger/behaviors/plunger_key_controlling_behavior.dart @@ -17,14 +17,14 @@ class PlungerKeyControllingBehavior extends Component @override bool onKeyEvent( - RawKeyEvent event, + KeyEvent event, Set keysPressed, ) { if (!_keys.contains(event.logicalKey)) return true; - if (event is RawKeyDownEvent) { + if (event is KeyDownEvent) { bloc.pulled(); - } else if (event is RawKeyUpEvent) { + } else if (event is KeyUpEvent) { bloc.released(); } diff --git a/packages/pinball_components/lib/src/components/plunger/plunger.dart b/packages/pinball_components/lib/src/components/plunger/plunger.dart index 488c79bb..397675dc 100644 --- a/packages/pinball_components/lib/src/components/plunger/plunger.dart +++ b/packages/pinball_components/lib/src/components/plunger/plunger.dart @@ -99,7 +99,7 @@ class _PlungerSpriteAnimationGroupComponent final startedReleasing = state.isReleasing && !current!.isReleasing; final startedPulling = state.isPulling && !current!.isPulling; if (startedReleasing || startedPulling) { - animation?.reset(); + animationTicker?.reset(); } current = state; diff --git a/packages/pinball_components/lib/src/components/score_component/behaviors/score_component_scaling_behavior.dart b/packages/pinball_components/lib/src/components/score_component/behaviors/score_component_scaling_behavior.dart index 5e3d184b..5cbe90c7 100644 --- a/packages/pinball_components/lib/src/components/score_component/behaviors/score_component_scaling_behavior.dart +++ b/packages/pinball_components/lib/src/components/score_component/behaviors/score_component_scaling_behavior.dart @@ -1,6 +1,5 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// Scales a [ScoreComponent] according to its position on the board. class ScoreComponentScalingBehavior extends Component diff --git a/packages/pinball_components/lib/src/components/skill_shot/behaviors/skill_shot_blinking_behavior.dart b/packages/pinball_components/lib/src/components/skill_shot/behaviors/skill_shot_blinking_behavior.dart index ea62fc25..bf6d0208 100644 --- a/packages/pinball_components/lib/src/components/skill_shot/behaviors/skill_shot_blinking_behavior.dart +++ b/packages/pinball_components/lib/src/components/skill_shot/behaviors/skill_shot_blinking_behavior.dart @@ -1,6 +1,5 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// {@template skill_shot_blinking_behavior} /// Makes a [SkillShot] blink between [SkillShotSpriteState.lit] and diff --git a/packages/pinball_components/lib/src/components/skill_shot/skill_shot.dart b/packages/pinball_components/lib/src/components/skill_shot/skill_shot.dart index a3ea2af2..d22b2339 100644 --- a/packages/pinball_components/lib/src/components/skill_shot/skill_shot.dart +++ b/packages/pinball_components/lib/src/components/skill_shot/skill_shot.dart @@ -127,10 +127,11 @@ class PinSpriteAnimationComponent extends SpriteAnimationComponent textureSize: textureSize, loop: false, ), - )..onComplete = () { - animation?.reset(); - playing = false; - }; + ); + animationTicker?.onComplete = () { + animationTicker?.reset(); + playing = false; + }; } } diff --git a/packages/pinball_components/lib/src/components/spaceship_rail.dart b/packages/pinball_components/lib/src/components/spaceship_rail.dart index 7dbabc93..a7398191 100644 --- a/packages/pinball_components/lib/src/components/spaceship_rail.dart +++ b/packages/pinball_components/lib/src/components/spaceship_rail.dart @@ -15,7 +15,7 @@ class SpaceshipRail extends Component { children: [ _SpaceshipRail(), _SpaceshipRailExit(), - _SpaceshipRailExitSpriteComponent() + _SpaceshipRailExitSpriteComponent(), ], ); } diff --git a/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart b/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart index 8044b79a..a8d11506 100644 --- a/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart +++ b/packages/pinball_components/lib/src/components/spaceship_ramp/spaceship_ramp.dart @@ -430,7 +430,7 @@ class SpaceshipRampBase extends BodyComponent // Although, the Layer should already be taking care of the contact // filtering, this is to ensure the ball doesn't collide with the ramp base // when the filtering is calculated on different time steps. - contact.setEnabled(other.layer == Layer.board); + contact.isEnabled = other.layer == Layer.board; } @override diff --git a/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behavior.dart b/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behavior.dart index 2c2c50fe..baf570c1 100644 --- a/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behavior.dart +++ b/packages/pinball_components/lib/src/components/sparky_bumper/behaviors/sparky_bumper_blinking_behavior.dart @@ -1,6 +1,5 @@ import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// {@template sparky_bumper_blinking_behavior} /// Makes a [SparkyBumper] blink back to [SparkyBumperState.lit] when diff --git a/packages/pinball_components/pubspec.yaml b/packages/pinball_components/pubspec.yaml index 7fe3ac5e..e18cdee9 100644 --- a/packages/pinball_components/pubspec.yaml +++ b/packages/pinball_components/pubspec.yaml @@ -4,20 +4,16 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dependencies: bloc: ^8.0.3 - flame: ^1.1.1 - flame_bloc: ^1.4.0 - flame_forge2d: - git: - url: https://github.com/flame-engine/flame - path: packages/flame_forge2d/ - ref: a50d4a1e7d9eaf66726ed1bb9894c9d495547d8f + flame: ^1.18.0 + flame_bloc: ^1.12.0 + flame_forge2d: ^0.18.1 flutter: sdk: flutter - intl: ^0.17.0 + intl: ^0.19.0 pinball_audio: path: ../pinball_audio pinball_flame: @@ -32,8 +28,8 @@ dev_dependencies: flame_test: ^1.3.0 flutter_test: sdk: flutter - mocktail: ^0.2.0 - very_good_analysis: ^2.4.0 + mocktail: ^1.0.4 + very_good_analysis: ^6.0.0 flutter: uses-material-design: true diff --git a/packages/pinball_components/sandbox/lib/common/games.dart b/packages/pinball_components/sandbox/lib/common/games.dart index bee6a280..cc926afc 100644 --- a/packages/pinball_components/sandbox/lib/common/games.dart +++ b/packages/pinball_components/sandbox/lib/common/games.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:flame/components.dart'; +import 'package:flame/events.dart'; import 'package:flame/input.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flutter/material.dart'; @@ -18,7 +19,7 @@ abstract class AssetsGame extends Forge2DGame { Future onLoad() async { await super.onLoad(); if (_imagesFileNames != null) { - await images.loadAll(_imagesFileNames!); + await images.loadAll(_imagesFileNames); } } } @@ -37,19 +38,18 @@ abstract class LineGame extends AssetsGame with PanDetector { @override Future onLoad() async { await super.onLoad(); - - camera.followVector2(Vector2.zero()); - unawaited(add(_PreviewLine())); + camera.follow(PositionComponent(position: Vector2.zero())); + add(_PreviewLine()); } @override void onPanStart(DragStartInfo info) { - _lineEnd = info.eventPosition.game; + _lineEnd = info.eventPosition.global; } @override void onPanUpdate(DragUpdateInfo info) { - _lineEnd = info.eventPosition.game; + _lineEnd = info.eventPosition.global; } @override diff --git a/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_a_game.dart b/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_a_game.dart index 78cebd95..40fccf9e 100644 --- a/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_a_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_a_game.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flame/extensions.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -23,7 +23,7 @@ class AndroidBumperAGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add( AndroidBumper.a()..priority = 1, ); diff --git a/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_b_game.dart b/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_b_game.dart index 9bd2caff..9bfa70df 100644 --- a/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_b_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_b_game.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flame/extensions.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -23,7 +23,7 @@ class AndroidBumperBGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add( AndroidBumper.b()..priority = 1, ); diff --git a/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_cow_game.dart b/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_cow_game.dart index ac1bc6fe..ada1ead6 100644 --- a/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_cow_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/android_acres/android_bumper_cow_game.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flame/extensions.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -23,7 +23,7 @@ class AndroidBumperCowGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add( AndroidBumper.cow()..priority = 1, ); diff --git a/packages/pinball_components/sandbox/lib/stories/android_acres/android_spaceship_game.dart b/packages/pinball_components/sandbox/lib/stories/android_acres/android_spaceship_game.dart index c7c9b76c..6d2bb2b7 100644 --- a/packages/pinball_components/sandbox/lib/stories/android_acres/android_spaceship_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/android_acres/android_spaceship_game.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flame/input.dart'; +import 'package:flame/components.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; @@ -29,7 +29,7 @@ class AndroidSpaceshipGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add( FlameBlocProvider( create: AndroidSpaceshipCubit.new, diff --git a/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_rail_game.dart b/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_rail_game.dart index 9acee409..3955476c 100644 --- a/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_rail_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_rail_game.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flame/input.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -27,7 +27,7 @@ class SpaceshipRailGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2(-30, -10)); + camera.follow(PositionComponent(position: Vector2(-30, -10))); await add(SpaceshipRail()); await ready(); await traceAllBodies(); diff --git a/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_ramp_game.dart b/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_ramp_game.dart index b19aef56..6f7d6dea 100644 --- a/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_ramp_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/android_acres/spaceship_ramp_game.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:flame/components.dart'; import 'package:flame/input.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -43,7 +44,7 @@ class SpaceshipRampGame extends BallGame with KeyboardEvents { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2(-12, -50)); + camera.follow(PositionComponent(position: Vector2(-12, -50))); _spaceshipRamp = SpaceshipRamp(); await add(_spaceshipRamp); @@ -52,11 +53,10 @@ class SpaceshipRampGame extends BallGame with KeyboardEvents { @override KeyEventResult onKeyEvent( - RawKeyEvent event, + KeyEvent event, Set keysPressed, ) { - if (event is RawKeyDownEvent && - event.logicalKey == LogicalKeyboardKey.space) { + if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.space) { _spaceshipRamp .readBloc() .onProgressed(); diff --git a/packages/pinball_components/sandbox/lib/stories/arrow_icon/arrow_icon_game.dart b/packages/pinball_components/sandbox/lib/stories/arrow_icon/arrow_icon_game.dart index 23af63b0..aa5adf86 100644 --- a/packages/pinball_components/sandbox/lib/stories/arrow_icon/arrow_icon_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/arrow_icon/arrow_icon_game.dart @@ -1,8 +1,9 @@ -import 'package:flame/game.dart'; +import 'package:flame/components.dart'; +import 'package:flame/events.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/common/games.dart'; -class ArrowIconGame extends AssetsGame with HasTappables { +class ArrowIconGame extends AssetsGame with TapCallbacks { ArrowIconGame() : super( imagesFileNames: [ @@ -16,7 +17,7 @@ class ArrowIconGame extends AssetsGame with HasTappables { @override Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add( ArrowIcon( diff --git a/packages/pinball_components/sandbox/lib/stories/ball/basic_ball_game.dart b/packages/pinball_components/sandbox/lib/stories/ball/basic_ball_game.dart index b5e29a8e..cc4e0c69 100644 --- a/packages/pinball_components/sandbox/lib/stories/ball/basic_ball_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/ball/basic_ball_game.dart @@ -1,4 +1,4 @@ -import 'package:flame/input.dart'; +import 'package:flame/events.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; import 'package:pinball_theme/pinball_theme.dart' as theme; @@ -43,7 +43,7 @@ class BallGame extends AssetsGame with TapDetector, Traceable { Ball( assetPath: characterBallPaths[character], ) - ..initialPosition = info.eventPosition.game + ..initialPosition = info.eventPosition.global ..layer = ballLayer ..priority = ballPriority, ); diff --git a/packages/pinball_components/sandbox/lib/stories/bottom_group/baseboard_game.dart b/packages/pinball_components/sandbox/lib/stories/bottom_group/baseboard_game.dart index 4e86f732..d1af132d 100644 --- a/packages/pinball_components/sandbox/lib/stories/bottom_group/baseboard_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/bottom_group/baseboard_game.dart @@ -21,8 +21,7 @@ class BaseboardGame extends BallGame { @override Future onLoad() async { await super.onLoad(); - - final center = screenToWorld(camera.viewport.canvasSize! / 2); + final center = screenToWorld(camera.viewport.size / 2); await addAll([ Baseboard(side: BoardSide.left) ..initialPosition = center - Vector2(25, 0) diff --git a/packages/pinball_components/sandbox/lib/stories/bottom_group/flipper_game.dart b/packages/pinball_components/sandbox/lib/stories/bottom_group/flipper_game.dart index bdb23141..d73f24e0 100644 --- a/packages/pinball_components/sandbox/lib/stories/bottom_group/flipper_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/bottom_group/flipper_game.dart @@ -28,7 +28,7 @@ class FlipperGame extends BallGame with KeyboardEvents { Future onLoad() async { await super.onLoad(); - final center = screenToWorld(camera.viewport.canvasSize! / 2); + final center = screenToWorld(camera.viewport.size / 2); await addAll([ leftFlipper = Flipper(side: BoardSide.left) ..initialPosition = center - Vector2(Flipper.size.x, 0), diff --git a/packages/pinball_components/sandbox/lib/stories/bottom_group/kicker_game.dart b/packages/pinball_components/sandbox/lib/stories/bottom_group/kicker_game.dart index 590638e0..636431fb 100644 --- a/packages/pinball_components/sandbox/lib/stories/bottom_group/kicker_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/bottom_group/kicker_game.dart @@ -24,7 +24,7 @@ class KickerGame extends BallGame { Future onLoad() async { await super.onLoad(); - final center = screenToWorld(camera.viewport.canvasSize! / 2); + final center = screenToWorld(camera.viewport.size / 2); await addAll( [ Kicker(side: BoardSide.left) diff --git a/packages/pinball_components/sandbox/lib/stories/boundaries/boundaries_game.dart b/packages/pinball_components/sandbox/lib/stories/boundaries/boundaries_game.dart index 12e8ec26..14886580 100644 --- a/packages/pinball_components/sandbox/lib/stories/boundaries/boundaries_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/boundaries/boundaries_game.dart @@ -1,4 +1,4 @@ -import 'package:flame/extensions.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -24,8 +24,8 @@ class BoundariesGame extends BallGame { await super.onLoad(); camera - ..followVector2(Vector2.zero()) - ..zoom = 6; + ..follow(PositionComponent(position: Vector2.zero())) + ..viewfinder.zoom = 6; await add(Boundaries()); await ready(); await traceAllBodies(); diff --git a/packages/pinball_components/sandbox/lib/stories/dino_desert/chrome_dino_game.dart b/packages/pinball_components/sandbox/lib/stories/dino_desert/chrome_dino_game.dart index d6e7ef95..a644af64 100644 --- a/packages/pinball_components/sandbox/lib/stories/dino_desert/chrome_dino_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/dino_desert/chrome_dino_game.dart @@ -1,4 +1,4 @@ -import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -22,7 +22,7 @@ class ChromeDinoGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add(ChromeDino()); await traceAllBodies(); diff --git a/packages/pinball_components/sandbox/lib/stories/dino_desert/dino_walls_game.dart b/packages/pinball_components/sandbox/lib/stories/dino_desert/dino_walls_game.dart index 849e17a8..2520261e 100644 --- a/packages/pinball_components/sandbox/lib/stories/dino_desert/dino_walls_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/dino_desert/dino_walls_game.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flame/input.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -25,7 +25,7 @@ class DinoWallsGame extends BallGame { ]); await add(DinoWalls()); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await traceAllBodies(); } } diff --git a/packages/pinball_components/sandbox/lib/stories/dino_desert/slingshots_game.dart b/packages/pinball_components/sandbox/lib/stories/dino_desert/slingshots_game.dart index 1a9eb2e5..28482018 100644 --- a/packages/pinball_components/sandbox/lib/stories/dino_desert/slingshots_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/dino_desert/slingshots_game.dart @@ -1,4 +1,4 @@ -import 'package:flame/extensions.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -22,7 +22,7 @@ class SlingshotsGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add(Slingshots()); await ready(); await traceAllBodies(); diff --git a/packages/pinball_components/sandbox/lib/stories/effects/camera_zoom_game.dart b/packages/pinball_components/sandbox/lib/stories/effects/camera_zoom_game.dart index 11f2b776..be270350 100644 --- a/packages/pinball_components/sandbox/lib/stories/effects/camera_zoom_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/effects/camera_zoom_game.dart @@ -24,7 +24,7 @@ class CameraZoomGame extends AssetsGame with TapDetector { ), ); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); } @override diff --git a/packages/pinball_components/sandbox/lib/stories/error_component/error_component_game.dart b/packages/pinball_components/sandbox/lib/stories/error_component/error_component_game.dart index c64e6d48..4521dec0 100644 --- a/packages/pinball_components/sandbox/lib/stories/error_component/error_component_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/error_component/error_component_game.dart @@ -11,7 +11,7 @@ class ErrorComponentGame extends AssetsGame { @override Future onLoad() async { - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add(ErrorComponent(label: text)); await add( diff --git a/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_a_game.dart b/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_a_game.dart index 4d437f76..9fe514e2 100644 --- a/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_a_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_a_game.dart @@ -1,7 +1,7 @@ import 'dart:async'; +import 'package:flame/components.dart'; import 'package:flame_bloc/flame_bloc.dart'; -import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -24,7 +24,7 @@ class DashBumperAGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add( FlameBlocProvider( create: DashBumpersCubit.new, diff --git a/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_b_game.dart b/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_b_game.dart index 64af8c59..3145c7c8 100644 --- a/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_b_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_b_game.dart @@ -1,7 +1,7 @@ import 'dart:async'; +import 'package:flame/components.dart'; import 'package:flame_bloc/flame_bloc.dart'; -import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -24,7 +24,7 @@ class DashBumperBGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add( FlameBlocProvider( create: DashBumpersCubit.new, diff --git a/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_main_game.dart b/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_main_game.dart index 773ead8d..958c9cc1 100644 --- a/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_main_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/flutter_forest/dash_bumper_main_game.dart @@ -1,7 +1,7 @@ import 'dart:async'; +import 'package:flame/components.dart'; import 'package:flame_bloc/flame_bloc.dart'; -import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -24,7 +24,7 @@ class DashBumperMainGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add( FlameBlocProvider( create: DashBumpersCubit.new, diff --git a/packages/pinball_components/sandbox/lib/stories/flutter_forest/signpost_game.dart b/packages/pinball_components/sandbox/lib/stories/flutter_forest/signpost_game.dart index 3174f6f7..d4c4a1a1 100644 --- a/packages/pinball_components/sandbox/lib/stories/flutter_forest/signpost_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/flutter_forest/signpost_game.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flame/input.dart'; +import 'package:flame/components.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -30,7 +30,7 @@ class SignpostGame extends BallGame { await super.onLoad(); _bloc = SignpostCubit(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add( FlameMultiBlocProvider( providers: [ diff --git a/packages/pinball_components/sandbox/lib/stories/google_word/google_letter_game.dart b/packages/pinball_components/sandbox/lib/stories/google_word/google_letter_game.dart index 94389f60..fa258a58 100644 --- a/packages/pinball_components/sandbox/lib/stories/google_word/google_letter_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/google_word/google_letter_game.dart @@ -1,4 +1,4 @@ -import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -21,7 +21,7 @@ class GoogleLetterGame extends BallGame { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await add(GoogleLetter(0)); await traceAllBodies(); diff --git a/packages/pinball_components/sandbox/lib/stories/launch_ramp/launch_ramp_game.dart b/packages/pinball_components/sandbox/lib/stories/launch_ramp/launch_ramp_game.dart index fef1a145..02fc9e2e 100644 --- a/packages/pinball_components/sandbox/lib/stories/launch_ramp/launch_ramp_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/launch_ramp/launch_ramp_game.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flame/input.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -29,8 +29,8 @@ class LaunchRampGame extends BallGame { await super.onLoad(); camera - ..followVector2(Vector2.zero()) - ..zoom = 7.5; + ..follow(PositionComponent(position: Vector2.zero())) + ..viewfinder.zoom = 7.5; await add(LaunchRamp()); await ready(); await traceAllBodies(); diff --git a/packages/pinball_components/sandbox/lib/stories/multiball/multiball_game.dart b/packages/pinball_components/sandbox/lib/stories/multiball/multiball_game.dart index 83b53785..a6489089 100644 --- a/packages/pinball_components/sandbox/lib/stories/multiball/multiball_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/multiball/multiball_game.dart @@ -1,3 +1,4 @@ +import 'package:flame/components.dart'; import 'package:flame/input.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -31,7 +32,7 @@ class MultiballGame extends BallGame with KeyboardEvents { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await addAll(multiballs); await traceAllBodies(); @@ -39,11 +40,10 @@ class MultiballGame extends BallGame with KeyboardEvents { @override KeyEventResult onKeyEvent( - RawKeyEvent event, + KeyEvent event, Set keysPressed, ) { - if (event is RawKeyDownEvent && - event.logicalKey == LogicalKeyboardKey.space) { + if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.space) { for (final multiball in multiballs) { multiball.bloc.onBlink(); } diff --git a/packages/pinball_components/sandbox/lib/stories/multipliers/multipliers_game.dart b/packages/pinball_components/sandbox/lib/stories/multipliers/multipliers_game.dart index ae641623..e1fe3c3c 100644 --- a/packages/pinball_components/sandbox/lib/stories/multipliers/multipliers_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/multipliers/multipliers_game.dart @@ -1,4 +1,5 @@ import 'dart:math' as math; +import 'package:flame/components.dart'; import 'package:flame/input.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -56,7 +57,7 @@ class MultipliersGame extends BallGame with KeyboardEvents { Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); await addAll(multipliers); await traceAllBodies(); @@ -64,10 +65,10 @@ class MultipliersGame extends BallGame with KeyboardEvents { @override KeyEventResult onKeyEvent( - RawKeyEvent event, + KeyEvent event, Set keysPressed, ) { - if (event is RawKeyDownEvent) { + if (event is KeyDownEvent) { var currentMultiplier = 1; if (event.logicalKey == LogicalKeyboardKey.digit2) { diff --git a/packages/pinball_components/sandbox/lib/stories/plunger/plunger_game.dart b/packages/pinball_components/sandbox/lib/stories/plunger/plunger_game.dart index 328afce4..914b5b1a 100644 --- a/packages/pinball_components/sandbox/lib/stories/plunger/plunger_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/plunger/plunger_game.dart @@ -24,7 +24,7 @@ class PlungerGame extends BallGame Future onLoad() async { await super.onLoad(); - final center = screenToWorld(camera.viewport.canvasSize! / 2); + final center = screenToWorld(camera.viewport.size / 2); final plunger = Plunger() ..initialPosition = Vector2(center.x - 8.8, center.y); await add( diff --git a/packages/pinball_components/sandbox/lib/stories/score/score_game.dart b/packages/pinball_components/sandbox/lib/stories/score/score_game.dart index edb4fa36..78fde2b5 100644 --- a/packages/pinball_components/sandbox/lib/stories/score/score_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/score/score_game.dart @@ -1,6 +1,8 @@ import 'dart:math'; +import 'package:flame/components.dart'; import 'package:flame/effects.dart'; +import 'package:flame/events.dart'; import 'package:flame/input.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/common/common.dart'; @@ -27,7 +29,7 @@ class ScoreGame extends AssetsGame with TapDetector { @override Future onLoad() async { await super.onLoad(); - camera.followVector2(Vector2.zero()); + camera.follow(PositionComponent(position: Vector2.zero())); } @override @@ -38,7 +40,7 @@ class ScoreGame extends AssetsGame with TapDetector { add( ScoreComponent( points: score, - position: info.eventPosition.game..multiply(Vector2(1, -1)), + position: info.eventPosition.global..multiply(Vector2(1, -1)), effectController: EffectController(duration: 1), ), ); diff --git a/packages/pinball_components/sandbox/lib/stories/sparky_scorch/sparky_bumper_game.dart b/packages/pinball_components/sandbox/lib/stories/sparky_scorch/sparky_bumper_game.dart index c45c4895..4b40e492 100644 --- a/packages/pinball_components/sandbox/lib/stories/sparky_scorch/sparky_bumper_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/sparky_scorch/sparky_bumper_game.dart @@ -25,7 +25,7 @@ class SparkyBumperGame extends BallGame { Assets.images.sparky.bumper.c.dimmed.keyName, ]); - final center = screenToWorld(camera.viewport.canvasSize! / 2); + final center = screenToWorld(camera.viewport.size / 2); final sparkyBumperA = SparkyBumper.a() ..initialPosition = Vector2(center.x - 20, center.y + 20) ..priority = 1; diff --git a/packages/pinball_components/sandbox/lib/stories/sparky_scorch/sparky_computer_game.dart b/packages/pinball_components/sandbox/lib/stories/sparky_scorch/sparky_computer_game.dart index b4002479..dfba57bb 100644 --- a/packages/pinball_components/sandbox/lib/stories/sparky_scorch/sparky_computer_game.dart +++ b/packages/pinball_components/sandbox/lib/stories/sparky_scorch/sparky_computer_game.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flame/input.dart'; +import 'package:flame/components.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:sandbox/stories/ball/basic_ball_game.dart'; @@ -22,7 +22,7 @@ class SparkyComputerGame extends BallGame { Assets.images.sparky.computer.glow.keyName, ]); - camera.followVector2(Vector2(-10, -40)); + camera.follow(PositionComponent(position: Vector2(-10, -40))); await add(SparkyComputer()); await ready(); await traceAllBodies(); diff --git a/packages/pinball_components/sandbox/pubspec.lock b/packages/pinball_components/sandbox/pubspec.lock index 5e4c6061..ac8ec57e 100644 --- a/packages/pinball_components/sandbox/pubspec.lock +++ b/packages/pinball_components/sandbox/pubspec.lock @@ -5,144 +5,218 @@ packages: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "0bd9a99b6eb96f07af141f0eb53eace8983e8e5aa5de59777aca31684680ef22" + url: "https://pub.dev" source: hosted version: "2.3.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.11.0" audioplayers: dependency: transitive description: name: audioplayers - url: "https://pub.dartlang.org" + sha256: "752039d6aa752597c98ec212e9759519061759e402e7da59a511f39d43aa07d2" + url: "https://pub.dev" source: hosted - version: "0.20.1" + version: "6.0.0" + audioplayers_android: + dependency: transitive + description: + name: audioplayers_android + sha256: de576b890befe27175c2f511ba8b742bec83765fa97c3ce4282bba46212f58e4 + url: "https://pub.dev" + source: hosted + version: "5.0.0" + audioplayers_darwin: + dependency: transitive + description: + name: audioplayers_darwin + sha256: e507887f3ff18d8e5a10a668d7bedc28206b12e10b98347797257c6ae1019c3b + url: "https://pub.dev" + source: hosted + version: "6.0.0" + audioplayers_linux: + dependency: transitive + description: + name: audioplayers_linux + sha256: "3d3d244c90436115417f170426ce768856d8fe4dfc5ed66a049d2890acfa82f9" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + audioplayers_platform_interface: + dependency: transitive + description: + name: audioplayers_platform_interface + sha256: "6834dd48dfb7bc6c2404998ebdd161f79cd3774a7e6779e1348d54a3bfdcfaa5" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + audioplayers_web: + dependency: transitive + description: + name: audioplayers_web + sha256: db8fc420dadf80da18e2286c18e746fb4c3b2c5adbf0c963299dde046828886d + url: "https://pub.dev" + source: hosted + version: "5.0.0" + audioplayers_windows: + dependency: transitive + description: + name: audioplayers_windows + sha256: "8605762dddba992138d476f6a0c3afd9df30ac5b96039929063eceed416795c2" + url: "https://pub.dev" + source: hosted + version: "4.0.0" bloc: dependency: transitive description: name: bloc - url: "https://pub.dartlang.org" + sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e" + url: "https://pub.dev" source: hosted - version: "8.0.3" + version: "8.1.4" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" source: hosted version: "1.3.1" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.18.0" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" dashbook: dependency: "direct main" description: name: dashbook - url: "https://pub.dartlang.org" + sha256: a022d40095694c7345cac93ade887de3b0a8935cc45602dc533ec75568f4ef74 + url: "https://pub.dev" source: hosted version: "0.1.7" device_frame: dependency: transitive description: name: device_frame - url: "https://pub.dartlang.org" + sha256: d5b4541a8755a36ac50b6605200e51db6d264438a38f327aec2ce31870e49885 + url: "https://pub.dev" source: hosted version: "1.0.0" equatable: dependency: transitive description: name: equatable - url: "https://pub.dartlang.org" + sha256: c6094fd1efad3046334a9c40bee022147e55c25401ccd89b94e373e3edadd375 + url: "https://pub.dev" source: hosted version: "2.0.3" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: "35d0f481d939de0d640b3db9a7aa36a52cd22054a798a73b4f50bdad5ce12678" + url: "https://pub.dev" source: hosted version: "1.1.2" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: b69516f2c26a5bcac4eee2e32512e1a5205ab312b3536c1c1227b2b942b5f9ad + url: "https://pub.dev" source: hosted version: "6.1.2" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flame: dependency: "direct main" description: name: flame - url: "https://pub.dartlang.org" + sha256: "79133dc46a3ff870950f41d0dc1598414e7bd7ae2c29bd9f0a9de208d9a70cb7" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.18.0" flame_audio: dependency: transitive description: name: flame_audio - url: "https://pub.dartlang.org" + sha256: "32e5788945469cebb807e741027e645a737e2618afc9b682e7f48607e0637f48" + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "2.10.2" flame_bloc: dependency: "direct main" description: name: flame_bloc - url: "https://pub.dartlang.org" + sha256: "19d907204b65f81b08adf71da02e632e68757b1a6738378d8dd4bc024c1660b8" + url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.12.0" flame_forge2d: dependency: "direct main" description: - path: "packages/flame_forge2d" - ref: a50d4a1e7d9eaf66726ed1bb9894c9d495547d8f - resolved-ref: a50d4a1e7d9eaf66726ed1bb9894c9d495547d8f - url: "https://github.com/flame-engine/flame" - source: git - version: "0.11.0" + name: flame_forge2d + sha256: "1ec1c5b4978b64d2d16ca90f86de469959991ef996970866c3f9de580b3dbe40" + url: "https://pub.dev" + source: hosted + version: "0.18.1" flutter: dependency: "direct main" description: flutter @@ -152,21 +226,24 @@ packages: dependency: transitive description: name: flutter_bloc - url: "https://pub.dartlang.org" + sha256: f0ecf6e6eb955193ca60af2d5ca39565a86b8a142452c5b24d96fb477428f4d2 + url: "https://pub.dev" source: hosted - version: "8.0.1" + version: "8.1.5" flutter_colorpicker: dependency: transitive description: name: flutter_colorpicker - url: "https://pub.dartlang.org" + sha256: "458a6ed8ea480eb16ff892aedb4b7092b2804affd7e046591fb03127e8d8ef8b" + url: "https://pub.dev" source: hosted version: "1.0.3" flutter_markdown: dependency: transitive description: name: flutter_markdown - url: "https://pub.dartlang.org" + sha256: "5a3ecbecfed294a464b952494daafc05cf97f6faf9441168f507e9c9400f50e0" + url: "https://pub.dev" source: hosted version: "0.6.9" flutter_test: @@ -183,14 +260,16 @@ packages: dependency: transitive description: name: forge2d - url: "https://pub.dartlang.org" + sha256: "40915333b688ddaaa616d9c8ab9ff205faea0adf83dddc1a6e617694ffa9e16e" + url: "https://pub.dev" source: hosted - version: "0.11.0" + version: "0.13.0" freezed_annotation: dependency: transitive description: name: freezed_annotation - url: "https://pub.dartlang.org" + sha256: "1be037f901137bf2b9a0c309e9bf2694d6ec77687645211218191ade4f41a4b8" + url: "https://pub.dev" source: hosted version: "1.1.0" geometry: @@ -204,133 +283,160 @@ packages: dependency: transitive description: name: http - url: "https://pub.dartlang.org" + sha256: "2ed163531e071c2c6b7c659635112f24cb64ecbebf6af46b550d536c0b1aa112" + url: "https://pub.dev" source: hosted version: "0.13.4" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: e362d639ba3bc07d5a71faebb98cde68c05bfbcfbbb444b60b6f60bb67719185 + url: "https://pub.dev" source: hosted version: "4.0.0" intl: dependency: transitive description: name: intl - url: "https://pub.dartlang.org" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" source: hosted - version: "0.17.0" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.3" + version: "0.19.0" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: "2639efc0237c7b71c6584696c0847ea4e4733ddaf571ae9c79d5295e8ae17272" + url: "https://pub.dev" source: hosted version: "4.4.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" markdown: dependency: transitive description: name: markdown - url: "https://pub.dartlang.org" + sha256: "01512006c8429f604eb10f9848717baeaedf99e991d14a50d540d9beff08e5c6" + url: "https://pub.dev" source: hosted version: "4.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" source: hosted - version: "0.1.3" + version: "0.8.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.12.0" nested: dependency: transitive description: name: nested - url: "https://pub.dartlang.org" + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" source: hosted version: "1.0.0" ordered_set: dependency: transitive description: name: ordered_set - url: "https://pub.dartlang.org" + sha256: "1bfaaaee0419e43ecc9eaebd410eb4bd5039657b72011de75ff3e2915c9aac60" + url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.0.3" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.0" path_provider: dependency: transitive description: name: path_provider - url: "https://pub.dartlang.org" + sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + url: "https://pub.dev" source: hosted - version: "2.0.9" + version: "2.0.15" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: "32bbab16092df3bedab89ed9f2c1cfaedf25d96a5036f62f16d5e372890d068c" + url: "https://pub.dev" source: hosted version: "2.0.13" - path_provider_ios: + path_provider_foundation: dependency: transitive description: - name: path_provider_ios - url: "https://pub.dartlang.org" + name: path_provider_foundation + sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" + url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "2.2.4" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: "1e109f4df28bd95eab71e323008b53d19c4d633bc1ab05b577518773474e9621" + url: "https://pub.dev" source: hosted version: "2.1.5" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.5" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: "3dc0d51b07f85fec3746d9f4e8d31c73bb173cafa2e763f03f8df2e8d1878882" + url: "https://pub.dev" source: hosted version: "2.0.3" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: "366ad4e3541ea707f859e7148d4d5aba67d589d7936cee04a05c464a277eeb27" + url: "https://pub.dev" source: hosted version: "2.0.5" pinball_audio: @@ -372,84 +478,96 @@ packages: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "075f927ebbab4262ace8d0b283929ac5410c0ac4e7fc123c76429564facfb757" + url: "https://pub.dev" source: hosted version: "2.1.2" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" provider: dependency: transitive description: name: provider - url: "https://pub.dartlang.org" + sha256: "7896193cf752c40ba7f7732a95264319a787871e5d628225357f5c909182bc06" + url: "https://pub.dev" source: hosted version: "6.0.2" shared_preferences: dependency: transitive description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: "1cd0c3c0be0826eb52362ab018a81eed13b616ad9a52548c6ceb1bb349e6b6eb" + url: "https://pub.dev" source: hosted version: "2.0.13" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - url: "https://pub.dartlang.org" + sha256: bc236594233d10b7668dd90414fe0e09d906115aaa1dfe269e478e5f2af532a6 + url: "https://pub.dev" source: hosted version: "2.0.11" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios - url: "https://pub.dartlang.org" + sha256: "69d593a80fee48b97c66787eb930cdd42941c1537e80a1ff88a8c12a926c47d4" + url: "https://pub.dev" source: hosted version: "2.1.0" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.dartlang.org" + sha256: ac361c65c4cf342dfc0a8b9e45eab66b9b3ad6eaff9785850d4ec0cf6b474422 + url: "https://pub.dev" source: hosted version: "2.1.0" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos - url: "https://pub.dartlang.org" + sha256: f063907c3f678de8daa033d234b7c9e420df5fe3d499a97bfb82cc30cf171496 + url: "https://pub.dev" source: hosted version: "2.0.3" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: "992f0fdc46d0a3c0ac2e5859f2de0e577bbe51f78a77ee8f357cbe626a2ad32d" + url: "https://pub.dev" source: hosted version: "2.0.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: "09da0185028a227d51721cade7a3cbd5cc5f163a19593266f2acba87f729bf9c" + url: "https://pub.dev" source: hosted version: "2.0.3" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: ae68cf0df0910e38c95522dbd8a6082ce9715053c369750c5709d17de81d032e + url: "https://pub.dev" source: hosted version: "2.1.0" sky_engine: @@ -461,149 +579,194 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + url: "https://pub.dev" source: hosted - version: "3.0.0+2" + version: "3.1.0+1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + url: "https://pub.dev" source: hosted - version: "0.4.8" + version: "0.7.0" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee" + url: "https://pub.dev" source: hosted version: "1.3.0" url_launcher: dependency: transitive description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: "2d9de5efddbd134ee68d73d0735e7477c00bcbf1ee91afa37514d6c876d38587" + url: "https://pub.dev" source: hosted version: "6.1.0" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + sha256: b693e6698f7e6985710d67a050e3acbdda3b9cfc4b43b9f1c40cdbe42c705b92 + url: "https://pub.dev" source: hosted version: "6.0.15" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + sha256: e51a93f0da65733beb69fdbc43cea524d86ed8e524479e9faefc9304cec34a57 + url: "https://pub.dev" source: hosted version: "6.0.15" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: c3ec89d52305ec647cf037eafe2be8d2f1149b5723d1f2ec716fc3d58469de5d + url: "https://pub.dev" source: hosted version: "3.0.0" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: c028c7f80fdb99cf48b94c471c0f8b9b855a188f4865df76e2a7663ae640e9d2 + url: "https://pub.dev" source: hosted version: "3.0.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: "1b9c4dab07794498b83b5f938e26b20f68c3b460a3015b0307f9541cb34ef93d" + url: "https://pub.dev" source: hosted version: "2.0.5" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "2b5494722d4eb0fe1a12ceb15a4b132ba7dfc92793089c243bf109bed828d97f" + url: "https://pub.dev" source: hosted version: "2.0.9" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: aa14bdb9265fa22416fc387b33e44eb37fd38768bf465fafcec73d283f3457b1 + url: "https://pub.dev" source: hosted version: "3.0.0" uuid: dependency: transitive description: name: uuid - url: "https://pub.dartlang.org" + sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" + url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "4.4.0" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.4" very_good_analysis: dependency: "direct dev" description: name: very_good_analysis - url: "https://pub.dartlang.org" + sha256: cecd7a0e92978dbece97c255502c8965f2db3439cde5a11f4b2c65f1955911ee + url: "https://pub.dev" source: hosted version: "2.4.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + url: "https://pub.dev" + source: hosted + version: "14.2.1" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: "8dd0c450f748d553a8181c6cb9fdf12b987cebaeccdbc75032186b89ae93907b" + url: "https://pub.dev" source: hosted version: "2.4.4" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: "060b6e1c891d956f72b5ac9463466c37cce3fa962a921532fc001e86fe93438e" + url: "https://pub.dev" source: hosted version: "0.2.0+1" sdks: - dart: ">=2.16.0 <3.0.0" - flutter: ">=2.10.0" + dart: ">=3.4.3 <4.0.0" + flutter: ">=3.22.0" diff --git a/packages/pinball_components/sandbox/pubspec.yaml b/packages/pinball_components/sandbox/pubspec.yaml index cbe1c7be..730aaab4 100644 --- a/packages/pinball_components/sandbox/pubspec.yaml +++ b/packages/pinball_components/sandbox/pubspec.yaml @@ -4,17 +4,13 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.1" dependencies: dashbook: ^0.1.7 - flame: ^1.1.1 - flame_bloc: ^1.4.0 - flame_forge2d: - git: - url: https://github.com/flame-engine/flame - path: packages/flame_forge2d/ - ref: a50d4a1e7d9eaf66726ed1bb9894c9d495547d8f + flame: ^1.18.0 + flame_bloc: ^1.12.0 + flame_forge2d: ^0.18.1 flutter: sdk: flutter pinball_components: diff --git a/packages/pinball_components/sandbox/web/index.html b/packages/pinball_components/sandbox/web/index.html index 55e4c8cc..170e9cb9 100644 --- a/packages/pinball_components/sandbox/web/index.html +++ b/packages/pinball_components/sandbox/web/index.html @@ -1,5 +1,6 @@ + - + sandbox + - + + \ No newline at end of file diff --git a/packages/pinball_components/test/helpers/test_game.dart b/packages/pinball_components/test/helpers/test_game.dart index 57c7961c..c96f3c3a 100644 --- a/packages/pinball_components/test/helpers/test_game.dart +++ b/packages/pinball_components/test/helpers/test_game.dart @@ -1,5 +1,4 @@ -import 'package:flame/game.dart'; -import 'package:flame/input.dart'; +import 'package:flame/events.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; class TestGame extends Forge2DGame { @@ -12,7 +11,7 @@ class TestGame extends Forge2DGame { @override Future onLoad() async { if (_assets != null) { - await images.loadAll(_assets!); + await images.loadAll(_assets); } await super.onLoad(); } @@ -22,6 +21,6 @@ class KeyboardTestGame extends TestGame with HasKeyboardHandlerComponents { KeyboardTestGame([List? assets]) : super(assets); } -class TappablesTestGame extends TestGame with HasTappables { +class TappablesTestGame extends TestGame with TapCallbacks { TappablesTestGame([List? assets]) : super(assets); } diff --git a/packages/pinball_components/test/src/components/android_animatronic/behaviors/android_animatronic_ball_contact_behavior_test.dart b/packages/pinball_components/test/src/components/android_animatronic/behaviors/android_animatronic_ball_contact_behavior_test.dart index 4d8bb675..d7d864e2 100644 --- a/packages/pinball_components/test/src/components/android_animatronic/behaviors/android_animatronic_ball_contact_behavior_test.dart +++ b/packages/pinball_components/test/src/components/android_animatronic/behaviors/android_animatronic_ball_contact_behavior_test.dart @@ -11,8 +11,8 @@ import 'package:pinball_components/src/components/android_animatronic/behaviors/ import '../../../../helpers/helpers.dart'; -class _MockAndroidSpaceshipCubit extends Mock implements AndroidSpaceshipCubit { -} +class _MockAndroidSpaceshipCubit extends Mock + implements AndroidSpaceshipCubit {} class _MockBall extends Mock implements Ball {} @@ -32,9 +32,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'beginContact calls onBallContacted when in contact with a ball', - (game) async { + setUp: (game, _) async { final behavior = AndroidAnimatronicBallContactBehavior(); final bloc = _MockAndroidSpaceshipCubit(); whenListen( @@ -48,12 +48,24 @@ void main() { AndroidSpaceshipState>.value( value: bloc, children: [ - AndroidSpaceship.test(children: [animatronic]) + AndroidSpaceship.test(children: [animatronic]), ], ); await animatronic.add(behavior); await game.ensureAdd(androidSpaceship); - + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; behavior.beginContact(_MockBall(), _MockContact()); verify(bloc.onBallContacted).called(1); diff --git a/packages/pinball_components/test/src/components/android_animatronic_test.dart b/packages/pinball_components/test/src/components/android_animatronic_test.dart index 55b564fe..a0b27ca3 100644 --- a/packages/pinball_components/test/src/components/android_animatronic_test.dart +++ b/packages/pinball_components/test/src/components/android_animatronic_test.dart @@ -18,15 +18,19 @@ void main() { 'renders correctly', setUp: (game, tester) async { await game.images.load(asset); - await game.ensureAdd(AndroidAnimatronic()); - game.camera.followVector2(Vector2.zero()); + await game.world.ensureAdd(AndroidAnimatronic()); + game.camera.moveTo(Vector2.zero()); await tester.pump(); }, verify: (game, tester) async { final animationDuration = game - .firstChild()! - .firstChild()! - .animation! + .descendants() + .whereType() + .single + .descendants() + .whereType() + .single + .animationTicker! .totalDuration(); await expectLater( @@ -50,35 +54,54 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final androidAnimatronic = AndroidAnimatronic(); await game.ensureAdd(androidAnimatronic); - expect(game.contains(androidAnimatronic), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); group('adds', () { - flameTester.test('new children', (game) async { - final component = Component(); - final androidAnimatronic = AndroidAnimatronic( - children: [component], - ); - await game.ensureAdd(androidAnimatronic); - expect(androidAnimatronic.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + final component = Component(); + final androidAnimatronic = AndroidAnimatronic( + children: [component], + ); + await game.ensureAdd(androidAnimatronic); + }, + verify: (game, _) async { + final androidAnimatronic = + game.descendants().whereType().single; + expect( + androidAnimatronic.children.whereType(), + isNotEmpty, + ); + }, + ); - flameTester.test('a AndroidAnimatronicBallContactBehavior', (game) async { - final androidAnimatronic = AndroidAnimatronic(); - await game.ensureAdd(androidAnimatronic); - expect( - androidAnimatronic.children - .whereType() - .single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a AndroidAnimatronicBallContactBehavior', + setUp: (game, _) async { + final androidAnimatronic = AndroidAnimatronic(); + await game.ensureAdd(androidAnimatronic); + }, + verify: (game, _) async { + final androidAnimatronic = + game.descendants().whereType().single; + expect( + androidAnimatronic.children + .whereType() + .single, + isNotNull, + ); + }, + ); }); }); } diff --git a/packages/pinball_components/test/src/components/android_bumper/android_bumper_test.dart b/packages/pinball_components/test/src/components/android_bumper/android_bumper_test.dart index 52e196dc..e58d844c 100644 --- a/packages/pinball_components/test/src/components/android_bumper/android_bumper_test.dart +++ b/packages/pinball_components/test/src/components/android_bumper/android_bumper_test.dart @@ -26,123 +26,225 @@ void main() { final flameTester = FlameTester(() => TestGame(assets)); group('AndroidBumper', () { - flameTester.test('"a" loads correctly', (game) async { - final androidBumper = AndroidBumper.a(); - await game.ensureAdd(androidBumper); - expect(game.contains(androidBumper), isTrue); - }); - - flameTester.test('"b" loads correctly', (game) async { - final androidBumper = AndroidBumper.b(); - await game.ensureAdd(androidBumper); - expect(game.contains(androidBumper), isTrue); - }); - - flameTester.test('"cow" loads correctly', (game) async { - final androidBumper = AndroidBumper.cow(); - await game.ensureAdd(androidBumper); - expect(game.contains(androidBumper), isTrue); - }); - - flameTester.test('closes bloc when removed', (game) async { - final bloc = _MockAndroidBumperCubit(); - whenListen( - bloc, - const Stream.empty(), - initialState: AndroidBumperState.lit, - ); - when(bloc.close).thenAnswer((_) async {}); - final androidBumper = AndroidBumper.test(bloc: bloc); - - await game.ensureAdd(androidBumper); - game.remove(androidBumper); - await game.ready(); - - verify(bloc.close).called(1); - }); - - group('adds', () { - flameTester.test('an AndroidBumperBallContactBehavior', (game) async { + flameTester.testGameWidget( + '"a" loads correctly', + setUp: (game, _) async { + await game.onLoad(); final androidBumper = AndroidBumper.a(); await game.ensureAdd(androidBumper); - expect( - androidBumper.children - .whereType() - .single, - isNotNull, + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); + + flameTester.testGameWidget( + '"b" loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final androidBumper = AndroidBumper.b(); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); + + flameTester.testGameWidget( + '"cow" loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final androidBumper = AndroidBumper.cow(); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); + + flameTester.testGameWidget( + 'closes bloc when removed', + setUp: (game, _) async { + await game.onLoad(); + final bloc = _MockAndroidBumperCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: AndroidBumperState.lit, ); - }); + when(bloc.close).thenAnswer((_) async {}); + final androidBumper = AndroidBumper.test(bloc: bloc); - flameTester.test('an AndroidBumperBlinkingBehavior', (game) async { - final androidBumper = AndroidBumper.a(); await game.ensureAdd(androidBumper); - expect( - androidBumper.children - .whereType() - .single, - isNotNull, - ); - }); + await game.ready(); + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + final bloc = androidBumper.bloc; + game.remove(androidBumper); + game.update(0); + expect(game.descendants().whereType(), isEmpty); + verify(bloc.close).called(1); + }, + ); + + group('adds', () { + flameTester.testGameWidget( + 'an AndroidBumperBallContactBehavior', + setUp: (game, _) async { + await game.onLoad(); + final androidBumper = AndroidBumper.a(); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + expect( + androidBumper.children + .whereType(), + isNotEmpty, + ); + }, + ); + + flameTester.testGameWidget( + 'an AndroidBumperBlinkingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final androidBumper = AndroidBumper.a(); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + expect( + androidBumper.children + .whereType() + .single, + isNotNull, + ); + }, + ); }); group("'a' adds", () { - flameTester.test('new children', (game) async { - final component = Component(); - final androidBumper = AndroidBumper.a( - children: [component], - ); - await game.ensureAdd(androidBumper); - expect(androidBumper.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final androidBumper = AndroidBumper.a( + children: [component], + ); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + expect(androidBumper.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a BumpingBehavior', (game) async { - final androidBumper = AndroidBumper.a(); - await game.ensureAdd(androidBumper); - expect( - androidBumper.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final androidBumper = AndroidBumper.a(); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + expect( + androidBumper.children.whereType().single, + isNotNull, + ); + }, + ); }); group("'b' adds", () { - flameTester.test('new children', (game) async { - final component = Component(); - final androidBumper = AndroidBumper.b( - children: [component], - ); - await game.ensureAdd(androidBumper); - expect(androidBumper.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final androidBumper = AndroidBumper.b( + children: [component], + ); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + expect(androidBumper.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a BumpingBehavior', (game) async { - final androidBumper = AndroidBumper.b(); - await game.ensureAdd(androidBumper); - expect( - androidBumper.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final androidBumper = AndroidBumper.b(); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + expect( + androidBumper.children.whereType().single, + isNotNull, + ); + }, + ); }); group("'cow' adds", () { - flameTester.test('new children', (game) async { - final component = Component(); - final androidBumper = AndroidBumper.cow( - children: [component], - ); - await game.ensureAdd(androidBumper); - expect(androidBumper.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final androidBumper = AndroidBumper.cow( + children: [component], + ); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + expect(androidBumper.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a BumpingBehavior', (game) async { - final androidBumper = AndroidBumper.cow(); - await game.ensureAdd(androidBumper); - expect( - androidBumper.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final androidBumper = AndroidBumper.cow(); + await game.ensureAdd(androidBumper); + await game.ready(); + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + expect( + androidBumper.children.whereType().single, + isNotNull, + ); + }, + ); }); }); } diff --git a/packages/pinball_components/test/src/components/android_bumper/behaviors/android_bumper_ball_contact_behavior_test.dart b/packages/pinball_components/test/src/components/android_bumper/behaviors/android_bumper_ball_contact_behavior_test.dart index 8c44a199..2fbfd1a7 100644 --- a/packages/pinball_components/test/src/components/android_bumper/behaviors/android_bumper_ball_contact_behavior_test.dart +++ b/packages/pinball_components/test/src/components/android_bumper/behaviors/android_bumper_ball_contact_behavior_test.dart @@ -30,9 +30,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'beginContact emits onBallContacted when contacts with a ball', - (game) async { + setUp: (game, _) async { final behavior = AndroidBumperBallContactBehavior(); final bloc = _MockAndroidBumperCubit(); whenListen( @@ -44,7 +44,14 @@ void main() { final androidBumper = AndroidBumper.test(bloc: bloc); await androidBumper.add(behavior); await game.ensureAdd(androidBumper); - + }, + verify: (game, _) async { + final androidBumper = + game.descendants().whereType().single; + final behavior = game + .descendants() + .whereType() + .single; behavior.beginContact(_MockBall(), _MockContact()); verify(androidBumper.bloc.onBallContacted).called(1); diff --git a/packages/pinball_components/test/src/components/android_spaceship/android_spaceship_test.dart b/packages/pinball_components/test/src/components/android_spaceship/android_spaceship_test.dart index a282865c..1ff2ebab 100644 --- a/packages/pinball_components/test/src/components/android_spaceship/android_spaceship_test.dart +++ b/packages/pinball_components/test/src/components/android_spaceship/android_spaceship_test.dart @@ -10,8 +10,8 @@ import 'package:pinball_flame/pinball_flame.dart'; import '../../../helpers/helpers.dart'; -class _MockAndroidSpaceshipCubit extends Mock implements AndroidSpaceshipCubit { -} +class _MockAndroidSpaceshipCubit extends Mock + implements AndroidSpaceshipCubit {} void main() { group('AndroidSpaceship', () { @@ -26,15 +26,25 @@ void main() { bloc = _MockAndroidSpaceshipCubit(); }); - flameTester.test('loads correctly', (game) async { - final component = - FlameBlocProvider.value( - value: bloc, - children: [AndroidSpaceship(position: Vector2.zero())], - ); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = FlameBlocProvider.value( + value: bloc, + children: [AndroidSpaceship(position: Vector2.zero())], + ); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect( + game.descendants().whereType< + FlameBlocProvider>(), + isNotEmpty, + ); + }, + ); flameTester.testGameWidget( 'renders correctly', @@ -49,8 +59,8 @@ void main() { ), ], ); - await game.ensureAdd(canvas); - game.camera.followVector2(Vector2.zero()); + await game.world.ensureAdd(canvas); + game.camera.moveTo(Vector2.zero()); await game.ready(); await tester.pump(); }, @@ -60,7 +70,7 @@ void main() { .descendants() .whereType() .single - .animation! + .animationTicker! .totalDuration(); await expectLater( diff --git a/packages/pinball_components/test/src/components/arcade_background/arcade_background_test.dart b/packages/pinball_components/test/src/components/arcade_background/arcade_background_test.dart index a5c336d5..3d577496 100644 --- a/packages/pinball_components/test/src/components/arcade_background/arcade_background_test.dart +++ b/packages/pinball_components/test/src/components/arcade_background/arcade_background_test.dart @@ -28,50 +28,56 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { - final ball = ArcadeBackground(); + setUp: (game, _) async { + final background = ArcadeBackground(); await game.ready(); - await game.ensureAdd(ball); - - expect(game.contains(ball), isTrue); + await game.ensureAdd(background); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); - flameTester.test( + flameTester.testGameWidget( 'has only one SpriteComponent', - (game) async { - final ball = ArcadeBackground(); + setUp: (game, _) async { + final background = ArcadeBackground(); await game.ready(); - await game.ensureAdd(ball); - + await game.ensureAdd(background); + }, + verify: (game, _) async { + final background = + game.descendants().whereType().single; expect( - ball.descendants().whereType().length, + background.descendants().whereType().length, equals(1), ); }, ); - flameTester.test( + flameTester.testGameWidget( 'ArcadeBackgroundSpriteComponent changes sprite onNewState', - (game) async { - final ball = ArcadeBackground(); + setUp: (game, _) async { + final background = ArcadeBackground(); + await game.onLoad(); await game.ready(); - await game.ensureAdd(ball); - - final ballSprite = ball + await game.ensureAdd(background); + }, + verify: (game, _) async { + final background = + game.descendants().whereType().single; + final backgroundSprite = background .descendants() .whereType() .single; - final originalSprite = ballSprite.sprite; - - ballSprite.onNewState( + final originalSprite = backgroundSprite.sprite; + backgroundSprite.onNewState( const ArcadeBackgroundState(characterTheme: theme.DinoTheme()), ); - await game.ready(); - - final newSprite = ballSprite.sprite; + game.update(0); + final newSprite = backgroundSprite.sprite; expect(newSprite != originalSprite, isTrue); }, ); diff --git a/packages/pinball_components/test/src/components/arrow_icon_test.dart b/packages/pinball_components/test/src/components/arrow_icon_test.dart index c8a1c5aa..96cef188 100644 --- a/packages/pinball_components/test/src/components/arrow_icon_test.dart +++ b/packages/pinball_components/test/src/components/arrow_icon_test.dart @@ -50,8 +50,8 @@ void main() { 'renders correctly', setUp: (game, tester) async { await game.images.loadAll(assets); - game.camera.followVector2(Vector2.zero()); - await game.add( + game.camera.moveTo(Vector2.zero()); + await game.world.add( ArrowIcon( position: Vector2.zero(), direction: ArrowIconDirection.left, @@ -74,8 +74,8 @@ void main() { 'renders correctly', setUp: (game, tester) async { await game.images.loadAll(assets); - game.camera.followVector2(Vector2.zero()); - await game.add( + game.camera.moveTo(Vector2.zero()); + await game.world.add( ArrowIcon( position: Vector2.zero(), direction: ArrowIconDirection.right, diff --git a/packages/pinball_components/test/src/components/ball/ball_test.dart b/packages/pinball_components/test/src/components/ball/ball_test.dart index 9bf0bf27..b65b5742 100644 --- a/packages/pinball_components/test/src/components/ball/ball_test.dart +++ b/packages/pinball_components/test/src/components/ball/ball_test.dart @@ -30,24 +30,29 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final ball = Ball(); - await game.ready(); await game.ensureAdd(ball); - - expect(game.contains(ball), isTrue); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); - flameTester.test( + flameTester.testGameWidget( 'has only one SpriteComponent', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final ball = Ball(); - await game.ready(); await game.ensureAdd(ball); - + await game.ready(); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; expect( ball.descendants().whereType().length, equals(1), @@ -55,13 +60,16 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'BallSpriteComponent changes sprite onNewState', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final ball = Ball(); - await game.ready(); await game.ensureAdd(ball); - + await game.ready(); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; final ballSprite = ball.descendants().whereType().single; final originalSprite = ballSprite.sprite; @@ -69,7 +77,7 @@ void main() { ballSprite.onNewState( const BallState(characterTheme: theme.DinoTheme()), ); - await game.ready(); + game.update(0); final newSprite = ballSprite.sprite; expect(newSprite != originalSprite, isTrue); @@ -77,84 +85,120 @@ void main() { ); group('adds', () { - flameTester.test('a BallScalingBehavior', (game) async { - final ball = Ball(); - await game.ensureAdd(ball); - expect( - ball.descendants().whereType().length, - equals(1), - ); - }); + flameTester.testGameWidget( + 'a BallScalingBehavior', + setUp: (game, _) async { + final ball = Ball(); + await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; + expect( + ball.descendants().whereType().length, + equals(1), + ); + }, + ); - flameTester.test('a BallGravitatingBehavior', (game) async { - final ball = Ball(); - await game.ensureAdd(ball); - expect( - ball.descendants().whereType().length, - equals(1), - ); - }); + flameTester.testGameWidget( + 'a BallGravitatingBehavior', + setUp: (game, _) async { + final ball = Ball(); + await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; + expect( + ball.descendants().whereType().length, + equals(1), + ); + }, + ); }); group('body', () { - flameTester.test( + flameTester.testGameWidget( 'is dynamic', - (game) async { + setUp: (game, _) async { final ball = Ball(); await game.ensureAdd(ball); - + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; expect(ball.body.bodyType, equals(BodyType.dynamic)); }, ); group('can be moved', () { - flameTester.test('by its weight', (game) async { - final ball = Ball(); - await game.ensureAdd(ball); + flameTester.testGameWidget( + 'by its weight', + setUp: (game, _) async { + final ball = Ball(); + await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; - game.update(1); - expect(ball.body.position, isNot(equals(ball.initialPosition))); - }); + game.update(1); + expect(ball.body.position, isNot(equals(ball.initialPosition))); + }, + ); - flameTester.test('by applying velocity', (game) async { - final ball = Ball(); - await game.ensureAdd(ball); + flameTester.testGameWidget( + 'by applying velocity', + setUp: (game, _) async { + final ball = Ball(); + await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; - ball.body.gravityScale = Vector2.zero(); - ball.body.linearVelocity.setValues(10, 10); - game.update(1); - expect(ball.body.position, isNot(equals(ball.initialPosition))); - }); + ball.body.gravityScale = Vector2.zero(); + ball.body.linearVelocity.setValues(10, 10); + game.update(1); + expect(ball.body.position, isNot(equals(ball.initialPosition))); + }, + ); }); }); group('fixture', () { - flameTester.test( + flameTester.testGameWidget( 'exists', - (game) async { + setUp: (game, _) async { final ball = Ball(); await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; expect(ball.body.fixtures[0], isA()); }, ); - flameTester.test( + flameTester.testGameWidget( 'is dense', - (game) async { + setUp: (game, _) async { final ball = Ball(); await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; final fixture = ball.body.fixtures[0]; expect(fixture.density, greaterThan(0)); }, ); - flameTester.test( + flameTester.testGameWidget( 'shape is circular', - (game) async { - final ball = Ball(); - await game.ensureAdd(ball); + setUp: (game, _) async { + final ball = Ball.test(); + await game.world.ensureAdd(ball); + await game.ready(); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; final fixture = ball.body.fixtures[0]; expect(fixture.shape.shapeType, equals(ShapeType.circle)); @@ -162,13 +206,14 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'has Layer.all as default filter maskBits', - (game) async { + setUp: (game, _) async { final ball = Ball(); - await game.ready(); await game.ensureAdd(ball); - await game.ready(); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; final fixture = ball.body.fixtures[0]; expect(fixture.filterData.maskBits, equals(Layer.board.maskBits)); @@ -178,24 +223,33 @@ void main() { group('stop', () { group("can't be moved", () { - flameTester.test('by its weight', (game) async { - final ball = Ball(); - await game.ensureAdd(ball); - ball.stop(); + flameTester.testGameWidget( + 'by its weight', + setUp: (game, _) async { + final ball = Ball(); + await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; + ball.stop(); - game.update(1); - expect(ball.body.position, equals(ball.initialPosition)); - }); + game.update(1); + expect(ball.body.position, equals(ball.initialPosition)); + }, + ); }); }); group('resume', () { group('can move', () { - flameTester.test( + flameTester.testGameWidget( 'by its weight when previously stopped', - (game) async { + setUp: (game, _) async { final ball = Ball(); await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; ball.stop(); ball.resume(); @@ -204,11 +258,14 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'by applying velocity when previously stopped', - (game) async { + setUp: (game, _) async { final ball = Ball(); await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; ball.stop(); ball.resume(); diff --git a/packages/pinball_components/test/src/components/ball/behaviors/ball_gravitating_behavior_test.dart b/packages/pinball_components/test/src/components/ball/behaviors/ball_gravitating_behavior_test.dart index ce193dc8..136d832e 100644 --- a/packages/pinball_components/test/src/components/ball/behaviors/ball_gravitating_behavior_test.dart +++ b/packages/pinball_components/test/src/components/ball/behaviors/ball_gravitating_behavior_test.dart @@ -21,20 +21,26 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final ball = Ball.test(); - final behavior = BallGravitatingBehavior(); - await ball.add(behavior); - await game.ensureAdd(ball); - expect( - ball.firstChild(), - equals(behavior), - ); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final ball = Ball.test(); + final behavior = BallGravitatingBehavior(); + await ball.add(behavior); + await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; + expect( + ball.firstChild(), + isNotNull, + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( "overrides the body's horizontal gravity symmetrically", - (game) async { + setUp: (game, _) async { final ball1 = Ball.test()..initialPosition = Vector2(10, 0); await ball1.add(BallGravitatingBehavior()); @@ -42,15 +48,18 @@ void main() { await ball2.add(BallGravitatingBehavior()); await game.ensureAddAll([ball1, ball2]); + }, + verify: (game, _) async { + final balls = game.descendants().whereType().toList(); game.update(1); expect( - ball1.body.gravityOverride!.x, - equals(-ball2.body.gravityOverride!.x), + balls[0].body.gravityOverride!.x, + equals(-balls[1].body.gravityOverride!.x), ); expect( - ball1.body.gravityOverride!.y, - equals(ball2.body.gravityOverride!.y), + balls[0].body.gravityOverride!.y, + equals(balls[1].body.gravityOverride!.y), ); }, ); diff --git a/packages/pinball_components/test/src/components/ball/behaviors/ball_implusing_behavior_test.dart b/packages/pinball_components/test/src/components/ball/behaviors/ball_implusing_behavior_test.dart index 53ab4553..a44c2514 100644 --- a/packages/pinball_components/test/src/components/ball/behaviors/ball_implusing_behavior_test.dart +++ b/packages/pinball_components/test/src/components/ball/behaviors/ball_implusing_behavior_test.dart @@ -24,27 +24,31 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'impulses the ball with the given velocity when loaded ' 'and then removes itself', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final ball = Ball.test(); await game.ensureAdd(ball); final impulse = Vector2.all(1); final behavior = BallImpulsingBehavior(impulse: impulse); await ball.ensureAdd(behavior); - + await game.ready(); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; expect( ball.body.linearVelocity.x, - equals(impulse.x), + equals(1), ); expect( ball.body.linearVelocity.y, - equals(impulse.y), + equals(1), ); expect( - game.descendants().whereType().isEmpty, - isTrue, + game.descendants().whereType(), + isEmpty, ); }, ); diff --git a/packages/pinball_components/test/src/components/ball/behaviors/ball_scaling_behavior_test.dart b/packages/pinball_components/test/src/components/ball/behaviors/ball_scaling_behavior_test.dart index 1fe84ae4..0efc7c8e 100644 --- a/packages/pinball_components/test/src/components/ball/behaviors/ball_scaling_behavior_test.dart +++ b/packages/pinball_components/test/src/components/ball/behaviors/ball_scaling_behavior_test.dart @@ -22,38 +22,50 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final ball = Ball.test(); - final behavior = BallScalingBehavior(); - await ball.add(behavior); - await game.ensureAdd(ball); - expect( - ball.firstChild(), - equals(behavior), - ); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final ball = Ball.test(); + final behavior = BallScalingBehavior(); + await ball.add(behavior); + await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; + expect( + ball.firstChild(), + isNotNull, + ); + }, + ); - flameTester.test('scales the shape radius', (game) async { - final ball1 = Ball.test()..initialPosition = Vector2(0, 10); - await ball1.add(BallScalingBehavior()); + flameTester.testGameWidget( + 'scales the shape radius', + setUp: (game, _) async { + final ball1 = Ball.test()..initialPosition = Vector2(0, 10); + await ball1.add(BallScalingBehavior()); - final ball2 = Ball.test()..initialPosition = Vector2(0, -10); - await ball2.add(BallScalingBehavior()); + final ball2 = Ball.test()..initialPosition = Vector2(0, -10); + await ball2.add(BallScalingBehavior()); - await game.ensureAddAll([ball1, ball2]); - game.update(1); + await game.ensureAddAll([ball1, ball2]); + }, + verify: (game, _) async { + final balls = game.descendants().whereType().toList(); + game.update(1); - final shape1 = ball1.body.fixtures.first.shape; - final shape2 = ball2.body.fixtures.first.shape; - expect( - shape1.radius, - greaterThan(shape2.radius), - ); - }); + final shape1 = balls[0].body.fixtures.first.shape; + final shape2 = balls[1].body.fixtures.first.shape; + expect( + shape1.radius, + greaterThan(shape2.radius), + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'scales the sprite', - (game) async { + setUp: (game, _) async { final ball1 = Ball.test()..initialPosition = Vector2(0, 10); await ball1.add(BallScalingBehavior()); @@ -61,10 +73,15 @@ void main() { await ball2.add(BallScalingBehavior()); await game.ensureAddAll([ball1, ball2]); + }, + verify: (game, _) async { + final balls = game.descendants().whereType().toList(); game.update(1); - final sprite1 = ball1.descendants().whereType().single; - final sprite2 = ball2.descendants().whereType().single; + final sprite1 = + balls[0].descendants().whereType().single; + final sprite2 = + balls[1].descendants().whereType().single; expect( sprite1.scale.x, greaterThan(sprite2.scale.x), diff --git a/packages/pinball_components/test/src/components/ball/behaviors/ball_turbo_charging_behavior_test.dart b/packages/pinball_components/test/src/components/ball/behaviors/ball_turbo_charging_behavior_test.dart index 09eabe0e..f043cb5d 100644 --- a/packages/pinball_components/test/src/components/ball/behaviors/ball_turbo_charging_behavior_test.dart +++ b/packages/pinball_components/test/src/components/ball/behaviors/ball_turbo_charging_behavior_test.dart @@ -27,68 +27,89 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final ball = Ball.test(); - final behavior = BallTurboChargingBehavior(impulse: Vector2.zero()); - await ball.add(behavior); - await game.ensureAdd(ball); - expect( - ball.firstChild(), - equals(behavior), - ); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final ball = Ball.test(); + final behavior = BallTurboChargingBehavior(impulse: Vector2.zero()); + await ball.add(behavior); + await game.ensureAdd(ball); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; + expect( + ball.firstChild(), + isNotNull, + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'impulses the ball velocity when loaded', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final ball = Ball.test(); await game.ensureAdd(ball); final impulse = Vector2.all(1); final behavior = BallTurboChargingBehavior(impulse: impulse); await ball.ensureAdd(behavior); - + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; expect( ball.body.linearVelocity.x, - equals(impulse.x), + equals(1), ); expect( ball.body.linearVelocity.y, - equals(impulse.y), + equals(1), ); }, ); - flameTester.test('adds sprite', (game) async { - final ball = Ball(); - await game.ensureAdd(ball); - - await ball.ensureAdd( - BallTurboChargingBehavior(impulse: Vector2.zero()), - ); - - expect( - ball.children.whereType().single, - isNotNull, - ); - }); - - flameTester.test('removes sprite after it finishes', (game) async { - final ball = Ball(); - await game.ensureAdd(ball); - - final behavior = BallTurboChargingBehavior(impulse: Vector2.zero()); - await ball.ensureAdd(behavior); - - final turboChargeSpriteAnimation = - ball.children.whereType().single; - - expect(ball.contains(turboChargeSpriteAnimation), isTrue); + flameTester.testGameWidget( + 'adds sprite', + setUp: (game, _) async { + await game.onLoad(); + final ball = Ball(); + await game.ensureAdd(ball); + await ball.ensureAdd( + BallTurboChargingBehavior(impulse: Vector2.zero()), + ); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; + expect( + ball.children.whereType().single, + isNotNull, + ); + }, + ); - game.update(behavior.timer.limit); - game.update(0.1); + flameTester.testGameWidget( + 'removes sprite after it finishes', + setUp: (game, _) async { + await game.onLoad(); + final ball = Ball(); + await game.ensureAdd(ball); - expect(ball.contains(turboChargeSpriteAnimation), isFalse); - }); + final behavior = BallTurboChargingBehavior(impulse: Vector2.zero()); + await ball.ensureAdd(behavior); + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; + final turboChargeSpriteAnimation = + ball.children.whereType().single; + final behavior = + game.descendants().whereType().single; + expect(ball.contains(turboChargeSpriteAnimation), isTrue); + + game.update(behavior.timer.limit); + game.update(0.1); + + expect(ball.contains(turboChargeSpriteAnimation), isFalse); + }, + ); }, ); } diff --git a/packages/pinball_components/test/src/components/baseboard_test.dart b/packages/pinball_components/test/src/components/baseboard_test.dart index 101e3e21..a2808eaa 100644 --- a/packages/pinball_components/test/src/components/baseboard_test.dart +++ b/packages/pinball_components/test/src/components/baseboard_test.dart @@ -27,8 +27,8 @@ void main() { side: BoardSide.right, )..initialPosition = Vector2(20, 0); - await game.ensureAddAll([leftBaseboard, rightBaseboard]); - game.camera.followVector2(Vector2.zero()); + await game.world.ensureAddAll([leftBaseboard, rightBaseboard]); + game.camera.moveTo(Vector2.zero()); await tester.pump(); }, verify: (game, tester) async { @@ -39,9 +39,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { await game.ready(); final leftBaseboard = Baseboard( side: BoardSide.left, @@ -51,29 +51,31 @@ void main() { ); await game.ensureAddAll([leftBaseboard, rightBaseboard]); - - expect(game.contains(leftBaseboard), isTrue); - expect(game.contains(rightBaseboard), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(2)); }, ); group('body', () { - flameTester.test( + flameTester.testGameWidget( 'is static', - (game) async { + setUp: (game, _) async { final baseboard = Baseboard( side: BoardSide.left, ); await game.ensureAdd(baseboard); - + }, + verify: (game, _) async { + final baseboard = game.descendants().whereType().single; expect(baseboard.body.bodyType, equals(BodyType.static)); }, ); - flameTester.test( + flameTester.testGameWidget( 'is at an angle', - (game) async { + setUp: (game, _) async { final leftBaseboard = Baseboard( side: BoardSide.left, ); @@ -81,22 +83,27 @@ void main() { side: BoardSide.right, ); await game.ensureAddAll([leftBaseboard, rightBaseboard]); + }, + verify: (game, _) async { + final baseboards = game.descendants().whereType().toList(); - expect(leftBaseboard.body.angle, isPositive); - expect(rightBaseboard.body.angle, isNegative); + expect(baseboards[0].body.angle, isPositive); + expect(baseboards[1].body.angle, isNegative); }, ); }); group('fixtures', () { - flameTester.test( + flameTester.testGameWidget( 'has seven', - (game) async { + setUp: (game, _) async { final baseboard = Baseboard( side: BoardSide.left, ); await game.ensureAdd(baseboard); - + }, + verify: (game, _) async { + final baseboard = game.descendants().whereType().single; expect(baseboard.body.fixtures.length, equals(7)); }, ); diff --git a/packages/pinball_components/test/src/components/board_background_sprite_component_test.dart b/packages/pinball_components/test/src/components/board_background_sprite_component_test.dart index 79e8c56b..f1b87ee5 100644 --- a/packages/pinball_components/test/src/components/board_background_sprite_component_test.dart +++ b/packages/pinball_components/test/src/components/board_background_sprite_component_test.dart @@ -15,13 +15,18 @@ void main() { final flameTester = FlameTester(() => TestGame(assets)); group('BoardBackgroundSpriteComponent', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { + await game.images.loadAll(assets); final boardBackground = BoardBackgroundSpriteComponent(); await game.ensureAdd(boardBackground); - - expect(game.contains(boardBackground), isTrue); + }, + verify: (game, _) async { + expect( + game.descendants().whereType(), + isNotEmpty, + ); }, ); @@ -30,12 +35,12 @@ void main() { setUp: (game, tester) async { await game.images.loadAll(assets); final boardBackground = BoardBackgroundSpriteComponent(); - await game.ensureAdd(boardBackground); + await game.world.ensureAdd(boardBackground); await tester.pump(); game.camera - ..followVector2(Vector2.zero()) - ..zoom = 3.7; + ..moveTo(Vector2.zero()) + ..viewfinder.zoom = 3.7; }, verify: (game, tester) async { await expectLater( diff --git a/packages/pinball_components/test/src/components/boundaries_test.dart b/packages/pinball_components/test/src/components/boundaries_test.dart index c119719e..0b179633 100644 --- a/packages/pinball_components/test/src/components/boundaries_test.dart +++ b/packages/pinball_components/test/src/components/boundaries_test.dart @@ -1,6 +1,6 @@ // ignore_for_file: cascade_invocations -import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame/components.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -19,21 +19,26 @@ void main() { ]; final flameTester = FlameTester(() => TestGame(assets)); - flameTester.test('loads correctly', (game) async { - final component = Boundaries(); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = Boundaries(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); + }, + ); flameTester.testGameWidget( 'render correctly', setUp: (game, tester) async { await game.images.loadAll(assets); final canvas = ZCanvasComponent(children: [Boundaries()]); - await game.ensureAdd(canvas); + await game.world.ensureAdd(canvas); - game.camera.followVector2(Vector2.zero()); - game.camera.zoom = 3.2; + game.camera.moveTo(Vector2.zero()); + game.camera.viewfinder.zoom = 3.2; await tester.pump(); }, verify: (game, tester) async { diff --git a/packages/pinball_components/test/src/components/bumping_behavior_test.dart b/packages/pinball_components/test/src/components/bumping_behavior_test.dart index 7a87a46c..e44eecd9 100644 --- a/packages/pinball_components/test/src/components/bumping_behavior_test.dart +++ b/packages/pinball_components/test/src/components/bumping_behavior_test.dart @@ -16,7 +16,7 @@ class _TestBodyComponent extends BodyComponent { @override Body createBody() => world.createBody( BodyDef(type: BodyType.dynamic), - )..createFixtureFromShape(CircleShape(), 1); + )..createFixtureFromShape(CircleShape()); } void main() { @@ -38,12 +38,21 @@ void main() { ); }); - flameTester.test('can be added', (game) async { - final behavior = BumpingBehavior(strength: 0); - final component = _TestBodyComponent(); - await component.add(behavior); - await game.ensureAdd(component); - }); + flameTester.testGameWidget( + 'can be added', + setUp: (game, _) async { + final behavior = BumpingBehavior(strength: 0); + final component = _TestBodyComponent(); + await component.add(behavior); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); flameTester.testGameWidget( 'the bump is greater when the strength is greater', diff --git a/packages/pinball_components/test/src/components/camera_zoom_test.dart b/packages/pinball_components/test/src/components/camera_zoom_test.dart index a7f64eca..c0d18159 100644 --- a/packages/pinball_components/test/src/components/camera_zoom_test.dart +++ b/packages/pinball_components/test/src/components/camera_zoom_test.dart @@ -14,13 +14,13 @@ void main() { tester.testGameWidget( 'renders correctly', setUp: (game, tester) async { - game.camera.followVector2(Vector2.zero()); - game.camera.zoom = 10; + game.camera.moveTo(Vector2.zero()); + game.camera.viewfinder.zoom = 10; final sprite = await game.loadSprite( Assets.images.signpost.inactive.keyName, ); - await game.add( + await game.world.add( SpriteComponent( sprite: sprite, size: Vector2(4, 8), @@ -56,29 +56,33 @@ void main() { }, ); - tester.test( + tester.testGameWidget( 'completes when checked after it is finished', - (game) async { + setUp: (game, _) async { await game.add(CameraZoom(value: 40)); + }, + verify: (game, _) async { game.update(10); - final cameraZoom = game.firstChild(); - final future = cameraZoom!.completed; + final cameraZoom = game.descendants().whereType().single; + final future = cameraZoom.completed; expect(future, completes); }, ); - tester.test( + tester.testGameWidget( 'completes when checked before it is finished', - (game) async { + setUp: (game, _) async { final zoom = CameraZoom(value: 40); - final future = zoom.completed; - await game.add(zoom); + }, + verify: (game, _) async { + final cameraZoom = game.descendants().whereType().single; + final completed = cameraZoom.completed; game.update(10); game.update(0); - expect(future, completes); + expect(completed, completes); }, ); }); diff --git a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior_test.dart b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior_test.dart index f5fd2b42..8f6a9a96 100644 --- a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior_test.dart +++ b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_chomping_behavior_test.dart @@ -35,9 +35,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'beginContact sets ball sprite to be invisible and calls onChomp', - (game) async { + setUp: (game, _) async { final ball = Ball(); final behavior = ChromeDinoChompingBehavior(); final bloc = _MockChromeDinoCubit(); @@ -53,11 +53,16 @@ void main() { final chromeDino = ChromeDino.test(bloc: bloc); await chromeDino.add(behavior); await game.ensureAddAll([chromeDino, ball]); - + }, + verify: (game, _) async { final contact = _MockContact(); final fixture = _MockFixture(); when(() => contact.fixtureA).thenReturn(fixture); when(() => fixture.userData).thenReturn('inside_mouth'); + final behavior = + game.descendants().whereType().single; + final ball = game.descendants().whereType().single; + final bloc = game.descendants().whereType().single.bloc; behavior.beginContact(ball, contact); diff --git a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_mouth_opening_behavior_test.dart b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_mouth_opening_behavior_test.dart index 69f57114..820f30ef 100644 --- a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_mouth_opening_behavior_test.dart +++ b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_mouth_opening_behavior_test.dart @@ -32,10 +32,10 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'preSolve disables contact when the mouth is open ' 'and there is not ball in the mouth', - (game) async { + setUp: (game, _) async { final behavior = ChromeDinoMouthOpeningBehavior(); final bloc = _MockChromeDinoCubit(); whenListen( @@ -50,15 +50,19 @@ void main() { final chromeDino = ChromeDino.test(bloc: bloc); await chromeDino.add(behavior); await game.ensureAdd(chromeDino); - + }, + verify: (game, _) async { final contact = _MockContact(); final fixture = _MockFixture(); when(() => contact.fixtureA).thenReturn(fixture); when(() => fixture.userData).thenReturn('mouth_opening'); + final behavior = game + .descendants() + .whereType() + .single; behavior.preSolve(_MockBall(), contact, Manifold()); - - verify(() => contact.setEnabled(false)).called(1); + verify(() => contact.isEnabled = false).called(1); }, ); }, diff --git a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_spitting_behavior_test.dart b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_spitting_behavior_test.dart index 0748040e..730e2cc9 100644 --- a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_spitting_behavior_test.dart +++ b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_spitting_behavior_test.dart @@ -33,9 +33,10 @@ void main() { }); group('on the next time the mouth opens and status is chomping', () { - flameTester.test( + flameTester.testGameWidget( 'sets ball sprite to visible and sets a linear velocity', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final ball = Ball(); final behavior = ChromeDinoSpittingBehavior(); final bloc = _MockChromeDinoCubit(); @@ -54,11 +55,12 @@ void main() { final chromeDino = ChromeDino.test(bloc: bloc); await chromeDino.add(behavior); await game.ensureAddAll([chromeDino, ball]); - streamController.add(chompingState.copyWith(isMouthOpen: false)); streamController.add(chompingState.copyWith(isMouthOpen: true)); await game.ready(); - + }, + verify: (game, _) async { + final ball = game.descendants().whereType().single; game .descendants() .whereType() @@ -78,9 +80,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'calls onSpit', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final ball = Ball(); final behavior = ChromeDinoSpittingBehavior(); final bloc = _MockChromeDinoCubit(); @@ -103,7 +106,9 @@ void main() { streamController.add(chompingState.copyWith(isMouthOpen: false)); streamController.add(chompingState.copyWith(isMouthOpen: true)); await game.ready(); - + }, + verify: (game, _) async { + final bloc = game.descendants().whereType().single.bloc; game .descendants() .whereType() diff --git a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_swiveling_behavior_test.dart b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_swiveling_behavior_test.dart index 4b34940c..7ee8e716 100644 --- a/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_swiveling_behavior_test.dart +++ b/packages/pinball_components/test/src/components/chrome_dino/behaviors/chrome_dino_swiveling_behavior_test.dart @@ -28,9 +28,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'creates a RevoluteJoint', - (game) async { + setUp: (game, _) async { final behavior = ChromeDinoSwivelingBehavior(); final bloc = _MockChromeDinoCubit(); whenListen( @@ -42,17 +42,18 @@ void main() { final chromeDino = ChromeDino.test(bloc: bloc); await chromeDino.add(behavior); await game.ensureAdd(chromeDino); - + }, + verify: (game, _) async { expect( - game.world.joints.whereType().single, + game.world.physicsWorld.joints.whereType().single, isNotNull, ); }, ); - flameTester.test( + flameTester.testGameWidget( 'reverses swivel direction on each timer tick', - (game) async { + setUp: (game, _) async { final behavior = ChromeDinoSwivelingBehavior(); final bloc = _MockChromeDinoCubit(); whenListen( @@ -64,9 +65,15 @@ void main() { final chromeDino = ChromeDino.test(bloc: bloc); await chromeDino.add(behavior); await game.ensureAdd(chromeDino); - + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; final timer = behavior.timer; - final joint = game.world.joints.whereType().single; + final joint = + game.world.physicsWorld.joints.whereType().single; expect(joint.motorSpeed, isPositive); @@ -98,7 +105,9 @@ void main() { await chromeDino.add(behavior); await game.ensureAdd(chromeDino); - final joint = game.world.joints.whereType().single; + final joint = game.world.physicsWorld.joints + .whereType() + .single; final angle = joint.jointAngle(); expect( angle < joint.upperLimit && angle > joint.lowerLimit, @@ -122,17 +131,20 @@ void main() { initialState: const ChromeDinoState.initial().copyWith(isMouthOpen: false), ); - final chromeDino = ChromeDino.test(bloc: bloc); await chromeDino.add(behavior); - await game.ensureAdd(chromeDino); - - final joint = game.world.joints.whereType().single; - + await game.world.ensureAdd(chromeDino); + await game.ready(); + }, + verify: (game, _) async { + final bloc = + game.world.descendants().whereType().single.bloc; game.update(swivelPeriod / 2); - await tester.pump(); + final joint = game.world.physicsWorld.joints + .whereType() + .single; final angle = joint.jointAngle(); - expect(angle >= joint.upperLimit, isTrue); + expect(angle, greaterThanOrEqualTo(joint.upperLimit)); verify(bloc.onOpenMouth).called(1); }, @@ -153,15 +165,24 @@ void main() { final chromeDino = ChromeDino.test(bloc: bloc); await chromeDino.add(behavior); - await game.ensureAdd(chromeDino); - - final joint = game.world.joints.whereType().single; - + await game.world.ensureAdd(chromeDino); + await game.ready(); + }, + verify: (game, _) async { + final bloc = + game.world.descendants().whereType().single.bloc; + final behavior = game + .descendants() + .whereType() + .single; + behavior.timer.onTick!(); game.update(swivelPeriod * 1.5); - await tester.pump(); + final joint = game.world.physicsWorld.joints + .whereType() + .single; final angle = joint.jointAngle(); - expect(angle <= joint.lowerLimit, isTrue); + expect(angle, lessThanOrEqualTo(joint.lowerLimit)); verify(bloc.onOpenMouth).called(1); }, ); diff --git a/packages/pinball_components/test/src/components/chrome_dino/chrome_dino_test.dart b/packages/pinball_components/test/src/components/chrome_dino/chrome_dino_test.dart index a2e1c933..b1e006aa 100644 --- a/packages/pinball_components/test/src/components/chrome_dino/chrome_dino_test.dart +++ b/packages/pinball_components/test/src/components/chrome_dino/chrome_dino_test.dart @@ -21,13 +21,16 @@ void main() { final flameTester = FlameTester(() => TestGame(assets)); group('ChromeDino', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final chromeDino = ChromeDino(); await game.ensureAdd(chromeDino); - - expect(game.contains(chromeDino), isTrue); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); @@ -35,8 +38,8 @@ void main() { 'renders correctly', setUp: (game, tester) async { await game.images.loadAll(assets); - await game.ensureAdd(ChromeDino()); - game.camera.followVector2(Vector2.zero()); + await game.world.ensureAdd(ChromeDino()); + game.camera.moveTo(Vector2.zero()); await tester.pump(); }, verify: (game, tester) async { @@ -44,9 +47,10 @@ void main() { .descendants() .whereType() .first - .animation! + .animationTicker! .totalDuration() / 2; + game.update(swivelAnimationDuration); await tester.pump(); @@ -71,70 +75,117 @@ void main() { }, ); - flameTester.test('closes bloc when removed', (game) async { - final bloc = _MockChromeDinoCubit(); - whenListen( - bloc, - const Stream.empty(), - initialState: const ChromeDinoState.initial(), - ); - when(bloc.close).thenAnswer((_) async {}); - final chromeDino = ChromeDino.test(bloc: bloc); - - await game.ensureAdd(chromeDino); - game.remove(chromeDino); - await game.ready(); + flameTester.testGameWidget( + 'closes bloc when removed', + setUp: (game, _) async { + await game.onLoad(); + final bloc = _MockChromeDinoCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: const ChromeDinoState.initial(), + ); + when(bloc.close).thenAnswer((_) async {}); + final chromeDino = ChromeDino.test(bloc: bloc); - verify(bloc.close).called(1); - }); + await game.ensureAdd(chromeDino); + await game.ready(); + }, + verify: (game, _) async { + final chromeDino = game.descendants().whereType().single; + game.remove(chromeDino); + game.update(0); + verify(chromeDino.bloc.close).called(1); + }, + ); group('adds', () { - flameTester.test('a ChromeDinoMouthOpeningBehavior', (game) async { - final chromeDino = ChromeDino(); - await game.ensureAdd(chromeDino); - expect( - chromeDino.children - .whereType() - .single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a ChromeDinoMouthOpeningBehavior', + setUp: (game, _) async { + await game.onLoad(); + final chromeDino = ChromeDino(); + await game.ensureAdd(chromeDino); + await game.ready(); + }, + verify: (game, _) async { + final chromeDino = game.descendants().whereType().single; + expect( + chromeDino.children + .whereType() + .single, + isNotNull, + ); + }, + ); - flameTester.test('a ChromeDinoSwivelingBehavior', (game) async { - final chromeDino = ChromeDino(); - await game.ensureAdd(chromeDino); - expect( - chromeDino.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a ChromeDinoSwivelingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final chromeDino = ChromeDino(); + await game.ensureAdd(chromeDino); + await game.ready(); + }, + verify: (game, _) async { + final chromeDino = game.descendants().whereType().single; + expect( + chromeDino.children.whereType().single, + isNotNull, + ); + }, + ); - flameTester.test('a ChromeDinoChompingBehavior', (game) async { - final chromeDino = ChromeDino(); - await game.ensureAdd(chromeDino); - expect( - chromeDino.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a ChromeDinoChompingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final chromeDino = ChromeDino(); + await game.ensureAdd(chromeDino); + await game.ready(); + }, + verify: (game, _) async { + final chromeDino = game.descendants().whereType().single; + expect( + chromeDino.children.whereType().single, + isNotNull, + ); + }, + ); - flameTester.test('a ChromeDinoSpittingBehavior', (game) async { - final chromeDino = ChromeDino(); - await game.ensureAdd(chromeDino); - expect( - chromeDino.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a ChromeDinoSpittingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final chromeDino = ChromeDino(); + await game.ensureAdd(chromeDino); + await game.ready(); + }, + verify: (game, _) async { + final chromeDino = game.descendants().whereType().single; + expect( + chromeDino.children.whereType().single, + isNotNull, + ); + }, + ); - flameTester.test('new children', (game) async { - final component = Component(); - final chromeDino = ChromeDino( - children: [component], - ); - await game.ensureAdd(chromeDino); - expect(chromeDino.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final chromeDino = ChromeDino( + children: [component], + ); + await game.ensureAdd(chromeDino); + await game.ready(); + }, + verify: (game, _) async { + final chromeDino = game.descendants().whereType().single; + expect(chromeDino.children.whereType(), isNotEmpty); + }, + ); }); }); } diff --git a/packages/pinball_components/test/src/components/chrome_dino/cubit/chrome_dino_cubit_test.dart b/packages/pinball_components/test/src/components/chrome_dino/cubit/chrome_dino_cubit_test.dart index 80c01983..0df2e6b0 100644 --- a/packages/pinball_components/test/src/components/chrome_dino/cubit/chrome_dino_cubit_test.dart +++ b/packages/pinball_components/test/src/components/chrome_dino/cubit/chrome_dino_cubit_test.dart @@ -17,7 +17,7 @@ void main() { (state) => state.isMouthOpen, 'isMouthOpen', true, - ) + ), ], ); @@ -30,7 +30,7 @@ void main() { (state) => state.isMouthOpen, 'isMouthOpen', false, - ) + ), ], ); @@ -41,16 +41,16 @@ void main() { act: (bloc) => bloc.onChomp(ball), expect: () => [ isA() - ..having( - (state) => state.status, - 'status', - ChromeDinoStatus.chomping, - ) - ..having( - (state) => state.ball, - 'ball', - ball, - ) + .having( + (state) => state.status, + 'status', + ChromeDinoStatus.chomping, + ) + .having( + (state) => state.ball, + 'ball', + ball, + ), ], ); @@ -67,15 +67,17 @@ void main() { build: ChromeDinoCubit.new, act: (bloc) => bloc.onSpit(), expect: () => [ - isA().having( - (state) => state.status, - 'status', - ChromeDinoStatus.idle, - )..having( - (state) => state.ball, - 'ball', - null, - ) + isA() + .having( + (state) => state.status, + 'status', + ChromeDinoStatus.idle, + ) + .having( + (state) => state.ball, + 'ball', + null, + ), ], ); }, diff --git a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/down.png b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/down.png index 58180a63..c2c733cb 100644 Binary files a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/down.png and b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/down.png differ diff --git a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/middle.png b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/middle.png index b6d31b1f..0394b69f 100644 Binary files a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/middle.png and b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/middle.png differ diff --git a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/up.png b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/up.png index 48a834c0..bb5aaca6 100644 Binary files a/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/up.png and b/packages/pinball_components/test/src/components/chrome_dino/golden/chrome_dino/up.png differ diff --git a/packages/pinball_components/test/src/components/dash_animatronic_test.dart b/packages/pinball_components/test/src/components/dash_animatronic_test.dart index 282e9f8d..306d798b 100644 --- a/packages/pinball_components/test/src/components/dash_animatronic_test.dart +++ b/packages/pinball_components/test/src/components/dash_animatronic_test.dart @@ -17,13 +17,17 @@ void main() { 'renders correctly', setUp: (game, tester) async { await game.images.load(asset); - await game.ensureAdd(DashAnimatronic()..playing = true); - game.camera.followVector2(Vector2.zero()); + await game.world.ensureAdd(DashAnimatronic()..playing = true); + game.camera.moveTo(Vector2.zero()); await tester.pump(); }, verify: (game, tester) async { - final animationDuration = - game.firstChild()!.animation!.totalDuration(); + final animationDuration = game + .descendants() + .whereType() + .single + .animationTicker! + .totalDuration(); await expectLater( find.byGame(), @@ -46,23 +50,37 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final dashAnimatronic = DashAnimatronic(); await game.ensureAdd(dashAnimatronic); - - expect(game.contains(dashAnimatronic), isTrue); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); }, ); - flameTester.test('adds new children', (game) async { - final component = Component(); - final dashAnimatronic = DashAnimatronic( - children: [component], - ); - await game.ensureAdd(dashAnimatronic); - expect(dashAnimatronic.children, contains(component)); - }); + flameTester.testGameWidget( + 'adds new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final dashAnimatronic = DashAnimatronic( + children: [component], + ); + await game.ensureAdd(dashAnimatronic); + await game.ready(); + }, + verify: (game, _) async { + final dashAnimatronic = + game.descendants().whereType().single; + expect(dashAnimatronic.children.whereType(), isNotNull); + }, + ); }); } diff --git a/packages/pinball_components/test/src/components/dash_nest_bumper/behaviors/dash_bumper_ball_contact_behavior_test.dart b/packages/pinball_components/test/src/components/dash_nest_bumper/behaviors/dash_bumper_ball_contact_behavior_test.dart index e80b743e..651e7b44 100644 --- a/packages/pinball_components/test/src/components/dash_nest_bumper/behaviors/dash_bumper_ball_contact_behavior_test.dart +++ b/packages/pinball_components/test/src/components/dash_nest_bumper/behaviors/dash_bumper_ball_contact_behavior_test.dart @@ -31,10 +31,10 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'beginContact emits onBallContacted with the bumper ID ' 'when contacts with a ball', - (game) async { + setUp: (game, _) async { final behavior = DashBumperBallContactBehavior(); final bloc = _MockDashBumpersCubit(); const id = DashBumperId.main; @@ -52,10 +52,21 @@ void main() { children: [bumper], ), ); - + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; behavior.beginContact(_MockBall(), _MockContact()); - verify(() => bloc.onBallContacted(id)).called(1); + verify(() => bloc.onBallContacted(DashBumperId.main)).called(1); }, ); }, diff --git a/packages/pinball_components/test/src/components/dash_nest_bumper/cubit/dash_bumpers_cubit_test.dart b/packages/pinball_components/test/src/components/dash_nest_bumper/cubit/dash_bumpers_cubit_test.dart index 2de127c5..f4dbd0da 100644 --- a/packages/pinball_components/test/src/components/dash_nest_bumper/cubit/dash_bumpers_cubit_test.dart +++ b/packages/pinball_components/test/src/components/dash_nest_bumper/cubit/dash_bumpers_cubit_test.dart @@ -26,7 +26,8 @@ void main() { build: DashBumpersCubit.new, seed: () => DashBumpersState( bumperSpriteStates: { - for (var id in DashBumperId.values) id: DashBumperSpriteState.active + for (final id in DashBumperId.values) + id: DashBumperSpriteState.active, }, ), act: (bloc) => bloc.onReset(), diff --git a/packages/pinball_components/test/src/components/dash_nest_bumper/dash_bumper_test.dart b/packages/pinball_components/test/src/components/dash_nest_bumper/dash_bumper_test.dart index 034e5664..dc86c42d 100644 --- a/packages/pinball_components/test/src/components/dash_nest_bumper/dash_bumper_test.dart +++ b/packages/pinball_components/test/src/components/dash_nest_bumper/dash_bumper_test.dart @@ -39,91 +39,148 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('DashBumper', () { - flameTester.test('"main" can be added', (game) async { - final bumper = DashBumper.main(); - await game.pump(bumper); - expect(game.descendants().contains(bumper), isTrue); - }); - - flameTester.test('"a" can be added', (game) async { - final bumper = DashBumper.a(); - await game.pump(bumper); - expect(game.descendants().contains(bumper), isTrue); - }); - - flameTester.test('"b" can be added', (game) async { - final bumper = DashBumper.b(); - await game.pump(bumper); - expect(game.descendants().contains(bumper), isTrue); - }); + flameTester.testGameWidget( + '"main" can be added', + setUp: (game, _) async { + final bumper = DashBumper.main(); + await game.pump(bumper); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); - flameTester.test('adds a DashBumperBallContactBehavior', (game) async { - final bumper = DashBumper.a(); - await game.pump(bumper); - expect( - bumper.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + '"a" can be added', + setUp: (game, _) async { + final bumper = DashBumper.a(); + await game.pump(bumper); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); - group("'main' adds", () { - flameTester.test('new children', (game) async { - final component = Component(); - final bumper = DashBumper.main( - children: [component], - ); + flameTester.testGameWidget( + '"b" can be added', + setUp: (game, _) async { + final bumper = DashBumper.b(); await game.pump(bumper); - expect(bumper.children, contains(component)); - }); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); - flameTester.test('a BumpingBehavior', (game) async { - final bumper = DashBumper.main(); + flameTester.testGameWidget( + 'adds a DashBumperBallContactBehavior', + setUp: (game, _) async { + final bumper = DashBumper.a(); await game.pump(bumper); + }, + verify: (game, _) async { + final bumper = game.descendants().whereType().single; expect( - bumper.children.whereType().single, + bumper.children.whereType().single, isNotNull, ); - }); + }, + ); + + group("'main' adds", () { + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + final component = Component(); + final bumper = DashBumper.main( + children: [component], + ); + await game.pump(bumper); + }, + verify: (game, _) async { + final bumper = game.descendants().whereType().single; + expect(bumper.children.whereType(), isNotEmpty); + }, + ); + + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + final bumper = DashBumper.main(); + await game.pump(bumper); + }, + verify: (game, _) async { + final bumper = game.descendants().whereType().single; + expect( + bumper.children.whereType().single, + isNotNull, + ); + }, + ); }); group("'a' adds", () { - flameTester.test('new children', (game) async { - final component = Component(); - final bumper = DashBumper.a( - children: [component], - ); - await game.pump(bumper); - expect(bumper.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + final component = Component(); + final bumper = DashBumper.a( + children: [component], + ); + await game.pump(bumper); + }, + verify: (game, _) async { + final bumper = game.descendants().whereType().single; + expect(bumper.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a BumpingBehavior', (game) async { - final bumper = DashBumper.a(); - await game.pump(bumper); - expect( - bumper.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + final bumper = DashBumper.a(); + await game.pump(bumper); + }, + verify: (game, _) async { + final bumper = game.descendants().whereType().single; + expect( + bumper.children.whereType().single, + isNotNull, + ); + }, + ); }); group("'b' adds", () { - flameTester.test('new children', (game) async { - final component = Component(); - final bumper = DashBumper.b( - children: [component], - ); - await game.pump(bumper); - expect(bumper.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + final component = Component(); + final bumper = DashBumper.b( + children: [component], + ); + await game.pump(bumper); + }, + verify: (game, _) async { + final bumper = game.descendants().whereType().single; + expect(bumper.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a BumpingBehavior', (game) async { - final bumper = DashBumper.b(); - await game.pump(bumper); - expect( - bumper.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + final bumper = DashBumper.b(); + await game.pump(bumper); + }, + verify: (game, _) async { + final bumper = game.descendants().whereType().single; + expect( + bumper.children.whereType().single, + isNotNull, + ); + }, + ); }); group('SpriteGroupComponent', () { @@ -136,12 +193,14 @@ void main() { ); group('listenWhen', () { - flameTester.test( + flameTester.testGameWidget( 'is true when the sprite state for the given ID has changed', - (game) async { + setUp: (game, _) async { final bumper = DashBumper.main(); await game.pump(bumper); - + }, + verify: (game, _) async { + final bumper = game.descendants().whereType().single; final listenWhen = bumper.firstChild()!.listenWhen( DashBumpersState.initial(), @@ -152,19 +211,20 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'onNewState updates the current sprite', - (game) async { + setUp: (game, _) async { final bumper = DashBumper.main(); await game.pump(bumper); - + await game.ready(); + }, + verify: (game, _) async { + final bumper = game.descendants().whereType().single; final spriteGroupComponent = bumper.firstChild()!; final originalSprite = spriteGroupComponent.current; - spriteGroupComponent.onNewState(mainBumperActivatedState); - await game.ready(); - + game.update(0); final newSprite = spriteGroupComponent.current; expect(newSprite, isNot(equals(originalSprite))); }, diff --git a/packages/pinball_components/test/src/components/dino_walls_test.dart b/packages/pinball_components/test/src/components/dino_walls_test.dart index dd8172ac..90ac6367 100644 --- a/packages/pinball_components/test/src/components/dino_walls_test.dart +++ b/packages/pinball_components/test/src/components/dino_walls_test.dart @@ -1,6 +1,6 @@ // ignore_for_file: cascade_invocations -import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame/components.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -17,24 +17,30 @@ void main() { ]; final flameTester = FlameTester(() => TestGame(assets)); - flameTester.test('loads correctly', (game) async { - final component = DinoWalls(); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = DinoWalls(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); + }, + ); flameTester.testGameWidget( 'renders correctly', setUp: (game, tester) async { + await game.onLoad(); await game.images.loadAll(assets); - await game.ensureAdd(DinoWalls()); + await game.world.ensureAdd(DinoWalls()); - game.camera.followVector2(Vector2.zero()); - game.camera.zoom = 6.5; - - await tester.pump(); + game.camera.moveTo(Vector2.zero()); + game.camera.viewfinder.zoom = 6.5; + await game.ready(); }, verify: (game, tester) async { + await tester.pump(); await expectLater( find.byGame(), matchesGoldenFile('golden/dino_walls.png'), diff --git a/packages/pinball_components/test/src/components/error_component_test.dart b/packages/pinball_components/test/src/components/error_component_test.dart index c50ac629..bb165236 100644 --- a/packages/pinball_components/test/src/components/error_component_test.dart +++ b/packages/pinball_components/test/src/components/error_component_test.dart @@ -23,35 +23,49 @@ void main() { ]; final flameTester = FlameTester(() => TestGame(assets)); - flameTester.test('renders correctly', (game) async { - await game.ensureAdd(ErrorComponent(label: 'Error Message')); - final count = game.descendants().countTexts('Error Message'); - - expect(count, equals(1)); - }); + flameTester.testGameWidget( + 'renders correctly', + setUp: (game, _) async { + await game.ensureAdd(ErrorComponent(label: 'Error Message')); + }, + verify: (game, _) async { + final count = game.descendants().countTexts('Error Message'); + expect(count, equals(1)); + }, + ); group('when the text is longer than one line', () { - flameTester.test('renders correctly', (game) async { - await game.ensureAdd( - ErrorComponent( - label: 'Error With A Longer Message', - ), - ); - final count1 = game.descendants().countTexts('Error With A'); - final count2 = game.descendants().countTexts('Longer Message'); - - expect(count1, equals(1)); - expect(count2, equals(1)); - }); + flameTester.testGameWidget( + 'renders correctly', + setUp: (game, _) async { + await game.ensureAdd( + ErrorComponent( + label: 'Error With A Longer Message', + ), + ); + }, + verify: (game, _) async { + final count1 = game.descendants().countTexts('Error With A'); + final count2 = game.descendants().countTexts('Longer Message'); + + expect(count1, equals(1)); + expect(count2, equals(1)); + }, + ); }); group('when using the bold font', () { - flameTester.test('renders correctly', (game) async { - await game.ensureAdd(ErrorComponent.bold(label: 'Error Message')); - final count = game.descendants().countTexts('Error Message'); + flameTester.testGameWidget( + 'renders correctly', + setUp: (game, _) async { + await game.ensureAdd(ErrorComponent.bold(label: 'Error Message')); + }, + verify: (game, _) async { + final count = game.descendants().countTexts('Error Message'); - expect(count, equals(1)); - }); + expect(count, equals(1)); + }, + ); }); }); } diff --git a/packages/pinball_components/test/src/components/flapper/behaviors/flapper_spinning_behavior_test.dart b/packages/pinball_components/test/src/components/flapper/behaviors/flapper_spinning_behavior_test.dart index c53dc17b..3b365ad9 100644 --- a/packages/pinball_components/test/src/components/flapper/behaviors/flapper_spinning_behavior_test.dart +++ b/packages/pinball_components/test/src/components/flapper/behaviors/flapper_spinning_behavior_test.dart @@ -32,9 +32,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'beginContact plays the flapper animation', - (game) async { + setUp: (game, _) async { final behavior = FlapperSpinningBehavior(); final entrance = FlapperEntrance(); final flap = FlapSpriteAnimationComponent(); @@ -42,7 +42,17 @@ void main() { await flapper.addAll([entrance, flap]); await entrance.add(behavior); await game.ensureAdd(flapper); - + }, + verify: (game, _) async { + final behavior = + game.descendants().whereType().single; + final flap = game + .descendants() + .whereType() + .single + .children + .whereType() + .single; behavior.beginContact(_MockBall(), _MockContact()); expect(flap.playing, isTrue); diff --git a/packages/pinball_components/test/src/components/flapper/flapper_test.dart b/packages/pinball_components/test/src/components/flapper/flapper_test.dart index c9be94f9..04fa96f8 100644 --- a/packages/pinball_components/test/src/components/flapper/flapper_test.dart +++ b/packages/pinball_components/test/src/components/flapper/flapper_test.dart @@ -1,6 +1,6 @@ // ignore_for_file: cascade_invocations -import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame/components.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -19,21 +19,26 @@ void main() { ]; final flameTester = FlameTester(() => TestGame(assets)); - flameTester.test('loads correctly', (game) async { - final component = Flapper(); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = Flapper(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); flameTester.testGameWidget( 'renders correctly', setUp: (game, tester) async { await game.images.loadAll(assets); final canvas = ZCanvasComponent(children: [Flapper()]); - await game.ensureAdd(canvas); + await game.world.ensureAdd(canvas); game.camera - ..followVector2(Vector2(3, -70)) - ..zoom = 25; + ..moveTo(Vector2(3, -70)) + ..viewfinder.zoom = 25; await tester.pump(); }, verify: (game, tester) async { @@ -44,7 +49,7 @@ void main() { .first ..playing = true; final animationDuration = - flapSpriteAnimationComponent.animation!.totalDuration(); + flapSpriteAnimationComponent.animationTicker!.totalDuration(); await expectLater( find.byGame(), @@ -67,30 +72,43 @@ void main() { }, ); - flameTester.test('adds a FlapperSpinningBehavior to FlapperEntrance', - (game) async { - final flapper = Flapper(); - await game.ensureAdd(flapper); - - final flapperEntrance = flapper.firstChild()!; - expect( - flapperEntrance.firstChild(), - isNotNull, - ); - }); + flameTester.testGameWidget( + 'adds a FlapperSpinningBehavior to FlapperEntrance', + setUp: (game, _) async { + await game.onLoad(); + final flapper = Flapper(); + await game.ensureAdd(flapper); + await game.ready(); + }, + verify: (game, _) async { + final flapper = game.descendants().whereType().single; + final flapperEntrance = flapper.firstChild()!; + expect( + flapperEntrance.firstChild(), + isNotNull, + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'flap stops animating after animation completes', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final flapper = Flapper(); await game.ensureAdd(flapper); + await game.ready(); + }, + verify: (game, _) async { + final flapper = game.descendants().whereType().single; - final flapSpriteAnimationComponent = - flapper.firstChild()!; + final flapSpriteAnimationComponent = flapper + .descendants() + .whereType() + .single; flapSpriteAnimationComponent.playing = true; game.update( - flapSpriteAnimationComponent.animation!.totalDuration() + 0.1, + flapSpriteAnimationComponent.animationTicker!.totalDuration() + 0.1, ); expect(flapSpriteAnimationComponent.playing, isFalse); diff --git a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_jointing_behavior_test.dart b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_jointing_behavior_test.dart index 3128d286..dd9c3c35 100644 --- a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_jointing_behavior_test.dart +++ b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_jointing_behavior_test.dart @@ -17,20 +17,34 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final parent = Flipper.test(side: BoardSide.left); - final behavior = FlipperJointingBehavior(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); - expect(parent.contains(behavior), isTrue); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final parent = Flipper.test(side: BoardSide.left); + final behavior = FlipperJointingBehavior(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final parent = game.descendants().whereType().single; + final behavior = + game.descendants().whereType().single; + expect(parent.contains(behavior), isTrue); + }, + ); - flameTester.test('creates a joint', (game) async { - final parent = Flipper.test(side: BoardSide.left); - final behavior = FlipperJointingBehavior(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); - expect(parent.body.joints, isNotEmpty); - }); + flameTester.testGameWidget( + 'creates a joint', + setUp: (game, _) async { + final parent = Flipper.test(side: BoardSide.left); + final behavior = FlipperJointingBehavior(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final parent = game.descendants().whereType().single; + expect(parent.body.joints, isNotEmpty); + }, + ); }); } diff --git a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_key_controlling_behavior_test.dart b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_key_controlling_behavior_test.dart index 307264f0..382fdd09 100644 --- a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_key_controlling_behavior_test.dart +++ b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_key_controlling_behavior_test.dart @@ -4,8 +4,6 @@ import 'package:bloc_test/bloc_test.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/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -30,14 +28,14 @@ class _TestGame extends Forge2DGame { class _MockFlipperCubit extends Mock implements FlipperCubit {} -class _MockRawKeyDownEvent extends Mock implements RawKeyDownEvent { +class _MockKeyDownEvent extends Mock implements KeyDownEvent { @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return super.toString(); } } -class _MockRawKeyUpEvent extends Mock implements RawKeyUpEvent { +class _MockKeyUpEvent extends Mock implements KeyUpEvent { @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return super.toString(); @@ -64,106 +62,135 @@ void main() { }); group('on right Flipper', () { - flameTester.test( + flameTester.testGameWidget( 'moves upwards when right arrow is pressed', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, flipperBloc: flipperBloc, side: BoardSide.right, ); - - final event = _MockRawKeyDownEvent(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowRight, ); behavior.onKeyEvent(event, {}); - await Future.delayed(Duration.zero); + game.update(0); verify(flipperBloc.moveUp).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( 'moves downwards when right arrow is released', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.right, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyUpEvent(); + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowRight, ); behavior.onKeyEvent(event, {}); - await Future.delayed(Duration.zero); + game.update(0); verify(flipperBloc.moveDown).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( 'moves upwards when D is pressed', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.right, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyDownEvent(); + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyD, ); behavior.onKeyEvent(event, {}); - await Future.delayed(Duration.zero); + game.update(0); verify(flipperBloc.moveUp).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( 'moves downwards when D is released', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.right, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyUpEvent(); + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyD, ); behavior.onKeyEvent(event, {}); - await Future.delayed(Duration.zero); + game.update(0); verify(flipperBloc.moveDown).called(1); }, ); group("doesn't move when", () { - flameTester.test( + flameTester.testGameWidget( 'left arrow is pressed', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.right, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyDownEvent(); + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowLeft, ); @@ -175,17 +202,22 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'left arrow is released', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.right, flipperBloc: flipperBloc, ); - - final event = _MockRawKeyUpEvent(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowLeft, ); @@ -197,17 +229,22 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'A is pressed', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.right, flipperBloc: flipperBloc, ); - - final event = _MockRawKeyDownEvent(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyA, ); @@ -219,17 +256,23 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'A is released', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.right, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyUpEvent(); + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyA, ); @@ -244,106 +287,134 @@ void main() { }); group('on left Flipper', () { - flameTester.test( + flameTester.testGameWidget( 'moves upwards when left arrow is pressed', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.left, flipperBloc: flipperBloc, ); - - final event = _MockRawKeyDownEvent(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowLeft, ); behavior.onKeyEvent(event, {}); - await Future.delayed(Duration.zero); + game.update(0); verify(flipperBloc.moveUp).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( 'moves downwards when left arrow is released', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.left, flipperBloc: flipperBloc, ); - - final event = _MockRawKeyUpEvent(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowLeft, ); behavior.onKeyEvent(event, {}); - await Future.delayed(Duration.zero); + game.update(0); verify(flipperBloc.moveDown).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( 'moves upwards when A is pressed', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.left, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyDownEvent(); + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyA, ); behavior.onKeyEvent(event, {}); - await Future.delayed(Duration.zero); + game.update(0); verify(flipperBloc.moveUp).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( 'moves downwards when A is released', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.left, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyUpEvent(); + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyA, ); behavior.onKeyEvent(event, {}); - await Future.delayed(Duration.zero); + game.update(0); verify(flipperBloc.moveDown).called(1); }, ); group("doesn't move when", () { - flameTester.test( + flameTester.testGameWidget( 'right arrow is pressed', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.left, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyDownEvent(); + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowRight, ); @@ -355,17 +426,23 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'right arrow is released', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.left, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyUpEvent(); + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowRight, ); @@ -377,17 +454,22 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'D is pressed', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.left, flipperBloc: flipperBloc, ); - - final event = _MockRawKeyDownEvent(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyD, ); @@ -399,17 +481,23 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'D is released', - (game) async { + setUp: (game, _) async { final behavior = FlipperKeyControllingBehavior(); await game.pump( behavior, side: BoardSide.left, flipperBloc: flipperBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyUpEvent(); + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyD, ); diff --git a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_moving_behavior_test.dart b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_moving_behavior_test.dart index de379201..563a3214 100644 --- a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_moving_behavior_test.dart +++ b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_moving_behavior_test.dart @@ -49,15 +49,23 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final behavior = FlipperMovingBehavior(strength: 0); - await game.pump(behavior); - expect(game.descendants(), contains(behavior)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final behavior = FlipperMovingBehavior(strength: 0); + await game.pump(behavior); + }, + verify: (game, _) async { + expect( + game.descendants().whereType(), + isNotEmpty, + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'applies vertical velocity to flipper when moving down', - (game) async { + setUp: (game, _) async { final bloc = _MockFlipperCubit(); final streamController = StreamController(); whenListen( @@ -71,17 +79,19 @@ void main() { await game.pump(behavior, flipperBloc: bloc); streamController.add(FlipperState.movingDown); - await Future.delayed(Duration.zero); + }, + verify: (game, _) async { + game.update(0); - final flipper = behavior.ancestors().whereType().single; + final flipper = game.descendants().whereType().single; expect(flipper.body.linearVelocity.x, 0); - expect(flipper.body.linearVelocity.y, strength); + expect(flipper.body.linearVelocity.y, 10.0); }, ); - flameTester.test( + flameTester.testGameWidget( 'applies vertical velocity to flipper when moving up', - (game) async { + setUp: (game, _) async { final bloc = _MockFlipperCubit(); whenListen( bloc, @@ -92,11 +102,13 @@ void main() { const strength = 10.0; final behavior = FlipperMovingBehavior(strength: strength); await game.pump(behavior, flipperBloc: bloc); + }, + verify: (game, _) async { game.update(0); - final flipper = behavior.ancestors().whereType().single; + final flipper = game.descendants().whereType().single; expect(flipper.body.linearVelocity.x, 0); - expect(flipper.body.linearVelocity.y, -strength); + expect(flipper.body.linearVelocity.y, -10.0); }, ); }); diff --git a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_noise_behavior_test.dart b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_noise_behavior_test.dart index 2a046a0b..eb9c41a5 100644 --- a/packages/pinball_components/test/src/components/flipper/behaviors/flipper_noise_behavior_test.dart +++ b/packages/pinball_components/test/src/components/flipper/behaviors/flipper_noise_behavior_test.dart @@ -52,9 +52,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'plays the flipper sound when moving up', - (game) async { + setUp: (game, _) async { final audioPlayer = _MockPinballAudioPlayer(); final bloc = _MockFlipperCubit(); whenListen( @@ -69,6 +69,16 @@ void main() { flipperBloc: bloc, audioPlayer: audioPlayer, ); + await game.ready(); + }, + verify: (game, _) async { + final behavior = + game.descendants().whereType().single; + final audioPlayer = game + .descendants() + .whereType>() + .single + .provider; behavior.onNewState(FlipperState.movingUp); game.update(0); diff --git a/packages/pinball_components/test/src/components/flipper/flipper_test.dart b/packages/pinball_components/test/src/components/flipper/flipper_test.dart index 0aba00bc..e85aa208 100644 --- a/packages/pinball_components/test/src/components/flipper/flipper_test.dart +++ b/packages/pinball_components/test/src/components/flipper/flipper_test.dart @@ -29,8 +29,8 @@ void main() { side: BoardSide.right, )..initialPosition = Vector2(10, 0); - await game.ensureAddAll([leftFlipper, rightFlipper]); - game.camera.followVector2(Vector2.zero()); + await game.world.ensureAddAll([leftFlipper, rightFlipper]); + game.camera.moveTo(Vector2.zero()); await tester.pump(); }, verify: (game, tester) async { @@ -41,16 +41,16 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final leftFlipper = Flipper(side: BoardSide.left); final rightFlipper = Flipper(side: BoardSide.right); await game.ready(); await game.ensureAddAll([leftFlipper, rightFlipper]); - - expect(game.contains(leftFlipper), isTrue); - expect(game.contains(rightFlipper), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(2)); }, ); @@ -65,33 +65,42 @@ void main() { }); group('body', () { - flameTester.test( + flameTester.testGameWidget( 'is dynamic', - (game) async { + setUp: (game, _) async { final flipper = Flipper(side: BoardSide.left); await game.ensureAdd(flipper); + }, + verify: (game, _) async { + final flipper = game.descendants().whereType().single; expect(flipper.body.bodyType, equals(BodyType.dynamic)); }, ); - flameTester.test( + flameTester.testGameWidget( 'ignores gravity', - (game) async { + setUp: (game, _) async { final flipper = Flipper(side: BoardSide.left); await game.ensureAdd(flipper); + }, + verify: (game, _) async { + final flipper = game.descendants().whereType().single; expect(flipper.body.gravityScale, equals(Vector2.zero())); }, ); - flameTester.test( + flameTester.testGameWidget( 'has greater mass than Ball', - (game) async { + setUp: (game, _) async { final flipper = Flipper(side: BoardSide.left); final ball = Ball(); - await game.ready(); await game.ensureAddAll([flipper, ball]); + }, + verify: (game, _) async { + final flipper = game.descendants().whereType().single; + final ball = game.descendants().whereType().single; expect( flipper.body.getMassData().mass, @@ -102,21 +111,26 @@ void main() { }); group('fixtures', () { - flameTester.test( + flameTester.testGameWidget( 'has three', - (game) async { + setUp: (game, _) async { final flipper = Flipper(side: BoardSide.left); await game.ensureAdd(flipper); - + }, + verify: (game, _) async { + final flipper = game.descendants().whereType().single; expect(flipper.body.fixtures.length, equals(3)); }, ); - flameTester.test( + flameTester.testGameWidget( 'has density', - (game) async { + setUp: (game, _) async { final flipper = Flipper(side: BoardSide.left); await game.ensureAdd(flipper); + }, + verify: (game, _) async { + final flipper = game.descendants().whereType().single; final fixtures = flipper.body.fixtures; final density = fixtures.fold( diff --git a/packages/pinball_components/test/src/components/golden/arrow_icon_left.png b/packages/pinball_components/test/src/components/golden/arrow_icon_left.png index dab87d41..7e83c215 100644 Binary files a/packages/pinball_components/test/src/components/golden/arrow_icon_left.png and b/packages/pinball_components/test/src/components/golden/arrow_icon_left.png differ diff --git a/packages/pinball_components/test/src/components/golden/arrow_icon_right.png b/packages/pinball_components/test/src/components/golden/arrow_icon_right.png index 185e9a9a..08f24b7d 100644 Binary files a/packages/pinball_components/test/src/components/golden/arrow_icon_right.png and b/packages/pinball_components/test/src/components/golden/arrow_icon_right.png differ diff --git a/packages/pinball_components/test/src/components/golden/baseboard.png b/packages/pinball_components/test/src/components/golden/baseboard.png index 4b051dfa..ff6421bc 100644 Binary files a/packages/pinball_components/test/src/components/golden/baseboard.png and b/packages/pinball_components/test/src/components/golden/baseboard.png differ diff --git a/packages/pinball_components/test/src/components/golden/board_background.png b/packages/pinball_components/test/src/components/golden/board_background.png index c15a29ce..9bd2cedc 100644 Binary files a/packages/pinball_components/test/src/components/golden/board_background.png and b/packages/pinball_components/test/src/components/golden/board_background.png differ diff --git a/packages/pinball_components/test/src/components/golden/flapper/end.png b/packages/pinball_components/test/src/components/golden/flapper/end.png index cd04b3d2..51d7aa48 100644 Binary files a/packages/pinball_components/test/src/components/golden/flapper/end.png and b/packages/pinball_components/test/src/components/golden/flapper/end.png differ diff --git a/packages/pinball_components/test/src/components/golden/flapper/middle.png b/packages/pinball_components/test/src/components/golden/flapper/middle.png index d4788641..fdcf270b 100644 Binary files a/packages/pinball_components/test/src/components/golden/flapper/middle.png and b/packages/pinball_components/test/src/components/golden/flapper/middle.png differ diff --git a/packages/pinball_components/test/src/components/golden/flapper/start.png b/packages/pinball_components/test/src/components/golden/flapper/start.png index d4e9b3fc..b73fb4b8 100644 Binary files a/packages/pinball_components/test/src/components/golden/flapper/start.png and b/packages/pinball_components/test/src/components/golden/flapper/start.png differ diff --git a/packages/pinball_components/test/src/components/golden/sparky_computer.png b/packages/pinball_components/test/src/components/golden/sparky_computer.png index 22fdc7e5..dd6c01d4 100644 Binary files a/packages/pinball_components/test/src/components/golden/sparky_computer.png and b/packages/pinball_components/test/src/components/golden/sparky_computer.png differ diff --git a/packages/pinball_components/test/src/components/google_letter_test.dart b/packages/pinball_components/test/src/components/google_letter_test.dart index 116c4d97..d7bb8e27 100644 --- a/packages/pinball_components/test/src/components/google_letter_test.dart +++ b/packages/pinball_components/test/src/components/google_letter_test.dart @@ -46,63 +46,69 @@ void main() { expect(GoogleLetter(0), isA()); }); - flameTester.test( + flameTester.testGameWidget( '0th loads correctly', - (game) async { + setUp: (game, _) async { final googleLetter = GoogleLetter(0); await game.pump(googleLetter); - - expect(game.descendants().contains(googleLetter), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( '1st loads correctly', - (game) async { + setUp: (game, _) async { final googleLetter = GoogleLetter(1); await game.pump(googleLetter); - - expect(game.descendants().contains(googleLetter), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( '2nd loads correctly', - (game) async { + setUp: (game, _) async { final googleLetter = GoogleLetter(2); await game.pump(googleLetter); - - expect(game.descendants().contains(googleLetter), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( '3d loads correctly', - (game) async { + setUp: (game, _) async { final googleLetter = GoogleLetter(3); await game.pump(googleLetter); - - expect(game.descendants().contains(googleLetter), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( '4th loads correctly', - (game) async { + setUp: (game, _) async { final googleLetter = GoogleLetter(4); await game.pump(googleLetter); - - expect(game.descendants().contains(googleLetter), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( '5th loads correctly', - (game) async { + setUp: (game, _) async { final googleLetter = GoogleLetter(5); await game.pump(googleLetter); - - expect(game.descendants().contains(googleLetter), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); @@ -123,12 +129,15 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( "listens when its index's state changes", - (game) async { + setUp: (game, _) async { final googleLetter = GoogleLetter(0); await game.pump(googleLetter); - + }, + verify: (game, _) async { + final googleLetter = + game.descendants().whereType().single; expect( googleLetter.listenWhen( GoogleWordState.initial(), @@ -139,16 +148,20 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'changes current sprite onNewState', - (game) async { + setUp: (game, _) async { final googleLetter = GoogleLetter(0); await game.pump(googleLetter); + }, + verify: (game, _) async { + final googleLetter = + game.descendants().whereType().single; final originalSprite = googleLetter.current; googleLetter.onNewState(firstLetterLitState); - await game.ready(); + game.update(0); final newSprite = googleLetter.current; expect(newSprite, isNot(equals(originalSprite))); diff --git a/packages/pinball_components/test/src/components/google_rollover/google_rollover_test.dart b/packages/pinball_components/test/src/components/google_rollover/google_rollover_test.dart index 199803a0..54bcc668 100644 --- a/packages/pinball_components/test/src/components/google_rollover/google_rollover_test.dart +++ b/packages/pinball_components/test/src/components/google_rollover/google_rollover_test.dart @@ -26,53 +26,94 @@ void main() { ); }); - flameTester.test('left loads correctly', (game) async { - final googleRollover = GoogleRollover(side: BoardSide.left); - await game.ensureAdd(googleRollover); - expect(game.contains(googleRollover), isTrue); - }); + flameTester.testGameWidget( + 'left loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final googleRollover = GoogleRollover(side: BoardSide.left); + await game.ensureAdd(googleRollover); + await game.ready(); + }, + verify: (game, _) async { + final googleRollover = + game.descendants().whereType().single; + expect(game.contains(googleRollover), isTrue); + }, + ); - flameTester.test('right loads correctly', (game) async { - final googleRollover = GoogleRollover(side: BoardSide.right); - await game.ensureAdd(googleRollover); - expect(game.contains(googleRollover), isTrue); - }); + flameTester.testGameWidget( + 'right loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final googleRollover = GoogleRollover(side: BoardSide.right); + await game.ensureAdd(googleRollover); + await game.ready(); + }, + verify: (game, _) async { + final googleRollover = + game.descendants().whereType().single; + expect(game.contains(googleRollover), isTrue); + }, + ); group('adds', () { - flameTester.test('new children', (game) async { - final component = Component(); - final googleRollover = GoogleRollover( - side: BoardSide.left, - children: [component], - ); - await game.ensureAdd(googleRollover); - expect(googleRollover.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final googleRollover = GoogleRollover( + side: BoardSide.left, + children: [component], + ); + await game.ensureAdd(googleRollover); + await game.ready(); + }, + verify: (game, _) async { + final googleRollover = + game.descendants().whereType().single; + expect(googleRollover.children.whereType(), isNotNull); + }, + ); - flameTester.test('a GoogleRolloverBallContactBehavior', (game) async { - final googleRollover = GoogleRollover(side: BoardSide.left); - await game.ensureAdd(googleRollover); - expect( - googleRollover.children - .whereType() - .single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a GoogleRolloverBallContactBehavior', + setUp: (game, _) async { + await game.onLoad(); + final googleRollover = GoogleRollover(side: BoardSide.left); + await game.ensureAdd(googleRollover); + await game.ready(); + }, + verify: (game, _) async { + final googleRollover = + game.descendants().whereType().single; + expect( + googleRollover.children + .whereType() + .single, + isNotNull, + ); + }, + ); }); - flameTester.test( + flameTester.testGameWidget( 'pin stops animating after animation completes', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final googleRollover = GoogleRollover(side: BoardSide.left); await game.ensureAdd(googleRollover); - + await game.ready(); + }, + verify: (game, _) async { + final googleRollover = + game.descendants().whereType().single; final pinSpriteAnimationComponent = googleRollover.firstChild()!; pinSpriteAnimationComponent.playing = true; game.update( - pinSpriteAnimationComponent.animation!.totalDuration() + 0.1, + pinSpriteAnimationComponent.animationTicker!.totalDuration() + 0.1, ); expect(pinSpriteAnimationComponent.playing, isFalse); diff --git a/packages/pinball_components/test/src/components/google_word/cubit/google_word_cubit_test.dart b/packages/pinball_components/test/src/components/google_word/cubit/google_word_cubit_test.dart index 152b5f96..de2e3758 100644 --- a/packages/pinball_components/test/src/components/google_word/cubit/google_word_cubit_test.dart +++ b/packages/pinball_components/test/src/components/google_word/cubit/google_word_cubit_test.dart @@ -11,14 +11,14 @@ void main() { if (i.isEven) i: GoogleLetterSpriteState.lit else - i: GoogleLetterSpriteState.dimmed + i: GoogleLetterSpriteState.dimmed, }; final litOdds = { for (int i = 0; i < 6; i++) if (i.isOdd) i: GoogleLetterSpriteState.lit else - i: GoogleLetterSpriteState.dimmed + i: GoogleLetterSpriteState.dimmed, }; blocTest( diff --git a/packages/pinball_components/test/src/components/google_word/google_word_test.dart b/packages/pinball_components/test/src/components/google_word/google_word_test.dart index daee7d37..a2765a3f 100644 --- a/packages/pinball_components/test/src/components/google_word/google_word_test.dart +++ b/packages/pinball_components/test/src/components/google_word/google_word_test.dart @@ -46,12 +46,14 @@ void main() { expect(GoogleWord(position: Vector2.zero()), isA()); }); - flameTester.test( + flameTester.testGameWidget( 'loads letters correctly', - (game) async { + setUp: (game, _) async { final googleWord = GoogleWord(position: Vector2.zero()); await game.pump(googleWord); - + }, + verify: (game, _) async { + final googleWord = game.descendants().whereType().single; expect( googleWord.children.whereType().length, equals(6), diff --git a/packages/pinball_components/test/src/components/initial_position_test.dart b/packages/pinball_components/test/src/components/initial_position_test.dart index b7495181..2ece555b 100644 --- a/packages/pinball_components/test/src/components/initial_position_test.dart +++ b/packages/pinball_components/test/src/components/initial_position_test.dart @@ -27,10 +27,10 @@ void main() { expect(component.initialPosition, Vector2(1, 2)); }); - flameTester.test( + flameTester.testGameWidget( 'throws AssertionError ' 'when BodyDef is not positioned with initialPosition', - (game) async { + setUp: (game, _) async { final component = TestBodyComponent() ..initialPosition = Vector2.all( 10, @@ -42,31 +42,39 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'positions correctly', - (game) async { + setUp: (game, _) async { final position = Vector2.all(10); final component = TestPositionedBodyComponent() ..initialPosition = position; await game.ensureAdd(component); - expect(component.body.position, equals(position)); + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; + expect(component.body.position, equals(Vector2.all(10))); }, ); - flameTester.test( + flameTester.testGameWidget( 'defaults to zero ' 'when no initialPosition is given', - (game) async { + setUp: (game, _) async { final component = TestBodyComponent(); await game.ensureAdd(component); + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; expect(component.body.position, equals(Vector2.zero())); }, ); - flameTester.test( + flameTester.testGameWidget( 'setting throws AssertionError ' 'when component has loaded', - (game) async { + setUp: (game, _) async { final component = TestBodyComponent(); await game.ensureAdd(component); diff --git a/packages/pinball_components/test/src/components/joint_anchor_test.dart b/packages/pinball_components/test/src/components/joint_anchor_test.dart index f7c341dd..d1b7ac3a 100644 --- a/packages/pinball_components/test/src/components/joint_anchor_test.dart +++ b/packages/pinball_components/test/src/components/joint_anchor_test.dart @@ -10,24 +10,28 @@ void main() { final flameTester = FlameTester(Forge2DGame.new); group('JointAnchor', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final anchor = JointAnchor(); await game.ready(); await game.ensureAdd(anchor); - - expect(game.contains(anchor), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); group('body', () { - flameTester.test( + flameTester.testGameWidget( 'is static', - (game) async { + setUp: (game, _) async { await game.ready(); final anchor = JointAnchor(); await game.ensureAdd(anchor); + }, + verify: (game, _) async { + final anchor = game.descendants().whereType().single; expect(anchor.body.bodyType, equals(BodyType.static)); }, @@ -35,11 +39,14 @@ void main() { }); group('fixtures', () { - flameTester.test( + flameTester.testGameWidget( 'has none', - (game) async { + setUp: (game, _) async { final anchor = JointAnchor(); await game.ensureAdd(anchor); + }, + verify: (game, _) async { + final anchor = game.descendants().whereType().single; expect(anchor.body.fixtures, isEmpty); }, diff --git a/packages/pinball_components/test/src/components/kicker/behaviors/kicker_ball_contact_behavior_test.dart b/packages/pinball_components/test/src/components/kicker/behaviors/kicker_ball_contact_behavior_test.dart index 6fa6d4a7..65466790 100644 --- a/packages/pinball_components/test/src/components/kicker/behaviors/kicker_ball_contact_behavior_test.dart +++ b/packages/pinball_components/test/src/components/kicker/behaviors/kicker_ball_contact_behavior_test.dart @@ -30,9 +30,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'beginContact emits onBallContacted when contacts with a ball', - (game) async { + setUp: (game, _) async { final behavior = KickerBallContactBehavior(); final bloc = _MockKickerCubit(); whenListen( @@ -47,6 +47,11 @@ void main() { ); await kicker.add(behavior); await game.ensureAdd(kicker); + }, + verify: (game, _) async { + final behavior = + game.descendants().whereType().single; + final kicker = game.descendants().whereType().single; behavior.beginContact(_MockBall(), _MockContact()); diff --git a/packages/pinball_components/test/src/components/kicker_test.dart b/packages/pinball_components/test/src/components/kicker_test.dart index e347032a..0faea797 100644 --- a/packages/pinball_components/test/src/components/kicker_test.dart +++ b/packages/pinball_components/test/src/components/kicker_test.dart @@ -36,8 +36,8 @@ void main() { side: BoardSide.right, )..initialPosition = Vector2(20, 0); - await game.ensureAddAll([leftKicker, rightKicker]); - game.camera.followVector2(Vector2.zero()); + await game.world.ensureAddAll([leftKicker, rightKicker]); + game.camera.moveTo(Vector2.zero()); await tester.pump(); }, verify: (game, tester) async { @@ -48,82 +48,125 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final kicker = Kicker.test( side: BoardSide.left, bloc: KickerCubit(), ); await game.ensureAdd(kicker); - - expect(game.contains(kicker), isTrue); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); - flameTester.test('closes bloc when removed', (game) async { - final bloc = _MockKickerCubit(); - whenListen( - bloc, - const Stream.empty(), - initialState: KickerState.lit, - ); - when(bloc.close).thenAnswer((_) async {}); - final kicker = Kicker.test( - side: BoardSide.left, - bloc: bloc, - ); + flameTester.testGameWidget( + 'closes bloc when removed', + setUp: (game, _) async { + await game.onLoad(); + final bloc = _MockKickerCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: KickerState.lit, + ); + when(bloc.close).thenAnswer((_) async {}); + final kicker = Kicker.test( + side: BoardSide.left, + bloc: bloc, + ); - await game.ensureAdd(kicker); - game.remove(kicker); - await game.ready(); + await game.ensureAdd(kicker); + await game.ready(); + }, + verify: (game, _) async { + final kicker = game.descendants().whereType().single; + game.remove(kicker); + game.update(0); - verify(bloc.close).called(1); - }); + verify(kicker.bloc.close).called(1); + }, + ); group('adds', () { - flameTester.test('new children', (game) async { - final component = Component(); - final kicker = Kicker( - side: BoardSide.left, - children: [component], - ); - await game.ensureAdd(kicker); - expect(kicker.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final kicker = Kicker( + side: BoardSide.left, + children: [component], + ); + await game.ensureAdd(kicker); + await game.ready(); + }, + verify: (game, _) async { + final kicker = game.descendants().whereType().single; + expect(kicker.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a BumpingBehavior', (game) async { - final kicker = Kicker( - side: BoardSide.left, - ); - await game.ensureAdd(kicker); - expect( - kicker.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final kicker = Kicker( + side: BoardSide.left, + ); + await game.ensureAdd(kicker); + await game.ready(); + }, + verify: (game, _) async { + final kicker = game.descendants().whereType().single; + expect( + kicker.children.whereType().single, + isNotNull, + ); + }, + ); - flameTester.test('a KickerBallContactBehavior', (game) async { - final kicker = Kicker( - side: BoardSide.left, - ); - await game.ensureAdd(kicker); - expect( - kicker.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a KickerBallContactBehavior', + setUp: (game, _) async { + await game.onLoad(); + final kicker = Kicker( + side: BoardSide.left, + ); + await game.ensureAdd(kicker); + await game.ready(); + }, + verify: (game, _) async { + final kicker = game.descendants().whereType().single; + expect( + kicker.children.whereType().single, + isNotNull, + ); + }, + ); - flameTester.test('a KickerBlinkingBehavior', (game) async { - final kicker = Kicker( - side: BoardSide.left, - ); - await game.ensureAdd(kicker); - expect( - kicker.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a KickerBlinkingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final kicker = Kicker( + side: BoardSide.left, + ); + await game.ensureAdd(kicker); + await game.ready(); + }, + verify: (game, _) async { + final kicker = game.descendants().whereType().single; + expect( + kicker.children.whereType().single, + isNotNull, + ); + }, + ); }); }); } diff --git a/packages/pinball_components/test/src/components/launch_ramp_test.dart b/packages/pinball_components/test/src/components/launch_ramp_test.dart index 11033b5a..c70fc2f5 100644 --- a/packages/pinball_components/test/src/components/launch_ramp_test.dart +++ b/packages/pinball_components/test/src/components/launch_ramp_test.dart @@ -1,6 +1,6 @@ // ignore_for_file: cascade_invocations -import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame/components.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -17,19 +17,27 @@ void main() { ]; final flameTester = FlameTester(() => TestGame(assets)); - flameTester.test('loads correctly', (game) async { - final component = LaunchRamp(); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = LaunchRamp(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); flameTester.testGameWidget( 'renders correctly', setUp: (game, tester) async { await game.images.loadAll(assets); - await game.ensureAdd(LaunchRamp()); - game.camera.followVector2(Vector2.zero()); - game.camera.zoom = 4.1; + await game.world.ensureAdd(LaunchRamp()); + game.camera.moveTo(Vector2.zero()); + game.camera.viewfinder.zoom = 4.1; await game.ready(); await tester.pump(); }, diff --git a/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart b/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart index b8701656..d5a61aac 100644 --- a/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart +++ b/packages/pinball_components/test/src/components/layer_sensor/behavior/layer_filtering_behavior_test.dart @@ -45,9 +45,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'loads', - (game) async { + setUp: (game, _) async { final behavior = LayerFilteringBehavior(); final parent = _TestLayerSensor( orientation: LayerEntranceOrientation.down, @@ -57,8 +57,9 @@ void main() { await parent.add(behavior); await game.ensureAdd(parent); - - expect(game.contains(parent), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType<_TestLayerSensor>(), isNotEmpty); }, ); @@ -78,59 +79,61 @@ void main() { when(() => ball.layer).thenReturn(Layer.board); }); - flameTester.test( - 'changes ball layer and zIndex ' - 'when a ball enters and exits a downward oriented LayerSensor', - (game) async { - final parent = _TestLayerSensor( - orientation: LayerEntranceOrientation.down, - insideZIndex: 1, - insideLayer: insideLayer, - )..initialPosition = Vector2(0, 10); - final behavior = LayerFilteringBehavior(); - - await parent.add(behavior); - await game.ensureAdd(parent); - - when(() => body.linearVelocity).thenReturn(Vector2(0, -1)); - - behavior.beginContact(ball, _MockContact()); - verify(() => ball.layer = insideLayer).called(1); - verify(() => ball.zIndex = insideZIndex).called(1); - - when(() => ball.layer).thenReturn(insideLayer); - - behavior.beginContact(ball, _MockContact()); - verify(() => ball.layer = Layer.board); - verify(() => ball.zIndex = ZIndexes.ballOnBoard).called(1); - }); - - flameTester.test( - 'changes ball layer and zIndex ' - 'when a ball enters and exits an upward oriented LayerSensor', - (game) async { - final parent = _TestLayerSensor( - orientation: LayerEntranceOrientation.up, - insideZIndex: 1, - insideLayer: insideLayer, - )..initialPosition = Vector2(0, 10); - final behavior = LayerFilteringBehavior(); - - await parent.add(behavior); - await game.ensureAdd(parent); - - when(() => body.linearVelocity).thenReturn(Vector2(0, 1)); - - behavior.beginContact(ball, _MockContact()); - verify(() => ball.layer = insideLayer).called(1); - verify(() => ball.zIndex = 1).called(1); - - when(() => ball.layer).thenReturn(insideLayer); + flameTester.testGameWidget( + 'changes ball layer and zIndex ' + 'when a ball enters and exits a downward oriented LayerSensor', + setUp: (game, _) async { + final parent = _TestLayerSensor( + orientation: LayerEntranceOrientation.down, + insideZIndex: 1, + insideLayer: insideLayer, + )..initialPosition = Vector2(0, 10); + await game.ensureAdd(parent); + }, + verify: (game, _) async { + when(() => body.linearVelocity).thenReturn(Vector2(0, -1)); + final behavior = + game.descendants().whereType().single; + + behavior.beginContact(ball, _MockContact()); + verify(() => ball.layer = insideLayer).called(1); + verify(() => ball.zIndex = insideZIndex).called(1); + + when(() => ball.layer).thenReturn(insideLayer); + + behavior.beginContact(ball, _MockContact()); + verify(() => ball.layer = Layer.board); + verify(() => ball.zIndex = ZIndexes.ballOnBoard).called(1); + }, + ); - behavior.beginContact(ball, _MockContact()); - verify(() => ball.layer = Layer.board); - verify(() => ball.zIndex = ZIndexes.ballOnBoard).called(1); - }); + flameTester.testGameWidget( + 'changes ball layer and zIndex ' + 'when a ball enters and exits an upward oriented LayerSensor', + setUp: (game, _) async { + final parent = _TestLayerSensor( + orientation: LayerEntranceOrientation.up, + insideZIndex: 1, + insideLayer: insideLayer, + )..initialPosition = Vector2(0, 10); + await game.ensureAdd(parent); + }, + verify: (game, _) async { + final behavior = + game.descendants().whereType().single; + when(() => body.linearVelocity).thenReturn(Vector2(0, 1)); + + behavior.beginContact(ball, _MockContact()); + verify(() => ball.layer = insideLayer).called(1); + verify(() => ball.zIndex = 1).called(1); + + when(() => ball.layer).thenReturn(insideLayer); + + behavior.beginContact(ball, _MockContact()); + verify(() => ball.layer = Layer.board); + verify(() => ball.zIndex = ZIndexes.ballOnBoard).called(1); + }, + ); }); }, ); diff --git a/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart b/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart index 2966b106..1a2ca990 100644 --- a/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart +++ b/packages/pinball_components/test/src/components/layer_sensor/layer_sensor_test.dart @@ -29,31 +29,35 @@ void main() { const insidePriority = 1; group('LayerSensor', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final layerSensor = TestLayerSensor( orientation: LayerEntranceOrientation.down, insideZIndex: insidePriority, insideLayer: Layer.spaceshipEntranceRamp, ); await game.ensureAdd(layerSensor); - - expect(game.contains(layerSensor), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); group('body', () { - flameTester.test( + flameTester.testGameWidget( 'is static', - (game) async { + setUp: (game, _) async { final layerSensor = TestLayerSensor( orientation: LayerEntranceOrientation.down, insideZIndex: insidePriority, insideLayer: Layer.spaceshipEntranceRamp, ); await game.ensureAdd(layerSensor); - + }, + verify: (game, _) async { + final layerSensor = + game.descendants().whereType().single; expect(layerSensor.body.bodyType, equals(BodyType.static)); }, ); @@ -62,44 +66,55 @@ void main() { const pathwayLayer = Layer.spaceshipEntranceRamp; const openingLayer = Layer.opening; - flameTester.test( + flameTester.testGameWidget( 'exists', - (game) async { + setUp: (game, _) async { final layerSensor = TestLayerSensor( orientation: LayerEntranceOrientation.down, insideZIndex: insidePriority, insideLayer: pathwayLayer, )..layer = openingLayer; await game.ensureAdd(layerSensor); - + }, + verify: (game, _) async { + final layerSensor = + game.descendants().whereType().single; expect(layerSensor.body.fixtures[0], isA()); }, ); - flameTester.test( + flameTester.testGameWidget( 'shape is a polygon', - (game) async { + setUp: (game, _) async { final layerSensor = TestLayerSensor( orientation: LayerEntranceOrientation.down, insideZIndex: insidePriority, insideLayer: pathwayLayer, )..layer = openingLayer; await game.ensureAdd(layerSensor); + }, + verify: (game, _) async { + final layerSensor = + game.descendants().whereType().single; final fixture = layerSensor.body.fixtures[0]; expect(fixture.shape.shapeType, equals(ShapeType.polygon)); }, ); - flameTester.test( + flameTester.testGameWidget( 'is sensor', - (game) async { + setUp: (game, _) async { final layerSensor = TestLayerSensor( orientation: LayerEntranceOrientation.down, insideZIndex: insidePriority, insideLayer: pathwayLayer, )..layer = openingLayer; await game.ensureAdd(layerSensor); + }, + verify: (game, _) async { + final layerSensor = + game.descendants().whereType().single; final fixture = layerSensor.body.fixtures[0]; expect(fixture.isSensor, isTrue); @@ -108,16 +123,19 @@ void main() { }); }); - flameTester.test( + flameTester.testGameWidget( 'adds a LayerFilteringBehavior', - (game) async { + setUp: (game, _) async { final layerSensor = TestLayerSensor( orientation: LayerEntranceOrientation.down, insideZIndex: insidePriority, insideLayer: Layer.spaceshipEntranceRamp, ); await game.ensureAdd(layerSensor); - + }, + verify: (game, _) async { + final layerSensor = + game.descendants().whereType().single; expect( layerSensor.children.whereType().length, equals(1), diff --git a/packages/pinball_components/test/src/components/multiball/cubit/multiball_cubit_test.dart b/packages/pinball_components/test/src/components/multiball/cubit/multiball_cubit_test.dart index 2fcb5ccc..ed1358e6 100644 --- a/packages/pinball_components/test/src/components/multiball/cubit/multiball_cubit_test.dart +++ b/packages/pinball_components/test/src/components/multiball/cubit/multiball_cubit_test.dart @@ -11,12 +11,11 @@ void main() { build: MultiballCubit.new, act: (bloc) => bloc.onAnimate(), expect: () => [ - isA() - ..having( - (state) => state.animationState, - 'animationState', - MultiballAnimationState.blinking, - ) + isA().having( + (state) => state.animationState, + 'animationState', + MultiballAnimationState.blinking, + ), ], ); @@ -25,12 +24,11 @@ void main() { build: MultiballCubit.new, act: (bloc) => bloc.onStop(), expect: () => [ - isA() - ..having( - (state) => state.animationState, - 'animationState', - MultiballAnimationState.idle, - ) + isA().having( + (state) => state.animationState, + 'animationState', + MultiballAnimationState.idle, + ), ], ); @@ -42,24 +40,21 @@ void main() { ..onBlink() ..onBlink(), expect: () => [ - isA() - ..having( - (state) => state.lightState, - 'lightState', - MultiballLightState.lit, - ), - isA() - ..having( - (state) => state.lightState, - 'lightState', - MultiballLightState.dimmed, - ), - isA() - ..having( - (state) => state.lightState, - 'lightState', - MultiballLightState.lit, - ) + isA().having( + (state) => state.lightState, + 'lightState', + MultiballLightState.lit, + ), + isA().having( + (state) => state.lightState, + 'lightState', + MultiballLightState.dimmed, + ), + isA().having( + (state) => state.lightState, + 'lightState', + MultiballLightState.lit, + ), ], ); }, diff --git a/packages/pinball_components/test/src/components/multiball/multiball_test.dart b/packages/pinball_components/test/src/components/multiball/multiball_test.dart index 26dcf8a8..f4a1e361 100644 --- a/packages/pinball_components/test/src/components/multiball/multiball_test.dart +++ b/packages/pinball_components/test/src/components/multiball/multiball_test.dart @@ -22,36 +22,55 @@ void main() { group('Multiball', () { group('loads correctly', () { - flameTester.test('"a"', (game) async { - final multiball = Multiball.a(); - await game.ensureAdd(multiball); - - expect(game.contains(multiball), isTrue); - }); + flameTester.testGameWidget( + '"a"', + setUp: (game, _) async { + final multiball = Multiball.a(); + await game.ensureAdd(multiball); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); - flameTester.test('"b"', (game) async { - final multiball = Multiball.b(); - await game.ensureAdd(multiball); - expect(game.contains(multiball), isTrue); - }); + flameTester.testGameWidget( + '"b"', + setUp: (game, _) async { + final multiball = Multiball.b(); + await game.ensureAdd(multiball); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); - flameTester.test('"c"', (game) async { - final multiball = Multiball.c(); - await game.ensureAdd(multiball); + flameTester.testGameWidget( + '"c"', + setUp: (game, _) async { + final multiball = Multiball.c(); + await game.ensureAdd(multiball); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); - expect(game.contains(multiball), isTrue); - }); - - flameTester.test('"d"', (game) async { - final multiball = Multiball.d(); - await game.ensureAdd(multiball); - expect(game.contains(multiball), isTrue); - }); + flameTester.testGameWidget( + '"d"', + setUp: (game, _) async { + final multiball = Multiball.d(); + await game.ensureAdd(multiball); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); }); - flameTester.test( + flameTester.testGameWidget( 'closes bloc when removed', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockMultiballCubit(); whenListen( bloc, @@ -62,31 +81,47 @@ void main() { final multiball = Multiball.test(bloc: bloc); await game.ensureAdd(multiball); - game.remove(multiball); await game.ready(); + }, + verify: (game, _) async { + final multiball = game.descendants().whereType().single; + game.remove(multiball); + game.update(0); - verify(bloc.close).called(1); + verify(multiball.bloc.close).called(1); }, ); group('adds', () { - flameTester.test('new children', (game) async { - final component = Component(); - final multiball = Multiball.a( - children: [component], - ); - await game.ensureAdd(multiball); - expect(multiball.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + final component = Component(); + final multiball = Multiball.a( + children: [component], + ); + await game.ensureAdd(multiball); + }, + verify: (game, _) async { + final multiball = game.descendants().whereType().single; + expect(multiball.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a MultiballBlinkingBehavior', (game) async { - final multiball = Multiball.a(); - await game.ensureAdd(multiball); - expect( - multiball.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a MultiballBlinkingBehavior', + setUp: (game, _) async { + final multiball = Multiball.a(); + await game.ensureAdd(multiball); + }, + verify: (game, _) async { + final multiball = game.descendants().whereType().single; + expect( + multiball.children.whereType(), + isNotEmpty, + ); + }, + ); }); }); } diff --git a/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_cubit_test.dart b/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_cubit_test.dart index 35ed652e..7c83600e 100644 --- a/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_cubit_test.dart +++ b/packages/pinball_components/test/src/components/multiplier/cubit/multiplier_cubit_test.dart @@ -13,12 +13,11 @@ void main() { build: () => MultiplierCubit(MultiplierValue.x2), act: (bloc) => bloc.next(2), expect: () => [ - isA() - ..having( - (state) => state.spriteState, - 'spriteState', - MultiplierSpriteState.lit, - ), + isA().having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), ], ); @@ -27,12 +26,11 @@ void main() { build: () => MultiplierCubit(MultiplierValue.x3), act: (bloc) => bloc.next(3), expect: () => [ - isA() - ..having( - (state) => state.spriteState, - 'spriteState', - MultiplierSpriteState.lit, - ), + isA().having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), ], ); @@ -41,12 +39,11 @@ void main() { build: () => MultiplierCubit(MultiplierValue.x4), act: (bloc) => bloc.next(4), expect: () => [ - isA() - ..having( - (state) => state.spriteState, - 'spriteState', - MultiplierSpriteState.lit, - ), + isA().having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), ], ); @@ -55,12 +52,11 @@ void main() { build: () => MultiplierCubit(MultiplierValue.x5), act: (bloc) => bloc.next(5), expect: () => [ - isA() - ..having( - (state) => state.spriteState, - 'spriteState', - MultiplierSpriteState.lit, - ), + isA().having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), ], ); @@ -69,12 +65,11 @@ void main() { build: () => MultiplierCubit(MultiplierValue.x6), act: (bloc) => bloc.next(6), expect: () => [ - isA() - ..having( - (state) => state.spriteState, - 'spriteState', - MultiplierSpriteState.lit, - ), + isA().having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.lit, + ), ], ); @@ -87,12 +82,11 @@ void main() { ), act: (bloc) => bloc.next(3), expect: () => [ - isA() - ..having( - (state) => state.spriteState, - 'spriteState', - MultiplierSpriteState.dimmed, - ), + isA().having( + (state) => state.spriteState, + 'spriteState', + MultiplierSpriteState.dimmed, + ), ], ); diff --git a/packages/pinball_components/test/src/components/multiplier/multiplier_test.dart b/packages/pinball_components/test/src/components/multiplier/multiplier_test.dart index 0a28ae54..3764d961 100644 --- a/packages/pinball_components/test/src/components/multiplier/multiplier_test.dart +++ b/packages/pinball_components/test/src/components/multiplier/multiplier_test.dart @@ -38,50 +38,80 @@ void main() { bloc = _MockMultiplierCubit(); }); - flameTester.test('"x2" loads correctly', (game) async { - final multiplier = Multiplier.x2( - position: Vector2.zero(), - angle: 0, - ); - await game.ensureAdd(multiplier); - expect(game.contains(multiplier), isTrue); - }); - - flameTester.test('"x3" loads correctly', (game) async { - final multiplier = Multiplier.x3( - position: Vector2.zero(), - angle: 0, - ); - await game.ensureAdd(multiplier); - expect(game.contains(multiplier), isTrue); - }); - - flameTester.test('"x4" loads correctly', (game) async { - final multiplier = Multiplier.x4( - position: Vector2.zero(), - angle: 0, - ); - await game.ensureAdd(multiplier); - expect(game.contains(multiplier), isTrue); - }); - - flameTester.test('"x5" loads correctly', (game) async { - final multiplier = Multiplier.x5( - position: Vector2.zero(), - angle: 0, - ); - await game.ensureAdd(multiplier); - expect(game.contains(multiplier), isTrue); - }); - - flameTester.test('"x6" loads correctly', (game) async { - final multiplier = Multiplier.x6( - position: Vector2.zero(), - angle: 0, - ); - await game.ensureAdd(multiplier); - expect(game.contains(multiplier), isTrue); - }); + flameTester.testGameWidget( + '"x2" loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final multiplier = Multiplier.x2( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); + + flameTester.testGameWidget( + '"x3" loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final multiplier = Multiplier.x3( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); + + flameTester.testGameWidget( + '"x4" loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final multiplier = Multiplier.x4( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); + + flameTester.testGameWidget( + '"x5" loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final multiplier = Multiplier.x5( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); + + flameTester.testGameWidget( + '"x6" loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final multiplier = Multiplier.x6( + position: Vector2.zero(), + angle: 0, + ); + await game.ensureAdd(multiplier); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); group('renders correctly', () { group('x2', () { @@ -105,10 +135,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -145,10 +175,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -189,10 +219,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -229,10 +259,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -273,10 +303,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -313,10 +343,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -357,10 +387,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -397,10 +427,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -441,10 +471,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -481,10 +511,10 @@ void main() { value: multiplierValue, bloc: bloc, ); - await game.ensureAdd(multiplier); + await game.world.ensureAdd(multiplier); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { expect( @@ -505,23 +535,30 @@ void main() { }); }); - flameTester.test('closes bloc when removed', (game) async { - whenListen( - bloc, - const Stream.empty(), - initialState: MultiplierState( - value: MultiplierValue.x2, - spriteState: MultiplierSpriteState.dimmed, - ), - ); - when(bloc.close).thenAnswer((_) async {}); - final multiplier = Multiplier.test(value: MultiplierValue.x2, bloc: bloc); - - await game.ensureAdd(multiplier); - game.remove(multiplier); - await game.ready(); - - verify(bloc.close).called(1); - }); + flameTester.testGameWidget( + 'closes bloc when removed', + setUp: (game, _) async { + whenListen( + bloc, + const Stream.empty(), + initialState: MultiplierState( + value: MultiplierValue.x2, + spriteState: MultiplierSpriteState.dimmed, + ), + ); + when(bloc.close).thenAnswer((_) async {}); + final multiplier = + Multiplier.test(value: MultiplierValue.x2, bloc: bloc); + + await game.ensureAdd(multiplier); + }, + verify: (game, _) async { + final multiplier = game.descendants().whereType().single; + game.remove(multiplier); + game.update(0); + + verify(bloc.close).called(1); + }, + ); }); } diff --git a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_jointing_behavior_test.dart b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_jointing_behavior_test.dart index 940ea625..8b70c9e1 100644 --- a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_jointing_behavior_test.dart +++ b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_jointing_behavior_test.dart @@ -17,20 +17,35 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final parent = Plunger.test(); - final behavior = PlungerJointingBehavior(compressionDistance: 0); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); - expect(parent.children, contains(behavior)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final parent = Plunger.test(); + final behavior = PlungerJointingBehavior(compressionDistance: 0); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final plunger = game.descendants().whereType().single; + expect( + plunger.children.whereType().length, + equals(1), + ); + }, + ); - flameTester.test('creates a joint', (game) async { - final behavior = PlungerJointingBehavior(compressionDistance: 0); - final parent = Plunger.test(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); - expect(parent.body.joints, isNotEmpty); - }); + flameTester.testGameWidget( + 'creates a joint', + setUp: (game, _) async { + final parent = Plunger.test(); + final behavior = PlungerJointingBehavior(compressionDistance: 0); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final plunger = game.descendants().whereType().single; + expect(plunger.body.joints, isNotEmpty); + }, + ); }); } diff --git a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_key_controlling_behavior_test.dart b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_key_controlling_behavior_test.dart index 1147d7f3..c97c9f43 100644 --- a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_key_controlling_behavior_test.dart +++ b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_key_controlling_behavior_test.dart @@ -3,7 +3,6 @@ import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -25,14 +24,14 @@ class _TestGame extends Forge2DGame { } } -class _MockRawKeyDownEvent extends Mock implements RawKeyDownEvent { +class _MockKeyDownEvent extends Mock implements KeyDownEvent { @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return super.toString(); } } -class _MockRawKeyUpEvent extends Mock implements RawKeyUpEvent { +class _MockKeyUpEvent extends Mock implements KeyUpEvent { @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return super.toString(); @@ -53,11 +52,19 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final behavior = PlungerKeyControllingBehavior(); - await game.pump(behavior); - expect(game.descendants(), contains(behavior)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final behavior = PlungerKeyControllingBehavior(); + await game.pump(behavior); + }, + verify: (game, _) async { + expect( + game.descendants().whereType(), + isNotEmpty, + ); + }, + ); group('onKeyEvent', () { late PlungerCubit plungerBloc; @@ -67,16 +74,21 @@ void main() { }); group('pulls when', () { - flameTester.test( + flameTester.testGameWidget( 'down arrow is pressed', - (game) async { + setUp: (game, _) async { final behavior = PlungerKeyControllingBehavior(); await game.pump( behavior, plungerBloc: plungerBloc, ); - - final event = _MockRawKeyDownEvent(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowDown, ); @@ -87,16 +99,22 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( '"s" is pressed', - (game) async { + setUp: (game, _) async { final behavior = PlungerKeyControllingBehavior(); await game.pump( behavior, plungerBloc: plungerBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyDownEvent(); + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyS, ); @@ -107,16 +125,22 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'space is pressed', - (game) async { + setUp: (game, _) async { final behavior = PlungerKeyControllingBehavior(); await game.pump( behavior, plungerBloc: plungerBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyDownEvent(); + final event = _MockKeyDownEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.space, ); @@ -129,16 +153,22 @@ void main() { }); group('releases when', () { - flameTester.test( + flameTester.testGameWidget( 'down arrow is released', - (game) async { + setUp: (game, _) async { final behavior = PlungerKeyControllingBehavior(); await game.pump( behavior, plungerBloc: plungerBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyUpEvent(); + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.arrowDown, ); @@ -149,16 +179,22 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( '"s" is released', - (game) async { + setUp: (game, _) async { final behavior = PlungerKeyControllingBehavior(); await game.pump( behavior, plungerBloc: plungerBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyUpEvent(); + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.keyS, ); @@ -169,16 +205,22 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'space is released', - (game) async { + setUp: (game, _) async { final behavior = PlungerKeyControllingBehavior(); await game.pump( behavior, plungerBloc: plungerBloc, ); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; - final event = _MockRawKeyUpEvent(); + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn( LogicalKeyboardKey.space, ); diff --git a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_noise_behavior_test.dart b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_noise_behavior_test.dart index a5e11ad0..5b468c2e 100644 --- a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_noise_behavior_test.dart +++ b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_noise_behavior_test.dart @@ -57,15 +57,23 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final behavior = PlungerNoiseBehavior(); - await game.pump(behavior); - expect(game.descendants(), contains(behavior)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final behavior = PlungerNoiseBehavior(); + await game.pump(behavior); + }, + verify: (game, _) async { + expect( + game.descendants().whereType(), + isNotEmpty, + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'plays the correct sound when released', - (game) async { + setUp: (game, _) async { final plungerBloc = _MockPlungerCubit(); final streamController = StreamController(); whenListen( @@ -80,9 +88,10 @@ void main() { pinballAudioPlayer: audioPlayer, plungerBloc: plungerBloc, ); - streamController.add(PlungerState.releasing); - await Future.delayed(Duration.zero); + }, + verify: (game, _) async { + game.update(0); verify(() => audioPlayer.play(PinballAudio.launcher)).called(1); }, diff --git a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_pulling_behavior_test.dart b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_pulling_behavior_test.dart index c289edee..31267841 100644 --- a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_pulling_behavior_test.dart +++ b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_pulling_behavior_test.dart @@ -20,7 +20,7 @@ class _TestGame extends Forge2DGame { await ensureAdd(plunger); return plunger.ensureAdd( FlameBlocProvider.value( - value: plungerBloc ?? _MockPlungerCubit(), + value: plungerBloc ?? PlungerCubit(), children: [behavior], ), ); @@ -50,15 +50,23 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final behavior = PlungerPullingBehavior(strength: 0); - await game.pump(behavior); - expect(game.descendants(), contains(behavior)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final behavior = PlungerPullingBehavior(strength: 0); + await game.pump(behavior); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'applies vertical linear velocity when pulled', - (game) async { + setUp: (game, _) async { final plungerBloc = _MockPlungerCubit(); whenListen( plungerBloc, @@ -66,19 +74,22 @@ void main() { initialState: PlungerState.pulling, ); - const strength = 2.0; final behavior = PlungerPullingBehavior( - strength: strength, + strength: 2, ); await game.pump( behavior, plungerBloc: plungerBloc, ); + }, + verify: (game, _) async { + final behavior = + game.descendants().whereType().single; game.update(0); final plunger = behavior.ancestors().whereType().single; expect(plunger.body.linearVelocity.x, equals(0)); - expect(plunger.body.linearVelocity.y, equals(strength)); + expect(plunger.body.linearVelocity.y, equals(2)); }, ); }); @@ -91,15 +102,23 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final behavior = PlungerAutoPullingBehavior(); - await game.pump(behavior); - expect(game.descendants(), contains(behavior)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final behavior = PlungerAutoPullingBehavior(); + await game.pump(behavior); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'releases when joint reaches limit', - (game) async { + setUp: (game, _) async { final plungerBloc = _MockPlungerCubit(); whenListen( plungerBloc, @@ -108,17 +127,22 @@ void main() { ); final behavior = PlungerAutoPullingBehavior(); + final joint = _MockPrismaticJoint(); + when(joint.getJointTranslation).thenReturn(0); + when(joint.getLowerLimit).thenReturn(0); await game.pump( behavior, plungerBloc: plungerBloc, ); - final plunger = behavior.ancestors().whereType().single; - final joint = _MockPrismaticJoint(); - when(joint.getJointTranslation).thenReturn(0); - when(joint.getLowerLimit).thenReturn(0); + final plunger = game.descendants().whereType().single; plunger.body.joints.add(joint); - - game.update(0); + }, + verify: (game, _) async { + final plungerBloc = game + .descendants() + .whereType>() + .single + .bloc; verify(plungerBloc.released).called(1); }, diff --git a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_releasing_behavior_test.dart b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_releasing_behavior_test.dart index 501753c4..d61640ed 100644 --- a/packages/pinball_components/test/src/components/plunger/behaviors/plunger_releasing_behavior_test.dart +++ b/packages/pinball_components/test/src/components/plunger/behaviors/plunger_releasing_behavior_test.dart @@ -47,33 +47,48 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final behavior = PlungerReleasingBehavior(strength: 0); - await game.pump(behavior); - expect(game.descendants(), contains(behavior)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final behavior = PlungerReleasingBehavior(strength: 0); + await game.pump(behavior); + }, + verify: (game, _) async { + expect( + game.descendants().whereType(), + isNotEmpty, + ); + }, + ); - flameTester.test('applies vertical linear velocity', (game) async { - final plungerBloc = _MockPlungerCubit(); - final streamController = StreamController(); - whenListen( - plungerBloc, - streamController.stream, - initialState: PlungerState.pulling, - ); + flameTester.testGameWidget( + 'applies vertical linear velocity', + setUp: (game, _) async { + final plungerBloc = _MockPlungerCubit(); + final streamController = StreamController(); + whenListen( + plungerBloc, + streamController.stream, + initialState: PlungerState.pulling, + ); - final behavior = PlungerReleasingBehavior(strength: 2); - await game.pump( - behavior, - plungerBloc: plungerBloc, - ); + final behavior = PlungerReleasingBehavior(strength: 2); + await game.pump( + behavior, + plungerBloc: plungerBloc, + ); - streamController.add(PlungerState.releasing); - await Future.delayed(Duration.zero); + streamController.add(PlungerState.releasing); + }, + verify: (game, _) async { + final behavior = + game.descendants().whereType().single; + game.update(0); - final plunger = behavior.ancestors().whereType().single; - expect(plunger.body.linearVelocity.x, equals(0)); - expect(plunger.body.linearVelocity.y, isNot(greaterThan(0))); - }); + final plunger = behavior.ancestors().whereType().single; + expect(plunger.body.linearVelocity.x, equals(0)); + expect(plunger.body.linearVelocity.y, isNot(greaterThan(0))); + }, + ); }); } diff --git a/packages/pinball_components/test/src/components/plunger/plunger_test.dart b/packages/pinball_components/test/src/components/plunger/plunger_test.dart index 6017f255..67158e3d 100644 --- a/packages/pinball_components/test/src/components/plunger/plunger_test.dart +++ b/packages/pinball_components/test/src/components/plunger/plunger_test.dart @@ -1,7 +1,7 @@ // ignore_for_file: cascade_invocations +import 'package:flame/components.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:pinball_components/pinball_components.dart'; @@ -18,21 +18,25 @@ void main() { expect(Plunger(), isA()); }); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final plunger = Plunger(); await game.ensureAdd(plunger); - expect(game.children, contains(plunger)); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); group('adds', () { - flameTester.test( + flameTester.testGameWidget( 'a PlungerReleasingBehavior', - (game) async { + setUp: (game, _) async { final plunger = Plunger(); await game.ensureAdd(plunger); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -40,11 +44,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'a PlungerJointingBehavior', - (game) async { + setUp: (game, _) async { final plunger = Plunger(); await game.ensureAdd(plunger); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -52,11 +58,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'a PlungerNoiseBehavior', - (game) async { + setUp: (game, _) async { final plunger = Plunger(); await game.ensureAdd(plunger); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -71,9 +79,9 @@ void main() { 'pulling', setUp: (game, tester) async { await game.images.load(asset); - await game.ensureAdd(Plunger()); - game.camera.followVector2(Vector2.zero()); - game.camera.zoom = 4.1; + await game.world.ensureAdd(Plunger()); + game.camera.moveTo(Vector2.zero()); + game.camera.viewfinder.zoom = 4.1; }, verify: (game, tester) async { final plunger = game.descendants().whereType().first; @@ -95,9 +103,9 @@ void main() { 'releasing', setUp: (game, tester) async { await game.images.load(asset); - await game.ensureAdd(Plunger()); - game.camera.followVector2(Vector2.zero()); - game.camera.zoom = 4.1; + await game.world.ensureAdd(Plunger()); + game.camera.moveTo(Vector2.zero()); + game.camera.viewfinder.zoom = 4.1; }, verify: (game, tester) async { final plunger = game.descendants().whereType().first; diff --git a/packages/pinball_components/test/src/components/rocket_test.dart b/packages/pinball_components/test/src/components/rocket_test.dart index 5bc9b136..59c7c979 100644 --- a/packages/pinball_components/test/src/components/rocket_test.dart +++ b/packages/pinball_components/test/src/components/rocket_test.dart @@ -19,11 +19,11 @@ void main() { 'renders correctly', setUp: (game, tester) async { await game.images.loadAll(assets); - await game.ensureAdd(RocketSpriteComponent()); + await game.world.ensureAdd(RocketSpriteComponent()); game.camera - ..followVector2(Vector2.zero()) - ..zoom = 8; + ..moveTo(Vector2.zero()) + ..viewfinder.zoom = 8; await tester.pump(); }, diff --git a/packages/pinball_components/test/src/components/score_component/behaviors/score_component_scaling_behavior_test.dart b/packages/pinball_components/test/src/components/score_component/behaviors/score_component_scaling_behavior_test.dart index 9bf0db2f..e1a2b3ed 100644 --- a/packages/pinball_components/test/src/components/score_component/behaviors/score_component_scaling_behavior_test.dart +++ b/packages/pinball_components/test/src/components/score_component/behaviors/score_component_scaling_behavior_test.dart @@ -28,22 +28,35 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final parent = ScoreComponent.test( - points: Points.fiveThousand, - position: Vector2.zero(), - effectController: EffectController(duration: 1), - ); - final behavior = ScoreComponentScalingBehavior(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); - - expect(parent.children, contains(behavior)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + await game.onLoad(); + final parent = ScoreComponent.test( + points: Points.fiveThousand, + position: Vector2.zero(), + effectController: EffectController(duration: 1), + ); + final behavior = ScoreComponentScalingBehavior(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final scoreComponent = + game.descendants().whereType().single; + expect( + scoreComponent.children + .whereType() + .length, + equals(1), + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'scales the sprite', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final parent1 = ScoreComponent.test( points: Points.fiveThousand, position: Vector2(0, 10), @@ -58,15 +71,19 @@ void main() { await parent1.ensureAdd(ScoreComponentScalingBehavior()); await parent2.ensureAdd(ScoreComponentScalingBehavior()); + }, + verify: (game, _) async { + final scoreComponents = + game.descendants().whereType().toList(); game.update(1); expect( - parent1.scale.x, - greaterThan(parent2.scale.x), + scoreComponents[0].scale.x, + greaterThan(scoreComponents[1].scale.x), ); expect( - parent1.scale.y, - greaterThan(parent2.scale.y), + scoreComponents[0].scale.y, + greaterThan(scoreComponents[1].scale.y), ); }, ); diff --git a/packages/pinball_components/test/src/components/score_component/score_component_test.dart b/packages/pinball_components/test/src/components/score_component/score_component_test.dart index 00c08d5c..91d2c94c 100644 --- a/packages/pinball_components/test/src/components/score_component/score_component_test.dart +++ b/packages/pinball_components/test/src/components/score_component/score_component_test.dart @@ -36,7 +36,7 @@ void main() { 'loads correctly', setUp: (game, tester) async { await game.onLoad(); - game.camera.followVector2(Vector2.zero()); + game.camera.follow(PositionComponent(position: Vector2.zero())); await game.ensureAdd( ScoreComponent( points: Points.oneMillion, @@ -51,20 +51,25 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds a ScoreComponentScalingBehavior', - (game) async { + setUp: (game, _) async { await game.onLoad(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); final component = ScoreComponent( points: Points.oneMillion, position: Vector2.zero(), effectController: EffectController(duration: 1), ); await game.ensureAdd(component); - + }, + verify: (game, _) async { + final scoreComponent = + game.descendants().whereType().single; expect( - component.children.whereType().length, + scoreComponent.children + .whereType() + .length, equals(1), ); }, @@ -74,7 +79,7 @@ void main() { 'has a movement effect', setUp: (game, tester) async { await game.onLoad(); - game.camera.followVector2(Vector2.zero()); + game.camera.follow(PositionComponent(position: Vector2.zero())); await game.ensureAdd( ScoreComponent.test( points: Points.oneMillion, @@ -96,7 +101,7 @@ void main() { 'is removed once finished', setUp: (game, tester) async { await game.onLoad(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); await game.ensureAdd( ScoreComponent.test( points: Points.oneMillion, @@ -110,7 +115,7 @@ void main() { await tester.pump(); }, verify: (game, tester) async { - expect(game.children.length, equals(0)); + expect(game.children.whereType().length, equals(0)); }, ); @@ -121,7 +126,7 @@ void main() { '5000 points', setUp: (game, tester) async { await game.onLoad(); - await game.ensureAdd( + await game.world.ensureAdd( ScoreComponent.test( points: Points.fiveThousand, position: Vector2.zero(), @@ -130,8 +135,8 @@ void main() { ); game.camera - ..followVector2(Vector2.zero()) - ..zoom = 8; + ..moveTo(Vector2.zero()) + ..viewfinder.zoom = 8; await tester.pump(); }, @@ -147,7 +152,7 @@ void main() { '20000 points', setUp: (game, tester) async { await game.onLoad(); - await game.ensureAdd( + await game.world.ensureAdd( ScoreComponent.test( points: Points.twentyThousand, position: Vector2.zero(), @@ -156,8 +161,8 @@ void main() { ); game.camera - ..followVector2(Vector2.zero()) - ..zoom = 8; + ..moveTo(Vector2.zero()) + ..viewfinder.zoom = 8; await tester.pump(); }, @@ -173,7 +178,7 @@ void main() { '200000 points', setUp: (game, tester) async { await game.onLoad(); - await game.ensureAdd( + await game.world.ensureAdd( ScoreComponent.test( points: Points.twoHundredThousand, position: Vector2.zero(), @@ -182,8 +187,8 @@ void main() { ); game.camera - ..followVector2(Vector2.zero()) - ..zoom = 8; + ..moveTo(Vector2.zero()) + ..viewfinder.zoom = 8; await tester.pump(); }, @@ -199,7 +204,7 @@ void main() { '1000000 points', setUp: (game, tester) async { await game.onLoad(); - await game.ensureAdd( + await game.world.ensureAdd( ScoreComponent.test( points: Points.oneMillion, position: Vector2.zero(), @@ -208,8 +213,8 @@ void main() { ); game.camera - ..followVector2(Vector2.zero()) - ..zoom = 8; + ..moveTo(Vector2.zero()) + ..viewfinder.zoom = 8; await tester.pump(); }, diff --git a/packages/pinball_components/test/src/components/signpost/signpost_test.dart b/packages/pinball_components/test/src/components/signpost/signpost_test.dart index 0874a8bd..705a72ea 100644 --- a/packages/pinball_components/test/src/components/signpost/signpost_test.dart +++ b/packages/pinball_components/test/src/components/signpost/signpost_test.dart @@ -29,7 +29,7 @@ class _TestGame extends Forge2DGame { DashBumpersCubit? dashBumpersBloc, }) async { await onLoad(); - await ensureAdd( + await world.ensureAdd( FlameMultiBlocProvider( providers: [ FlameBlocProvider.value( @@ -61,12 +61,17 @@ void main() { expect(Signpost(), isA()); }); - flameTester.test( + flameTester.testGameWidget( 'can be added', - (game) async { + setUp: (game, _) async { final signpost = Signpost(); await game.pump(signpost); - expect(game.descendants().contains(signpost), isTrue); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); }, ); @@ -83,7 +88,7 @@ void main() { equals(SignpostState.inactive), ); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { await expectLater( @@ -107,7 +112,7 @@ void main() { equals(SignpostState.active1), ); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { await expectLater( @@ -133,7 +138,7 @@ void main() { equals(SignpostState.active2), ); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { await expectLater( @@ -160,7 +165,7 @@ void main() { equals(SignpostState.active3), ); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { await expectLater( @@ -176,7 +181,8 @@ void main() { setUp: (game, tester) async { final activatedBumpersState = DashBumpersState( bumperSpriteStates: { - for (var id in DashBumperId.values) id: DashBumperSpriteState.active + for (final id in DashBumperId.values) + id: DashBumperSpriteState.active, }, ); final signpost = Signpost(); @@ -201,9 +207,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'onNewState calls onProgressed and onReset', - (game) async { + setUp: (game, _) async { final signpost = Signpost(); final signpostBloc = _MockSignpostCubit(); whenListen( @@ -222,7 +228,18 @@ void main() { signpostBloc: signpostBloc, dashBumpersBloc: dashBumpersBloc, ); - + }, + verify: (game, _) async { + final signpostBloc = game + .descendants() + .whereType>() + .single + .bloc; + final dashBumpersBloc = game + .descendants() + .whereType>() + .single + .bloc; game .descendants() .whereType>() @@ -234,13 +251,19 @@ void main() { }, ); - flameTester.test('adds new children', (game) async { - final component = Component(); - final signpost = Signpost( - children: [component], - ); - await game.pump(signpost); - expect(signpost.children, contains(component)); - }); + flameTester.testGameWidget( + 'adds new children', + setUp: (game, _) async { + final component = Component(); + final signpost = Signpost( + children: [component], + ); + await game.pump(signpost); + }, + verify: (game, _) async { + final signpost = game.descendants().whereType().single; + expect(signpost.children.whereType(), isNotEmpty); + }, + ); }); } diff --git a/packages/pinball_components/test/src/components/skill_shot/cubit/skill_shot_cubit_test.dart b/packages/pinball_components/test/src/components/skill_shot/cubit/skill_shot_cubit_test.dart index b165db99..b1c1a192 100644 --- a/packages/pinball_components/test/src/components/skill_shot/cubit/skill_shot_cubit_test.dart +++ b/packages/pinball_components/test/src/components/skill_shot/cubit/skill_shot_cubit_test.dart @@ -29,7 +29,7 @@ void main() { (state) => state.spriteState, 'spriteState', SkillShotSpriteState.lit, - ) + ), ], ); @@ -46,7 +46,7 @@ void main() { (state) => state.spriteState, 'spriteState', SkillShotSpriteState.dimmed, - ) + ), ], ); diff --git a/packages/pinball_components/test/src/components/skill_shot/skill_shot_test.dart b/packages/pinball_components/test/src/components/skill_shot/skill_shot_test.dart index beb159b8..d218da9c 100644 --- a/packages/pinball_components/test/src/components/skill_shot/skill_shot_test.dart +++ b/packages/pinball_components/test/src/components/skill_shot/skill_shot_test.dart @@ -23,70 +23,113 @@ void main() { final flameTester = FlameTester(() => TestGame(assets)); group('SkillShot', () { - flameTester.test('loads correctly', (game) async { - final skillShot = SkillShot(); - await game.ensureAdd(skillShot); - expect(game.contains(skillShot), isTrue); - }); - - flameTester.test('closes bloc when removed', (game) async { - final bloc = _MockSkillShotCubit(); - whenListen( - bloc, - const Stream.empty(), - initialState: const SkillShotState.initial(), - ); - when(bloc.close).thenAnswer((_) async {}); - final skillShot = SkillShot.test(bloc: bloc); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final skillShot = SkillShot(); + await game.ensureAdd(skillShot); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); + }, + ); - await game.ensureAdd(skillShot); - game.remove(skillShot); - await game.ready(); + flameTester.testGameWidget( + 'closes bloc when removed', + setUp: (game, _) async { + await game.onLoad(); + final bloc = _MockSkillShotCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: const SkillShotState.initial(), + ); + when(bloc.close).thenAnswer((_) async {}); + final skillShot = SkillShot.test(bloc: bloc); - verify(bloc.close).called(1); - }); + await game.ensureAdd(skillShot); + await game.ready(); + }, + verify: (game, _) async { + final skillShot = game.descendants().whereType().single; + game.remove(skillShot); + game.update(0); + verify(skillShot.bloc.close).called(1); + }, + ); group('adds', () { - flameTester.test('new children', (game) async { - final component = Component(); - final skillShot = SkillShot( - children: [component], - ); - await game.ensureAdd(skillShot); - expect(skillShot.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final skillShot = SkillShot( + children: [component], + ); + await game.ensureAdd(skillShot); + await game.ready(); + }, + verify: (game, _) async { + final skillShot = game.descendants().whereType().single; + expect(skillShot.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a SkillShotBallContactBehavior', (game) async { - final skillShot = SkillShot(); - await game.ensureAdd(skillShot); - expect( - skillShot.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a SkillShotBallContactBehavior', + setUp: (game, _) async { + await game.onLoad(); + final skillShot = SkillShot(); + await game.ensureAdd(skillShot); + await game.ready(); + }, + verify: (game, _) async { + final skillShot = game.descendants().whereType().single; + expect( + skillShot.children.whereType().single, + isNotNull, + ); + }, + ); - flameTester.test('a SkillShotBlinkingBehavior', (game) async { - final skillShot = SkillShot(); - await game.ensureAdd(skillShot); - expect( - skillShot.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a SkillShotBlinkingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final skillShot = SkillShot(); + await game.ensureAdd(skillShot); + await game.ready(); + }, + verify: (game, _) async { + final skillShot = game.descendants().whereType().single; + expect( + skillShot.children.whereType().single, + isNotNull, + ); + }, + ); }); - flameTester.test( + flameTester.testGameWidget( 'pin stops animating after animation completes', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final skillShot = SkillShot(); await game.ensureAdd(skillShot); + await game.ready(); + }, + verify: (game, _) async { + final skillShot = game.descendants().whereType().single; final pinSpriteAnimationComponent = skillShot.firstChild()!; pinSpriteAnimationComponent.playing = true; game.update( - pinSpriteAnimationComponent.animation!.totalDuration() + 0.1, + pinSpriteAnimationComponent.animationTicker!.totalDuration() + 0.1, ); expect(pinSpriteAnimationComponent.playing, isFalse); diff --git a/packages/pinball_components/test/src/components/slingshot_test.dart b/packages/pinball_components/test/src/components/slingshot_test.dart index 21885550..7f3688f0 100644 --- a/packages/pinball_components/test/src/components/slingshot_test.dart +++ b/packages/pinball_components/test/src/components/slingshot_test.dart @@ -1,6 +1,6 @@ // ignore_for_file: cascade_invocations -import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame/components.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -16,18 +16,23 @@ void main() { ]; final flameTester = FlameTester(() => TestGame(assets)); - flameTester.test('loads correctly', (game) async { - final component = Slingshots(); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = Slingshots(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); + }, + ); flameTester.testGameWidget( 'renders correctly', setUp: (game, tester) async { await game.images.loadAll(assets); - await game.ensureAdd(Slingshots()); - game.camera.followVector2(Vector2.zero()); + await game.world.ensureAdd(Slingshots()); + game.camera.moveTo(Vector2.zero()); await game.ready(); await tester.pump(); }, @@ -39,12 +44,18 @@ void main() { }, ); - flameTester.test('adds BumpingBehavior', (game) async { - final slingshots = Slingshots(); - await game.ensureAdd(slingshots); - for (final slingshot in slingshots.children) { - expect(slingshot.firstChild(), isNotNull); - } - }); + flameTester.testGameWidget( + 'adds BumpingBehavior', + setUp: (game, _) async { + final slingshots = Slingshots(); + await game.ensureAdd(slingshots); + }, + verify: (game, _) async { + final slingshots = game.descendants().whereType().single; + for (final slingshot in slingshots.children) { + expect(slingshot.firstChild(), isNotNull); + } + }, + ); }); } diff --git a/packages/pinball_components/test/src/components/spaceship_rail_test.dart b/packages/pinball_components/test/src/components/spaceship_rail_test.dart index 78aa4aaa..80ad8bed 100644 --- a/packages/pinball_components/test/src/components/spaceship_rail_test.dart +++ b/packages/pinball_components/test/src/components/spaceship_rail_test.dart @@ -1,6 +1,6 @@ // ignore_for_file: cascade_invocations -import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame/components.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pinball_components/pinball_components.dart'; @@ -16,21 +16,26 @@ void main() { ]; final flameTester = FlameTester(() => TestGame(assets)); - flameTester.test('loads correctly', (game) async { - final component = SpaceshipRail(); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = SpaceshipRail(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); + }, + ); flameTester.testGameWidget( 'renders correctly', setUp: (game, tester) async { await game.images.loadAll(assets); - await game.ensureAdd(SpaceshipRail()); + await game.world.ensureAdd(SpaceshipRail()); await tester.pump(); - game.camera.followVector2(Vector2.zero()); - game.camera.zoom = 8; + game.camera.moveTo(Vector2.zero()); + game.camera.viewfinder.zoom = 8; }, verify: (game, tester) async { await expectLater( diff --git a/packages/pinball_components/test/src/components/spaceship_ramp/behavior/ramp_ball_ascending_contact_behavior_test.dart b/packages/pinball_components/test/src/components/spaceship_ramp/behavior/ramp_ball_ascending_contact_behavior_test.dart index 9051059c..e8b936bb 100644 --- a/packages/pinball_components/test/src/components/spaceship_ramp/behavior/ramp_ball_ascending_contact_behavior_test.dart +++ b/packages/pinball_components/test/src/components/spaceship_ramp/behavior/ramp_ball_ascending_contact_behavior_test.dart @@ -77,9 +77,10 @@ void main() { when(() => ball.body).thenReturn(body); }); - flameTester.test( + flameTester.testGameWidget( "calls 'onAscendingBallEntered' when a ball enters into the ramp", - (game) async { + setUp: (game, _) async { + await game.onLoad(); final behavior = RampBallAscendingContactBehavior(); final bloc = _MockSpaceshipRampCubit(); whenListen( @@ -100,16 +101,28 @@ void main() { bloc: bloc, ); await opening.ensureAdd(behavior); - + await game.ready(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; behavior.beginContact(ball, _MockContact()); - verify(bloc.onAscendingBallEntered).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( "doesn't call 'onAscendingBallEntered' when a ball goes out the ramp", - (game) async { + setUp: (game, _) async { + await game.onLoad(); final behavior = RampBallAscendingContactBehavior(); final bloc = _MockSpaceshipRampCubit(); whenListen( @@ -130,7 +143,19 @@ void main() { bloc: bloc, ); await opening.ensureAdd(behavior); - + await game.ready(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; behavior.beginContact(ball, _MockContact()); verifyNever(bloc.onAscendingBallEntered); diff --git a/packages/pinball_components/test/src/components/spaceship_ramp/spaceship_ramp_test.dart b/packages/pinball_components/test/src/components/spaceship_ramp/spaceship_ramp_test.dart index e1dafc59..1d300ac2 100644 --- a/packages/pinball_components/test/src/components/spaceship_ramp/spaceship_ramp_test.dart +++ b/packages/pinball_components/test/src/components/spaceship_ramp/spaceship_ramp_test.dart @@ -60,9 +60,9 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('SpaceshipRamp', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final bloc = _MockSpaceshipRampCubit(); final streamController = StreamController(); whenListen( @@ -72,29 +72,38 @@ void main() { ); final ramp = SpaceshipRamp.test(); await game.pump(ramp, bloc: bloc); - expect(game.descendants(), contains(ramp)); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); group('adds', () { - flameTester.test('a FlameBlocProvider', (game) async { - final ramp = SpaceshipRamp(); - await game.ensureAdd(ramp); - expect( - ramp.children - .whereType< - FlameBlocProvider>() - .single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a FlameBlocProvider', + setUp: (game, _) async { + final ramp = SpaceshipRamp(); + await game.ensureAdd(ramp); + }, + verify: (game, _) async { + final ramp = game.descendants().whereType().single; + expect( + ramp.children + .whereType< + FlameBlocProvider>() + .single, + isNotNull, + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'a SpaceshipRampBoardOpening', - (game) async { + setUp: (game, _) async { final ramp = SpaceshipRamp(); await game.ensureAdd(ramp); - + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -102,12 +111,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'a SpaceshipRampArrowSpriteComponent', - (game) async { + setUp: (game, _) async { final ramp = SpaceshipRamp(); await game.ensureAdd(ramp); - + }, + verify: (game, _) async { expect( game .descendants() @@ -118,13 +128,19 @@ void main() { }, ); - flameTester.test('new children', (game) async { - final component = Component(); - final ramp = SpaceshipRamp(children: [component]); - await game.ensureAdd(ramp); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + final component = Component(); + final ramp = SpaceshipRamp(children: [component]); + await game.ensureAdd(ramp); + }, + verify: (game, _) async { + final ramp = game.descendants().whereType().single; - expect(ramp.descendants(), contains(component)); - }); + expect(ramp.descendants().whereType(), isNotEmpty); + }, + ); }); }); @@ -133,39 +149,57 @@ void main() { expect(SpaceshipRampBase(), isA()); }); - flameTester.test('can be loaded', (game) async { - final component = SpaceshipRampBase(); - await game.ensureAdd(component); - expect(game.children, contains(component)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final component = SpaceshipRampBase(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'postSolves disables contact when ball is not on Layer.board', - (game) async { - final ball = _MockBall(); - final contact = _MockContact(); - when(() => ball.layer).thenReturn(Layer.spaceshipEntranceRamp); + setUp: (game, _) async { + await game.onLoad(); final component = SpaceshipRampBase(); await game.ensureAdd(component); + await game.ready(); + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; + final ball = _MockBall(); + when(() => ball.layer).thenReturn(Layer.spaceshipEntranceRamp); + final contact = _MockContact(); component.preSolve(ball, contact, _MockManifold()); - - verify(() => contact.setEnabled(false)).called(1); + game.update(0); + verify(() => contact.isEnabled = false).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( 'postSolves enables contact when ball is on Layer.board', - (game) async { + setUp: (game, _) async { + final component = SpaceshipRampBase(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; final ball = _MockBall(); final contact = _MockContact(); when(() => ball.layer).thenReturn(Layer.board); - final component = SpaceshipRampBase(); - await game.ensureAdd(component); component.preSolve(ball, contact, _MockManifold()); - verify(() => contact.setEnabled(true)).called(1); + verify(() => contact.isEnabled = true).called(1); }, ); }); @@ -175,33 +209,55 @@ void main() { expect(SpaceshipRampBoardOpening(), isA()); }); - flameTester.test('can be loaded', (game) async { - final component = SpaceshipRampBoardOpening(); - final parent = SpaceshipRamp.test(); - await game.pump(parent, bloc: _MockSpaceshipRampCubit()); - - await parent.ensureAdd(component); - expect(parent.children, contains(component)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final component = SpaceshipRampBoardOpening(); + final parent = SpaceshipRamp.test(); + await game.pump(parent, bloc: _MockSpaceshipRampCubit()); - flameTester.test('adds a RampBallAscendingContactBehavior', (game) async { - final component = SpaceshipRampBoardOpening(); - final parent = SpaceshipRamp.test(); - await game.pump(parent, bloc: _MockSpaceshipRampCubit()); + await parent.ensureAdd(component); + }, + verify: (game, _) async { + final spaceshipRamp = + game.descendants().whereType().single; + expect( + spaceshipRamp.children.whereType().length, + equals(1), + ); + }, + ); - await parent.ensureAdd(component); - expect( - component.children.whereType().length, - equals(1), - ); - }); + flameTester.testGameWidget( + 'adds a RampBallAscendingContactBehavior', + setUp: (game, _) async { + final component = SpaceshipRampBoardOpening(); + final parent = SpaceshipRamp.test(); + await game.pump(parent, bloc: _MockSpaceshipRampCubit()); + await parent.ensureAdd(component); + await game.ready(); + }, + verify: (game, _) async { + final spaceshipRamp = + game.descendants().whereType().single; + expect( + spaceshipRamp + .descendants() + .whereType() + .length, + equals(1), + ); + }, + ); }); group('SpaceshipRampArrowSpriteComponent', () { - flameTester.test( + flameTester.testGameWidget( 'changes current state ' 'when SpaceshipRampState changes lightState', - (game) async { + setUp: (game, _) async { + await game.onLoad(); + await game.ready(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -216,14 +272,17 @@ void main() { ramp, bloc: bloc, ); - expect(arrow.current, ArrowLightState.inactive); streamController .add(state.copyWith(lightState: ArrowLightState.active1)); - - await game.ready(); - + }, + verify: (game, _) async { + final arrow = game + .descendants() + .whereType() + .single; + game.update(0); expect(arrow.current, ArrowLightState.active1); }, ); diff --git a/packages/pinball_components/test/src/components/sparky_animatronic_test.dart b/packages/pinball_components/test/src/components/sparky_animatronic_test.dart index 175c9596..709aeac0 100644 --- a/packages/pinball_components/test/src/components/sparky_animatronic_test.dart +++ b/packages/pinball_components/test/src/components/sparky_animatronic_test.dart @@ -18,14 +18,19 @@ void main() { 'renders correctly', setUp: (game, tester) async { await game.images.load(asset); - await game.ensureAdd(SparkyAnimatronic()..playing = true); + await game.world.ensureAdd(SparkyAnimatronic()..playing = true); await tester.pump(); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); + await game.ready(); }, verify: (game, tester) async { - final animationDuration = - game.firstChild()!.animation!.totalDuration(); + final animationDuration = game + .descendants() + .whereType() + .single + .animationTicker! + .totalDuration(); await expectLater( find.byGame(), @@ -48,23 +53,36 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { + await game.images.load(asset); final sparkyAnimatronic = SparkyAnimatronic(); await game.ensureAdd(sparkyAnimatronic); - + }, + verify: (game, _) async { + final sparkyAnimatronic = + game.descendants().whereType().single; expect(game.contains(sparkyAnimatronic), isTrue); }, ); - flameTester.test('adds new children', (game) async { - final component = Component(); - final sparkyAnimatronic = SparkyAnimatronic( - children: [component], - ); - await game.ensureAdd(sparkyAnimatronic); - expect(sparkyAnimatronic.children, contains(component)); - }); + flameTester.testGameWidget( + 'adds new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final sparkyAnimatronic = SparkyAnimatronic( + children: [component], + ); + await game.ensureAdd(sparkyAnimatronic); + await game.ready(); + }, + verify: (game, _) async { + final sparkyAnimatronic = + game.descendants().whereType().single; + expect(sparkyAnimatronic.children.whereType(), isNotEmpty); + }, + ); }); } diff --git a/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior_test.dart b/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior_test.dart index 1d10d0aa..dedc34b2 100644 --- a/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior_test.dart +++ b/packages/pinball_components/test/src/components/sparky_bumper/behaviors/sparky_bumper_ball_contact_behavior_test.dart @@ -30,9 +30,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'beginContact emits onBallContacted when contacts with a ball', - (game) async { + setUp: (game, _) async { final behavior = SparkyBumperBallContactBehavior(); final bloc = _MockSparkyBumperCubit(); whenListen( @@ -44,7 +44,14 @@ void main() { final sparkyBumper = SparkyBumper.test(bloc: bloc); await sparkyBumper.add(behavior); await game.ensureAdd(sparkyBumper); - + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final sparkyBumper = + game.descendants().whereType().single; behavior.beginContact(_MockBall(), _MockContact()); verify(sparkyBumper.bloc.onBallContacted).called(1); diff --git a/packages/pinball_components/test/src/components/sparky_bumper/sparky_bumper_test.dart b/packages/pinball_components/test/src/components/sparky_bumper/sparky_bumper_test.dart index 45c55790..bbaf2731 100644 --- a/packages/pinball_components/test/src/components/sparky_bumper/sparky_bumper_test.dart +++ b/packages/pinball_components/test/src/components/sparky_bumper/sparky_bumper_test.dart @@ -26,122 +26,223 @@ void main() { final flameTester = FlameTester(() => TestGame(assets)); group('SparkyBumper', () { - flameTester.test('"a" loads correctly', (game) async { - final sparkyBumper = SparkyBumper.a(); - await game.ensureAdd(sparkyBumper); - expect(game.contains(sparkyBumper), isTrue); - }); - - flameTester.test('"b" loads correctly', (game) async { - final sparkyBumper = SparkyBumper.b(); - await game.ensureAdd(sparkyBumper); - expect(game.contains(sparkyBumper), isTrue); - }); - - flameTester.test('"c" loads correctly', (game) async { - final sparkyBumper = SparkyBumper.c(); - await game.ensureAdd(sparkyBumper); - expect(game.contains(sparkyBumper), isTrue); - }); - - flameTester.test('closes bloc when removed', (game) async { - final bloc = _MockSparkyBumperCubit(); - whenListen( - bloc, - const Stream.empty(), - initialState: SparkyBumperState.lit, - ); - when(bloc.close).thenAnswer((_) async {}); - final sparkyBumper = SparkyBumper.test(bloc: bloc); - - await game.ensureAdd(sparkyBumper); - game.remove(sparkyBumper); - await game.ready(); - - verify(bloc.close).called(1); - }); - - group('adds', () { - flameTester.test('a SparkyBumperBallContactBehavior', (game) async { + flameTester.testGameWidget( + '"a" loads correctly', + setUp: (game, _) async { + await game.onLoad(); final sparkyBumper = SparkyBumper.a(); await game.ensureAdd(sparkyBumper); - expect( - sparkyBumper.children - .whereType() - .single, - isNotNull, + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); + }, + ); + + flameTester.testGameWidget( + '"b" loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final sparkyBumper = SparkyBumper.b(); + await game.ensureAdd(sparkyBumper); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); + }, + ); + + flameTester.testGameWidget( + '"c" loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final sparkyBumper = SparkyBumper.c(); + await game.ensureAdd(sparkyBumper); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); + }, + ); + + flameTester.testGameWidget( + 'closes bloc when removed', + setUp: (game, _) async { + await game.onLoad(); + final bloc = _MockSparkyBumperCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: SparkyBumperState.lit, ); - }); + when(bloc.close).thenAnswer((_) async {}); + final sparkyBumper = SparkyBumper.test(bloc: bloc); - flameTester.test('a SparkyBumperBlinkingBehavior', (game) async { - final sparkyBumper = SparkyBumper.a(); await game.ensureAdd(sparkyBumper); - expect( - sparkyBumper.children - .whereType() - .single, - isNotNull, - ); - }); + await game.ready(); + }, + verify: (game, _) async { + final sparkyBumper = + game.descendants().whereType().single; + game.remove(sparkyBumper); + game.update(0); + verify(sparkyBumper.bloc.close).called(1); + }, + ); + + group('adds', () { + flameTester.testGameWidget( + 'a SparkyBumperBallContactBehavior', + setUp: (game, _) async { + await game.onLoad(); + final sparkyBumper = SparkyBumper.a(); + await game.ensureAdd(sparkyBumper); + await game.ready(); + }, + verify: (game, _) async { + final sparkyBumper = + game.descendants().whereType().single; + expect( + sparkyBumper.children + .whereType() + .single, + isNotNull, + ); + }, + ); + + flameTester.testGameWidget( + 'a SparkyBumperBlinkingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final sparkyBumper = SparkyBumper.a(); + await game.ensureAdd(sparkyBumper); + await game.ready(); + }, + verify: (game, _) async { + final sparkyBumper = + game.descendants().whereType().single; + expect( + sparkyBumper.children + .whereType() + .single, + isNotNull, + ); + }, + ); }); group("'a' adds", () { - flameTester.test('new children', (game) async { - final component = Component(); - final sparkyBumper = SparkyBumper.a( - children: [component], - ); - await game.ensureAdd(sparkyBumper); - expect(sparkyBumper.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final sparkyBumper = SparkyBumper.a( + children: [component], + ); + await game.ensureAdd(sparkyBumper); + await game.ready(); + }, + verify: (game, _) async { + final sparkyBumper = + game.descendants().whereType().single; + expect(sparkyBumper.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a BumpingBehavior', (game) async { - final sparkyBumper = SparkyBumper.a(); - await game.ensureAdd(sparkyBumper); - expect( - sparkyBumper.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final sparkyBumper = SparkyBumper.a(); + await game.ensureAdd(sparkyBumper); + await game.ready(); + }, + verify: (game, _) async { + final sparkyBumper = + game.descendants().whereType().single; + expect( + sparkyBumper.children.whereType().single, + isNotNull, + ); + }, + ); }); group("'b' adds", () { - flameTester.test('new children', (game) async { - final component = Component(); - final sparkyBumper = SparkyBumper.b( - children: [component], - ); - await game.ensureAdd(sparkyBumper); - expect(sparkyBumper.children, contains(component)); - }); - - flameTester.test('a BumpingBehavior', (game) async { - final sparkyBumper = SparkyBumper.b(); - await game.ensureAdd(sparkyBumper); - expect( - sparkyBumper.children.whereType().single, - isNotNull, - ); - }); - - group("'c' adds", () { - flameTester.test('new children', (game) async { + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); final component = Component(); - final sparkyBumper = SparkyBumper.c( + final sparkyBumper = SparkyBumper.b( children: [component], ); await game.ensureAdd(sparkyBumper); - expect(sparkyBumper.children, contains(component)); - }); + await game.ready(); + }, + verify: (game, _) async { + final sparkyBumper = + game.descendants().whereType().single; + expect(sparkyBumper.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a BumpingBehavior', (game) async { - final sparkyBumper = SparkyBumper.c(); + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final sparkyBumper = SparkyBumper.b(); await game.ensureAdd(sparkyBumper); + await game.ready(); + }, + verify: (game, _) async { + final sparkyBumper = + game.descendants().whereType().single; expect( sparkyBumper.children.whereType().single, isNotNull, ); - }); + }, + ); + + group("'c' adds", () { + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final sparkyBumper = SparkyBumper.c( + children: [component], + ); + await game.ensureAdd(sparkyBumper); + await game.ready(); + }, + verify: (game, _) async { + final sparkyBumper = + game.descendants().whereType().single; + expect(sparkyBumper.children.whereType(), isNotEmpty); + }, + ); + + flameTester.testGameWidget( + 'a BumpingBehavior', + setUp: (game, _) async { + await game.onLoad(); + final sparkyBumper = SparkyBumper.c(); + await game.ensureAdd(sparkyBumper); + await game.ready(); + }, + verify: (game, _) async { + final sparkyBumper = + game.descendants().whereType().single; + expect( + sparkyBumper.children.whereType().single, + isNotNull, + ); + }, + ); }); }); }); diff --git a/packages/pinball_components/test/src/components/sparky_computer/behaviors/sparky_computer_sensor_ball_contact_behavior_test.dart b/packages/pinball_components/test/src/components/sparky_computer/behaviors/sparky_computer_sensor_ball_contact_behavior_test.dart index d90cc2c9..62b9fdb2 100644 --- a/packages/pinball_components/test/src/components/sparky_computer/behaviors/sparky_computer_sensor_ball_contact_behavior_test.dart +++ b/packages/pinball_components/test/src/components/sparky_computer/behaviors/sparky_computer_sensor_ball_contact_behavior_test.dart @@ -32,9 +32,9 @@ void main() { }); group('beginContact', () { - flameTester.test( + flameTester.testGameWidget( 'stops a ball', - (game) async { + setUp: (game, _) async { final behavior = SparkyComputerSensorBallContactBehavior(); final bloc = _MockSparkyComputerCubit(); whenListen( @@ -48,7 +48,13 @@ void main() { ); await sparkyComputer.add(behavior); await game.ensureAdd(sparkyComputer); - + await game.ready(); + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; final ball = _MockBall(); await behavior.beginContact(ball, _MockContact()); @@ -56,9 +62,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'emits onBallEntered when contacts with a ball', - (game) async { + setUp: (game, _) async { final behavior = SparkyComputerSensorBallContactBehavior(); final bloc = _MockSparkyComputerCubit(); whenListen( @@ -72,16 +78,23 @@ void main() { ); await sparkyComputer.add(behavior); await game.ensureAdd(sparkyComputer); - + }, + verify: (game, _) async { + final behavior = game + .descendants() + .whereType() + .single; + final sparkyComputer = + game.descendants().whereType().single; await behavior.beginContact(_MockBall(), _MockContact()); verify(sparkyComputer.bloc.onBallEntered).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( 'adds TimerComponent when contacts with a ball', - (game) async { + setUp: (game, _) async { final behavior = SparkyComputerSensorBallContactBehavior(); final bloc = _MockSparkyComputerCubit(); whenListen( @@ -98,7 +111,10 @@ void main() { await behavior.beginContact(_MockBall(), _MockContact()); await game.ready(); - + }, + verify: (game, _) async { + final sparkyComputer = + game.descendants().whereType().single; expect( sparkyComputer.firstChild(), isA(), @@ -106,9 +122,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'TimerComponent resumes ball and calls onBallTurboCharged onTick', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final behavior = SparkyComputerSensorBallContactBehavior(); final bloc = _MockSparkyComputerCubit(); whenListen( @@ -122,16 +139,26 @@ void main() { ); await sparkyComputer.add(behavior); await game.ensureAdd(sparkyComputer); - + await game.ready(); + }, + verify: (game, tester) async { final ball = _MockBall(); + final behavior = game + .descendants() + .whereType() + .single; + final sparkyComputer = + game.descendants().whereType().single; await behavior.beginContact(ball, _MockContact()); - await game.ready(); + game.update(0); + game.update( sparkyComputer.firstChild()!.timer.limit, ); - await game.ready(); + game.update(1); verify(ball.resume).called(1); + await tester.pump(); verify(sparkyComputer.bloc.onBallTurboCharged).called(1); }, ); diff --git a/packages/pinball_components/test/src/components/sparky_computer/sparky_computer_test.dart b/packages/pinball_components/test/src/components/sparky_computer/sparky_computer_test.dart index 0c045cb1..6c8607ea 100644 --- a/packages/pinball_components/test/src/components/sparky_computer/sparky_computer_test.dart +++ b/packages/pinball_components/test/src/components/sparky_computer/sparky_computer_test.dart @@ -22,22 +22,29 @@ void main() { ]; final flameTester = FlameTester(() => TestGame(assets)); - flameTester.test('loads correctly', (game) async { - final component = SparkyComputer(); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + await game.onLoad(); + final component = SparkyComputer(); + await game.ensureAdd(component); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, 1); + }, + ); flameTester.testGameWidget( 'renders correctly', setUp: (game, tester) async { await game.images.loadAll(assets); - await game.ensureAdd(SparkyComputer()); + await game.world.ensureAdd(SparkyComputer()); await tester.pump(); game.camera - ..followVector2(Vector2(0, -20)) - ..zoom = 7; + ..moveTo(Vector2(0, -20)) + ..viewfinder.zoom = 7; }, verify: (game, tester) async { await expectLater( @@ -47,44 +54,70 @@ void main() { }, ); - flameTester.test('closes bloc when removed', (game) async { - final bloc = _MockSparkyComputerCubit(); - whenListen( - bloc, - const Stream.empty(), - initialState: SparkyComputerState.withoutBall, - ); - when(bloc.close).thenAnswer((_) async {}); - final sparkyComputer = SparkyComputer.test(bloc: bloc); + flameTester.testGameWidget( + 'closes bloc when removed', + setUp: (game, _) async { + await game.onLoad(); + final bloc = _MockSparkyComputerCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: SparkyComputerState.withoutBall, + ); + when(bloc.close).thenAnswer((_) async {}); + final sparkyComputer = SparkyComputer.test(bloc: bloc); - await game.ensureAdd(sparkyComputer); - game.remove(sparkyComputer); - await game.ready(); + await game.ensureAdd(sparkyComputer); + await game.ready(); + }, + verify: (game, _) async { + final sparkyComputer = + game.descendants().whereType().single; + game.remove(sparkyComputer); + game.update(0); - verify(bloc.close).called(1); - }); + verify(sparkyComputer.bloc.close).called(1); + }, + ); group('adds', () { - flameTester.test('new children', (game) async { - final component = Component(); - final sparkyComputer = SparkyComputer( - children: [component], - ); - await game.ensureAdd(sparkyComputer); - expect(sparkyComputer.children, contains(component)); - }); + flameTester.testGameWidget( + 'new children', + setUp: (game, _) async { + await game.onLoad(); + final component = Component(); + final sparkyComputer = SparkyComputer( + children: [component], + ); + await game.ensureAdd(sparkyComputer); + await game.ready(); + }, + verify: (game, _) async { + final sparkyComputer = + game.descendants().whereType().single; + expect(sparkyComputer.children.whereType(), isNotEmpty); + }, + ); - flameTester.test('a SparkyComputerSensorBallContactBehavior', - (game) async { - final sparkyComputer = SparkyComputer(); - await game.ensureAdd(sparkyComputer); - expect( - sparkyComputer.children - .whereType() - .single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a SparkyComputerSensorBallContactBehavior', + setUp: (game, _) async { + await game.onLoad(); + final sparkyComputer = SparkyComputer(); + await game.ensureAdd(sparkyComputer); + await game.ready(); + }, + verify: (game, _) async { + final sparkyComputer = + game.descendants().whereType().single; + expect( + sparkyComputer.children + .whereType() + .single, + isNotNull, + ); + }, + ); }); }); } diff --git a/packages/pinball_flame/lib/pinball_flame.dart b/packages/pinball_flame/lib/pinball_flame.dart index 410d3151..90ed1f2c 100644 --- a/packages/pinball_flame/lib/pinball_flame.dart +++ b/packages/pinball_flame/lib/pinball_flame.dart @@ -5,7 +5,5 @@ export 'src/canvas/canvas.dart'; export 'src/flame_provider.dart'; export 'src/keyboard_input_controller.dart'; export 'src/layer.dart'; -export 'src/parent_is_a.dart'; -export 'src/pinball_forge2d_game.dart'; export 'src/shapes/shapes.dart'; export 'src/sprite_animation.dart'; diff --git a/packages/pinball_flame/lib/src/behaviors/contact_behavior.dart b/packages/pinball_flame/lib/src/behaviors/contact_behavior.dart index 855bb620..7ab81c07 100644 --- a/packages/pinball_flame/lib/src/behaviors/contact_behavior.dart +++ b/packages/pinball_flame/lib/src/behaviors/contact_behavior.dart @@ -1,6 +1,5 @@ import 'package:flame/components.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; -import 'package:pinball_flame/pinball_flame.dart'; /// Appends a new [ContactCallbacks] to the parent. /// diff --git a/packages/pinball_flame/lib/src/canvas/canvas_wrapper.dart b/packages/pinball_flame/lib/src/canvas/canvas_wrapper.dart index 3abe8c1c..191d9e30 100644 --- a/packages/pinball_flame/lib/src/canvas/canvas_wrapper.dart +++ b/packages/pinball_flame/lib/src/canvas/canvas_wrapper.dart @@ -174,4 +174,24 @@ class CanvasWrapper implements Canvas { @override void translate(double dx, double dy) => canvas.translate(dx, dy); + + @override + Rect getDestinationClipBounds() { + throw UnimplementedError(); + } + + @override + Rect getLocalClipBounds() { + throw UnimplementedError(); + } + + @override + Float64List getTransform() { + throw UnimplementedError(); + } + + @override + void restoreToCount(int count) { + throw UnimplementedError(); + } } diff --git a/packages/pinball_flame/lib/src/flame_provider.dart b/packages/pinball_flame/lib/src/flame_provider.dart index dcc6a5ae..1901f9b7 100644 --- a/packages/pinball_flame/lib/src/flame_provider.dart +++ b/packages/pinball_flame/lib/src/flame_provider.dart @@ -17,7 +17,7 @@ class FlameProvider extends Component { final T provider; } -//// {@template multi_flame_provider} +/// {@template multi_flame_provider} /// MultiProvider-style component, similar to MultiProvider in Flutter, /// but used to retrieve more than one [Component] object previously provided /// {@endtemplate} diff --git a/packages/pinball_flame/lib/src/keyboard_input_controller.dart b/packages/pinball_flame/lib/src/keyboard_input_controller.dart index b0d64ee6..a8a0f794 100644 --- a/packages/pinball_flame/lib/src/keyboard_input_controller.dart +++ b/packages/pinball_flame/lib/src/keyboard_input_controller.dart @@ -31,8 +31,8 @@ class KeyboardInputController extends Component with KeyboardHandler { } @override - bool onKeyEvent(RawKeyEvent event, Set keysPressed) { - final isUp = event is RawKeyUpEvent; + bool onKeyEvent(KeyEvent event, Set keysPressed) { + final isUp = event is KeyUpEvent; final handlers = isUp ? _keyUp : _keyDown; final handler = handlers[event.logicalKey]; diff --git a/packages/pinball_flame/lib/src/parent_is_a.dart b/packages/pinball_flame/lib/src/parent_is_a.dart deleted file mode 100644 index 720a07b6..00000000 --- a/packages/pinball_flame/lib/src/parent_is_a.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flame/components.dart'; - -/// A mixin that ensures a parent is of the given type [T]. -mixin ParentIsA on Component { - @override - T get parent => super.parent! as T; - - @override - Future? addToParent(covariant T parent) { - return super.addToParent(parent); - } -} diff --git a/packages/pinball_flame/lib/src/pinball_forge2d_game.dart b/packages/pinball_flame/lib/src/pinball_forge2d_game.dart deleted file mode 100644 index b98e78ae..00000000 --- a/packages/pinball_flame/lib/src/pinball_forge2d_game.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'dart:math'; - -import 'package:flame/game.dart'; -import 'package:flame_forge2d/flame_forge2d.dart'; -import 'package:flame_forge2d/world_contact_listener.dart'; - -// NOTE: This should be removed when https://github.com/flame-engine/flame/pull/1597 is solved. -/// {@template pinball_forge2d_game} -/// A [Game] that uses the Forge2D physics engine. -/// {@endtemplate} -class PinballForge2DGame extends FlameGame implements Forge2DGame { - /// {@macro pinball_forge2d_game} - PinballForge2DGame({ - required Vector2 gravity, - }) : world = World(gravity), - super(camera: Camera()) { - camera.zoom = Forge2DGame.defaultZoom; - world.setContactListener(WorldContactListener()); - } - - @override - final World world; - - @override - void update(double dt) { - super.update(dt); - world.stepDt(clampDt(dt)); - } - - @override - Vector2 screenToFlameWorld(Vector2 position) { - throw UnimplementedError(); - } - - @override - Vector2 screenToWorld(Vector2 position) { - throw UnimplementedError(); - } - - @override - Vector2 worldToScreen(Vector2 position) { - throw UnimplementedError(); - } - - /// Clamp the [dt] in such a way that it would never exceed the minimal of - /// 1/60th of a second. - /// - /// Note: this is a static method because composing this class as a generic - /// on `BodyComponent` and mixins for that class will crash the Dart analyzer - /// server. - static double clampDt(double dt) { - return min(dt, 1 / 60); - } -} diff --git a/packages/pinball_flame/lib/src/sprite_animation.dart b/packages/pinball_flame/lib/src/sprite_animation.dart index 60fd1c8b..9b386fb1 100644 --- a/packages/pinball_flame/lib/src/sprite_animation.dart +++ b/packages/pinball_flame/lib/src/sprite_animation.dart @@ -2,6 +2,7 @@ import 'dart:math'; import 'package:flame/components.dart'; import 'package:flame/image_composition.dart'; +import 'package:flame/sprite.dart'; import 'package:flutter/material.dart' hide Animation; /// {@template flame.widgets.sprite_animation_widget} @@ -28,7 +29,7 @@ class SpriteAnimationWidget extends StatelessWidget { builder: (_, __) { return CustomPaint( painter: SpritePainter( - controller.animation.getSprite(), + controller.animationTicker.getSprite(), anchor, ), ); @@ -45,13 +46,17 @@ class SpriteAnimationController extends AnimationController { SpriteAnimationController({ required TickerProvider vsync, required this.animation, + required this.animationTicker, }) : super(vsync: vsync) { - duration = Duration(seconds: animation.totalDuration().ceil()); + duration = Duration(seconds: animationTicker.totalDuration().ceil()); } /// [SpriteAnimation] associated to this controller final SpriteAnimation animation; + /// [SpriteAnimationTicker] associated to this controller + final SpriteAnimationTicker animationTicker; + double? _lastUpdated; @override @@ -60,7 +65,7 @@ class SpriteAnimationController extends AnimationController { final now = DateTime.now().millisecond.toDouble(); final dt = max(0, (now - (_lastUpdated ?? 0)) / 1000); - animation.update(dt); + animationTicker.update(dt); _lastUpdated = now; } } diff --git a/packages/pinball_flame/pubspec.yaml b/packages/pinball_flame/pubspec.yaml index 327951a1..4fdc8776 100644 --- a/packages/pinball_flame/pubspec.yaml +++ b/packages/pinball_flame/pubspec.yaml @@ -4,17 +4,13 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dependencies: bloc: ^8.0.0 - flame: ^1.1.1 - flame_bloc: ^1.4.0 - flame_forge2d: - git: - url: https://github.com/flame-engine/flame - path: packages/flame_forge2d/ - ref: a50d4a1e7d9eaf66726ed1bb9894c9d495547d8f + flame: ^1.18.0 + flame_bloc: ^1.12.0 + flame_forge2d: ^0.18.1 flutter: sdk: flutter geometry: @@ -24,5 +20,5 @@ dev_dependencies: flame_test: ^1.3.0 flutter_test: sdk: flutter - mocktail: ^0.3.0 - very_good_analysis: ^2.4.0 + mocktail: ^1.0.4 + very_good_analysis: ^6.0.0 diff --git a/packages/pinball_flame/test/layer_test.dart b/packages/pinball_flame/test/layer_test.dart index 93ab29a6..2e6bda5c 100644 --- a/packages/pinball_flame/test/layer_test.dart +++ b/packages/pinball_flame/test/layer_test.dart @@ -40,10 +40,13 @@ void main() { } } - flameTester.test('TestBodyComponent has fixtures', (game) async { - final component = _TestBodyComponent(); - await game.ensureAdd(component); - }); + flameTester.testGameWidget( + 'TestBodyComponent has fixtures', + setUp: (game, _) async { + final component = _TestBodyComponent(); + await game.ensureAdd(component); + }, + ); test('correctly sets and gets', () { final component = _TestLayeredBodyComponent() @@ -51,24 +54,27 @@ void main() { expect(component.layer, Layer.spaceshipEntranceRamp); }); - flameTester.test( + flameTester.testGameWidget( 'layers correctly before being loaded', - (game) async { - const expectedLayer = Layer.spaceshipEntranceRamp; - final component = _TestLayeredBodyComponent()..layer = expectedLayer; + setUp: (game, _) async { + final component = _TestLayeredBodyComponent() + ..layer = Layer.spaceshipEntranceRamp; await game.ensureAdd(component); - + }, + verify: (game, _) async { + final component = + game.descendants().whereType<_TestLayeredBodyComponent>().single; _expectLayerOnFixtures( fixtures: component.body.fixtures, - layer: expectedLayer, + layer: Layer.spaceshipEntranceRamp, ); }, ); - flameTester.test( + flameTester.testGameWidget( 'layers correctly before being loaded ' 'when multiple different sets', - (game) async { + setUp: (game, _) async { const expectedLayer = Layer.launcher; final component = _TestLayeredBodyComponent() ..layer = Layer.spaceshipEntranceRamp; @@ -77,32 +83,39 @@ void main() { component.layer = expectedLayer; await game.ensureAdd(component); - + }, + verify: (game, _) async { + final component = + game.descendants().whereType<_TestLayeredBodyComponent>().single; _expectLayerOnFixtures( fixtures: component.body.fixtures, - layer: expectedLayer, + layer: Layer.launcher, ); }, ); - flameTester.test( + flameTester.testGameWidget( 'layers correctly after being loaded', - (game) async { + setUp: (game, _) async { const expectedLayer = Layer.spaceshipEntranceRamp; final component = _TestLayeredBodyComponent(); await game.ensureAdd(component); component.layer = expectedLayer; + }, + verify: (game, _) async { + final component = + game.descendants().whereType<_TestLayeredBodyComponent>().single; _expectLayerOnFixtures( fixtures: component.body.fixtures, - layer: expectedLayer, + layer: Layer.spaceshipEntranceRamp, ); }, ); - flameTester.test( + flameTester.testGameWidget( 'layers correctly after being loaded ' 'when multiple different sets', - (game) async { + setUp: (game, _) async { const expectedLayer = Layer.launcher; final component = _TestLayeredBodyComponent(); await game.ensureAdd(component); @@ -110,27 +123,34 @@ void main() { component.layer = Layer.spaceshipEntranceRamp; expect(component.layer, isNot(equals(expectedLayer))); component.layer = expectedLayer; - + }, + verify: (game, _) async { + final component = + game.descendants().whereType<_TestLayeredBodyComponent>().single; _expectLayerOnFixtures( fixtures: component.body.fixtures, - layer: expectedLayer, + layer: Layer.launcher, ); }, ); - flameTester.test( + flameTester.testGameWidget( 'defaults to Layer.all ' 'when no layer is given', - (game) async { + setUp: (game, _) async { final component = _TestLayeredBodyComponent(); await game.ensureAdd(component); + }, + verify: (game, _) async { + final component = + game.descendants().whereType<_TestLayeredBodyComponent>().single; expect(component.layer, equals(Layer.all)); }, ); - flameTester.test( + flameTester.testGameWidget( 'nested Layered children will keep their layer', - (game) async { + setUp: (game, _) async { const parentLayer = Layer.spaceshipEntranceRamp; const childLayer = Layer.board; @@ -140,19 +160,22 @@ void main() { await game.ensureAdd(component); expect(childLayer, isNot(equals(parentLayer))); - + }, + verify: (game, _) async { + final component = + game.children.whereType<_TestLayeredBodyComponent>().single; for (final child in component.children) { expect( (child as _TestLayeredBodyComponent).layer, - equals(childLayer), + equals(Layer.board), ); } }, ); - flameTester.test( + flameTester.testGameWidget( 'nested children will keep their layer', - (game) async { + setUp: (game, _) async { const parentLayer = Layer.spaceshipEntranceRamp; final component = _TestLayeredBodyComponent()..layer = parentLayer; @@ -160,7 +183,10 @@ void main() { await component.add(childComponent); await game.ensureAdd(component); - + }, + verify: (game, _) async { + final component = + game.descendants().whereType<_TestLayeredBodyComponent>().single; for (final child in component.children) { expect( (child as _TestBodyComponent) diff --git a/packages/pinball_flame/test/src/behaviors/contact_behavior_test.dart b/packages/pinball_flame/test/src/behaviors/contact_behavior_test.dart index cf7fe35a..559541ad 100644 --- a/packages/pinball_flame/test/src/behaviors/contact_behavior_test.dart +++ b/packages/pinball_flame/test/src/behaviors/contact_behavior_test.dart @@ -68,44 +68,50 @@ void main() { fixtureDef = FixtureDef(CircleShape()); }); - flameTester.test( + flameTester.testGameWidget( "should add a new ContactCallbacks to the parent's body userData " 'when not applied to fixtures', - (game) async { + setUp: (game, _) async { final parent = _TestBodyComponent(); final contactBehavior = ContactBehavior(); await parent.add(contactBehavior); await game.ensureAdd(parent); - + }, + verify: (game, _) async { + final parent = + game.descendants().whereType<_TestBodyComponent>().single; expect(parent.body.userData, isA()); }, ); - flameTester.test( + flameTester.testGameWidget( 'should add a new ContactCallbacks to the targeted fixture ', - (game) async { + setUp: (game, _) async { final parent = _TestBodyComponent(); await game.ensureAdd(parent); final fixture1 = parent.body.createFixture(fixtureDef..userData = 'foo'); - final fixture2 = parent.body.createFixture(fixtureDef..userData = null); + parent.body.createFixture(fixtureDef..userData = null); final contactBehavior = ContactBehavior() ..applyTo( [fixture1.userData!], ); await parent.ensureAdd(contactBehavior); - + }, + verify: (game, _) async { + final parent = + game.descendants().whereType<_TestBodyComponent>().single; expect(parent.body.userData, isNull); - expect(fixture1.userData, isA()); - expect(fixture2.userData, isNull); + expect(parent.body.fixtures[0].userData, isA()); + expect(parent.body.fixtures[1].userData, isNull); }, ); - flameTester.test( + flameTester.testGameWidget( 'should add a new ContactCallbacks to the targeted fixtures ', - (game) async { + setUp: (game, _) async { final parent = _TestBodyComponent(); await game.ensureAdd(parent); @@ -120,17 +126,20 @@ void main() { ]); await parent.ensureAdd(contactBehavior); - + }, + verify: (game, _) async { + final parent = + game.descendants().whereType<_TestBodyComponent>().single; expect(parent.body.userData, isNull); - expect(fixture1.userData, isA()); - expect(fixture2.userData, isA()); + expect(parent.body.fixtures[0].userData, isA()); + expect(parent.body.fixtures[1].userData, isA()); }, ); - flameTester.test( + flameTester.testGameWidget( "should respect the previous ContactCallbacks in the parent's userData " 'when not applied to fixtures', - (game) async { + setUp: (game, _) async { final parent = _TestBodyComponent(); await game.ensureAdd(parent); final contactCallbacks1 = _MockContactCallbacks(); @@ -163,9 +172,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'can group multiple ContactBehaviors and keep listening', - (game) async { + setUp: (game, _) async { final parent = _TestBodyComponent(); await game.ensureAdd(parent); @@ -202,10 +211,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'can group multiple ContactBehaviors and keep listening ' 'when applied to a fixture', - (game) async { + setUp: (game, _) async { final parent = _TestBodyComponent(); await game.ensureAdd(parent); diff --git a/packages/pinball_flame/test/src/behaviors/layer_contact_behavior_test.dart b/packages/pinball_flame/test/src/behaviors/layer_contact_behavior_test.dart index d4b7ba18..da1a86b7 100644 --- a/packages/pinball_flame/test/src/behaviors/layer_contact_behavior_test.dart +++ b/packages/pinball_flame/test/src/behaviors/layer_contact_behavior_test.dart @@ -34,45 +34,63 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final behavior = LayerContactBehavior(layer: Layer.all); - final parent = _TestBodyComponent(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); - expect(parent.children, contains(behavior)); - }); - - flameTester.test('beginContact changes layer', (game) async { - const oldLayer = Layer.all; - const newLayer = Layer.board; - final behavior = LayerContactBehavior(layer: newLayer); - final parent = _TestBodyComponent(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); - - final component = _TestLayeredBodyComponent(layer: oldLayer); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final behavior = LayerContactBehavior(layer: Layer.all); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final parent = + game.descendants().whereType<_TestBodyComponent>().single; + expect( + parent.children.whereType().length, + equals(1), + ); + }, + ); - behavior.beginContact(component, _MockContact()); + flameTester.testGameWidget( + 'beginContact changes layer', + setUp: (game, _) async { + final behavior = LayerContactBehavior(layer: Layer.board); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final component = _TestLayeredBodyComponent(layer: Layer.all); + final behavior = + game.descendants().whereType().single; - expect(component.layer, newLayer); - }); + behavior.beginContact(component, _MockContact()); - flameTester.test('endContact changes layer', (game) async { - const oldLayer = Layer.all; - const newLayer = Layer.board; - final behavior = LayerContactBehavior( - layer: newLayer, - onBegin: false, - ); - final parent = _TestBodyComponent(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); + expect(component.layer, Layer.board); + }, + ); - final component = _TestLayeredBodyComponent(layer: oldLayer); + flameTester.testGameWidget( + 'endContact changes layer', + setUp: (game, _) async { + final behavior = LayerContactBehavior( + layer: Layer.board, + onBegin: false, + ); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final component = _TestLayeredBodyComponent(layer: Layer.all); + final behavior = + game.descendants().whereType().single; - behavior.endContact(component, _MockContact()); + behavior.endContact(component, _MockContact()); - expect(component.layer, newLayer); - }); + expect(component.layer, Layer.board); + }, + ); }); } diff --git a/packages/pinball_flame/test/src/behaviors/z_index_contact_behavior_test.dart b/packages/pinball_flame/test/src/behaviors/z_index_contact_behavior_test.dart index 292a51fc..0baa17b3 100644 --- a/packages/pinball_flame/test/src/behaviors/z_index_contact_behavior_test.dart +++ b/packages/pinball_flame/test/src/behaviors/z_index_contact_behavior_test.dart @@ -34,42 +34,60 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final behavior = ZIndexContactBehavior(zIndex: 0); - final parent = _TestBodyComponent(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); - expect(parent.children, contains(behavior)); - }); - - flameTester.test('beginContact changes zIndex', (game) async { - const oldIndex = 0; - const newIndex = 1; - final behavior = ZIndexContactBehavior(zIndex: newIndex); - final parent = _TestBodyComponent(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final behavior = ZIndexContactBehavior(zIndex: 0); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final parent = + game.descendants().whereType<_TestBodyComponent>().single; + expect( + parent.children.whereType().length, + equals(1), + ); + }, + ); - final component = _TestZIndexBodyComponent(zIndex: oldIndex); + flameTester.testGameWidget( + 'beginContact changes zIndex', + setUp: (game, _) async { + final behavior = ZIndexContactBehavior(zIndex: 1); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final behavior = + game.descendants().whereType().single; + final component = _TestZIndexBodyComponent(zIndex: 0); - behavior.beginContact(component, _MockContact()); + behavior.beginContact(component, _MockContact()); - expect(component.zIndex, newIndex); - }); + expect(component.zIndex, 1); + }, + ); - flameTester.test('endContact changes zIndex', (game) async { - const oldIndex = 0; - const newIndex = 1; - final behavior = ZIndexContactBehavior(zIndex: newIndex, onBegin: false); - final parent = _TestBodyComponent(); - await game.ensureAdd(parent); - await parent.ensureAdd(behavior); + flameTester.testGameWidget( + 'endContact changes zIndex', + setUp: (game, _) async { + final behavior = ZIndexContactBehavior(zIndex: 1, onBegin: false); + final parent = _TestBodyComponent(); + await game.ensureAdd(parent); + await parent.ensureAdd(behavior); + }, + verify: (game, _) async { + final behavior = + game.descendants().whereType().single; + final component = _TestZIndexBodyComponent(zIndex: 0); - final component = _TestZIndexBodyComponent(zIndex: oldIndex); + behavior.endContact(component, _MockContact()); - behavior.endContact(component, _MockContact()); - - expect(component.zIndex, newIndex); - }); + expect(component.zIndex, 1); + }, + ); }); } diff --git a/packages/pinball_flame/test/src/canvas/canvas_component_test.dart b/packages/pinball_flame/test/src/canvas/canvas_component_test.dart index 2ad45b6c..63b16049 100644 --- a/packages/pinball_flame/test/src/canvas/canvas_component_test.dart +++ b/packages/pinball_flame/test/src/canvas/canvas_component_test.dart @@ -25,15 +25,20 @@ void main() { ); }); - flameTester.test('loads correctly', (game) async { - final component = CanvasComponent(); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = CanvasComponent(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'adds children', - (game) async { + setUp: (game, _) async { final component = Component(); final canvas = CanvasComponent( onSpritePainted: (paint) => paint.filterQuality = FilterQuality.high, @@ -41,10 +46,12 @@ void main() { ); await game.ensureAdd(canvas); - + }, + verify: (game, _) async { + final canvas = game.descendants().whereType().single; expect( - canvas.children.contains(component), - isTrue, + canvas.children.whereType(), + isNotEmpty, ); }, ); diff --git a/packages/pinball_flame/test/src/canvas/canvas_wrapper_test.dart b/packages/pinball_flame/test/src/canvas/canvas_wrapper_test.dart index 58da1ecd..01e4bfde 100644 --- a/packages/pinball_flame/test/src/canvas/canvas_wrapper_test.dart +++ b/packages/pinball_flame/test/src/canvas/canvas_wrapper_test.dart @@ -14,8 +14,6 @@ class _MockPicture extends Mock implements Picture {} class _MockParagraph extends Mock implements Paragraph {} -class _MockVertices extends Mock implements Vertices {} - void main() { group('CanvasWrapper', () { group('CanvasWrapper', () { @@ -50,7 +48,7 @@ void main() { int32list = Int32List(1); picture = _MockPicture(); paragraph = _MockParagraph(); - vertices = _MockVertices(); + vertices = Vertices(VertexMode.triangles, [Offset.zero]); }); test("clipPath calls Canvas's clipPath", () { @@ -276,15 +274,6 @@ void main() { ).called(1); }); - test("drawVertices calls Canvas's drawVertices", () { - CanvasWrapper() - ..canvas = canvas - ..drawVertices(vertices, blendMode, paint); - verify( - () => canvas.drawVertices(vertices, blendMode, paint), - ).called(1); - }); - test("getSaveCount calls Canvas's getSaveCount", () { final canvasWrapper = CanvasWrapper()..canvas = canvas; when(() => canvas.getSaveCount()).thenReturn(1); @@ -342,12 +331,41 @@ void main() { verify(() => canvas.transform(float64list)).called(1); }); + test("drawVertices calls Canvas's drawVertices", () { + CanvasWrapper() + ..canvas = canvas + ..drawVertices(vertices, blendMode, paint); + verify( + () => canvas.drawVertices(vertices, blendMode, paint), + ).called(1); + }); + test("translate calls Canvas's translate", () { CanvasWrapper() ..canvas = canvas ..translate(0, 0); verify(() => canvas.translate(0, 0)).called(1); }); + + test('throws exception for unimplemented methods', () { + final canvasWrapper = CanvasWrapper()..canvas = canvas; + expect( + canvasWrapper.getDestinationClipBounds, + throwsUnimplementedError, + ); + expect( + canvasWrapper.getLocalClipBounds, + throwsUnimplementedError, + ); + expect( + canvasWrapper.getTransform, + throwsUnimplementedError, + ); + expect( + () => canvasWrapper.restoreToCount(0), + throwsUnimplementedError, + ); + }); }); }); } diff --git a/packages/pinball_flame/test/src/canvas/z_canvas_component_test.dart b/packages/pinball_flame/test/src/canvas/z_canvas_component_test.dart index 67c45ec7..bac00c7b 100644 --- a/packages/pinball_flame/test/src/canvas/z_canvas_component_test.dart +++ b/packages/pinball_flame/test/src/canvas/z_canvas_component_test.dart @@ -29,11 +29,19 @@ void main() { ); }); - flameTester.test('loads correctly', (game) async { - final component = ZCanvasComponent(); - await game.ensureAdd(component); - expect(game.contains(component), isTrue); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = ZCanvasComponent(); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().single, + isNotNull, + ); + }, + ); flameTester.testGameWidget( 'red circle renders behind blue circle', @@ -44,9 +52,9 @@ void main() { _TestCircleComponent(Colors.red)..zIndex = 0, ], ); - await game.ensureAdd(canvas); + await game.world.ensureAdd(canvas); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { await expectLater( @@ -62,12 +70,12 @@ void main() { final canvas = ZCanvasComponent( children: [ _TestCircleComponent(Colors.blue)..zIndex = 0, - _TestCircleComponent(Colors.red)..zIndex = 1 + _TestCircleComponent(Colors.red)..zIndex = 1, ], ); - await game.ensureAdd(canvas); + await game.world.ensureAdd(canvas); - game.camera.followVector2(Vector2.zero()); + game.camera.moveTo(Vector2.zero()); }, verify: (game, tester) async { await expectLater( diff --git a/packages/pinball_flame/test/src/flame_provider_test.dart b/packages/pinball_flame/test/src/flame_provider_test.dart index 71d69e0c..8171a4cd 100644 --- a/packages/pinball_flame/test/src/flame_provider_test.dart +++ b/packages/pinball_flame/test/src/flame_provider_test.dart @@ -24,21 +24,39 @@ void main() { ); }); - flameTester.test('can be loaded', (game) async { - final component = FlameProvider.value(true); - await game.ensureAdd(component); - expect(game.children, contains(component)); - }); + flameTester.testGameWidget( + 'can be loaded', + setUp: (game, _) async { + final component = FlameProvider.value(true); + await game.ensureAdd(component); + }, + verify: (game, _) async { + expect( + game.children.whereType>().length, + equals(1), + ); + }, + ); - flameTester.test('adds children', (game) async { - final component = Component(); - final provider = FlameProvider.value( - true, - children: [component], - ); - await game.ensureAdd(provider); - expect(provider.children, contains(component)); - }); + flameTester.testGameWidget( + 'adds children', + setUp: (game, _) async { + final component = Component(); + final provider = FlameProvider.value( + true, + children: [component], + ); + await game.ensureAdd(provider); + }, + verify: (game, _) async { + final provider = + game.descendants().whereType>().single; + expect( + provider.children.whereType().length, + equals(1), + ); + }, + ); }, ); @@ -54,48 +72,80 @@ void main() { ); }); - flameTester.test('adds multiple providers', (game) async { - final provider1 = FlameProvider.value(true); - final provider2 = FlameProvider.value(true); - final providers = MultiFlameProvider( - providers: [provider1, provider2], - ); - await game.ensureAdd(providers); - expect(providers.children, contains(provider1)); - expect(provider1.children, contains(provider2)); - }); + flameTester.testGameWidget( + 'adds multiple providers', + setUp: (game, _) async { + final provider1 = FlameProvider.value(true); + final provider2 = FlameProvider.value(true); + final providers = MultiFlameProvider( + providers: [provider1, provider2], + ); + await game.ensureAdd(providers); + }, + verify: (game, _) async { + final providers = + game.descendants().whereType().single; + expect( + providers.children.whereType>().length, + equals(1), + ); + final provider1 = + providers.children.whereType>().single; + expect( + provider1.children.whereType>().length, + equals(1), + ); + }, + ); - flameTester.test('adds children under provider', (game) async { - final component = Component(); - final provider = FlameProvider.value(true); - final providers = MultiFlameProvider( - providers: [provider], - children: [component], - ); - await game.ensureAdd(providers); - expect(provider.children, contains(component)); - }); + flameTester.testGameWidget( + 'adds children under provider', + setUp: (game, _) async { + final component = Component(); + final provider = FlameProvider.value(true); + final providers = MultiFlameProvider( + providers: [provider], + children: [component], + ); + await game.ensureAdd(providers); + }, + verify: (game, _) async { + final provider = + game.descendants().whereType>().single; + expect(provider.children.whereType().length, equals(1)); + }, + ); }); group( 'ReadFlameProvider', () { - flameTester.test('loads provider', (game) async { - final component = Component(); - final provider = FlameProvider.value( - true, - children: [component], - ); - await game.ensureAdd(provider); - expect(component.readProvider(), isTrue); - }); + flameTester.testGameWidget( + 'loads provider', + setUp: (game, _) async { + final component = Component(); + final provider = FlameProvider.value( + true, + children: [component], + ); + await game.ensureAdd(provider); + }, + verify: (game, _) async { + final component = game + .descendants() + .whereType>() + .single + .children + .first; + expect(component.readProvider(), isTrue); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'throws assertionError when no provider is found', - (game) async { + setUp: (game, _) async { final component = Component(); await game.ensureAdd(component); - expect( () => component.readProvider(), throwsAssertionError, @@ -108,23 +158,37 @@ void main() { group( 'ReadFlameBlocProvider', () { - flameTester.test('loads provider', (game) async { - final component = Component(); - final bloc = _FakeCubit(); - final provider = FlameBlocProvider<_FakeCubit, Object>.value( - value: bloc, - children: [component], - ); - await game.ensureAdd(provider); - expect(component.readBloc<_FakeCubit, Object>(), equals(bloc)); - }); + flameTester.testGameWidget( + 'loads provider', + setUp: (game, _) async { + final component = Component(); + final bloc = _FakeCubit(); + final provider = FlameBlocProvider<_FakeCubit, Object>.value( + value: bloc, + children: [component], + ); + await game.ensureAdd(provider); + }, + verify: (game, _) async { + final provider = game + .descendants() + .whereType>() + .single; + expect( + provider.children.first.readBloc<_FakeCubit, Object>(), + equals(provider.bloc), + ); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'throws assertionError when no provider is found', - (game) async { + setUp: (game, _) async { final component = Component(); await game.ensureAdd(component); - + }, + verify: (game, _) async { + final component = game.descendants().whereType().first; expect( () => component.readBloc<_FakeCubit, Object>(), throwsAssertionError, diff --git a/packages/pinball_flame/test/src/goldens/rendering/blue_red.png b/packages/pinball_flame/test/src/goldens/rendering/blue_red.png index 4ca86375..0f51311c 100644 Binary files a/packages/pinball_flame/test/src/goldens/rendering/blue_red.png and b/packages/pinball_flame/test/src/goldens/rendering/blue_red.png differ diff --git a/packages/pinball_flame/test/src/goldens/rendering/red_blue.png b/packages/pinball_flame/test/src/goldens/rendering/red_blue.png index a657024f..8ab04816 100644 Binary files a/packages/pinball_flame/test/src/goldens/rendering/red_blue.png and b/packages/pinball_flame/test/src/goldens/rendering/red_blue.png differ diff --git a/packages/pinball_flame/test/src/keyboard_input_controller_test.dart b/packages/pinball_flame/test/src/keyboard_input_controller_test.dart index f3c783ad..656d183b 100644 --- a/packages/pinball_flame/test/src/keyboard_input_controller_test.dart +++ b/packages/pinball_flame/test/src/keyboard_input_controller_test.dart @@ -2,7 +2,6 @@ import 'package:flame/game.dart'; import 'package:flame_test/flame_test.dart'; -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -37,14 +36,14 @@ abstract class _KeyCall { class _MockKeyCall extends Mock implements _KeyCall {} -class _MockRawKeyUpEvent extends Mock implements RawKeyUpEvent { +class _MockRawKeyUpEvent extends Mock implements KeyUpEvent { @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return super.toString(); } } -RawKeyUpEvent _mockKeyUp(LogicalKeyboardKey key) { +KeyUpEvent _mockKeyUp(LogicalKeyboardKey key) { final event = _MockRawKeyUpEvent(); when(() => event.logicalKey).thenReturn(key); return event; @@ -104,11 +103,16 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('onVirtualKeyUp', () { - flameTester.test('triggers the event', (game) async { - await game.ready(); - game.triggerVirtualKeyUp(LogicalKeyboardKey.enter); - expect(game.pressed, isTrue); - }); + flameTester.testGameWidget( + 'triggers the event', + setUp: (game, _) async { + await game.ready(); + game.triggerVirtualKeyUp(LogicalKeyboardKey.enter); + }, + verify: (game, _) async { + expect(game.pressed, isTrue); + }, + ); }); }); } diff --git a/packages/pinball_flame/test/src/pinball_forge2d_game_test.dart b/packages/pinball_flame/test/src/pinball_forge2d_game_test.dart deleted file mode 100644 index 2da32f0e..00000000 --- a/packages/pinball_flame/test/src/pinball_forge2d_game_test.dart +++ /dev/null @@ -1,63 +0,0 @@ -// ignore_for_file: cascade_invocations - -import 'package:flame/extensions.dart'; -import 'package:flame_test/flame_test.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:pinball_flame/pinball_flame.dart'; - -void main() { - final flameTester = FlameTester( - () => PinballForge2DGame(gravity: Vector2.zero()), - ); - - group('PinballForge2DGame', () { - test('can instantiate', () { - expect( - () => PinballForge2DGame(gravity: Vector2.zero()), - returnsNormally, - ); - }); - - flameTester.test( - 'screenToFlameWorld throws UnimplementedError', - (game) async { - expect( - () => game.screenToFlameWorld(Vector2.zero()), - throwsUnimplementedError, - ); - }, - ); - - flameTester.test( - 'screenToWorld throws UnimplementedError', - (game) async { - expect( - () => game.screenToWorld(Vector2.zero()), - throwsUnimplementedError, - ); - }, - ); - - flameTester.test( - 'worldToScreen throws UnimplementedError', - (game) async { - expect( - () => game.worldToScreen(Vector2.zero()), - throwsUnimplementedError, - ); - }, - ); - - group('clampDt', () { - test('returns dt', () { - const dt = 0.0001; - expect(PinballForge2DGame.clampDt(dt), equals(dt)); - }); - - test('returns result of 1/60 as dt is to high', () { - const dt = 1.0; - expect(PinballForge2DGame.clampDt(dt), equals(1 / 60)); - }); - }); - }); -} diff --git a/packages/pinball_flame/test/src/sprite_animation_test.dart b/packages/pinball_flame/test/src/sprite_animation_test.dart index 5483ee6e..b7a80071 100644 --- a/packages/pinball_flame/test/src/sprite_animation_test.dart +++ b/packages/pinball_flame/test/src/sprite_animation_test.dart @@ -1,4 +1,5 @@ import 'package:flame/components.dart'; +import 'package:flame/sprite.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:pinball_flame/pinball_flame.dart'; @@ -8,23 +9,33 @@ class _MockSpriteAnimationController extends Mock class _MockSpriteAnimation extends Mock implements SpriteAnimation {} +class _MockSpriteAnimationTicker extends Mock implements SpriteAnimationTicker { + @override + double totalDuration() { + return 1; + } +} + class _MockSprite extends Mock implements Sprite {} void main() { group('PinballSpriteAnimationWidget', () { late SpriteAnimationController controller; late SpriteAnimation animation; + late SpriteAnimationTicker animationTicker; late Sprite sprite; setUp(() { controller = _MockSpriteAnimationController(); animation = _MockSpriteAnimation(); + animationTicker = _MockSpriteAnimationTicker(); sprite = _MockSprite(); + when(() => animationTicker.getSprite()).thenAnswer((_) => sprite); + when(() => controller.animation).thenAnswer((_) => animation); + when(() => controller.animationTicker).thenAnswer((_) => animationTicker); - when(() => animation.totalDuration()).thenAnswer((_) => 1); - when(() => animation.getSprite()).thenAnswer((_) => sprite); when(() => sprite.srcSize).thenAnswer((_) => Vector2(1, 1)); when(() => sprite.srcSize).thenAnswer((_) => Vector2(1, 1)); }); @@ -46,9 +57,10 @@ void main() { SpriteAnimationController( vsync: const TestVSync(), animation: animation, + animationTicker: animationTicker, ).notifyListeners(); - verify(() => animation.update(any())).called(1); + verify(() => animationTicker.update(any())).called(1); }); testWidgets('SpritePainter shouldRepaint returns true when Sprite changed', diff --git a/packages/pinball_theme/pubspec.yaml b/packages/pinball_theme/pubspec.yaml index 57522939..f2707d37 100644 --- a/packages/pinball_theme/pubspec.yaml +++ b/packages/pinball_theme/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dependencies: equatable: ^2.0.3 @@ -14,7 +14,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - very_good_analysis: ^2.4.0 + very_good_analysis: ^6.0.0 flutter: generate: true diff --git a/packages/pinball_ui/lib/src/dialog/pinball_dialog.dart b/packages/pinball_ui/lib/src/dialog/pinball_dialog.dart index 8ff04754..62f1a07f 100644 --- a/packages/pinball_ui/lib/src/dialog/pinball_dialog.dart +++ b/packages/pinball_ui/lib/src/dialog/pinball_dialog.dart @@ -48,7 +48,7 @@ class _Title extends StatelessWidget { @override Widget build(BuildContext context) => Text( title, - style: Theme.of(context).textTheme.headline3!.copyWith( + style: Theme.of(context).textTheme.displaySmall!.copyWith( fontWeight: FontWeight.bold, color: PinballColors.darkBlue, ), @@ -79,7 +79,8 @@ class _TitleAndSubtitle extends StatelessWidget { subtitle, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, - style: textTheme.headline3!.copyWith(fontWeight: FontWeight.normal), + style: + textTheme.displaySmall!.copyWith(fontWeight: FontWeight.normal), ), ], ); diff --git a/packages/pinball_ui/lib/src/theme/pinball_text_style.dart b/packages/pinball_ui/lib/src/theme/pinball_text_style.dart index 8319fc1c..1d6da913 100644 --- a/packages/pinball_ui/lib/src/theme/pinball_text_style.dart +++ b/packages/pinball_ui/lib/src/theme/pinball_text_style.dart @@ -8,7 +8,7 @@ const _primaryFontFamily = FontFamily.pixeloidSans; /// Different [TextStyle] used in the game abstract class PinballTextStyle { /// Font size: 28 | Color: white - static const headline1 = TextStyle( + static const displayLarge = TextStyle( fontSize: 28, package: _fontPackage, fontFamily: _primaryFontFamily, @@ -16,7 +16,7 @@ abstract class PinballTextStyle { ); /// Font size: 24 | Color: white - static const headline2 = TextStyle( + static const displayMedium = TextStyle( fontSize: 24, package: _fontPackage, fontFamily: _primaryFontFamily, @@ -24,7 +24,7 @@ abstract class PinballTextStyle { ); /// Font size: 20 | Color: darkBlue - static const headline3 = TextStyle( + static const displaySmall = TextStyle( color: PinballColors.darkBlue, fontSize: 20, package: _fontPackage, @@ -33,7 +33,7 @@ abstract class PinballTextStyle { ); /// Font size: 16 | Color: white - static const headline4 = TextStyle( + static const headlineMedium = TextStyle( color: PinballColors.white, fontSize: 16, package: _fontPackage, @@ -41,7 +41,7 @@ abstract class PinballTextStyle { ); /// Font size: 214| Color: white - static const headline5 = TextStyle( + static const headlineSmall = TextStyle( color: PinballColors.white, fontSize: 14, package: _fontPackage, @@ -49,7 +49,7 @@ abstract class PinballTextStyle { ); /// Font size: 12 | Color: white - static const subtitle1 = TextStyle( + static const titleMedium = TextStyle( fontSize: 12, fontFamily: _primaryFontFamily, package: _fontPackage, diff --git a/packages/pinball_ui/lib/src/theme/pinball_theme.dart b/packages/pinball_ui/lib/src/theme/pinball_theme.dart index cc08ec9d..6a6d8fad 100644 --- a/packages/pinball_ui/lib/src/theme/pinball_theme.dart +++ b/packages/pinball_ui/lib/src/theme/pinball_theme.dart @@ -12,12 +12,12 @@ class PinballTheme { static TextTheme get _textTheme { return const TextTheme( - headline1: PinballTextStyle.headline1, - headline2: PinballTextStyle.headline2, - headline3: PinballTextStyle.headline3, - headline4: PinballTextStyle.headline4, - headline5: PinballTextStyle.headline5, - subtitle1: PinballTextStyle.subtitle1, + displayLarge: PinballTextStyle.displayLarge, + displayMedium: PinballTextStyle.displayMedium, + displaySmall: PinballTextStyle.displaySmall, + headlineMedium: PinballTextStyle.headlineMedium, + headlineSmall: PinballTextStyle.headlineSmall, + titleMedium: PinballTextStyle.titleMedium, ); } } diff --git a/packages/pinball_ui/lib/src/widgets/pinball_button.dart b/packages/pinball_ui/lib/src/widgets/pinball_button.dart index febedf4c..928839d4 100644 --- a/packages/pinball_ui/lib/src/widgets/pinball_button.dart +++ b/packages/pinball_ui/lib/src/widgets/pinball_button.dart @@ -43,7 +43,7 @@ class PinballButton extends StatelessWidget { text, style: Theme.of(context) .textTheme - .headline3! + .displaySmall! .copyWith(color: PinballColors.white), ), ), diff --git a/packages/pinball_ui/lib/src/widgets/pinball_loading_indicator.dart b/packages/pinball_ui/lib/src/widgets/pinball_loading_indicator.dart index ac9b4f46..3f960b83 100644 --- a/packages/pinball_ui/lib/src/widgets/pinball_loading_indicator.dart +++ b/packages/pinball_ui/lib/src/widgets/pinball_loading_indicator.dart @@ -27,7 +27,7 @@ class PinballLoadingIndicator extends StatelessWidget { _InnerIndicator(value: value), _InnerIndicator(value: value), _InnerIndicator(value: value, widthFactor: 0.98), - _InnerIndicator(value: value, widthFactor: 0.95) + _InnerIndicator(value: value, widthFactor: 0.95), ], ); } diff --git a/packages/pinball_ui/pubspec.yaml b/packages/pinball_ui/pubspec.yaml index 747b1b8f..b94af576 100644 --- a/packages/pinball_ui/pubspec.yaml +++ b/packages/pinball_ui/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dependencies: flutter: @@ -14,9 +14,9 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - mocktail: ^0.3.0 - test: ^1.19.2 - very_good_analysis: ^2.4.0 + mocktail: ^1.0.4 + test: ^1.25.2 + very_good_analysis: ^6.0.0 flutter: uses-material-design: true diff --git a/packages/pinball_ui/test/src/dialog/pinball_dialog_test.dart b/packages/pinball_ui/test/src/dialog/pinball_dialog_test.dart index 85e2c4da..0c86adb1 100644 --- a/packages/pinball_ui/test/src/dialog/pinball_dialog_test.dart +++ b/packages/pinball_ui/test/src/dialog/pinball_dialog_test.dart @@ -8,8 +8,8 @@ void main() { group('PinballDialog', () { group('with title only', () { testWidgets('renders the title and the body', (tester) async { - tester.binding.window.physicalSizeTestValue = const Size(2000, 4000); - addTearDown(tester.binding.window.clearPhysicalSizeTestValue); + tester.view.physicalSize = const Size(2000, 4000); + addTearDown(tester.view.resetPhysicalSize); await tester.pumpWidget( const MaterialApp( home: PinballDialog(title: 'title', child: Placeholder()), @@ -23,8 +23,8 @@ void main() { group('with title and subtitle', () { testWidgets('renders the title, subtitle and the body', (tester) async { - tester.binding.window.physicalSizeTestValue = const Size(2000, 4000); - addTearDown(tester.binding.window.clearPhysicalSizeTestValue); + tester.view.physicalSize = const Size(2000, 4000); + addTearDown(tester.view.resetPhysicalSize); await tester.pumpWidget( MaterialApp( home: PinballDialog( diff --git a/packages/pinball_ui/test/src/external_links/external_links_test.dart b/packages/pinball_ui/test/src/external_links/external_links_test.dart index a1b11a26..49038236 100644 --- a/packages/pinball_ui/test/src/external_links/external_links_test.dart +++ b/packages/pinball_ui/test/src/external_links/external_links_test.dart @@ -7,6 +7,8 @@ class _MockUrlLauncher extends Mock with MockPlatformInterfaceMixin implements UrlLauncherPlatform {} +class _MockLaunchOptions extends Mock implements LaunchOptions {} + void main() { late UrlLauncherPlatform urlLauncher; @@ -15,6 +17,10 @@ void main() { UrlLauncherPlatform.instance = urlLauncher; }); + setUpAll(() { + registerFallbackValue(_MockLaunchOptions()); + }); + group('openLink', () { test('launches the link', () async { when( @@ -23,28 +29,15 @@ void main() { (_) 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'), - ), + () => urlLauncher.launchUrl(any(), any()), ).thenAnswer( - (_) async => true, + (_) async => Future.value(true), ); await openLink('uri'); verify( - () => urlLauncher.launch( + () => urlLauncher.launchUrl( + any(), 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'), ), ); }); diff --git a/packages/pinball_ui/test/src/theme/pinball_text_style_test.dart b/packages/pinball_ui/test/src/theme/pinball_text_style_test.dart index ed1f1cb6..d84cb10a 100644 --- a/packages/pinball_ui/test/src/theme/pinball_text_style_test.dart +++ b/packages/pinball_ui/test/src/theme/pinball_text_style_test.dart @@ -3,31 +3,37 @@ import 'package:pinball_ui/pinball_ui.dart'; void main() { group('PinballTextStyle', () { - test('headline1 has fontSize 28 and white color', () { - const style = PinballTextStyle.headline1; + test('displayLarge has fontSize 28 and white color', () { + const style = PinballTextStyle.displayLarge; expect(style.fontSize, 28); expect(style.color, PinballColors.white); }); - test('headline2 has fontSize 24', () { - const style = PinballTextStyle.headline2; + test('displayMedium has fontSize 24', () { + const style = PinballTextStyle.displayMedium; expect(style.fontSize, 24); }); - test('headline3 has fontSize 20 and dark blue color', () { - const style = PinballTextStyle.headline3; + test('displaySmall has fontSize 20 and dark blue color', () { + const style = PinballTextStyle.displaySmall; expect(style.fontSize, 20); expect(style.color, PinballColors.darkBlue); }); - test('headline4 has fontSize 16 and white color', () { - const style = PinballTextStyle.headline4; + test('headlineMedium has fontSize 16 and white color', () { + const style = PinballTextStyle.headlineMedium; expect(style.fontSize, 16); expect(style.color, PinballColors.white); }); - test('subtitle1 has fontSize 12 and yellow color', () { - const style = PinballTextStyle.subtitle1; + test('headlineSmall has fontSize 14 and white color', () { + const style = PinballTextStyle.headlineSmall; + expect(style.fontSize, 14); + expect(style.color, PinballColors.white); + }); + + test('titleMedium has fontSize 12 and yellow color', () { + const style = PinballTextStyle.titleMedium; expect(style.fontSize, 12); expect(style.color, PinballColors.yellow); }); diff --git a/packages/pinball_ui/test/src/theme/pinball_theme_test.dart b/packages/pinball_ui/test/src/theme/pinball_theme_test.dart index 7eda2c1d..e98f64e4 100644 --- a/packages/pinball_ui/test/src/theme/pinball_theme_test.dart +++ b/packages/pinball_ui/test/src/theme/pinball_theme_test.dart @@ -4,78 +4,78 @@ import 'package:pinball_ui/pinball_ui.dart'; void main() { group('PinballTheme', () { group('standard', () { - test('headline1 matches PinballTextStyle#headline1', () { + test('displayLarge matches PinballTextStyle#displayLarge', () { expect( - PinballTheme.standard.textTheme.headline1!.fontSize, - PinballTextStyle.headline1.fontSize, + PinballTheme.standard.textTheme.displayLarge!.fontSize, + PinballTextStyle.displayLarge.fontSize, ); expect( - PinballTheme.standard.textTheme.headline1!.color, - PinballTextStyle.headline1.color, + PinballTheme.standard.textTheme.displayLarge!.color, + PinballTextStyle.displayLarge.color, ); expect( - PinballTheme.standard.textTheme.headline1!.fontFamily, - PinballTextStyle.headline1.fontFamily, + PinballTheme.standard.textTheme.displayLarge!.fontFamily, + PinballTextStyle.displayLarge.fontFamily, ); }); - test('headline2 matches PinballTextStyle#headline2', () { + test('displayMedium matches PinballTextStyle#displayMedium', () { expect( - PinballTheme.standard.textTheme.headline2!.fontSize, - PinballTextStyle.headline2.fontSize, + PinballTheme.standard.textTheme.displayMedium!.fontSize, + PinballTextStyle.displayMedium.fontSize, ); expect( - PinballTheme.standard.textTheme.headline2!.fontFamily, - PinballTextStyle.headline2.fontFamily, + PinballTheme.standard.textTheme.displayMedium!.fontFamily, + PinballTextStyle.displayMedium.fontFamily, ); expect( - PinballTheme.standard.textTheme.headline2!.fontWeight, - PinballTextStyle.headline2.fontWeight, + PinballTheme.standard.textTheme.displayMedium!.fontWeight, + PinballTextStyle.displayMedium.fontWeight, ); }); - test('headline3 matches PinballTextStyle#headline3', () { + test('displaySmall matches PinballTextStyle#displaySmall', () { expect( - PinballTheme.standard.textTheme.headline3!.fontSize, - PinballTextStyle.headline3.fontSize, + PinballTheme.standard.textTheme.displaySmall!.fontSize, + PinballTextStyle.displaySmall.fontSize, ); expect( - PinballTheme.standard.textTheme.headline3!.color, - PinballTextStyle.headline3.color, + PinballTheme.standard.textTheme.displaySmall!.color, + PinballTextStyle.displaySmall.color, ); expect( - PinballTheme.standard.textTheme.headline3!.fontFamily, - PinballTextStyle.headline3.fontFamily, + PinballTheme.standard.textTheme.displaySmall!.fontFamily, + PinballTextStyle.displaySmall.fontFamily, ); }); - test('headline4 matches PinballTextStyle#headline4', () { + test('headlineMedium matches PinballTextStyle#headlineMedium', () { expect( - PinballTheme.standard.textTheme.headline4!.fontSize, - PinballTextStyle.headline4.fontSize, + PinballTheme.standard.textTheme.headlineMedium!.fontSize, + PinballTextStyle.headlineMedium.fontSize, ); expect( - PinballTheme.standard.textTheme.headline4!.color, - PinballTextStyle.headline4.color, + PinballTheme.standard.textTheme.headlineMedium!.color, + PinballTextStyle.headlineMedium.color, ); expect( - PinballTheme.standard.textTheme.headline4!.fontFamily, - PinballTextStyle.headline4.fontFamily, + PinballTheme.standard.textTheme.headlineMedium!.fontFamily, + PinballTextStyle.headlineMedium.fontFamily, ); }); - test('subtitle1 matches PinballTextStyle#subtitle1', () { + test('titleMedium matches PinballTextStyle#titleMedium', () { expect( - PinballTheme.standard.textTheme.subtitle1!.fontSize, - PinballTextStyle.subtitle1.fontSize, + PinballTheme.standard.textTheme.titleMedium!.fontSize, + PinballTextStyle.titleMedium.fontSize, ); expect( - PinballTheme.standard.textTheme.subtitle1!.color, - PinballTextStyle.subtitle1.color, + PinballTheme.standard.textTheme.titleMedium!.color, + PinballTextStyle.titleMedium.color, ); expect( - PinballTheme.standard.textTheme.subtitle1!.fontFamily, - PinballTextStyle.subtitle1.fontFamily, + PinballTheme.standard.textTheme.titleMedium!.fontFamily, + PinballTextStyle.titleMedium.fontFamily, ); }); }); diff --git a/packages/platform_helper/pubspec.yaml b/packages/platform_helper/pubspec.yaml index edff346a..21552059 100644 --- a/packages/platform_helper/pubspec.yaml +++ b/packages/platform_helper/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dependencies: flutter: @@ -13,4 +13,4 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - very_good_analysis: ^2.4.0 \ No newline at end of file + very_good_analysis: ^6.0.0 \ No newline at end of file diff --git a/packages/share_repository/pubspec.yaml b/packages/share_repository/pubspec.yaml index dc3d4e86..467ea6e9 100644 --- a/packages/share_repository/pubspec.yaml +++ b/packages/share_repository/pubspec.yaml @@ -4,10 +4,10 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" + sdk: "^3.4.3" dev_dependencies: coverage: ^1.1.0 - mocktail: ^0.2.0 - test: ^1.19.2 - very_good_analysis: ^2.4.0 + mocktail: ^1.0.4 + test: ^1.25.2 + very_good_analysis: ^6.0.0 diff --git a/pubspec.lock b/pubspec.lock index 7199435a..b39dc758 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,37 +5,98 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" + url: "https://pub.dev" source: hosted - version: "31.0.0" + version: "67.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: a315d1c444402c3fa468de626d33a1c666041c87e9e195e8fb355b7084aefcc1 + url: "https://pub.dev" + source: hosted + version: "1.3.38" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" + url: "https://pub.dev" source: hosted - version: "2.8.0" + version: "6.4.1" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.5.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.11.0" audioplayers: dependency: transitive description: name: audioplayers - url: "https://pub.dartlang.org" + sha256: "752039d6aa752597c98ec212e9759519061759e402e7da59a511f39d43aa07d2" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + audioplayers_android: + dependency: transitive + description: + name: audioplayers_android + sha256: de576b890befe27175c2f511ba8b742bec83765fa97c3ce4282bba46212f58e4 + url: "https://pub.dev" + source: hosted + version: "5.0.0" + audioplayers_darwin: + dependency: transitive + description: + name: audioplayers_darwin + sha256: e507887f3ff18d8e5a10a668d7bedc28206b12e10b98347797257c6ae1019c3b + url: "https://pub.dev" + source: hosted + version: "6.0.0" + audioplayers_linux: + dependency: transitive + description: + name: audioplayers_linux + sha256: "3d3d244c90436115417f170426ce768856d8fe4dfc5ed66a049d2890acfa82f9" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + audioplayers_platform_interface: + dependency: transitive + description: + name: audioplayers_platform_interface + sha256: "6834dd48dfb7bc6c2404998ebdd161f79cd3774a7e6779e1348d54a3bfdcfaa5" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + audioplayers_web: + dependency: transitive + description: + name: audioplayers_web + sha256: db8fc420dadf80da18e2286c18e746fb4c3b2c5adbf0c963299dde046828886d + url: "https://pub.dev" source: hosted - version: "0.20.1" + version: "5.0.0" + audioplayers_windows: + dependency: transitive + description: + name: audioplayers_windows + sha256: "8605762dddba992138d476f6a0c3afd9df30ac5b96039929063eceed416795c2" + url: "https://pub.dev" + source: hosted + version: "4.0.0" authentication_repository: dependency: "direct main" description: @@ -47,214 +108,234 @@ packages: dependency: "direct main" description: name: bloc - url: "https://pub.dartlang.org" + sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e" + url: "https://pub.dev" source: hosted - version: "8.0.3" + version: "8.1.4" bloc_test: dependency: "direct dev" description: name: bloc_test - url: "https://pub.dartlang.org" + sha256: "165a6ec950d9252ebe36dc5335f2e6eb13055f33d56db0eeb7642768849b43d2" + url: "https://pub.dev" source: hosted - version: "9.0.3" + version: "9.1.7" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - cli_util: - dependency: transitive - description: - name: cli_util - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "0.3.5" + version: "1.3.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" cloud_firestore: dependency: "direct main" description: name: cloud_firestore - url: "https://pub.dartlang.org" + sha256: "1232370ad04c21c699d0e73b2dc2e1c3b49258f89a16f0119036fd3c6e8aa2f5" + url: "https://pub.dev" source: hosted - version: "3.1.10" + version: "5.0.2" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface - url: "https://pub.dartlang.org" + sha256: cfc64ae4a48bbb0ff6730b04f2d4653043c7a9b9008a991b1f2012a534b79e26 + url: "https://pub.dev" source: hosted - version: "5.5.1" + version: "6.2.8" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web - url: "https://pub.dartlang.org" + sha256: "3db4e4c10feae18d80da86982781578c8e76cb6a43cf83110d8d6a62af9a952a" + url: "https://pub.dev" source: hosted - version: "2.6.10" + version: "4.0.2" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.18.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.1" coverage: dependency: transitive description: name: coverage - url: "https://pub.dartlang.org" + sha256: "3945034e86ea203af7a056d98e98e42a5518fff200d6e8e6647e1886b07e936e" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.8.0" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.3" diff_match_patch: dependency: transitive description: name: diff_match_patch - url: "https://pub.dartlang.org" + sha256: "2efc9e6e8f449d0abe15be240e2c2a3bcd977c8d126cfd70598aee60af35c0a4" + url: "https://pub.dev" source: hosted version: "0.4.1" equatable: dependency: "direct main" description: name: equatable - url: "https://pub.dartlang.org" + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "2.0.5" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "2.1.2" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "7.0.0" firebase_auth: dependency: "direct main" description: name: firebase_auth - url: "https://pub.dartlang.org" + sha256: "087fdcb54b0af6f4c5c756e1db4f90e9b65871b9b3a75fabaa0e0ee578301669" + url: "https://pub.dev" source: hosted - version: "3.3.16" + version: "5.1.1" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface - url: "https://pub.dartlang.org" + sha256: "8fac689f71ac3489a785579e99a4bad24a93ad3d78c313fb786ee517012d25f1" + url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "7.4.1" firebase_auth_web: dependency: transitive description: name: firebase_auth_web - url: "https://pub.dartlang.org" + sha256: "486b2527fcfcab01278378d8d4791f4f7bee8a9f15bf35e801ba08fbdd84c234" + url: "https://pub.dev" source: hosted - version: "3.3.13" + version: "5.12.3" firebase_core: dependency: "direct main" description: name: firebase_core - url: "https://pub.dartlang.org" + sha256: "1e06b0538ab3108a61d895ee16951670b491c4a94fce8f2d30e5de7a5eca4b28" + url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "3.1.1" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - url: "https://pub.dartlang.org" + sha256: "1003a5a03a61fc9a22ef49f37cbcb9e46c86313a7b2e7029b9390cf8c6fc32cb" + url: "https://pub.dev" source: hosted - version: "4.2.5" + version: "5.1.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - url: "https://pub.dartlang.org" + sha256: "6643fe3dbd021e6ccfb751f7882b39df355708afbdeb4130fc50f9305a9d1a3d" + url: "https://pub.dev" + source: hosted + version: "2.17.2" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" source: hosted - version: "1.6.2" + version: "1.1.0" flame: dependency: "direct main" description: name: flame - url: "https://pub.dartlang.org" + sha256: "79133dc46a3ff870950f41d0dc1598414e7bd7ae2c29bd9f0a9de208d9a70cb7" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.18.0" flame_audio: dependency: transitive description: name: flame_audio - url: "https://pub.dartlang.org" + sha256: "32e5788945469cebb807e741027e645a737e2618afc9b682e7f48607e0637f48" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "2.10.2" flame_bloc: dependency: "direct main" description: name: flame_bloc - url: "https://pub.dartlang.org" + sha256: "19d907204b65f81b08adf71da02e632e68757b1a6738378d8dd4bc024c1660b8" + url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.12.0" flame_forge2d: dependency: "direct main" description: - path: "packages/flame_forge2d" - ref: a50d4a1e7d9eaf66726ed1bb9894c9d495547d8f - resolved-ref: a50d4a1e7d9eaf66726ed1bb9894c9d495547d8f - url: "https://github.com/flame-engine/flame" - source: git - version: "0.11.0" + name: flame_forge2d + sha256: "1ec1c5b4978b64d2d16ca90f86de469959991ef996970866c3f9de580b3dbe40" + url: "https://pub.dev" + source: hosted + version: "0.18.1" flame_test: dependency: "direct dev" description: name: flame_test - url: "https://pub.dartlang.org" + sha256: dbcd03cec4af6d52b26c36ea376c66302ca922e84f91580bd07ed28df2261dd7 + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.16.2" flutter: dependency: "direct main" description: flutter @@ -264,9 +345,10 @@ packages: dependency: "direct main" description: name: flutter_bloc - url: "https://pub.dartlang.org" + sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a + url: "https://pub.dev" source: hosted - version: "8.0.1" + version: "8.1.6" flutter_localizations: dependency: "direct main" description: flutter @@ -286,16 +368,18 @@ packages: dependency: transitive description: name: forge2d - url: "https://pub.dartlang.org" + sha256: "40915333b688ddaaa616d9c8ab9ff205faea0adf83dddc1a6e617694ffa9e16e" + url: "https://pub.dev" source: hosted - version: "0.11.0" + version: "0.13.0" frontend_server_client: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "4.0.0" geometry: dependency: "direct main" description: @@ -307,58 +391,66 @@ packages: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.2" http: dependency: transitive description: name: http - url: "https://pub.dartlang.org" + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + url: "https://pub.dev" source: hosted - version: "0.13.4" + version: "1.2.1" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.2" intl: dependency: "direct main" description: name: intl - url: "https://pub.dartlang.org" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.19.0" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" source: hosted - version: "0.6.3" + version: "0.7.1" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.9.0" leaderboard_repository: dependency: "direct main" description: @@ -366,132 +458,166 @@ packages: relative: true source: path version: "1.0.0+1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.2.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" source: hosted - version: "0.1.3" + version: "0.8.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.12.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.5" mocktail: dependency: "direct dev" description: name: mocktail - url: "https://pub.dartlang.org" + sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8" + url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "1.0.4" nested: dependency: transitive description: name: nested - url: "https://pub.dartlang.org" + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" source: hosted version: "1.0.0" node_preamble: dependency: transitive description: name: node_preamble - url: "https://pub.dartlang.org" + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" ordered_set: dependency: transitive description: name: ordered_set - url: "https://pub.dartlang.org" + sha256: "1bfaaaee0419e43ecc9eaebd410eb4bd5039657b72011de75ff3e2915c9aac60" + url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.0.3" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.0" path_provider: dependency: transitive description: name: path_provider - url: "https://pub.dartlang.org" + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + url: "https://pub.dev" source: hosted - version: "2.0.9" + version: "2.1.3" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: "9c96da072b421e98183f9ea7464898428e764bc0ce5567f27ec8693442e72514" + url: "https://pub.dev" source: hosted - version: "2.0.12" - path_provider_ios: + version: "2.2.5" + path_provider_foundation: dependency: transitive description: - name: path_provider_ios - url: "https://pub.dartlang.org" + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "2.4.0" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" source: hosted - version: "2.1.5" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.5" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "2.1.2" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.2.1" pinball_audio: dependency: "direct main" description: @@ -531,9 +657,10 @@ packages: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.5" platform_helper: dependency: "direct main" description: @@ -545,37 +672,34 @@ packages: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.8" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted - version: "1.5.0" - process: - dependency: transitive - description: - name: process - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.4" + version: "1.5.1" provider: dependency: transitive description: name: provider - url: "https://pub.dartlang.org" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c + url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "6.1.2" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.4" share_repository: dependency: "direct main" description: @@ -587,30 +711,34 @@ packages: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.4.1" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler - url: "https://pub.dartlang.org" + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.2" shelf_static: dependency: transitive description: name: shelf_static - url: "https://pub.dartlang.org" + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -620,212 +748,258 @@ packages: dependency: transitive description: name: source_map_stack_trace - url: "https://pub.dartlang.org" + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" source_maps: dependency: transitive description: name: source_maps - url: "https://pub.dartlang.org" + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" source: hosted - version: "0.10.10" + version: "0.10.12" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + url: "https://pub.dev" source: hosted - version: "3.0.0+2" + version: "3.1.0+1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" test: dependency: transitive description: name: test - url: "https://pub.dartlang.org" + sha256: "7ee446762c2c50b3bd4ea96fe13ffac69919352bd3b4b17bac3f3465edc58073" + url: "https://pub.dev" source: hosted - version: "1.19.5" + version: "1.25.2" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + url: "https://pub.dev" source: hosted - version: "0.4.8" + version: "0.7.0" test_core: dependency: transitive description: name: test_core - url: "https://pub.dartlang.org" + sha256: "2bc4b4ecddd75309300d8096f781c0e3280ca1ef85beda558d33fcbedc2eead4" + url: "https://pub.dev" source: hosted - version: "0.4.9" + version: "0.6.0" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.2" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.3.0" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + sha256: ceb2625f0c24ade6ef6778d1de0b2e44f2db71fded235eb52295247feba8c5cf + url: "https://pub.dev" source: hosted - version: "6.0.16" + version: "6.3.3" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89" + url: "https://pub.dev" source: hosted - version: "6.0.15" + version: "6.3.0" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.1.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.2.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.3.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" + url: "https://pub.dev" source: hosted - version: "2.0.9" + version: "2.3.1" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.1.1" uuid: dependency: transitive description: name: uuid - url: "https://pub.dartlang.org" + sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" + url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "4.4.0" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.4" very_good_analysis: dependency: "direct dev" description: name: very_good_analysis - url: "https://pub.dartlang.org" + sha256: "1fb637c0022034b1f19ea2acb42a3603cbd8314a470646a59a2fb01f5f3a8629" + url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "6.0.0" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + url: "https://pub.dev" source: hosted - version: "7.5.0" + version: "14.2.1" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.4.5" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol - url: "https://pub.dartlang.org" + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.2.1" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 + url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "5.5.1" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" source: hosted - version: "0.2.0+1" + version: "1.0.4" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.2" sdks: - dart: ">=2.16.0 <3.0.0" - flutter: ">=2.10.5" + dart: ">=3.4.3 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index 7f925688..a7b28284 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,24 +4,19 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.16.0 <3.0.0" - flutter: 2.10.5 + sdk: "^3.4.3" dependencies: authentication_repository: path: packages/authentication_repository - bloc: ^8.0.2 - cloud_firestore: ^3.1.10 + bloc: ^8.1.4 + cloud_firestore: ^5.0.2 equatable: ^2.0.3 - firebase_auth: ^3.3.16 - firebase_core: ^1.15.0 - flame: ^1.1.1 - flame_bloc: ^1.4.0 - flame_forge2d: - git: - url: https://github.com/flame-engine/flame - path: packages/flame_forge2d/ - ref: a50d4a1e7d9eaf66726ed1bb9894c9d495547d8f + firebase_auth: ^5.1.1 + firebase_core: ^3.1.1 + flame: ^1.18.0 + flame_bloc: ^1.12.0 + flame_forge2d: ^0.18.1 flutter: sdk: flutter flutter_bloc: ^8.0.1 @@ -29,7 +24,7 @@ dependencies: sdk: flutter geometry: path: packages/geometry - intl: ^0.17.0 + intl: ^0.19.0 leaderboard_repository: path: packages/leaderboard_repository pinball_audio: @@ -53,8 +48,8 @@ dev_dependencies: flame_test: ^1.3.0 flutter_test: sdk: flutter - mocktail: ^0.3.0 - very_good_analysis: ^2.4.0 + mocktail: ^1.0.4 + very_good_analysis: ^6.0.0 flutter: uses-material-design: true diff --git a/test/app/view/app_test.dart b/test/app/view/app_test.dart index d719767e..2440fdf5 100644 --- a/test/app/view/app_test.dart +++ b/test/app/view/app_test.dart @@ -13,8 +13,8 @@ class _MockAuthenticationRepository extends Mock class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} -class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { -} +class _MockLeaderboardRepository extends Mock + implements LeaderboardRepository {} class _MockShareRepository extends Mock implements ShareRepository {} diff --git a/test/game/behaviors/animatronic_looping_behavior_test.dart b/test/game/behaviors/animatronic_looping_behavior_test.dart index 0aacd508..0903cc25 100644 --- a/test/game/behaviors/animatronic_looping_behavior_test.dart +++ b/test/game/behaviors/animatronic_looping_behavior_test.dart @@ -1,6 +1,7 @@ // ignore_for_file: cascade_invocations import 'package:flame/components.dart'; +import 'package:flame/sprite.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -18,7 +19,24 @@ class _TestGame extends Forge2DGame { class _TestSpriteAnimationComponent extends SpriteAnimationComponent {} -class _MockSpriteAnimation extends Mock implements SpriteAnimation {} +class _MockSpriteAnimation extends Mock implements SpriteAnimation { + @override + SpriteAnimationTicker createTicker() { + return _MockSpriteAnimationTicker(); + } +} + +class _MockSpriteAnimationTicker extends Mock implements SpriteAnimationTicker { + @override + Sprite getSprite() { + return _MockSprite(); + } +} + +class _MockSprite extends Mock implements Sprite { + @override + Vector2 get srcSize => Vector2.zero(); +} void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -33,69 +51,98 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'can be added', - (game) async { + setUp: (game, tester) async { final behavior = AnimatronicLoopingBehavior(animationCoolDown: 1); final animation = _MockSpriteAnimation(); final spriteAnimationComponent = _TestSpriteAnimationComponent() ..animation = animation; await game.ensureAdd(spriteAnimationComponent); await spriteAnimationComponent.add(behavior); - await game.ready(); - - expect(game.contains(spriteAnimationComponent), isTrue); - expect(spriteAnimationComponent.contains(behavior), isTrue); + }, + verify: (game, _) async { + final spriteAnimationComponent = + game.children.whereType<_TestSpriteAnimationComponent>().single; + expect(spriteAnimationComponent, isNotNull); + expect( + spriteAnimationComponent + .descendants() + .whereType() + .length, + 1, + ); }, ); - flameTester.test( + flameTester.testGameWidget( 'onTick starts playing the animation', - (game) async { + setUp: (game, _) async { final behavior = AnimatronicLoopingBehavior(animationCoolDown: 1); final spriteAnimationComponent = _TestSpriteAnimationComponent(); await game.ensureAdd(spriteAnimationComponent); await spriteAnimationComponent.add(behavior); - spriteAnimationComponent.playing = false; + }, + verify: (game, tester) async { + final spriteAnimationComponent = + game.children.whereType<_TestSpriteAnimationComponent>().single; + final behavior = spriteAnimationComponent + .descendants() + .whereType() + .single; game.update(behavior.timer.limit); - expect(spriteAnimationComponent.playing, isTrue); }, ); - flameTester.test( + flameTester.testGameWidget( 'animation onComplete resets and stops playing the animation', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final behavior = AnimatronicLoopingBehavior(animationCoolDown: 1); final spriteAnimationComponent = DashAnimatronic(); await game.ensureAdd(spriteAnimationComponent); await spriteAnimationComponent.add(behavior); - + }, + verify: (game, _) async { + final spriteAnimationComponent = + game.children.whereType().single; game.update(1); expect(spriteAnimationComponent.playing, isTrue); - spriteAnimationComponent.animation!.onComplete!.call(); + spriteAnimationComponent.animationTicker!.onComplete!.call(); expect(spriteAnimationComponent.playing, isFalse); - expect(spriteAnimationComponent.animation!.currentIndex, equals(0)); + expect( + spriteAnimationComponent.animationTicker!.currentIndex, + equals(0), + ); }, ); - flameTester.test( + flameTester.testGameWidget( 'animation onComplete resets and starts the timer', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final behavior = AnimatronicLoopingBehavior(animationCoolDown: 1); final spriteAnimationComponent = DashAnimatronic(); - await game.ensureAdd(spriteAnimationComponent); await spriteAnimationComponent.add(behavior); - + await game.ensureAdd(spriteAnimationComponent); + }, + verify: (game, _) async { + final spriteAnimationComponent = + game.children.whereType().single; + final behavior = spriteAnimationComponent + .descendants() + .whereType() + .single; game.update(0.5); expect(behavior.timer.current, equals(0.5)); - spriteAnimationComponent.animation!.onComplete!.call(); + spriteAnimationComponent.animationTicker!.onComplete!.call(); expect(behavior.timer.current, equals(0)); expect(behavior.timer.isRunning(), isTrue); diff --git a/test/game/behaviors/ball_spawning_behavior_test.dart b/test/game/behaviors/ball_spawning_behavior_test.dart index dc272571..6c875b2d 100644 --- a/test/game/behaviors/ball_spawning_behavior_test.dart +++ b/test/game/behaviors/ball_spawning_behavior_test.dart @@ -55,12 +55,17 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'loads', - (game) async { + setUp: (game, _) async { final behavior = BallSpawningBehavior(); await game.pump([behavior]); - expect(game.descendants(), contains(behavior)); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); }, ); @@ -123,20 +128,27 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'onNewState adds a ball', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final behavior = BallSpawningBehavior(); await game.pump([ behavior, ZCanvasComponent(), Plunger.test(), ]); - expect(game.descendants().whereType(), isEmpty); - - behavior.onNewState(_MockGameState()); await game.ready(); - + }, + verify: (game, tester) async { + expect(game.descendants().whereType(), isEmpty); + game + .descendants() + .whereType() + .single + .onNewState(_MockGameState()); + game.update(0); + await tester.pump(); expect(game.descendants().whereType(), isNotEmpty); }, ); diff --git a/test/game/behaviors/bonus_ball_spawning_behavior_test.dart b/test/game/behaviors/bonus_ball_spawning_behavior_test.dart index 1aacf506..931bac33 100644 --- a/test/game/behaviors/bonus_ball_spawning_behavior_test.dart +++ b/test/game/behaviors/bonus_ball_spawning_behavior_test.dart @@ -39,18 +39,27 @@ void main() { group('FlutterForestBonusBehavior', () { final flameTester = FlameTester(_TestGame.new); - flameTester.test( + flameTester.testGameWidget( 'adds a ball with a BallImpulsingBehavior to the game onTick ' 'resulting in a -40 x impulse', - (game) async { + setUp: (game, _) async { await game.onLoad(); final behavior = BonusBallSpawningBehavior(); await game.pump(behavior); - - game.update(behavior.timer.limit); await game.ready(); + }, + verify: (game, tester) async { + expect( + game.descendants().whereType(), + isNotEmpty, + ); + final behavior = + game.descendants().whereType().single; + game.update(behavior.timer.limit); + await tester.pump(); + expect(game.descendants().whereType(), isNotEmpty); final ball = game.descendants().whereType().single; expect(ball.body.linearVelocity.x, equals(-40)); diff --git a/test/game/behaviors/camera_focusing_behavior_test.dart b/test/game/behaviors/camera_focusing_behavior_test.dart index fb0d91c5..466f9290 100644 --- a/test/game/behaviors/camera_focusing_behavior_test.dart +++ b/test/game/behaviors/camera_focusing_behavior_test.dart @@ -23,52 +23,71 @@ void main() { ); }); - flameTester.test('loads', (game) async { - late final behavior = CameraFocusingBehavior(); - await game.ensureAdd( - FlameBlocProvider.value( - value: GameBloc(), - children: [behavior], - ), - ); - expect(game.descendants(), contains(behavior)); - }); - - flameTester.test('resizes and snaps', (game) async { - final behavior = CameraFocusingBehavior(); - await game.ensureAdd( - FlameBlocProvider.value( - value: GameBloc(), - children: [behavior], - ), - ); + flameTester.testGameWidget( + 'loads', + setUp: (game, _) async { + late final behavior = CameraFocusingBehavior(); + await game.ensureAdd( + FlameBlocProvider.value( + value: GameBloc(), + children: [behavior], + ), + ); + }, + verify: (game, _) async { + expect( + game.descendants().whereType(), + isNotEmpty, + ); + }, + ); - behavior.onGameResize(Vector2.all(10)); - expect(game.camera.zoom, greaterThan(0)); - }); + flameTester.testGameWidget( + 'resizes and snaps', + setUp: (game, _) async { + final behavior = CameraFocusingBehavior(); + await game.ensureAdd( + FlameBlocProvider.value( + value: GameBloc(), + children: [behavior], + ), + ); + }, + verify: (game, _) async { + game + .descendants() + .whereType() + .single + .onGameResize(Vector2.all(10)); + expect(game.camera.viewfinder.zoom, greaterThan(0)); + }, + ); - flameTester.test( + flameTester.testGameWidget( 'changes focus when loaded', - (game) async { + setUp: (game, _) async { + expect(game.camera.viewfinder.zoom, equals(1)); final behavior = CameraFocusingBehavior(); - final previousZoom = game.camera.zoom; - expect(game.camera.follow, isNull); - await game.ensureAdd( FlameBlocProvider.value( value: GameBloc(), children: [behavior], ), ); + }, + verify: (game, tester) async { + final behavior = + game.descendants().whereType().single; + + await behavior.onLoad(); - expect(game.camera.follow, isNotNull); - expect(game.camera.zoom, isNot(equals(previousZoom))); + expect(game.camera.viewfinder.zoom, isNot(equals(1))); }, ); - flameTester.test( + flameTester.testGameWidget( 'listenWhen only listens when status changes', - (game) async { + verify: (game, _) async { final behavior = CameraFocusingBehavior(); const waiting = GameState.initial(); final playing = @@ -91,9 +110,9 @@ void main() { ); group('onNewState', () { - flameTester.test( + flameTester.testGameWidget( 'zooms when started playing', - (game) async { + setUp: (game, _) async { final playing = const GameState.initial().copyWith(status: GameStatus.playing); @@ -105,24 +124,28 @@ void main() { ), ); behavior.onNewState(playing); - final previousPosition = game.camera.position.clone(); - await game.ready(); - + }, + verify: (game, _) async { + final previousPosition = Vector2(-23, -45); + game.camera.viewfinder.position = previousPosition; + final behavior = + game.descendants().whereType().single; + game.update(0); final zoom = behavior.children.whereType().single; game.update(zoom.controller.duration!); game.update(0); expect(zoom.controller.completed, isTrue); expect( - game.camera.position, + game.camera.viewfinder.position, isNot(equals(previousPosition)), ); }, ); - flameTester.test( + flameTester.testGameWidget( 'zooms when game is over', - (game) async { + setUp: (game, _) async { final playing = const GameState.initial().copyWith( status: GameStatus.gameOver, ); @@ -136,16 +159,19 @@ void main() { ); behavior.onNewState(playing); - final previousPosition = game.camera.position.clone(); - await game.ready(); - + }, + verify: (game, _) async { + final previousPosition = Vector2(-23, -45); + final behavior = + game.descendants().whereType().single; + game.update(0); final zoom = behavior.children.whereType().single; game.update(zoom.controller.duration!); game.update(0); expect(zoom.controller.completed, isTrue); expect( - game.camera.position, + game.camera.viewfinder.position, isNot(equals(previousPosition)), ); }, diff --git a/test/game/behaviors/character_selection_behavior_test.dart b/test/game/behaviors/character_selection_behavior_test.dart index 7fe5439f..05d3d282 100644 --- a/test/game/behaviors/character_selection_behavior_test.dart +++ b/test/game/behaviors/character_selection_behavior_test.dart @@ -47,8 +47,8 @@ class _TestGame extends Forge2DGame { class _MockBallCubit extends Mock implements BallCubit {} -class _MockArcadeBackgroundCubit extends Mock implements ArcadeBackgroundCubit { -} +class _MockArcadeBackgroundCubit extends Mock + implements ArcadeBackgroundCubit {} class _MockPlatformHelper extends Mock implements PlatformHelper {} @@ -67,19 +67,24 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'loads', - (game) async { + setUp: (game, _) async { final behavior = CharacterSelectionBehavior(); await game.pump([behavior]); - expect(game.descendants(), contains(behavior)); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); }, ); - flameTester.test( + flameTester.testGameWidget( 'onNewState does not call onCharacterSelected on the arcade background ' 'bloc when platform is mobile', - (game) async { + setUp: (game, _) async { final platformHelper = _MockPlatformHelper(); when(() => platformHelper.isMobile).thenAnswer((_) => true); final arcadeBackgroundBloc = _MockArcadeBackgroundCubit(); @@ -102,7 +107,7 @@ void main() { const dinoThemeState = CharacterThemeState(theme.DinoTheme()); behavior.onNewState(dinoThemeState); await game.ready(); - + game.update(0); verifyNever( () => arcadeBackgroundBloc .onCharacterSelected(dinoThemeState.characterTheme), @@ -110,10 +115,11 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'onNewState calls onCharacterSelected on the arcade background ' 'bloc when platform is not mobile', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final platformHelper = _MockPlatformHelper(); when(() => platformHelper.isMobile).thenAnswer((_) => false); final arcadeBackgroundBloc = _MockArcadeBackgroundCubit(); @@ -139,7 +145,6 @@ void main() { const dinoThemeState = CharacterThemeState(theme.DinoTheme()); behavior.onNewState(dinoThemeState); await game.ready(); - verify( () => arcadeBackgroundBloc .onCharacterSelected(dinoThemeState.characterTheme), @@ -147,9 +152,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'onNewState calls onCharacterSelected on the ball bloc', - (game) async { + setUp: (game, _) async { final platformHelper = _MockPlatformHelper(); when(() => platformHelper.isMobile).thenAnswer((_) => false); final ballBloc = _MockBallCubit(); @@ -174,7 +179,6 @@ void main() { const dinoThemeState = CharacterThemeState(theme.DinoTheme()); behavior.onNewState(dinoThemeState); await game.ready(); - verify( () => ballBloc.onCharacterSelected(dinoThemeState.characterTheme), ).called(1); diff --git a/test/game/behaviors/scoring_behavior_test.dart b/test/game/behaviors/scoring_behavior_test.dart index ef3f10ca..cac05e0e 100644 --- a/test/game/behaviors/scoring_behavior_test.dart +++ b/test/game/behaviors/scoring_behavior_test.dart @@ -27,7 +27,7 @@ class _TestGame extends Forge2DGame { FlameBlocProvider.value( value: gameBloc ?? GameBloc(), children: [ - ZCanvasComponent(children: [child]) + ZCanvasComponent(children: [child]), ], ), ); @@ -77,66 +77,68 @@ void main() { ); }); - flameBlocTester.test( + flameBlocTester.testGameWidget( 'can be loaded', - (game) async { + setUp: (game, _) async { + await game.onLoad(); await game.pump(parent); - final behavior = ScoringBehavior( points: Points.fiveThousand, position: Vector2.zero(), ); await parent.ensureAdd(behavior); - + }, + verify: (game, _) async { expect( parent.firstChild(), - equals(behavior), + isNotNull, ); }, ); - flameBlocTester.test( + flameBlocTester.testGameWidget( 'emits Scored event with points when added', - (game) async { + setUp: (game, _) async { + await game.onLoad(); await game.pump(parent, gameBloc: bloc); - const points = Points.oneMillion; final behavior = ScoringBehavior( - points: points, + points: Points.oneMillion, position: Vector2(0, 0), ); await parent.ensureAdd(behavior); - + }, + verify: (game, _) async { verify( () => bloc.add( - Scored(points: points.value), + Scored(points: Points.oneMillion.value), ), ).called(1); }, ); - flameBlocTester.test( + flameBlocTester.testGameWidget( 'correctly renders text', - (game) async { + setUp: (game, _) async { + await game.onLoad(); await game.pump(parent); - const points = Points.oneMillion; - final position = Vector2.all(1); final behavior = ScoringBehavior( - points: points, - position: position, + points: Points.oneMillion, + position: Vector2.all(1), ); await parent.ensureAdd(behavior); - + }, + verify: (game, _) async { final scoreText = game.descendants().whereType(); expect(scoreText.length, equals(1)); expect( scoreText.first.points, - equals(points), + equals(Points.oneMillion), ); expect( scoreText.first.position, - equals(position), + equals(Vector2.all(1)), ); }, ); diff --git a/test/game/bloc/game_bloc_test.dart b/test/game/bloc/game_bloc_test.dart index 2108b950..a1fe09d3 100644 --- a/test/game/bloc/game_bloc_test.dart +++ b/test/game/bloc/game_bloc_test.dart @@ -15,12 +15,11 @@ void main() { build: GameBloc.new, act: (bloc) => bloc.add(const GameStarted()), expect: () => [ - isA() - ..having( - (state) => state.status, - 'status', - GameStatus.playing, - ), + isA().having( + (state) => state.status, + 'status', + GameStatus.playing, + ), ], ); @@ -29,12 +28,11 @@ void main() { build: GameBloc.new, act: (bloc) => bloc.add(const GameOver()), expect: () => [ - isA() - ..having( - (state) => state.status, - 'status', - GameStatus.gameOver, - ), + isA().having( + (state) => state.status, + 'status', + GameStatus.gameOver, + ), ], ); @@ -47,7 +45,7 @@ void main() { bloc.add(const RoundLost()); }, expect: () => [ - isA()..having((state) => state.rounds, 'rounds', 2), + isA().having((state) => state.rounds, 'rounds', 2), ], ); @@ -61,11 +59,11 @@ void main() { ..add(const RoundLost()); }, expect: () => [ - isA()..having((state) => state.rounds, 'rounds', 2), - isA()..having((state) => state.rounds, 'rounds', 1), + isA().having((state) => state.rounds, 'rounds', 2), + isA().having((state) => state.rounds, 'rounds', 1), isA() - ..having((state) => state.rounds, 'rounds', 0) - ..having((state) => state.status, 'status', GameStatus.gameOver), + .having((state) => state.rounds, 'rounds', 0) + .having((state) => state.status, 'status', GameStatus.gameOver), ], ); @@ -86,8 +84,8 @@ void main() { }, expect: () => [ isA() - ..having((state) => state.totalScore, 'totalScore', 25) - ..having((state) => state.roundScore, 'roundScore', 0) + .having((state) => state.totalScore, 'totalScore', 25) + .having((state) => state.roundScore, 'roundScore', 0), ], ); @@ -104,12 +102,11 @@ void main() { ), act: (bloc) => bloc.add(const RoundLost()), expect: () => [ - isA() - ..having( - (state) => state.totalScore, - 'totalScore', - 9999999999, - ) + isA().having( + (state) => state.totalScore, + 'totalScore', + 9999999999, + ), ], ); @@ -128,7 +125,7 @@ void main() { bloc.add(const RoundLost()); }, expect: () => [ - isA()..having((state) => state.multiplier, 'multiplier', 1) + isA().having((state) => state.multiplier, 'multiplier', 1), ], ); }); @@ -143,13 +140,13 @@ void main() { ..add(const Scored(points: 3)), expect: () => [ isA() - ..having((state) => state.status, 'status', GameStatus.playing), + .having((state) => state.status, 'status', GameStatus.playing), isA() - ..having((state) => state.roundScore, 'roundScore', 2) - ..having((state) => state.status, 'status', GameStatus.playing), + .having((state) => state.roundScore, 'roundScore', 2) + .having((state) => state.status, 'status', GameStatus.playing), isA() - ..having((state) => state.roundScore, 'roundScore', 5) - ..having((state) => state.status, 'status', GameStatus.playing), + .having((state) => state.roundScore, 'roundScore', 5) + .having((state) => state.status, 'status', GameStatus.playing), ], ); @@ -164,29 +161,29 @@ void main() { }, expect: () => [ isA() - ..having((state) => state.roundScore, 'roundScore', 0) - ..having((state) => state.rounds, 'rounds', 2) - ..having( - (state) => state.status, - 'status', - GameStatus.gameOver, - ), + .having((state) => state.roundScore, 'roundScore', 0) + .having((state) => state.rounds, 'rounds', 2) + .having( + (state) => state.status, + 'status', + GameStatus.waiting, + ), isA() - ..having((state) => state.roundScore, 'roundScore', 0) - ..having((state) => state.rounds, 'rounds', 1) - ..having( - (state) => state.status, - 'status', - GameStatus.gameOver, - ), + .having((state) => state.roundScore, 'roundScore', 0) + .having((state) => state.rounds, 'rounds', 1) + .having( + (state) => state.status, + 'status', + GameStatus.waiting, + ), isA() - ..having((state) => state.roundScore, 'roundScore', 0) - ..having((state) => state.rounds, 'rounds', 0) - ..having( - (state) => state.status, - 'status', - GameStatus.gameOver, - ), + .having((state) => state.roundScore, 'roundScore', 0) + .having((state) => state.rounds, 'rounds', 0) + .having( + (state) => state.status, + 'status', + GameStatus.gameOver, + ), ], ); @@ -203,7 +200,7 @@ void main() { ), act: (bloc) => bloc.add(const Scored(points: 2)), expect: () => [ - isA()..having((state) => state.roundScore, 'roundScore', 1) + isA().having((state) => state.roundScore, 'roundScore', 1), ], ); }); @@ -219,21 +216,21 @@ void main() { ..add(const MultiplierIncreased()), expect: () => [ isA() - ..having((state) => state.status, 'status', GameStatus.playing), + .having((state) => state.status, 'status', GameStatus.playing), isA() - ..having((state) => state.multiplier, 'multiplier', 2) - ..having( - (state) => state.status, - 'status', - GameStatus.gameOver, - ), + .having((state) => state.multiplier, 'multiplier', 2) + .having( + (state) => state.status, + 'status', + GameStatus.playing, + ), isA() - ..having((state) => state.multiplier, 'multiplier', 3) - ..having( - (state) => state.status, - 'status', - GameStatus.gameOver, - ), + .having((state) => state.multiplier, 'multiplier', 3) + .having( + (state) => state.status, + 'status', + GameStatus.playing, + ), ], ); @@ -266,28 +263,28 @@ void main() { }, expect: () => [ isA() - ..having((state) => state.status, 'status', GameStatus.playing), + .having((state) => state.status, 'status', GameStatus.playing), isA() - ..having((state) => state.multiplier, 'multiplier', 1) - ..having( - (state) => state.status, - 'status', - GameStatus.gameOver, - ), + .having((state) => state.multiplier, 'multiplier', 1) + .having( + (state) => state.status, + 'status', + GameStatus.playing, + ), isA() - ..having((state) => state.multiplier, 'multiplier', 1) - ..having( - (state) => state.status, - 'status', - GameStatus.gameOver, - ), + .having((state) => state.multiplier, 'multiplier', 1) + .having( + (state) => state.status, + 'status', + GameStatus.playing, + ), isA() - ..having((state) => state.multiplier, 'multiplier', 1) - ..having( - (state) => state.status, - 'status', - GameStatus.gameOver, - ), + .having((state) => state.multiplier, 'multiplier', 1) + .having( + (state) => state.status, + 'status', + GameStatus.gameOver, + ), ], ); }); @@ -302,18 +299,16 @@ void main() { ..add(const BonusActivated(GameBonus.googleWord)) ..add(const BonusActivated(GameBonus.dashNest)), expect: () => [ - isA() - ..having( - (state) => state.bonusHistory, - 'bonusHistory', - [GameBonus.googleWord], - ), - isA() - ..having( - (state) => state.bonusHistory, - 'bonusHistory', - [GameBonus.googleWord, GameBonus.dashNest], - ), + isA().having( + (state) => state.bonusHistory, + 'bonusHistory', + [GameBonus.googleWord], + ), + isA().having( + (state) => state.bonusHistory, + 'bonusHistory', + [GameBonus.googleWord, GameBonus.dashNest], + ), ], ); }, diff --git a/test/game/components/android_acres/android_acres_test.dart b/test/game/components/android_acres/android_acres_test.dart index 14d3d69e..a70cb110 100644 --- a/test/game/components/android_acres/android_acres_test.dart +++ b/test/game/components/android_acres/android_acres_test.dart @@ -54,17 +54,25 @@ void main() { group('AndroidAcres', () { final flameTester = FlameTester(_TestGame.new); - flameTester.test('loads correctly', (game) async { - final component = AndroidAcres(); - await game.pump(component); - expect(game.descendants(), contains(component)); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); group('loads', () { - flameTester.test( + flameTester.testGameWidget( 'an AndroidSpaceship', - (game) async { - await game.pump(AndroidAcres()); + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -72,10 +80,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'an AndroidAnimatronic', - (game) async { - await game.pump(AndroidAcres()); + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -83,10 +94,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'a SpaceshipRamp', - (game) async { - await game.pump(AndroidAcres()); + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -94,10 +108,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'a SpaceshipRail', - (game) async { - await game.pump(AndroidAcres()); + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -105,10 +122,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'three AndroidBumper', - (game) async { - await game.pump(AndroidAcres()); + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(3), @@ -116,10 +136,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'three AndroidBumpers with BumperNoiseBehavior', - (game) async { - await game.pump(AndroidAcres()); + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { final bumpers = game.descendants().whereType(); for (final bumper in bumpers) { expect( @@ -130,10 +153,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'one AndroidBumper with CowBumperNoiseBehavior', - (game) async { - await game.pump(AndroidAcres()); + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { final bumpers = game.descendants().whereType(); expect( @@ -146,30 +172,45 @@ void main() { ); }); - flameTester.test('adds a FlameBlocProvider', (game) async { - final androidAcres = AndroidAcres(); - await game.pump(androidAcres); - expect( - androidAcres.children + flameTester.testGameWidget( + 'adds a FlameBlocProvider', + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { + final androidAcres = + game.descendants().whereType().single; + expect( + androidAcres.children + .whereType< + FlameBlocProvider>() + .single, + isNotNull, + ); + }, + ); + + flameTester.testGameWidget( + 'adds an AndroidSpaceshipBonusBehavior', + setUp: (game, _) async { + final component = AndroidAcres(); + await game.pump(component); + }, + verify: (game, _) async { + final androidAcres = + game.descendants().whereType().single; + final provider = androidAcres.children .whereType< FlameBlocProvider>() - .single, - isNotNull, - ); - }); - - flameTester.test('adds an AndroidSpaceshipBonusBehavior', (game) async { - final androidAcres = AndroidAcres(); - await game.pump(androidAcres); - final provider = androidAcres.children - .whereType< - FlameBlocProvider>() - .single; - expect( - provider.children.whereType().single, - isNotNull, - ); - }); + .single; + expect( + provider.children.whereType().single, + isNotNull, + ); + }, + ); }); } diff --git a/test/game/components/android_acres/behaviors/android_spaceship_bonus_behavior_test.dart b/test/game/components/android_acres/behaviors/android_spaceship_bonus_behavior_test.dart index e8ef68f8..2f95001b 100644 --- a/test/game/components/android_acres/behaviors/android_spaceship_bonus_behavior_test.dart +++ b/test/game/components/android_acres/behaviors/android_spaceship_bonus_behavior_test.dart @@ -67,8 +67,8 @@ class _TestGame extends Forge2DGame { class _MockGameBloc extends Mock implements GameBloc {} -class _MockAndroidSpaceshipCubit extends Mock implements AndroidSpaceshipCubit { -} +class _MockAndroidSpaceshipCubit extends Mock + implements AndroidSpaceshipCubit {} void main() { TestWidgetsFlutterBinding.ensureInitialized(); diff --git a/test/game/components/android_acres/behaviors/ramp_bonus_behavior_test.dart b/test/game/components/android_acres/behaviors/ramp_bonus_behavior_test.dart index dc0d0e28..3f4b8ba6 100644 --- a/test/game/components/android_acres/behaviors/ramp_bonus_behavior_test.dart +++ b/test/game/components/android_acres/behaviors/ramp_bonus_behavior_test.dart @@ -77,9 +77,10 @@ void main() { final flameTester = FlameTester(_TestGame.new); - flameTester.test( + flameTester.testGameWidget( 'when hits are multiples of 10 times adds a ScoringBehavior', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -99,16 +100,20 @@ void main() { streamController.add(state.copyWith(hits: 10)); - final scores = game.descendants().whereType(); await game.ready(); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final scores = game.descendants().whereType(); expect(scores.length, 1); }, ); - flameTester.test( + flameTester.testGameWidget( "when hits are not multiple of 10 times doesn't add any ScoringBehavior", - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -128,9 +133,12 @@ void main() { streamController.add(state.copyWith(hits: 9)); - final scores = game.descendants().whereType(); await game.ready(); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final scores = game.descendants().whereType(); expect(scores.length, 0); }, ); diff --git a/test/game/components/android_acres/behaviors/ramp_multiplier_behavior_test.dart b/test/game/components/android_acres/behaviors/ramp_multiplier_behavior_test.dart index 5413c3d3..307570c5 100644 --- a/test/game/components/android_acres/behaviors/ramp_multiplier_behavior_test.dart +++ b/test/game/components/android_acres/behaviors/ramp_multiplier_behavior_test.dart @@ -76,10 +76,11 @@ void main() { final flameTester = FlameTester(_TestGame.new); - flameTester.test( + flameTester.testGameWidget( 'adds MultiplierIncreased ' 'when hits are multiples of 5 times and multiplier is less than 6', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -105,16 +106,19 @@ void main() { ); streamController.add(state.copyWith(hits: 5)); - await Future.delayed(Duration.zero); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); verify(() => gameBloc.add(const MultiplierIncreased())).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( "doesn't add MultiplierIncreased " 'when hits are multiples of 5 times but multiplier is 6', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -139,16 +143,18 @@ void main() { ); streamController.add(state.copyWith(hits: 5)); - await Future.delayed(Duration.zero); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); verifyNever(() => gameBloc.add(const MultiplierIncreased())); }, ); - flameTester.test( + flameTester.testGameWidget( "doesn't add MultiplierIncreased " "when hits aren't multiples of 5 times", - (game) async { + setUp: (game, _) async { final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -175,7 +181,10 @@ void main() { streamController.add(state.copyWith(hits: 1)); await game.ready(); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); verifyNever(() => gameBloc.add(const MultiplierIncreased())); }, ); diff --git a/test/game/components/android_acres/behaviors/ramp_progress_behavior_test.dart b/test/game/components/android_acres/behaviors/ramp_progress_behavior_test.dart index 29e9f452..abdd9d09 100644 --- a/test/game/components/android_acres/behaviors/ramp_progress_behavior_test.dart +++ b/test/game/components/android_acres/behaviors/ramp_progress_behavior_test.dart @@ -73,10 +73,11 @@ void main() { final flameTester = FlameTester(_TestGame.new); - flameTester.test( + flameTester.testGameWidget( 'adds onProgressed ' 'when hits and multiplier are less than 6', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -104,15 +105,25 @@ void main() { streamController.add(state.copyWith(hits: 5)); await Future.delayed(Duration.zero); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; verify(bloc.onProgressed).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( 'adds onProgressed ' 'when hits and multiplier are 6 but arrow is not fully lit', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -140,15 +151,25 @@ void main() { streamController.add(state.copyWith(hits: 5)); await Future.delayed(Duration.zero); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; verify(bloc.onProgressed).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( "doesn't add onProgressed " 'when hits and multiplier are 6 and arrow is fully lit', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -180,16 +201,26 @@ void main() { lightState: ArrowLightState.active5, ), ); - await Future.delayed(Duration.zero); + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; verifyNever(bloc.onProgressed); }, ); - flameTester.test( + flameTester.testGameWidget( 'adds onProgressed to dim arrow ' 'when arrow is fully lit after hit and multiplier is less than 6', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -221,16 +252,25 @@ void main() { lightState: ArrowLightState.active5, ), ); - await Future.delayed(Duration.zero); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; verify(bloc.onProgressed).called(2); }, ); - flameTester.test( + flameTester.testGameWidget( "doesn't add onProgressed to dim arrow " 'when arrow is not fully lit after hit', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -262,16 +302,25 @@ void main() { lightState: ArrowLightState.active4, ), ); - await Future.delayed(Duration.zero); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; verify(bloc.onProgressed).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( "doesn't add onProgressed to dim arrow " 'when multiplier is 6 after hit', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -300,7 +349,16 @@ void main() { streamController.add( state.copyWith(hits: 4), ); - await Future.delayed(Duration.zero); + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; verify(bloc.onProgressed).called(1); }, diff --git a/test/game/components/android_acres/behaviors/ramp_reset_behavior_test.dart b/test/game/components/android_acres/behaviors/ramp_reset_behavior_test.dart index d141c62a..b3296082 100644 --- a/test/game/components/android_acres/behaviors/ramp_reset_behavior_test.dart +++ b/test/game/components/android_acres/behaviors/ramp_reset_behavior_test.dart @@ -73,9 +73,10 @@ void main() { final flameTester = FlameTester(_TestGame.new); - flameTester.test( + flameTester.testGameWidget( 'calls onReset when round lost', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = GameState.initial(); final streamController = StreamController(); @@ -96,15 +97,24 @@ void main() { ); streamController.add(state.copyWith(rounds: state.rounds - 1)); - await Future.delayed(Duration.zero); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; verify(bloc.onReset).called(1); }, ); - flameTester.test( + flameTester.testGameWidget( "doesn't call onReset when round stays the same", - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = GameState.initial(); final streamController = StreamController(); @@ -126,8 +136,16 @@ void main() { streamController .add(state.copyWith(roundScore: state.roundScore + 100)); - await Future.delayed(Duration.zero); - + }, + verify: (game, tester) async { + game.update(0); + await tester.pump(); + final bloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; verifyNever(bloc.onReset); }, ); diff --git a/test/game/components/android_acres/behaviors/ramp_shot_behavior_test.dart b/test/game/components/android_acres/behaviors/ramp_shot_behavior_test.dart index d5a5ecd6..5d5d17c0 100644 --- a/test/game/components/android_acres/behaviors/ramp_shot_behavior_test.dart +++ b/test/game/components/android_acres/behaviors/ramp_shot_behavior_test.dart @@ -41,7 +41,7 @@ class _TestGame extends Forge2DGame { required SpaceshipRampCubit bloc, required GameBloc gameBloc, }) async { - await ensureAdd( + await world.ensureAdd( FlameMultiBlocProvider( providers: [ FlameBlocProvider.value( @@ -77,9 +77,10 @@ void main() { final flameTester = FlameTester(_TestGame.new); - flameTester.test( + flameTester.testGameWidget( 'adds a ScoringBehavior when hit', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bloc = _MockSpaceshipRampCubit(); final state = SpaceshipRampState.initial(); final streamController = StreamController(); @@ -99,9 +100,10 @@ void main() { streamController.add(state.copyWith(hits: state.hits + 1)); - final scores = game.descendants().whereType(); await game.ready(); - + }, + verify: (game, _) async { + final scores = game.descendants().whereType(); expect(scores.length, 1); }, ); diff --git a/test/game/components/backbox/backbox_test.dart b/test/game/components/backbox/backbox_test.dart index 26f413f7..4c18a067 100644 --- a/test/game/components/backbox/backbox_test.dart +++ b/test/game/components/backbox/backbox_test.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:bloc_test/bloc_test.dart'; -import 'package:flame/game.dart'; +import 'package:flame/events.dart'; import 'package:flame/input.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; @@ -26,7 +26,7 @@ import 'package:plugin_platform_interface/plugin_platform_interface.dart'; import 'package:share_repository/share_repository.dart'; class _TestGame extends Forge2DGame - with HasKeyboardHandlerComponents, HasTappables { + with HasKeyboardHandlerComponents, TapCallbacks { final character = theme.DashTheme(); @override @@ -51,10 +51,25 @@ class _TestGame extends Forge2DGame Backbox component, { PlatformHelper? platformHelper, }) async { - // Not needed once https://github.com/flame-engine/flame/issues/1607 - // is fixed - await onLoad(); - await ensureAdd( + overlays.addEntry( + 'mobile_controls', + (context, game) { + return PinballButton( + text: 'mobile', + onTap: () {}, + ); + }, + ); + overlays.addEntry( + 'replay_button', + (context, game) { + return PinballButton( + text: 'replay', + onTap: () {}, + ); + }, + ); + await world.ensureAdd( FlameBlocProvider.value( value: GameBloc(), children: [ @@ -75,15 +90,15 @@ class _TestGame extends Forge2DGame } } -class _MockRawKeyUpEvent extends Mock implements RawKeyUpEvent { +class _MockKeyUpEvent extends Mock implements KeyUpEvent { @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { return super.toString(); } } -RawKeyUpEvent _mockKeyUp(LogicalKeyboardKey key) { - final event = _MockRawKeyUpEvent(); +KeyUpEvent _mockKeyUp(LogicalKeyboardKey key) { + final event = _MockKeyUpEvent(); when(() => event.logicalKey).thenReturn(key); return event; } @@ -92,14 +107,16 @@ class _MockPlatformHelper extends Mock implements PlatformHelper {} 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 _MockTapDownEvent extends Mock implements TapDownEvent {} + +class _MockTapUpEvent extends Mock implements TapUpEvent {} -class _MockTapUpInfo extends Mock implements TapUpInfo {} +class _MockLaunchOptions extends Mock implements LaunchOptions {} class _MockUrlLauncher extends Mock with MockPlatformInterfaceMixin @@ -196,10 +213,15 @@ void main() { when(() => platformHelper.isMobile).thenReturn(false); }); + setUpAll(() { + registerFallbackValue(_MockLaunchOptions()); + }); + group('Backbox', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final backbox = Backbox.test( bloc: bloc, shareRepository: _MockShareRepository(), @@ -208,7 +230,9 @@ void main() { backbox, platformHelper: platformHelper, ); - expect(game.descendants(), contains(backbox)); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); @@ -217,8 +241,8 @@ void main() { setUp: (game, tester) async { await game.onLoad(); game.camera - ..followVector2(Vector2(0, -130)) - ..zoom = 6; + ..moveTo(Vector2(0, -130)) + ..viewfinder.zoom = 6; await game.pump( Backbox.test( bloc: bloc, @@ -227,6 +251,8 @@ void main() { platformHelper: platformHelper, ); await tester.pump(); + await game.ready(); + game.update(0); }, verify: (game, tester) async { await expectLater( @@ -236,9 +262,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'requestInitials adds InitialsInputDisplay', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final backbox = Backbox.test( bloc: BackboxBloc( leaderboardRepository: _MockLeaderboardRepository(), @@ -255,18 +282,25 @@ void main() { character: game.character, ); await game.ready(); - + }, + verify: (game, tester) async { expect( - backbox.descendants().whereType().length, + game + .descendants() + .whereType() + .single + .descendants() + .whereType() + .length, equals(1), ); }, ); - flameTester.test( + flameTester.testGameWidget( 'adds PlayerInitialsSubmitted when initials are submitted', - (game) async { - final bloc = _MockBackboxBloc(); + setUp: (game, _) async { + await game.onLoad(); final state = InitialsFormState( score: 10, character: game.character, @@ -284,7 +318,9 @@ void main() { backbox, platformHelper: platformHelper, ); - + await game.ready(); + }, + verify: (game, tester) async { game.onKeyEvent(_mockKeyUp(LogicalKeyboardKey.enter), {}); verify( () => bloc.add( @@ -298,9 +334,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds GameOverInfoDisplay when InitialsSuccessState', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final state = InitialsSuccessState(score: 100); whenListen( bloc, @@ -315,7 +352,9 @@ void main() { backbox, platformHelper: platformHelper, ); - + await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -323,11 +362,11 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds the mobile controls overlay ' 'when platform is mobile at InitialsFormState', - (game) async { - final bloc = _MockBackboxBloc(); + setUp: (game, _) async { + await game.onLoad(); final platformHelper = _MockPlatformHelper(); final state = InitialsFormState( score: 10, @@ -347,19 +386,21 @@ void main() { backbox, platformHelper: platformHelper, ); - + await game.ready(); + }, + verify: (game, _) async { expect( - game.overlays.value, + game.overlays.activeOverlays.first, contains(PinballGame.mobileControlsOverlay), ); }, ); - flameTester.test( + flameTester.testGameWidget( 'remove the mobile controls overlay ' 'when InitialsSuccessState', - (game) async { - final bloc = _MockBackboxBloc(); + setUp: (game, _) async { + await game.onLoad(); final platformHelper = _MockPlatformHelper(); final state = InitialsSuccessState(score: 10); whenListen( @@ -376,17 +417,20 @@ void main() { backbox, platformHelper: platformHelper, ); - + await game.ready(); + }, + verify: (game, _) async { expect( - game.overlays.value, + game.overlays.activeOverlays.first, isNot(contains(PinballGame.mobileControlsOverlay)), ); }, ); - flameTester.test( + flameTester.testGameWidget( 'adds InitialsSubmissionSuccessDisplay on InitialsSuccessState', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final state = InitialsSuccessState(score: 100); whenListen( bloc, @@ -401,7 +445,9 @@ void main() { backbox, platformHelper: platformHelper, ); - + await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -409,9 +455,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds ShareScoreRequested event when sharing', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final state = InitialsSuccessState(score: 100); whenListen( bloc, @@ -429,8 +476,13 @@ void main() { final shareLink = game.descendants().whereType().first; - shareLink.onTapDown(_MockTapDownInfo()); - + shareLink.onTapDown(_MockTapDownEvent()); + await game.ready(); + }, + verify: (game, tester) async { + final state = bloc.state as InitialsSuccessState; + game.update(0); + await tester.pump(); verify( () => bloc.add( ShareScoreRequested(score: state.score), @@ -439,9 +491,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds InitialsSubmissionFailureDisplay on InitialsFailureState', - (game) async { + setUp: (game, _) async { + await game.onLoad(); whenListen( bloc, Stream.empty(), @@ -458,7 +511,9 @@ void main() { backbox, platformHelper: platformHelper, ); - + await game.ready(); + }, + verify: (game, _) async { expect( game .descendants() @@ -475,9 +530,10 @@ void main() { UrlLauncherPlatform.instance = urlLauncher; }); - flameTester.test( + flameTester.testGameWidget( 'adds ShareDisplay on ShareState', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final state = ShareState(score: 100); whenListen( bloc, @@ -492,7 +548,9 @@ void main() { backbox, platformHelper: platformHelper, ); - + await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -500,20 +558,16 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'opens Facebook link when sharing with Facebook', - (game) async { + setUp: (game, _) async { + await game.onLoad(); when(() => urlLauncher.canLaunch(any())) .thenAnswer((_) async => true); when( - () => urlLauncher.launch( + () => urlLauncher.launchUrl( + any(), 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); @@ -542,9 +596,11 @@ void main() { platformHelper: platformHelper, ); + expect(bloc.state, isA()); + final facebookButton = game.descendants().whereType().first; - facebookButton.onTapUp(_MockTapUpInfo()); + facebookButton.onTapUp(_MockTapUpEvent()); await game.ready(); @@ -557,9 +613,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'opens Twitter link when sharing with Twitter', - (game) async { + setUp: (game, tester) async { + await game.onLoad(); final state = ShareState(score: 100); whenListen( bloc, @@ -578,14 +635,9 @@ void main() { when(() => urlLauncher.canLaunch(any())) .thenAnswer((_) async => true); when( - () => urlLauncher.launch( + () => urlLauncher.launchUrl( + any(), 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); @@ -598,12 +650,13 @@ void main() { platformHelper: platformHelper, ); - final facebookButton = + expect(bloc.state, isA()); + + final twitterButton = game.descendants().whereType().first; - facebookButton.onTapUp(_MockTapUpInfo()); + twitterButton.onTapUp(_MockTapUpEvent()); await game.ready(); - verify( () => shareRepository.shareText( value: any(named: 'value'), @@ -614,9 +667,10 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'adds LeaderboardDisplay on LeaderboardSuccessState', - (game) async { + setUp: (game, _) async { + await game.onLoad(); whenListen( bloc, Stream.empty(), @@ -631,7 +685,9 @@ void main() { backbox, platformHelper: platformHelper, ); - + await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -639,9 +695,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds LeaderboardFailureDisplay on LeaderboardFailureState', - (game) async { + setUp: (game, _) async { + await game.onLoad(); whenListen( bloc, Stream.empty(), @@ -656,7 +713,9 @@ void main() { backbox, platformHelper: platformHelper, ); - + await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -664,9 +723,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'closes the subscription when it is removed', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final streamController = StreamController(); whenListen( bloc, @@ -704,9 +764,10 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds PlayerInitialsSubmitted when the timer is finished', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final initialState = InitialsFailureState( score: 10, character: theme.DashTheme(), @@ -725,8 +786,10 @@ void main() { backbox, platformHelper: platformHelper, ); + await game.ready(); + }, + verify: (game, _) async { game.update(4); - verify( () => bloc.add( PlayerInitialsRequested( diff --git a/test/game/components/backbox/bloc/backbox_bloc_test.dart b/test/game/components/backbox/bloc/backbox_bloc_test.dart index 050307dc..9d411395 100644 --- a/test/game/components/backbox/bloc/backbox_bloc_test.dart +++ b/test/game/components/backbox/bloc/backbox_bloc_test.dart @@ -7,8 +7,8 @@ import 'package:mocktail/mocktail.dart'; import 'package:pinball/game/components/backbox/bloc/backbox_bloc.dart'; import 'package:pinball_theme/pinball_theme.dart'; -class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { -} +class _MockLeaderboardRepository extends Mock + implements LeaderboardRepository {} void main() { late LeaderboardRepository leaderboardRepository; diff --git a/test/game/components/backbox/displays/game_over_info_display_test.dart b/test/game/components/backbox/displays/game_over_info_display_test.dart index bb092347..c6d0d485 100644 --- a/test/game/components/backbox/displays/game_over_info_display_test.dart +++ b/test/game/components/backbox/displays/game_over_info_display_test.dart @@ -1,14 +1,13 @@ // ignore_for_file: cascade_invocations -import 'package:flame/game.dart'; -import 'package:flame/input.dart'; +import 'package:flame/events.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/game_over_info_display.dart'; +import 'package:pinball/game/game.dart'; import 'package:pinball/l10n/l10n.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; @@ -16,7 +15,7 @@ import 'package:pinball_ui/pinball_ui.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; import 'package:share_repository/share_repository.dart'; -class _TestGame extends Forge2DGame with HasTappables { +class _TestGame extends Forge2DGame with TapCallbacks { @override Future onLoad() async { await super.onLoad(); @@ -29,6 +28,15 @@ class _TestGame extends Forge2DGame with HasTappables { } Future pump(GameOverInfoDisplay component) { + overlays.addEntry( + 'replay_button', + (context, game) { + return PinballButton( + text: 'replay', + onTap: () {}, + ); + }, + ); return ensureAdd( FlameBlocProvider.value( value: GameBloc(), @@ -66,9 +74,11 @@ class _MockAppLocalizations extends Mock implements AppLocalizations { String get openSourceCode => ''; } -class _MockTapDownInfo extends Mock implements TapDownInfo {} +class _MockTapDownEvent extends Mock implements TapDownEvent {} + +class _MockTapUpEvent extends Mock implements TapUpEvent {} -class _MockTapUpInfo extends Mock implements TapUpInfo {} +class _MockLaunchOptions extends Mock implements LaunchOptions {} class _MockUrlLauncher extends Mock with MockPlatformInterfaceMixin @@ -86,110 +96,104 @@ void main() { UrlLauncherPlatform.instance = urlLauncher; }); + setUpAll(() { + registerFallbackValue(_MockLaunchOptions()); + }); + group('InfoDisplay', () { - flameTester.test( + var tapped = false; + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final component = GameOverInfoDisplay(); await game.pump(component); - expect(game.descendants(), contains(component)); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); - flameTester.test( + flameTester.testGameWidget( 'calls onShare when Share link is tapped', - (game) async { - var tapped = false; - - final tapDownInfo = _MockTapDownInfo(); + setUp: (game, _) async { + await game.onLoad(); + tapped = false; final component = GameOverInfoDisplay( onShare: () => tapped = true, ); await game.pump(component); - + await game.ready(); + }, + verify: (game, _) async { + final tapDownEvent = _MockTapDownEvent(); + final component = + game.descendants().whereType().single; final shareLink = component.descendants().whereType().first; - shareLink.onTapDown(tapDownInfo); + shareLink.onTapDown(tapDownEvent); expect(tapped, isTrue); }, ); - flameTester.test( + flameTester.testGameWidget( 'open Google IO Event url when navigating', - (game) async { + setUp: (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); + () => urlLauncher.launchUrl(any(), any()), + ).thenAnswer((_) => Future.value(true)); final component = GameOverInfoDisplay(); await game.pump(component); - + await game.ready(); + }, + verify: (game, tester) async { + final component = + game.descendants().whereType().single; final googleLink = component.descendants().whereType().first; - googleLink.onTapUp(_MockTapUpInfo()); + googleLink.onTapUp(_MockTapUpEvent()); - await game.ready(); + game.update(0); + + await tester.pump(); verify( - () => urlLauncher.launch( + () => urlLauncher.launchUrl( ShareRepository.googleIOEvent, - useSafariVC: any(named: 'useSafariVC'), - useWebView: any(named: 'useWebView'), - enableJavaScript: any(named: 'enableJavaScript'), - enableDomStorage: any(named: 'enableDomStorage'), - universalLinksOnly: any(named: 'universalLinksOnly'), - headers: any(named: 'headers'), + any(), ), ); }, ); - flameTester.test( + flameTester.testGameWidget( 'open OpenSource url when navigating', - (game) async { + setUp: (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'), - ), + () => urlLauncher.launchUrl(any(), any()), ).thenAnswer((_) async => true); final component = GameOverInfoDisplay(); await game.pump(component); + await game.ready(); + }, + verify: (game, tester) async { + final component = + game.descendants().whereType().single; final openSourceLink = component.descendants().whereType().first; - openSourceLink.onTapUp(_MockTapUpInfo()); + openSourceLink.onTapUp(_MockTapUpEvent()); - await game.ready(); + game.update(0); + await tester.pump(); verify( - () => urlLauncher.launch( - ShareRepository.openSourceCode, - useSafariVC: any(named: 'useSafariVC'), - useWebView: any(named: 'useWebView'), - enableJavaScript: any(named: 'enableJavaScript'), - enableDomStorage: any(named: 'enableDomStorage'), - universalLinksOnly: any(named: 'universalLinksOnly'), - headers: any(named: 'headers'), - ), + () => urlLauncher.launchUrl(ShareRepository.openSourceCode, any()), ); }, ); diff --git a/test/game/components/backbox/displays/initials_input_display_test.dart b/test/game/components/backbox/displays/initials_input_display_test.dart index fd61c2c2..cddeb921 100644 --- a/test/game/components/backbox/displays/initials_input_display_test.dart +++ b/test/game/components/backbox/displays/initials_input_display_test.dart @@ -75,16 +75,21 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('InitialsInputDisplay', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final component = InitialsInputDisplay( score: 0, characterIconPath: game.characterIconPath, onSubmit: (_) {}, ); await game.pump(component); - expect(game.descendants(), contains(component)); + }, + verify: (game, _) async { + expect( + game.descendants().whereType(), + isNotEmpty, + ); }, ); diff --git a/test/game/components/backbox/displays/initials_submission_failure_display_test.dart b/test/game/components/backbox/displays/initials_submission_failure_display_test.dart index f0eb03c6..57979442 100644 --- a/test/game/components/backbox/displays/initials_submission_failure_display_test.dart +++ b/test/game/components/backbox/displays/initials_submission_failure_display_test.dart @@ -23,7 +23,7 @@ class _TestGame extends Forge2DGame { } Future pump(InitialsSubmissionFailureDisplay component) { - return ensureAdd( + return world.ensureAdd( FlameProvider.value( _MockAppLocalizations(), children: [component], @@ -45,33 +45,40 @@ void main() { group('InitialsSubmissionFailureDisplay', () { final flameTester = FlameTester(_TestGame.new); - flameTester.test('renders correctly', (game) async { - await game.pump( - InitialsSubmissionFailureDisplay( - onDismissed: () {}, - ), - ); - - expect( - game - .descendants() - .where( - (component) => - component is TextComponent && component.text == 'Title', - ) - .length, - equals(1), - ); - expect( - game - .descendants() - .where( - (component) => - component is TextComponent && component.text == 'Message', - ) - .length, - equals(1), - ); - }); + flameTester.testGameWidget( + 'renders correctly', + setUp: (game, _) async { + await game.onLoad(); + await game.pump( + InitialsSubmissionFailureDisplay( + onDismissed: () {}, + ), + ); + await game.ready(); + }, + verify: (game, tester) async { + await tester.pump(); + expect( + game + .descendants() + .where( + (component) => + component is TextComponent && component.text == 'Title', + ) + .length, + equals(1), + ); + expect( + game + .descendants() + .where( + (component) => + component is TextComponent && component.text == 'Message', + ) + .length, + equals(1), + ); + }, + ); }); } diff --git a/test/game/components/backbox/displays/initials_submission_success_display_test.dart b/test/game/components/backbox/displays/initials_submission_success_display_test.dart index 7ad3d182..42383333 100644 --- a/test/game/components/backbox/displays/initials_submission_success_display_test.dart +++ b/test/game/components/backbox/displays/initials_submission_success_display_test.dart @@ -10,12 +10,16 @@ void main() { group('InitialsSubmissionSuccessDisplay', () { final flameTester = FlameTester(Forge2DGame.new); - flameTester.test('renders correctly', (game) async { - await game.ensureAdd(InitialsSubmissionSuccessDisplay()); - - final component = game.firstChild(); - expect(component, isNotNull); - expect(component?.text, equals('Success!')); - }); + flameTester.testGameWidget( + 'renders correctly', + setUp: (game, _) async { + await game.ensureAdd(InitialsSubmissionSuccessDisplay()); + }, + verify: (game, _) async { + final component = game.firstChild(); + expect(component, isNotNull); + expect(component?.text, equals('Success!')); + }, + ); }); } diff --git a/test/game/components/backbox/displays/leaderboard_display_test.dart b/test/game/components/backbox/displays/leaderboard_display_test.dart index 46fe6cdc..bcdfdfff 100644 --- a/test/game/components/backbox/displays/leaderboard_display_test.dart +++ b/test/game/components/backbox/displays/leaderboard_display_test.dart @@ -1,7 +1,7 @@ // ignore_for_file: cascade_invocations import 'package:flame/components.dart'; -import 'package:flame/game.dart'; +import 'package:flame/events.dart'; import 'package:flame_forge2d/forge2d_game.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -24,7 +24,7 @@ class _MockAppLocalizations extends Mock implements AppLocalizations { String get name => 'name'; } -class _TestGame extends Forge2DGame with HasTappables { +class _TestGame extends Forge2DGame with TapCallbacks { @override Future onLoad() async { await super.onLoad(); @@ -105,89 +105,106 @@ void main() { final flameTester = FlameTester(_TestGame.new); - flameTester.test('renders the titles', (game) async { - await game.pump(LeaderboardDisplay(entries: const [])); - - final textComponents = - game.descendants().whereType().toList(); - expect(textComponents.length, equals(3)); - expect(textComponents[0].text, equals('rank')); - expect(textComponents[1].text, equals('score')); - expect(textComponents[2].text, equals('name')); - }); - - flameTester.test('renders the first 5 entries', (game) async { - await game.pump(LeaderboardDisplay(entries: leaderboard)); - - for (final text in [ - 'AAA', - 'BBB', - 'CCC', - 'DDD', - 'EEE', - '1st', - '2nd', - '3rd', - '4th', - '5th', - ]) { - expect( - game - .descendants() - .whereType() - .where((textComponent) => textComponent.text == text) - .length, - equals(1), - ); - } - }); - - flameTester.test('can open the second page', (game) async { - final display = LeaderboardDisplay(entries: leaderboard); - await game.pump(display); + flameTester.testGameWidget( + 'renders the titles', + setUp: (game, _) async { + await game.onLoad(); + await game.pump(LeaderboardDisplay(entries: const [])); + await game.ready(); + }, + verify: (game, _) async { + final textComponents = + game.descendants().whereType().toList(); + expect(textComponents.length, equals(3)); + expect(textComponents[0].text, equals('rank')); + expect(textComponents[1].text, equals('score')); + expect(textComponents[2].text, equals('name')); + }, + ); - final arrow = game - .descendants() - .whereType() - .where((arrow) => arrow.direction == ArrowIconDirection.right) - .single; + flameTester.testGameWidget( + 'renders the first 5 entries', + setUp: (game, _) async { + await game.onLoad(); + await game.pump(LeaderboardDisplay(entries: leaderboard)); + await game.ready(); + }, + verify: (game, _) async { + for (final text in [ + 'AAA', + 'BBB', + 'CCC', + 'DDD', + 'EEE', + '1st', + '2nd', + '3rd', + '4th', + '5th', + ]) { + expect( + game + .descendants() + .whereType() + .where((textComponent) => textComponent.text == text) + .length, + equals(1), + ); + } + }, + ); - // Tap the arrow - arrow.onTap(); - // Wait for the transition to finish - display.updateTree(5); - await game.ready(); + flameTester.testGameWidget( + 'can open the second page', + setUp: (game, _) async { + await game.onLoad(); + final display = LeaderboardDisplay(entries: leaderboard); + await game.pump(display); + final arrow = game + .descendants() + .whereType() + .where((arrow) => arrow.direction == ArrowIconDirection.right) + .single; - for (final text in [ - 'FFF', - 'GGG', - 'HHH', - 'III', - 'JJJ', - '6th', - '7th', - '8th', - '9th', - '10th', - ]) { - expect( - game - .descendants() - .whereType() - .where((textComponent) => textComponent.text == text) - .length, - equals(1), - ); - } - }); + // Tap the arrow + arrow.onTap(); + // Wait for the transition to finish + game.update(5); + await game.ready(); + }, + verify: (game, _) async { + for (final text in [ + 'FFF', + 'GGG', + 'HHH', + 'III', + 'JJJ', + '6th', + '7th', + '8th', + '9th', + '10th', + ]) { + expect( + game + .descendants() + .whereType() + .where((textComponent) => textComponent.text == text) + .length, + equals(1), + ); + } + }, + ); - flameTester.test( + flameTester.testGameWidget( 'can open the second page and go back to the first', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final display = LeaderboardDisplay(entries: leaderboard); await game.pump(display); - var arrow = game + final arrow = game .descendants() .whereType() .where((arrow) => arrow.direction == ArrowIconDirection.right) @@ -196,9 +213,10 @@ void main() { // Tap the arrow arrow.onTap(); // Wait for the transition to finish - display.updateTree(5); + game.update(5); await game.ready(); - + }, + verify: (game, tester) async { for (final text in [ 'FFF', 'GGG', @@ -221,7 +239,7 @@ void main() { ); } - arrow = game + final arrow = game .descendants() .whereType() .where((arrow) => arrow.direction == ArrowIconDirection.left) @@ -229,9 +247,10 @@ void main() { // Tap the arrow arrow.onTap(); + // Wait for the transition to finish - display.updateTree(5); - await game.ready(); + game.update(5); + await tester.pump(); for (final text in [ 'AAA', diff --git a/test/game/components/backbox/displays/leaderboard_failure_display_test.dart b/test/game/components/backbox/displays/leaderboard_failure_display_test.dart index 8ce4c839..f69c9049 100644 --- a/test/game/components/backbox/displays/leaderboard_failure_display_test.dart +++ b/test/game/components/backbox/displays/leaderboard_failure_display_test.dart @@ -23,7 +23,7 @@ class _TestGame extends Forge2DGame { } Future pump(LeaderboardFailureDisplay component) { - return ensureAdd( + return world.ensureAdd( FlameProvider.value( _MockAppLocalizations(), children: [component], @@ -42,19 +42,25 @@ void main() { group('LeaderboardFailureDisplay', () { final flameTester = FlameTester(_TestGame.new); - flameTester.test('renders correctly', (game) async { - await game.pump(LeaderboardFailureDisplay()); - - expect( - game - .descendants() - .where( - (component) => - component is TextComponent && component.text == 'Message', - ) - .length, - equals(1), - ); - }); + flameTester.testGameWidget( + 'renders correctly', + setUp: (game, _) async { + await game.onLoad(); + await game.pump(LeaderboardFailureDisplay()); + await game.ready(); + }, + verify: (game, _) async { + expect( + game + .descendants() + .where( + (component) => + component is TextComponent && component.text == 'Message', + ) + .length, + equals(1), + ); + }, + ); }); } diff --git a/test/game/components/backbox/displays/loading_display_test.dart b/test/game/components/backbox/displays/loading_display_test.dart index efd84097..2a504549 100644 --- a/test/game/components/backbox/displays/loading_display_test.dart +++ b/test/game/components/backbox/displays/loading_display_test.dart @@ -36,33 +36,41 @@ void main() { group('LoadingDisplay', () { final flameTester = FlameTester(_TestGame.new); - flameTester.test('renders correctly', (game) async { - await game.pump(LoadingDisplay()); - - final component = game.descendants().whereType().first; - expect(component, isNotNull); - expect(component.text, equals('Loading')); - }); - - flameTester.test('use ellipses as animation', (game) async { - await game.pump(LoadingDisplay()); + flameTester.testGameWidget( + 'renders correctly', + setUp: (game, _) async { + await game.pump(LoadingDisplay()); + }, + verify: (game, _) async { + final component = game.descendants().whereType().first; + expect(component, isNotNull); + expect(component.text, equals('Loading')); + }, + ); - final component = game.descendants().whereType().first; - expect(component.text, equals('Loading')); + flameTester.testGameWidget( + 'use ellipses as animation', + setUp: (game, _) async { + await game.pump(LoadingDisplay()); + }, + verify: (game, _) async { + final component = game.descendants().whereType().first; + expect(component.text, equals('Loading')); - final timer = component.firstChild(); + final timer = component.firstChild(); - timer?.update(1.1); - expect(component.text, equals('Loading.')); + timer?.update(1.1); + expect(component.text, equals('Loading.')); - timer?.update(1.1); - expect(component.text, equals('Loading..')); + timer?.update(1.1); + expect(component.text, equals('Loading..')); - timer?.update(1.1); - expect(component.text, equals('Loading...')); + timer?.update(1.1); + expect(component.text, equals('Loading...')); - timer?.update(1.1); - expect(component.text, equals('Loading')); - }); + timer?.update(1.1); + expect(component.text, equals('Loading')); + }, + ); }); } diff --git a/test/game/components/backbox/displays/share_display_test.dart b/test/game/components/backbox/displays/share_display_test.dart index ddcb4001..23b2cba5 100644 --- a/test/game/components/backbox/displays/share_display_test.dart +++ b/test/game/components/backbox/displays/share_display_test.dart @@ -1,7 +1,6 @@ // ignore_for_file: cascade_invocations -import 'package:flame/game.dart'; -import 'package:flame/input.dart'; +import 'package:flame/events.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; @@ -13,7 +12,7 @@ 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 { +class _TestGame extends Forge2DGame with TapCallbacks { @override Future onLoad() async { await super.onLoad(); @@ -52,7 +51,7 @@ class _MockAppLocalizations extends Mock implements AppLocalizations { String get socialMediaAccount => ''; } -class _MockTapUpInfo extends Mock implements TapUpInfo {} +class _MockTapUpEvent extends Mock implements TapUpEvent {} void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -60,46 +59,50 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('ShareDisplay', () { - flameTester.test( + var tapped = false; + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final component = ShareDisplay(); await game.pump(component); - expect(game.descendants(), contains(component)); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); - flameTester.test( + flameTester.testGameWidget( 'calls onShare when Facebook button is tapped', - (game) async { - var tapped = false; - - final tapUpInfo = _MockTapUpInfo(); + setUp: (game, _) async { + tapped = false; final component = ShareDisplay( onShare: (_) => tapped = true, ); await game.pump(component); - + }, + verify: (game, _) async { + final tapUpEvent = _MockTapUpEvent(); + final component = game.descendants().whereType().single; final facebookButton = component.descendants().whereType().first; - facebookButton.onTapUp(tapUpInfo); + facebookButton.onTapUp(tapUpEvent); expect(tapped, isTrue); }, ); - flameTester.test( + flameTester.testGameWidget( 'calls onShare when Twitter button is tapped', - (game) async { - var tapped = false; - - final tapUpInfo = _MockTapUpInfo(); + setUp: (game, _) async { final component = ShareDisplay( onShare: (_) => tapped = true, ); await game.pump(component); - + }, + verify: (game, _) async { + final tapUpInfo = _MockTapUpEvent(); + final component = game.descendants().whereType().single; final twitterButton = component.descendants().whereType().first; diff --git a/test/game/components/bottom_group_test.dart b/test/game/components/bottom_group_test.dart index 832d96d6..87007d00 100644 --- a/test/game/components/bottom_group_test.dart +++ b/test/game/components/bottom_group_test.dart @@ -30,9 +30,10 @@ void main() { group('BottomGroup', () { final flameTester = FlameTester(_TestGame.new); - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bottomGroup = BottomGroup(); await game.ensureAdd( FlameBlocProvider.value( @@ -40,15 +41,18 @@ void main() { children: [bottomGroup], ), ); - - expect(game.descendants(), contains(bottomGroup)); + await game.ready(); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); group('loads', () { - flameTester.test( + flameTester.testGameWidget( 'one left flipper', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bottomGroup = BottomGroup(); await game.ensureAdd( FlameBlocProvider.value( @@ -56,18 +60,26 @@ void main() { children: [bottomGroup], ), ); - - final leftFlippers = - bottomGroup.descendants().whereType().where( - (flipper) => flipper.side.isLeft, - ); + await game.ready(); + }, + verify: (game, _) async { + final leftFlippers = game + .descendants() + .whereType() + .single + .descendants() + .whereType() + .where( + (flipper) => flipper.side.isLeft, + ); expect(leftFlippers.length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( 'one right flipper', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bottomGroup = BottomGroup(); await game.ensureAdd( FlameBlocProvider.value( @@ -75,18 +87,26 @@ void main() { children: [bottomGroup], ), ); - - final rightFlippers = - bottomGroup.descendants().whereType().where( - (flipper) => flipper.side.isRight, - ); + await game.ready(); + }, + verify: (game, _) async { + final rightFlippers = game + .descendants() + .whereType() + .single + .descendants() + .whereType() + .where( + (flipper) => flipper.side.isRight, + ); expect(rightFlippers.length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( 'two Baseboards', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bottomGroup = BottomGroup(); await game.ensureAdd( FlameBlocProvider.value( @@ -94,16 +114,21 @@ void main() { children: [bottomGroup], ), ); - + await game.ready(); + }, + verify: (game, _) async { + final bottomGroup = + game.descendants().whereType().single; final baseBottomGroups = bottomGroup.descendants().whereType(); expect(baseBottomGroups.length, equals(2)); }, ); - flameTester.test( + flameTester.testGameWidget( 'two Kickers', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final bottomGroup = BottomGroup(); await game.ensureAdd( FlameBlocProvider.value( @@ -111,7 +136,11 @@ void main() { children: [bottomGroup], ), ); - + await game.ready(); + }, + verify: (game, _) async { + final bottomGroup = + game.descendants().whereType().single; final kickers = bottomGroup.descendants().whereType(); expect(kickers.length, equals(2)); }, diff --git a/test/game/components/dino_desert/dino_desert_test.dart b/test/game/components/dino_desert/dino_desert_test.dart index 7dea25a3..619331e0 100644 --- a/test/game/components/dino_desert/dino_desert_test.dart +++ b/test/game/components/dino_desert/dino_desert_test.dart @@ -43,17 +43,24 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('DinoDesert', () { - flameTester.test('loads correctly', (game) async { - final component = DinoDesert(); - await game.pump(component); - expect(game.descendants(), contains(component)); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = DinoDesert(); + await game.pump(component); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); group('loads', () { - flameTester.test( + flameTester.testGameWidget( 'a ChromeDino', - (game) async { + setUp: (game, _) async { await game.pump(DinoDesert()); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -61,10 +68,12 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'DinoWalls', - (game) async { + setUp: (game, _) async { await game.pump(DinoDesert()); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -72,10 +81,12 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'Slingshots', - (game) async { + setUp: (game, _) async { await game.pump(DinoDesert()); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -85,11 +96,12 @@ void main() { }); group('adds', () { - flameTester.test( + flameTester.testGameWidget( 'ScoringContactBehavior to ChromeDino', - (game) async { + setUp: (game, _) async { await game.pump(DinoDesert()); - + }, + verify: (game, _) async { final chromeDino = game.descendants().whereType().single; expect( chromeDino.firstChild(), @@ -98,14 +110,19 @@ void main() { }, ); - flameTester.test('a ChromeDinoBonusBehavior', (game) async { - final component = DinoDesert(); - await game.pump(component); - expect( - component.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a ChromeDinoBonusBehavior', + setUp: (game, _) async { + await game.pump(DinoDesert()); + }, + verify: (game, _) async { + final chromeDino = game.descendants().whereType().single; + expect( + chromeDino.children.whereType().single, + isNotNull, + ); + }, + ); }); }); } diff --git a/test/game/components/drain/behaviors/draining_behavior_test.dart b/test/game/components/drain/behaviors/draining_behavior_test.dart index d25a7da6..c91697e5 100644 --- a/test/game/components/drain/behaviors/draining_behavior_test.dart +++ b/test/game/components/drain/behaviors/draining_behavior_test.dart @@ -46,14 +46,22 @@ void main() { expect(DrainingBehavior(), isA()); }); - flameTester.test( + flameTester.testGameWidget( 'loads', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final parent = Drain.test(); final behavior = DrainingBehavior(); await parent.add(behavior); await game.ensureAdd(parent); - expect(parent.contains(behavior), isTrue); + await game.ready(); + }, + verify: (game, _) async { + final parent = game.descendants().whereType().single; + expect( + parent.descendants().whereType(), + isNotEmpty, + ); }, ); @@ -66,9 +74,10 @@ void main() { final flameBlocTester = FlameTester(_TestGame.new); - flameBlocTester.test( + flameBlocTester.testGameWidget( 'adds RoundLost when no balls left', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final drain = Drain.test(); final behavior = DrainingBehavior(); final ball = Ball.test(); @@ -81,15 +90,17 @@ void main() { behavior.beginContact(ball, _MockContact()); await game.ready(); - + }, + verify: (game, _) async { expect(game.descendants().whereType(), isEmpty); verify(() => gameBloc.add(const RoundLost())).called(1); }, ); - flameBlocTester.test( + flameBlocTester.testGameWidget( "doesn't add RoundLost when there are balls left", - (game) async { + setUp: (game, _) async { + await game.onLoad(); final drain = Drain.test(); final behavior = DrainingBehavior(); final ball1 = Ball.test(); @@ -103,15 +114,17 @@ void main() { behavior.beginContact(ball1, _MockContact()); await game.ready(); - + }, + verify: (game, _) async { expect(game.descendants().whereType(), isNotEmpty); verifyNever(() => gameBloc.add(const RoundLost())); }, ); - flameBlocTester.test( + flameBlocTester.testGameWidget( 'removes the Ball', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final drain = Drain.test(); final behavior = DrainingBehavior(); final ball = Ball.test(); @@ -124,7 +137,8 @@ void main() { behavior.beginContact(ball, _MockContact()); await game.ready(); - + }, + verify: (game, _) async { expect(game.descendants().whereType(), isEmpty); }, ); diff --git a/test/game/components/drain/drain_test.dart b/test/game/components/drain/drain_test.dart index b10c55e3..fc2f4730 100644 --- a/test/game/components/drain/drain_test.dart +++ b/test/game/components/drain/drain_test.dart @@ -11,29 +11,37 @@ void main() { final flameTester = FlameTester(Forge2DGame.new); group('Drain', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final drain = Drain(); await game.ensureAdd(drain); - expect(game.contains(drain), isTrue); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); - flameTester.test( + flameTester.testGameWidget( 'body is static', - (game) async { + setUp: (game, _) async { final drain = Drain(); await game.ensureAdd(drain); + }, + verify: (game, _) async { + final drain = game.descendants().whereType().single; expect(drain.body.bodyType, equals(BodyType.static)); }, ); - flameTester.test( + flameTester.testGameWidget( 'is sensor', - (game) async { + setUp: (game, _) async { final drain = Drain(); await game.ensureAdd(drain); + }, + verify: (game, _) async { + final drain = game.descendants().whereType().single; expect(drain.body.fixtures.first.isSensor, isTrue); }, ); diff --git a/test/game/components/flutter_forest/behaviors/flutter_forest_bonus_behavior_test.dart b/test/game/components/flutter_forest/behaviors/flutter_forest_bonus_behavior_test.dart index 8c59a62c..e3f9809a 100644 --- a/test/game/components/flutter_forest/behaviors/flutter_forest_bonus_behavior_test.dart +++ b/test/game/components/flutter_forest/behaviors/flutter_forest_bonus_behavior_test.dart @@ -77,6 +77,7 @@ void main() { 'adds GameBonus.dashNest to the game ' 'when signpost becomes fully activated', setUp: (game, tester) async { + await game.onLoad(); final behavior = FlutterForestBonusBehavior(); final parent = FlutterForest.test(); final signpostBloc = _MockSignpostCubit(); @@ -94,6 +95,7 @@ void main() { signpostBloc: signpostBloc, ); await parent.ensureAdd(behavior); + await game.ready(); streamController.add(SignpostState.active3); await tester.pump(); @@ -108,6 +110,7 @@ void main() { 'calls onProgressed and onReset ' 'when signpost becomes fully activated', setUp: (game, tester) async { + await game.onLoad(); final behavior = FlutterForestBonusBehavior(); final parent = FlutterForest.test(); final dashBumpersBloc = _MockDashBumpersCubit(); @@ -127,6 +130,7 @@ void main() { dashBumpersBloc: dashBumpersBloc, ); await parent.ensureAdd(behavior); + await game.ready(); streamController.add(SignpostState.active3); await tester.pump(); @@ -140,6 +144,7 @@ void main() { 'adds BonusBallSpawningBehavior to the game ' 'when signpost becomes fully activated', setUp: (game, tester) async { + await game.onLoad(); final behavior = FlutterForestBonusBehavior(); final parent = FlutterForest.test(); final signpostBloc = _MockSignpostCubit(); @@ -157,10 +162,9 @@ void main() { signpostBloc: signpostBloc, ); await parent.ensureAdd(behavior); - streamController.add(SignpostState.active3); - await tester.pump(); await game.ready(); + await tester.pump(); expect( game.descendants().whereType().length, diff --git a/test/game/components/flutter_forest/flutter_forest_test.dart b/test/game/components/flutter_forest/flutter_forest_test.dart index ae5d86ee..f07ffbc4 100644 --- a/test/game/components/flutter_forest/flutter_forest_test.dart +++ b/test/game/components/flutter_forest/flutter_forest_test.dart @@ -56,21 +56,27 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('FlutterForest', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final component = FlutterForest(); await game.pump(component); - expect(game.descendants(), contains(component)); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); group('loads', () { - flameTester.test( + flameTester.testGameWidget( 'a Signpost', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final component = FlutterForest(); await game.pump(component); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -78,11 +84,14 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'a DashAnimatronic', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final component = FlutterForest(); await game.pump(component); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -90,11 +99,14 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'three DashBumper', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final component = FlutterForest(); await game.pump(component); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(3), @@ -102,11 +114,14 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'three DashBumpers with BumperNoiseBehavior', - (game) async { + setUp: (game, _) async { + await game.onLoad(); final component = FlutterForest(); await game.pump(component); + }, + verify: (game, _) async { final bumpers = game.descendants().whereType(); for (final bumper in bumpers) { expect( diff --git a/test/game/components/game_bloc_status_listener_test.dart b/test/game/components/game_bloc_status_listener_test.dart index 05d70ad0..e542c5f6 100644 --- a/test/game/components/game_bloc_status_listener_test.dart +++ b/test/game/components/game_bloc_status_listener_test.dart @@ -1,7 +1,8 @@ // ignore_for_file: cascade_invocations +import 'package:bloc_test/bloc_test.dart'; import 'package:flame/components.dart'; -import 'package:flame/game.dart'; +import 'package:flame/events.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; @@ -15,10 +16,11 @@ import 'package:pinball_audio/pinball_audio.dart'; import 'package:pinball_components/pinball_components.dart'; import 'package:pinball_flame/pinball_flame.dart'; 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:share_repository/share_repository.dart'; -class _TestGame extends Forge2DGame with HasTappables { +class _TestGame extends Forge2DGame with TapCallbacks { @override Future onLoad() async { images.prefix = ''; @@ -40,6 +42,15 @@ class _TestGame extends Forge2DGame with HasTappables { DashBumpersCubit? dashBumpersBloc, SignpostCubit? signpostBloc, }) async { + overlays.addEntry( + 'mobile_controls', + (context, game) { + return PinballButton( + text: 'enter', + onTap: () => {}, + ); + }, + ); return ensureAdd( FlameMultiBlocProvider( providers: [ @@ -82,8 +93,8 @@ class _TestGame extends Forge2DGame with HasTappables { class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} -class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { -} +class _MockLeaderboardRepository extends Mock + implements LeaderboardRepository {} class _MockShareRepository extends Mock implements ShareRepository {} @@ -139,12 +150,17 @@ void main() { final flameTester = FlameTester(_TestGame.new); - flameTester.test( + flameTester.testGameWidget( 'can be loaded', - (game) async { + setUp: (game, _) async { final component = GameBlocStatusListener(); await game.pump([component]); - expect(game.descendants(), contains(component)); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); }, ); @@ -177,9 +193,9 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'changes the backbox display', - (game) async { + setUp: (game, _) async { final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); final shareRepository = _MockShareRepository(); @@ -190,14 +206,17 @@ void main() { ); await game.pump([component, backbox]); - + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; expect(() => component.onNewState(state), returnsNormally); }, ); - flameTester.test( + flameTester.testGameWidget( 'removes FlipperKeyControllingBehavior from Flipper', - (game) async { + setUp: (game, _) async { final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); final shareRepository = _MockShareRepository(); @@ -220,7 +239,9 @@ void main() { expect(state.status, GameStatus.gameOver); component.onNewState(state); await game.ready(); - + }, + verify: (game, _) async { + final flipper = game.descendants().whereType().single; expect( flipper.children.whereType(), isEmpty, @@ -228,9 +249,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'removes PlungerKeyControllingBehavior from Plunger', - (game) async { + setUp: (game, _) async { final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); final shareRepository = _MockShareRepository(); @@ -254,6 +275,9 @@ void main() { expect(state.status, GameStatus.gameOver); component.onNewState(state); await game.ready(); + }, + verify: (game, _) async { + final plunger = game.descendants().whereType().single; expect( plunger.children.whereType(), @@ -262,9 +286,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'removes PlungerPullingBehavior from Plunger', - (game) async { + setUp: (game, _) async { final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); final shareRepository = _MockShareRepository(); @@ -283,7 +307,7 @@ void main() { create: PlungerCubit.new, children: [ PlungerPullingBehavior(strength: 0), - PlungerAutoPullingBehavior() + PlungerAutoPullingBehavior(), ], ), ); @@ -291,7 +315,9 @@ void main() { expect(state.status, GameStatus.gameOver); component.onNewState(state); await game.ready(); - + }, + verify: (game, _) async { + final plunger = game.descendants().whereType().single; expect( plunger.children.whereType(), isEmpty, @@ -299,9 +325,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'plays the game over voice over', - (game) async { + setUp: (game, _) async { final audioPlayer = _MockPinballAudioPlayer(); final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); @@ -315,6 +341,15 @@ void main() { [component, backbox], pinballAudioPlayer: audioPlayer, ); + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; + final audioPlayer = game + .descendants() + .whereType>() + .single + .provider; component.onNewState(state); @@ -336,16 +371,24 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'plays the background music on start', - (game) async { + setUp: (game, _) async { final audioPlayer = _MockPinballAudioPlayer(); final component = GameBlocStatusListener(); await game.pump( [component], pinballAudioPlayer: audioPlayer, ); - + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; + final audioPlayer = game + .descendants() + .whereType>() + .single + .provider; expect(state.status, equals(GameStatus.playing)); component.onNewState(state); @@ -357,16 +400,25 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'resets the GoogleWordCubit', - (game) async { + setUp: (game, _) async { final googleWordBloc = _MockGoogleWordCubit(); final component = GameBlocStatusListener(); await game.pump( [component], googleWordBloc: googleWordBloc, ); - + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; + final googleWordBloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; expect(state.status, equals(GameStatus.playing)); component.onNewState(state); @@ -374,15 +426,25 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'resets the DashBumpersCubit', - (game) async { + setUp: (game, _) async { final dashBumpersBloc = _MockDashBumpersCubit(); final component = GameBlocStatusListener(); await game.pump( [component], dashBumpersBloc: dashBumpersBloc, ); + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; + final dashBumpersBloc = game + .descendants() + .whereType< + FlameBlocProvider>() + .single + .bloc; expect(state.status, equals(GameStatus.playing)); component.onNewState(state); @@ -391,13 +453,21 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'resets the SignpostCubit', - (game) async { + setUp: (game, _) async { final signpostBloc = _MockSignpostCubit(); final component = GameBlocStatusListener(); await game.pump([component], signpostBloc: signpostBloc); - + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; + final signpostBloc = game + .descendants() + .whereType>() + .single + .bloc; expect(state.status, equals(GameStatus.playing)); component.onNewState(state); @@ -405,9 +475,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds FlipperKeyControllingBehavior to Flippers', - (game) async { + setUp: (game, _) async { final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); final shareRepository = _MockShareRepository(); @@ -427,7 +497,9 @@ void main() { component.onNewState(state); await game.ready(); - + }, + verify: (game, _) async { + final flipper = game.descendants().whereType().single; expect( flipper .descendants() @@ -438,9 +510,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds PlungerKeyControllingBehavior to Plunger', - (game) async { + setUp: (game, _) async { final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); final shareRepository = _MockShareRepository(); @@ -450,10 +522,16 @@ void main() { entries: const [], ); final plunger = Plunger.test(); + final bloc = _MockPlungerCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: PlungerState.releasing, + ); await game.pump([component, backbox, plunger]); await plunger.ensureAdd( - FlameBlocProvider( - create: _MockPlungerCubit.new, + FlameBlocProvider.value( + value: bloc, ), ); @@ -461,7 +539,9 @@ void main() { component.onNewState(state); await game.ready(); - + }, + verify: (game, _) async { + final plunger = game.descendants().whereType().single; expect( plunger .descendants() @@ -472,9 +552,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds PlungerPullingBehavior to Plunger', - (game) async { + setUp: (game, _) async { final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); final shareRepository = _MockShareRepository(); @@ -484,10 +564,16 @@ void main() { entries: const [], ); final plunger = Plunger.test(); + final bloc = _MockPlungerCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: PlungerState.releasing, + ); await game.pump([component, backbox, plunger]); await plunger.ensureAdd( - FlameBlocProvider( - create: _MockPlungerCubit.new, + FlameBlocProvider.value( + value: bloc, ), ); @@ -495,7 +581,9 @@ void main() { component.onNewState(state); await game.ready(); - + }, + verify: (game, _) async { + final plunger = game.descendants().whereType().single; expect( plunger.descendants().whereType().length, equals(1), @@ -503,9 +591,9 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'adds PlungerAutoPullingBehavior to Plunger', - (game) async { + setUp: (game, _) async { final component = GameBlocStatusListener(); final leaderboardRepository = _MockLeaderboardRepository(); final shareRepository = _MockShareRepository(); @@ -514,11 +602,17 @@ void main() { shareRepository: shareRepository, entries: const [], ); + final bloc = _MockPlungerCubit(); + whenListen( + bloc, + const Stream.empty(), + initialState: PlungerState.releasing, + ); final plunger = Plunger.test(); await game.pump([component, backbox, plunger]); await plunger.ensureAdd( - FlameBlocProvider( - create: _MockPlungerCubit.new, + FlameBlocProvider.value( + value: bloc, ), ); @@ -526,7 +620,9 @@ void main() { component.onNewState(state); await game.ready(); - + }, + verify: (game, _) async { + final plunger = game.descendants().whereType().single; expect( plunger .descendants() diff --git a/test/game/components/google_gallery/google_gallery_test.dart b/test/game/components/google_gallery/google_gallery_test.dart index 719be2dc..d27dc5ab 100644 --- a/test/game/components/google_gallery/google_gallery_test.dart +++ b/test/game/components/google_gallery/google_gallery_test.dart @@ -52,17 +52,24 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('GoogleGallery', () { - flameTester.test('loads correctly', (game) async { - final component = GoogleGallery(); - await game.pump(component); - expect(game.descendants(), contains(component)); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = GoogleGallery(); + await game.pump(component); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); + }, + ); group('loads', () { - flameTester.test( + flameTester.testGameWidget( 'two GoogleRollovers', - (game) async { + setUp: (game, _) async { await game.pump(GoogleGallery()); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(2), @@ -70,10 +77,12 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'a GoogleWord', - (game) async { + setUp: (game, _) async { await game.pump(GoogleGallery()); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -83,11 +92,12 @@ void main() { }); group('adds', () { - flameTester.test( + flameTester.testGameWidget( 'ScoringContactBehavior to GoogleRollovers', - (game) async { + setUp: (game, _) async { await game.pump(GoogleGallery()); - + }, + verify: (game, _) async { game.descendants().whereType().forEach( (rollover) => expect( rollover.firstChild(), @@ -97,11 +107,12 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'RolloverNoiseBehavior to GoogleRollovers', - (game) async { + setUp: (game, _) async { await game.pump(GoogleGallery()); - + }, + verify: (game, _) async { game.descendants().whereType().forEach( (rollover) => expect( rollover.firstChild(), @@ -111,14 +122,20 @@ void main() { }, ); - flameTester.test('a GoogleWordBonusBehavior', (game) async { - final component = GoogleGallery(); - await game.pump(component); - expect( - component.descendants().whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a GoogleWordBonusBehavior', + setUp: (game, _) async { + await game.pump(GoogleGallery()); + }, + verify: (game, _) async { + final component = + game.descendants().whereType().single; + expect( + component.descendants().whereType().single, + isNotNull, + ); + }, + ); }); }); } diff --git a/test/game/components/launcher_test.dart b/test/game/components/launcher_test.dart index 35272569..fe9ffff9 100644 --- a/test/game/components/launcher_test.dart +++ b/test/game/components/launcher_test.dart @@ -38,58 +38,73 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('Launcher', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final component = Launcher(); await game.pump(component); - expect(game.descendants(), contains(component)); + }, + verify: (game, _) async { + expect(game.descendants().whereType().length, equals(1)); }, ); group('loads', () { - flameTester.test( + flameTester.testGameWidget( 'a LaunchRamp', - (game) async { + setUp: (game, _) async { final component = Launcher(); await game.pump(component); - - final descendantsQuery = - component.descendants().whereType(); + }, + verify: (game, _) async { + final descendantsQuery = game + .descendants() + .whereType() + .single + .descendants() + .whereType(); expect(descendantsQuery.length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( 'a Flapper', - (game) async { + setUp: (game, _) async { final component = Launcher(); await game.pump(component); - - final descendantsQuery = component.descendants().whereType(); + }, + verify: (game, _) async { + final launcher = game.descendants().whereType().single; + final descendantsQuery = launcher.descendants().whereType(); expect(descendantsQuery.length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( 'a Plunger', - (game) async { + setUp: (game, _) async { final component = Launcher(); await game.pump(component); + }, + verify: (game, _) async { + final launcher = game.descendants().whereType().single; - final descendantsQuery = component.descendants().whereType(); + final descendantsQuery = launcher.descendants().whereType(); expect(descendantsQuery.length, equals(1)); }, ); - flameTester.test( + flameTester.testGameWidget( 'a RocketSpriteComponent', - (game) async { + setUp: (game, _) async { final component = Launcher(); await game.pump(component); + }, + verify: (game, _) async { + final launcher = game.descendants().whereType().single; final descendantsQuery = - component.descendants().whereType(); + launcher.descendants().whereType(); expect(descendantsQuery.length, equals(1)); }, ); diff --git a/test/game/components/multiballs/behaviors/multiballs_behavior_test.dart b/test/game/components/multiballs/behaviors/multiballs_behavior_test.dart index af77ef32..ac9cd47b 100644 --- a/test/game/components/multiballs/behaviors/multiballs_behavior_test.dart +++ b/test/game/components/multiballs/behaviors/multiballs_behavior_test.dart @@ -49,14 +49,17 @@ void main() { ); }); - flameTester.test( + flameTester.testGameWidget( 'can be loaded', - (game) async { + setUp: (game, _) async { final parent = Multiballs.test(); final behavior = MultiballsBehavior(); await game.pump(parent); await parent.ensureAdd(behavior); - expect(parent.children, contains(behavior)); + }, + verify: (game, _) async { + final parent = game.descendants().whereType().single; + expect(parent.children.whereType(), isNotEmpty); }, ); diff --git a/test/game/components/multiballs/multiballs_test.dart b/test/game/components/multiballs/multiballs_test.dart index da736c27..f7bc308c 100644 --- a/test/game/components/multiballs/multiballs_test.dart +++ b/test/game/components/multiballs/multiballs_test.dart @@ -47,11 +47,14 @@ void main() { }, ); - flameBlocTester.test( + flameBlocTester.testGameWidget( 'loads four Multiball', - (game) async { + setUp: (game, _) async { final multiballs = Multiballs(); await game.pump(multiballs); + }, + verify: (game, _) async { + final multiballs = game.descendants().whereType().single; expect( multiballs.descendants().whereType().length, equals(4), diff --git a/test/game/components/multipliers/multipliers_test.dart b/test/game/components/multipliers/multipliers_test.dart index 7f98058e..7cef245d 100644 --- a/test/game/components/multipliers/multipliers_test.dart +++ b/test/game/components/multipliers/multipliers_test.dart @@ -41,20 +41,26 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('Multipliers', () { - flameTester.test( + flameTester.testGameWidget( 'loads correctly', - (game) async { + setUp: (game, _) async { final component = Multipliers(); await game.pump(component); - expect(game.descendants(), contains(component)); + }, + verify: (game, _) async { + expect(game.descendants().whereType(), isNotEmpty); }, ); - flameTester.test( + flameTester.testGameWidget( 'loads five Multiplier', - (game) async { + setUp: (game, _) async { final multipliersGroup = Multipliers(); await game.pump(multipliersGroup); + }, + verify: (game, _) async { + final multipliersGroup = + game.descendants().whereType().single; expect( multipliersGroup.descendants().whereType().length, equals(5), diff --git a/test/game/components/sparky_scorch/sparky_scorch_test.dart b/test/game/components/sparky_scorch/sparky_scorch_test.dart index 0cd7b806..e847b0d8 100644 --- a/test/game/components/sparky_scorch/sparky_scorch_test.dart +++ b/test/game/components/sparky_scorch/sparky_scorch_test.dart @@ -43,20 +43,27 @@ void main() { final flameTester = FlameTester(_TestGame.new); group('SparkyScorch', () { - flameTester.test('loads correctly', (game) async { - final component = SparkyScorch(); - await game.pump(component); - expect( - game.descendants().whereType().length, - equals(1), - ); - }); + flameTester.testGameWidget( + 'loads correctly', + setUp: (game, _) async { + final component = SparkyScorch(); + await game.pump(component); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); group('loads', () { - flameTester.test( + flameTester.testGameWidget( 'a SparkyComputer', - (game) async { + setUp: (game, _) async { await game.pump(SparkyScorch()); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -64,10 +71,12 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'a SparkyAnimatronic', - (game) async { + setUp: (game, _) async { await game.pump(SparkyScorch()); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -75,10 +84,12 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'three SparkyBumper', - (game) async { + setUp: (game, _) async { await game.pump(SparkyScorch()); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(3), @@ -86,10 +97,12 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'three SparkyBumpers with BumperNoiseBehavior', - (game) async { + setUp: (game, _) async { await game.pump(SparkyScorch()); + }, + verify: (game, _) async { final bumpers = game.descendants().whereType(); for (final bumper in bumpers) { expect( @@ -102,11 +115,12 @@ void main() { }); group('adds', () { - flameTester.test( + flameTester.testGameWidget( 'ScoringContactBehavior to SparkyComputer', - (game) async { + setUp: (game, _) async { await game.pump(SparkyScorch()); - + }, + verify: (game, _) async { final sparkyComputer = game.descendants().whereType().single; expect( @@ -116,14 +130,23 @@ void main() { }, ); - flameTester.test('a SparkyComputerBonusBehavior', (game) async { - final sparkyScorch = SparkyScorch(); - await game.pump(sparkyScorch); - expect( - sparkyScorch.children.whereType().single, - isNotNull, - ); - }); + flameTester.testGameWidget( + 'a SparkyComputerBonusBehavior', + setUp: (game, _) async { + final sparkyScorch = SparkyScorch(); + await game.pump(sparkyScorch); + }, + verify: (game, _) async { + final sparkyScorch = + game.descendants().whereType().single; + expect( + sparkyScorch.children + .whereType() + .single, + isNotNull, + ); + }, + ); }); }); } diff --git a/test/game/pinball_game_test.dart b/test/game/pinball_game_test.dart index 92608a1d..1a4e5875 100644 --- a/test/game/pinball_game_test.dart +++ b/test/game/pinball_game_test.dart @@ -1,18 +1,17 @@ // ignore_for_file: cascade_invocations -import 'dart:ui'; - import 'package:bloc_test/bloc_test.dart'; import 'package:flame/components.dart'; -import 'package:flame/input.dart'; +import 'package:flame/src/gestures/events.dart'; import 'package:flame_bloc/flame_bloc.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:leaderboard_repository/src/leaderboard_repository.dart'; +import 'package:leaderboard_repository/leaderboard_repository.dart'; import 'package:mocktail/mocktail.dart'; import 'package:pinball/game/behaviors/behaviors.dart'; +import 'package:pinball/game/components/backbox/displays/displays.dart'; import 'package:pinball/game/game.dart'; import 'package:pinball/select_character/select_character.dart'; import 'package:pinball_audio/src/pinball_audio.dart'; @@ -32,12 +31,10 @@ class _TestPinballGame extends PinballGame { platformHelper: _MockPlatformHelper(), ); - @override - Future onLoad() async { + Future preLoad() async { images.prefix = ''; final futures = preLoadAssets().map((loadableBuilder) => loadableBuilder()); await Future.wait(futures); - await super.onLoad(); } } @@ -53,12 +50,10 @@ class _TestDebugPinballGame extends DebugPinballGame { platformHelper: _MockPlatformHelper(), ); - @override - Future onLoad() async { + Future preLoad() async { images.prefix = ''; final futures = preLoadAssets().map((loadableBuilder) => loadableBuilder()); await Future.wait(futures); - await super.onLoad(); } } @@ -67,6 +62,15 @@ class _MockGameBloc extends Mock implements GameBloc {} class _MockAppLocalizations extends Mock implements AppLocalizations { @override String get leaderboardErrorMessage => ''; + + @override + String get rank => 'rank'; + + @override + String get score => 'score'; + + @override + String get name => 'name'; } class _MockEventPosition extends Mock implements EventPosition {} @@ -85,8 +89,8 @@ class _MockDragUpdateInfo extends Mock implements DragUpdateInfo {} class _MockDragEndInfo extends Mock implements DragEndInfo {} -class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { -} +class _MockLeaderboardRepository extends Mock + implements LeaderboardRepository {} class _MockShareRepository extends Mock implements ShareRepository {} @@ -115,10 +119,13 @@ void main() { final flameTester = FlameTester(_TestPinballGame.new); group('components', () { - flameTester.test( + flameTester.testGameWidget( 'has only one BallSpawningBehavior', - (game) async { + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -126,10 +133,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'has only one CharacterSelectionBehavior', - (game) async { + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -137,10 +147,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'has only one Drain', - (game) async { + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -148,10 +161,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'has only one BottomGroup', - (game) async { + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -159,10 +175,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'has only one Launcher', - (game) async { + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -170,10 +189,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'has one FlutterForest', - (game) async { + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -181,10 +203,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'has only one Multiballs', - (game) async { + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -192,10 +217,13 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'one GoogleGallery', - (game) async { + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { expect( game.descendants().whereType().length, equals(1), @@ -203,242 +231,305 @@ void main() { }, ); - flameTester.test('one SkillShot', (game) async { - await game.ready(); - expect( - game.descendants().whereType().length, - equals(1), - ); - }); - flameTester.testGameWidget( - 'paints sprites with FilterQuality.medium', - setUp: (game, tester) async { - game.images.prefix = ''; - final futures = - game.preLoadAssets().map((loadableBuilder) => loadableBuilder()); - await Future.wait(futures); - + 'one SkillShot', + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { + expect( + game.descendants().whereType().length, + equals(1), + ); + }, + ); - final descendants = game.descendants(); - final components = [ - ...descendants.whereType(), - ...descendants.whereType(), + flameTester.testGameWidget( + 'creates initial leaderboard if there are entries.', + setUp: (game, _) async { + final top10Scores = [ + 2500, + 2200, + 2200, + 2000, + 1800, + 1400, + 1300, + 1000, + 600, + 300, + 100, ]; - expect(components, isNotEmpty); + final top10Leaderboard = top10Scores + .map( + (score) => LeaderboardEntryData( + playerInitials: 'user$score', + score: score, + character: CharacterType.dash, + ), + ) + .toList(); + when(game.leaderboardRepository.fetchTop10Leaderboard) + .thenAnswer((_) async => top10Leaderboard); + await game.preFetchLeaderboard(); + await game.preLoad(); + await game.onLoad(); + await game.ready(); + }, + verify: (game, _) async { expect( - components.whereType().length, - equals(components.length), + game + .descendants() + .whereType() + .single + .descendants() + .whereType() + .length, + equals(18), ); + }, + ); - await tester.pump(); - - for (final component in components) { - if (component is! HasPaint) return; - expect( - component.paint.filterQuality, - equals(FilterQuality.medium), - ); - } + flameTester.testGameWidget( + 'creates empty leaderboard if there is an error loading.', + setUp: (game, _) async { + when(game.leaderboardRepository.fetchTop10Leaderboard) + .thenThrow(Exception()); + await game.preFetchLeaderboard(); + await game.preLoad(); + await game.onLoad(); + await game.ready(); + }, + verify: (game, _) async { + expect( + game.descendants().whereType(), + isEmpty, + ); }, ); }); group('flipper control', () { - flameTester.test('tap control only works if game is playing', - (game) async { - await game.ready(); + flameTester.testGameWidget( + 'tap control only works if game is playing', + setUp: (game, _) async { + await game.preLoad(); + await game.ready(); + }, + verify: (game, _) async { + final gameBloc = game + .descendants() + .whereType>() + .first + .bloc; - final gameBloc = game - .descendants() - .whereType>() - .first - .bloc; + final eventPosition = _MockEventPosition(); + when(() => eventPosition.global).thenReturn(Vector2.zero()); + when(() => eventPosition.widget).thenReturn(Vector2.zero()); - final eventPosition = _MockEventPosition(); - when(() => eventPosition.game).thenReturn(Vector2.zero()); - when(() => eventPosition.widget).thenReturn(Vector2.zero()); + final raw = _MockTapDownDetails(); + when(() => raw.kind).thenReturn(PointerDeviceKind.touch); - final raw = _MockTapDownDetails(); - when(() => raw.kind).thenReturn(PointerDeviceKind.touch); + final tapDownEvent = _MockTapDownInfo(); + when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); + when(() => tapDownEvent.raw).thenReturn(raw); - final tapDownEvent = _MockTapDownInfo(); - when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); - when(() => tapDownEvent.raw).thenReturn(raw); + final flipperBloc = game + .descendants() + .whereType() + .where((flipper) => flipper.side == BoardSide.left) + .single + .descendants() + .whereType>() + .first + .bloc; - final flipperBloc = game - .descendants() - .whereType() - .where((flipper) => flipper.side == BoardSide.left) - .single - .descendants() - .whereType>() - .first - .bloc; + gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.gameOver)); - gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.gameOver)); + game.onTapDown(0, tapDownEvent); + game.update(0); + expect(flipperBloc.state, FlipperState.movingDown); - game.onTapDown(0, tapDownEvent); - await Future.delayed(Duration.zero); - expect(flipperBloc.state, FlipperState.movingDown); + gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); - gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); + game.onTapDown(0, tapDownEvent); + game.update(0); + expect(flipperBloc.state, FlipperState.movingUp); + }, + ); - game.onTapDown(0, tapDownEvent); - await Future.delayed(Duration.zero); - expect(flipperBloc.state, FlipperState.movingUp); - }); + flameTester.testGameWidget( + 'tap down moves left flipper up', + setUp: (game, _) async { + await game.preLoad(); + await game.ready(); + }, + verify: (game, _) async { + final gameBloc = game + .descendants() + .whereType>() + .first + .bloc; - flameTester.test('tap down moves left flipper up', (game) async { - await game.ready(); + gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); - final gameBloc = game - .descendants() - .whereType>() - .first - .bloc; + final eventPosition = _MockEventPosition(); + when(() => eventPosition.global).thenReturn(Vector2.zero()); + when(() => eventPosition.widget).thenReturn(Vector2.zero()); - gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); + final raw = _MockTapDownDetails(); + when(() => raw.kind).thenReturn(PointerDeviceKind.touch); - final eventPosition = _MockEventPosition(); - when(() => eventPosition.game).thenReturn(Vector2.zero()); - when(() => eventPosition.widget).thenReturn(Vector2.zero()); - - final raw = _MockTapDownDetails(); - when(() => raw.kind).thenReturn(PointerDeviceKind.touch); - - final tapDownEvent = _MockTapDownInfo(); - when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); - when(() => tapDownEvent.raw).thenReturn(raw); - - game.onTapDown(0, tapDownEvent); - await Future.delayed(Duration.zero); - - final flipperBloc = game - .descendants() - .whereType() - .where((flipper) => flipper.side == BoardSide.left) - .single - .descendants() - .whereType>() - .first - .bloc; - expect(flipperBloc.state, FlipperState.movingUp); - }); - - flameTester.test('tap down moves right flipper up', (game) async { - await game.ready(); + final tapDownEvent = _MockTapDownInfo(); + when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); + when(() => tapDownEvent.raw).thenReturn(raw); - final gameBloc = game - .descendants() - .whereType>() - .first - .bloc; + game.onTapDown(0, tapDownEvent); + game.update(0); - gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); + final flipperBloc = game + .descendants() + .whereType() + .where((flipper) => flipper.side == BoardSide.left) + .single + .descendants() + .whereType>() + .first + .bloc; + expect(flipperBloc.state, FlipperState.movingUp); + }, + ); - final eventPosition = _MockEventPosition(); - when(() => eventPosition.game).thenReturn(Vector2.zero()); - when(() => eventPosition.widget).thenReturn(game.canvasSize); - - final raw = _MockTapDownDetails(); - when(() => raw.kind).thenReturn(PointerDeviceKind.touch); - - final tapDownEvent = _MockTapDownInfo(); - when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); - when(() => tapDownEvent.raw).thenReturn(raw); - - game.onTapDown(0, tapDownEvent); - final flipperBloc = game - .descendants() - .whereType() - .where((flipper) => flipper.side == BoardSide.right) - .single - .descendants() - .whereType>() - .first - .bloc; - - await Future.delayed(Duration.zero); - expect(flipperBloc.state, FlipperState.movingUp); - }); - - flameTester.test('tap up moves flipper down', (game) async { - await game.ready(); + flameTester.testGameWidget( + 'tap down moves right flipper up', + setUp: (game, _) async { + await game.preLoad(); + await game.ready(); + }, + verify: (game, _) async { + final gameBloc = game + .descendants() + .whereType>() + .first + .bloc; - final gameBloc = game - .descendants() - .whereType>() - .first - .bloc; + gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); - gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); + final eventPosition = _MockEventPosition(); + when(() => eventPosition.global).thenReturn(Vector2.zero()); + when(() => eventPosition.widget).thenReturn(game.canvasSize); - final eventPosition = _MockEventPosition(); - when(() => eventPosition.game).thenReturn(Vector2.zero()); - when(() => eventPosition.widget).thenReturn(Vector2.zero()); + final raw = _MockTapDownDetails(); + when(() => raw.kind).thenReturn(PointerDeviceKind.touch); - final tapUpEvent = _MockTapUpInfo(); - when(() => tapUpEvent.eventPosition).thenReturn(eventPosition); + final tapDownEvent = _MockTapDownInfo(); + when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); + when(() => tapDownEvent.raw).thenReturn(raw); - game.onTapUp(0, tapUpEvent); - await game.ready(); + game.onTapDown(0, tapDownEvent); + final flipperBloc = game + .descendants() + .whereType() + .where((flipper) => flipper.side == BoardSide.right) + .single + .descendants() + .whereType>() + .first + .bloc; - final flipperBloc = game - .descendants() - .whereType() - .where((flipper) => flipper.side == BoardSide.left) - .single - .descendants() - .whereType>() - .first - .bloc; - expect(flipperBloc.state, FlipperState.movingDown); - }); - - flameTester.test('tap cancel moves flipper down', (game) async { - await game.ready(); + game.update(0); + expect(flipperBloc.state, FlipperState.movingUp); + }, + ); - final gameBloc = game - .descendants() - .whereType>() - .first - .bloc; + flameTester.testGameWidget( + 'tap up moves flipper down', + setUp: (game, _) async { + await game.preLoad(); + await game.ready(); + }, + verify: (game, _) async { + final gameBloc = game + .descendants() + .whereType>() + .first + .bloc; - gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); + gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); - final eventPosition = _MockEventPosition(); - when(() => eventPosition.game).thenReturn(Vector2.zero()); - when(() => eventPosition.widget).thenReturn(Vector2.zero()); - - final raw = _MockTapDownDetails(); - when(() => raw.kind).thenReturn(PointerDeviceKind.touch); - - final tapDownEvent = _MockTapDownInfo(); - when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); - when(() => tapDownEvent.raw).thenReturn(raw); - - final flipperBloc = game - .descendants() - .whereType() - .where((flipper) => flipper.side == BoardSide.left) - .single - .descendants() - .whereType>() - .first - .bloc; - - game.onTapDown(0, tapDownEvent); - game.onTapCancel(0); - expect(flipperBloc.state, FlipperState.movingDown); - }); - - flameTester.test( - 'multiple touches control both flippers', - (game) async { + final eventPosition = _MockEventPosition(); + when(() => eventPosition.global).thenReturn(Vector2.zero()); + when(() => eventPosition.widget).thenReturn(Vector2.zero()); + + final tapUpEvent = _MockTapUpInfo(); + when(() => tapUpEvent.eventPosition).thenReturn(eventPosition); + + game.onTapUp(0, tapUpEvent); + game.update(0); + + final flipperBloc = game + .descendants() + .whereType() + .where((flipper) => flipper.side == BoardSide.left) + .single + .descendants() + .whereType>() + .first + .bloc; + expect(flipperBloc.state, FlipperState.movingDown); + }, + ); + + flameTester.testGameWidget( + 'tap cancel moves flipper down', + setUp: (game, _) async { + await game.preLoad(); await game.ready(); + }, + verify: (game, _) async { + final gameBloc = game + .descendants() + .whereType>() + .first + .bloc; + + gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); + + final eventPosition = _MockEventPosition(); + when(() => eventPosition.global).thenReturn(Vector2.zero()); + when(() => eventPosition.widget).thenReturn(Vector2.zero()); + final raw = _MockTapDownDetails(); + when(() => raw.kind).thenReturn(PointerDeviceKind.touch); + + final tapDownEvent = _MockTapDownInfo(); + when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); + when(() => tapDownEvent.raw).thenReturn(raw); + + final flipperBloc = game + .descendants() + .whereType() + .where((flipper) => flipper.side == BoardSide.left) + .single + .descendants() + .whereType>() + .first + .bloc; + + game.onTapDown(0, tapDownEvent); + game.onTapCancel(0); + expect(flipperBloc.state, FlipperState.movingDown); + }, + ); + + flameTester.testGameWidget( + 'multiple touches control both flippers', + setUp: (game, _) async { + await game.preLoad(); + await game.ready(); + }, + verify: (game, _) async { final gameBloc = game .descendants() .whereType>() @@ -451,11 +542,11 @@ void main() { when(() => raw.kind).thenReturn(PointerDeviceKind.touch); final leftEventPosition = _MockEventPosition(); - when(() => leftEventPosition.game).thenReturn(Vector2.zero()); + when(() => leftEventPosition.global).thenReturn(Vector2.zero()); when(() => leftEventPosition.widget).thenReturn(Vector2.zero()); final rightEventPosition = _MockEventPosition(); - when(() => rightEventPosition.game).thenReturn(Vector2.zero()); + when(() => rightEventPosition.global).thenReturn(Vector2.zero()); when(() => rightEventPosition.widget).thenReturn(game.canvasSize); final leftTapDownEvent = _MockTapDownInfo(); @@ -497,48 +588,62 @@ void main() { }); group('plunger control', () { - flameTester.test('plunger control tap down emits plunging', (game) async { - await game.ready(); - - final gameBloc = game - .descendants() - .whereType>() - .first - .bloc; + flameTester.testGameWidget( + 'plunger control tap down emits plunging', + setUp: (game, _) async { + await game.preLoad(); + await game.ready(); + }, + verify: (game, _) async { + final gameBloc = game + .descendants() + .whereType>() + .first + .bloc; - gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); + gameBloc.emit(gameBloc.state.copyWith(status: GameStatus.playing)); - final eventPosition = _MockEventPosition(); - when(() => eventPosition.game).thenReturn(Vector2(40, 60)); + final eventPosition = _MockEventPosition(); + when(() => eventPosition.widget).thenReturn( + game.worldToScreen(Vector2(40, 60)), + ); - final raw = _MockTapDownDetails(); - when(() => raw.kind).thenReturn(PointerDeviceKind.touch); + final raw = _MockTapDownDetails(); + when(() => raw.kind).thenReturn(PointerDeviceKind.touch); - final tapDownEvent = _MockTapDownInfo(); - when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); - when(() => tapDownEvent.raw).thenReturn(raw); + final tapDownEvent = _MockTapDownInfo(); + when(() => tapDownEvent.eventPosition).thenReturn(eventPosition); + when(() => tapDownEvent.raw).thenReturn(raw); - game.onTapDown(0, tapDownEvent); + game.onTapDown(0, tapDownEvent); - final plungerBloc = game - .descendants() - .whereType>() - .single - .bloc; + final plungerBloc = game + .descendants() + .whereType>() + .single + .bloc; - expect(plungerBloc.state, PlungerState.autoPulling); - }); + expect(plungerBloc.state, PlungerState.autoPulling); + }, + ); }); }); group('DebugPinballGame', () { final flameTester = FlameTester(_TestDebugPinballGame.new); - flameTester.test( + flameTester.testGameWidget( 'adds a ball on tap up', - (game) async { + setUp: (game, _) async { + await game.preLoad(); + await game.ready(); + }, + verify: (game, tester) async { + final previousBalls = game.descendants().whereType().toList(); + final eventPosition = _MockEventPosition(); - when(() => eventPosition.game).thenReturn(Vector2.all(10)); + when(() => eventPosition.widget) + .thenReturn(game.worldToScreen(Vector2.all(10))); final raw = _MockTapUpDetails(); when(() => raw.kind).thenReturn(PointerDeviceKind.mouse); @@ -547,11 +652,10 @@ void main() { when(() => tapUpEvent.eventPosition).thenReturn(eventPosition); when(() => tapUpEvent.raw).thenReturn(raw); - await game.ready(); - final previousBalls = game.descendants().whereType().toList(); - game.onTapUp(0, tapUpEvent); - await game.ready(); + game.update(0); + + await tester.pump(); final currentBalls = game.descendants().whereType().toList(); @@ -562,49 +666,71 @@ void main() { }, ); - flameTester.test( + flameTester.testGameWidget( 'set lineStart on pan start', - (game) async { - final startPosition = Vector2.all(10); + setUp: (game, _) async { + await game.preLoad(); final eventPosition = _MockEventPosition(); - when(() => eventPosition.game).thenReturn(startPosition); + when(() => eventPosition.widget) + .thenReturn(game.worldToScreen(Vector2.zero())); + + game.lineEnd = Vector2.all(10); final dragStartInfo = _MockDragStartInfo(); when(() => dragStartInfo.eventPosition).thenReturn(eventPosition); game.onPanStart(dragStartInfo); await game.ready(); - + }, + verify: (game, _) async { expect( game.lineStart, - equals(startPosition), + equals(Vector2.zero()), ); }, ); - flameTester.test( + flameTester.testGameWidget( 'set lineEnd on pan update', - (game) async { - final endPosition = Vector2.all(10); + setUp: (game, _) async { + await game.preLoad(); + await game.ready(); final eventPosition = _MockEventPosition(); - when(() => eventPosition.game).thenReturn(endPosition); + when(() => eventPosition.widget) + .thenReturn(game.worldToScreen(Vector2.all(10))); final dragUpdateInfo = _MockDragUpdateInfo(); when(() => dragUpdateInfo.eventPosition).thenReturn(eventPosition); - game.onPanUpdate(dragUpdateInfo); - await game.ready(); + game.lineStart = Vector2.zero(); + game.onPanUpdate(dragUpdateInfo); + game.update(0); + }, + verify: (game, _) async { expect( - game.lineEnd, - equals(endPosition), + game.lineEnd?.x, + greaterThanOrEqualTo(9.999), + ); + expect( + game.lineEnd?.x, + lessThanOrEqualTo(10.001), + ); + expect( + game.lineEnd?.y, + greaterThanOrEqualTo(9.999), + ); + expect( + game.lineEnd?.y, + lessThanOrEqualTo(10.001), ); }, ); - flameTester.test( + flameTester.testGameWidget( 'launch ball on pan end', - (game) async { + setUp: (game, _) async { + await game.preLoad(); final startPosition = Vector2.zero(); final endPosition = Vector2.all(10); @@ -612,10 +738,14 @@ void main() { game.lineEnd = endPosition; await game.ready(); + }, + verify: (game, tester) async { final previousBalls = game.descendants().whereType().toList(); game.onPanEnd(_MockDragEndInfo()); - await game.ready(); + game.update(0); + + await tester.pump(); expect( game.descendants().whereType().length, diff --git a/test/game/view/pinball_game_page_test.dart b/test/game/view/pinball_game_page_test.dart index da52bbd0..01deeb0f 100644 --- a/test/game/view/pinball_game_page_test.dart +++ b/test/game/view/pinball_game_page_test.dart @@ -64,8 +64,8 @@ class _MockAppLocalizations extends Mock implements AppLocalizations { class _MockPinballAudioPlayer extends Mock implements PinballAudioPlayer {} -class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { -} +class _MockLeaderboardRepository extends Mock + implements LeaderboardRepository {} class _MockShareRepository extends Mock implements ShareRepository {} @@ -301,25 +301,31 @@ void main() { expect(game.focusNode.hasFocus, isTrue); }); - testWidgets('mobile controls when the overlay is added', (tester) async { - await tester.pumpApp( - PinballGameView(game), - gameBloc: gameBloc, - startGameBloc: startGameBloc, - ); + testWidgets( + 'mobile controls when the overlay is added', + (tester) async { + await tester.pumpApp( + Material(child: PinballGameView(game)), + gameBloc: gameBloc, + startGameBloc: startGameBloc, + ); - game.overlays.add(PinballGame.mobileControlsOverlay); + game.overlays.add(PinballGame.mobileControlsOverlay); - await tester.pump(); + await tester.pump(); - expect(find.byType(MobileControls), findsOneWidget); - }); + expect( + game.overlays.isActive(PinballGame.mobileControlsOverlay), + isTrue, + ); + }, + ); testWidgets( 'ReplayButtonOverlay when the overlay is added', (tester) async { await tester.pumpApp( - PinballGameView(game), + Material(child: PinballGameView(game)), gameBloc: gameBloc, startGameBloc: startGameBloc, ); @@ -328,7 +334,10 @@ void main() { await tester.pump(); - expect(find.byType(ReplayButtonOverlay), findsOneWidget); + expect( + game.overlays.isActive(PinballGame.replayButtonOverlay), + isTrue, + ); }, ); diff --git a/test/game/view/widgets/bonus_animation_test.dart b/test/game/view/widgets/bonus_animation_test.dart index 5f67e968..9c34caa8 100644 --- a/test/game/view/widgets/bonus_animation_test.dart +++ b/test/game/view/widgets/bonus_animation_test.dart @@ -85,7 +85,7 @@ void main() { await tester.pump(); - await Future.delayed(const Duration(seconds: animationDuration)); + await Future.delayed(const Duration(seconds: animationDuration + 1)); await tester.pump(); @@ -116,7 +116,7 @@ void main() { .state(find.byType(BonusAnimation)) .didUpdateWidget(secondAnimation); - await Future.delayed(const Duration(seconds: animationDuration)); + await Future.delayed(const Duration(seconds: animationDuration + 1)); await tester.pump(); diff --git a/test/game/view/widgets/game_hud_test.dart b/test/game/view/widgets/game_hud_test.dart index f4fe4b89..8345fb72 100644 --- a/test/game/view/widgets/game_hud_test.dart +++ b/test/game/view/widgets/game_hud_test.dart @@ -137,7 +137,9 @@ void main() { ); await _pumpAppWithWidget(tester); await tester.pump(); - await Future.delayed(const Duration(seconds: 6)); + expect(find.byType(BonusAnimation), findsOneWidget); + await Future.delayed(const Duration(seconds: 6)); + await tester.pump(); await expectLater(find.byType(ScoreView), findsOneWidget); }); }, diff --git a/test/helpers/mock_flame_images.dart b/test/helpers/mock_flame_images.dart index 891ede7f..9fae92ab 100644 --- a/test/helpers/mock_flame_images.dart +++ b/test/helpers/mock_flame_images.dart @@ -1,6 +1,6 @@ import 'dart:typed_data'; -import 'package:flame/assets.dart'; +import 'package:flame/cache.dart'; import 'package:flame/flame.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/test/helpers/pump_app.dart b/test/helpers/pump_app.dart index c057bc83..eed0b750 100644 --- a/test/helpers/pump_app.dart +++ b/test/helpers/pump_app.dart @@ -17,8 +17,8 @@ import 'package:share_repository/share_repository.dart'; class _MockAssetsManagerCubit extends Mock implements AssetsManagerCubit {} -class _MockLeaderboardRepository extends Mock implements LeaderboardRepository { -} +class _MockLeaderboardRepository extends Mock + implements LeaderboardRepository {} class _MockShareRepository extends Mock implements ShareRepository {} diff --git a/test/more_information/more_information_dialog_test.dart b/test/more_information/more_information_dialog_test.dart index cf7ba149..b2c164ba 100644 --- a/test/more_information/more_information_dialog_test.dart +++ b/test/more_information/more_information_dialog_test.dart @@ -27,6 +27,8 @@ class _MockUrlLauncher extends Mock with MockPlatformInterfaceMixin implements UrlLauncherPlatform {} +class _MockLaunchOptions extends Mock implements LaunchOptions {} + void main() { group('MoreInformationDialog', () { late UrlLauncherPlatform urlLauncher; @@ -36,6 +38,10 @@ void main() { UrlLauncherPlatform.instance = urlLauncher; }); + setUpAll(() { + registerFallbackValue(_MockLaunchOptions()); + }); + group('showMoreInformationDialog', () { testWidgets('inflates the dialog', (tester) async { await tester.pumpApp( @@ -72,16 +78,8 @@ void main() { (tester) 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); + () => urlLauncher.launchUrl(any(), any()), + ).thenAnswer((_) async => Future.value(true)); await tester.pumpApp(const MoreInformationDialog()); final flutterTextFinder = find.byWidgetPredicate( (widget) => widget is RichText && _tapTextSpan(widget, 'Flutter'), @@ -89,14 +87,9 @@ void main() { await tester.tap(flutterTextFinder); await tester.pumpAndSettle(); verify( - () => urlLauncher.launch( + () => urlLauncher.launchUrl( 'https://flutter.dev', - useSafariVC: any(named: 'useSafariVC'), - useWebView: any(named: 'useWebView'), - enableJavaScript: any(named: 'enableJavaScript'), - enableDomStorage: any(named: 'enableDomStorage'), - universalLinksOnly: any(named: 'universalLinksOnly'), - headers: any(named: 'headers'), + any(), ), ); }, @@ -107,16 +100,8 @@ void main() { (tester) 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); + () => urlLauncher.launchUrl(any(), any()), + ).thenAnswer((_) async => Future.value(true)); await tester.pumpApp(const MoreInformationDialog()); final firebaseTextFinder = find.byWidgetPredicate( (widget) => widget is RichText && _tapTextSpan(widget, 'Firebase'), @@ -124,15 +109,7 @@ void main() { await tester.tap(firebaseTextFinder); await tester.pumpAndSettle(); verify( - () => urlLauncher.launch( - 'https://firebase.google.com', - useSafariVC: any(named: 'useSafariVC'), - useWebView: any(named: 'useWebView'), - enableJavaScript: any(named: 'enableJavaScript'), - enableDomStorage: any(named: 'enableDomStorage'), - universalLinksOnly: any(named: 'universalLinksOnly'), - headers: any(named: 'headers'), - ), + () => urlLauncher.launchUrl('https://firebase.google.com', any()), ); }, ); @@ -152,30 +129,17 @@ void main() { when(() => urlLauncher.canLaunch(any())) .thenAnswer((_) async => true); when( - () => urlLauncher.launch( - link, - 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); + () => urlLauncher.launchUrl(any(), any()), + ).thenAnswer((_) async => Future.value(true)); await tester.pumpApp(const MoreInformationDialog()); await tester.tap(find.text(text)); await tester.pumpAndSettle(); verify( - () => urlLauncher.launch( + () => urlLauncher.launchUrl( link, - useSafariVC: any(named: 'useSafariVC'), - useWebView: any(named: 'useWebView'), - enableJavaScript: any(named: 'enableJavaScript'), - enableDomStorage: any(named: 'enableDomStorage'), - universalLinksOnly: any(named: 'universalLinksOnly'), - headers: any(named: 'headers'), + any(), ), ); }, diff --git a/test/select_character/view/character_selection_page_test.dart b/test/select_character/view/character_selection_page_test.dart index a9c0c7ef..8a2f3fe3 100644 --- a/test/select_character/view/character_selection_page_test.dart +++ b/test/select_character/view/character_selection_page_test.dart @@ -105,7 +105,7 @@ class _TestCharacterPreviewState extends State<_TestCharacterPreview> { }); }, child: const Text('test'), - ) + ), ], ); } diff --git a/test/start_game/bloc/start_game_bloc_test.dart b/test/start_game/bloc/start_game_bloc_test.dart index 3b82e83d..cad54ca0 100644 --- a/test/start_game/bloc/start_game_bloc_test.dart +++ b/test/start_game/bloc/start_game_bloc_test.dart @@ -11,7 +11,7 @@ void main() { expect: () => [ const StartGameState( status: StartGameStatus.selectCharacter, - ) + ), ], ); @@ -22,7 +22,7 @@ void main() { expect: () => [ const StartGameState( status: StartGameStatus.selectCharacter, - ) + ), ], ); @@ -33,7 +33,7 @@ void main() { expect: () => [ const StartGameState( status: StartGameStatus.howToPlay, - ) + ), ], ); @@ -44,7 +44,7 @@ void main() { expect: () => [ const StartGameState( status: StartGameStatus.play, - ) + ), ], ); }); diff --git a/web/index.html b/web/index.html index 30eb9080..2e6b00cc 100644 --- a/web/index.html +++ b/web/index.html @@ -28,7 +28,7 @@ + content="https://firebasestorage.googleapis.com/v0/b/io-pinball.appspot.com/o/images%2Fpinball_share_image.png?alt=media"> I/O Pinball Machine - Flutter @@ -80,7 +85,6 @@ console.warn(e); }); - var serviceWorkerVersion = null; var scriptLoaded = false; function loadMainDartJs() { if (scriptLoaded) { @@ -99,7 +103,7 @@ // Wait for registration to finish before dropping the