Before Width: | Height: | Size: 3.2 MiB After Width: | Height: | Size: 2.2 MiB |
@ -0,0 +1 @@
|
||||
export 'assets.gen.dart';
|
@ -1 +0,0 @@
|
||||
export 'view/landing_page.dart';
|
@ -1 +1,2 @@
|
||||
export 'bloc/start_game_bloc.dart';
|
||||
export 'widgets/widgets.dart';
|
||||
|
@ -0,0 +1 @@
|
||||
export 'how_to_play_dialog.dart';
|
@ -0,0 +1,15 @@
|
||||
// ignore_for_file: public_member_api_docs
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class AppColors {
|
||||
static const Color white = Color(0xFFFFFFFF);
|
||||
|
||||
static const Color darkBlue = Color(0xFF0C32A4);
|
||||
|
||||
static const Color orange = Color(0xFFFFEE02);
|
||||
|
||||
static const Color blue = Color(0xFF4B94F6);
|
||||
|
||||
static const Color transparent = Color(0x00000000);
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
// ignore_for_file: public_member_api_docs
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:pinball/theme/theme.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
const _fontPackage = 'pinball_components';
|
||||
const _primaryFontFamily = PinballFonts.pixeloidSans;
|
||||
|
||||
abstract class AppTextStyle {
|
||||
static const headline1 = TextStyle(
|
||||
fontSize: 28,
|
||||
package: _fontPackage,
|
||||
fontFamily: _primaryFontFamily,
|
||||
);
|
||||
|
||||
static const headline2 = TextStyle(
|
||||
fontSize: 24,
|
||||
package: _fontPackage,
|
||||
fontFamily: _primaryFontFamily,
|
||||
);
|
||||
|
||||
static const headline3 = TextStyle(
|
||||
color: AppColors.white,
|
||||
fontSize: 20,
|
||||
package: _fontPackage,
|
||||
fontFamily: _primaryFontFamily,
|
||||
);
|
||||
|
||||
static const subtitle1 = TextStyle(
|
||||
fontSize: 10,
|
||||
fontFamily: _primaryFontFamily,
|
||||
package: _fontPackage,
|
||||
);
|
||||
}
|
@ -1,2 +1,4 @@
|
||||
export 'app_colors.dart';
|
||||
export 'app_text_style.dart';
|
||||
export 'cubit/theme_cubit.dart';
|
||||
export 'view/view.dart';
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 390 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 283 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 290 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,2 @@
|
||||
export 'assets.gen.dart';
|
||||
export 'pinball_fonts.dart';
|
@ -1,16 +1,14 @@
|
||||
import 'package:pinball_components/gen/fonts.gen.dart';
|
||||
|
||||
String _prefixFont(String font) {
|
||||
return 'packages/pinball_components/$font';
|
||||
}
|
||||
const String _fontPath = 'packages/pinball_components/';
|
||||
|
||||
/// Class with the fonts available on the pinball game
|
||||
class PinballFonts {
|
||||
PinballFonts._();
|
||||
|
||||
/// Mono variation of the Pixeloid font
|
||||
static final String pixeloidMono = _prefixFont(FontFamily.pixeloidMono);
|
||||
static const String pixeloidMono = '$_fontPath/${FontFamily.pixeloidMono}';
|
||||
|
||||
/// Sans variation of the Pixeloid font
|
||||
static final String pixeloidSans = _prefixFont(FontFamily.pixeloidSans);
|
||||
static const String pixeloidSans = '$_fontPath/${FontFamily.pixeloidSans}';
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
library pinball_components;
|
||||
|
||||
export 'gen/assets.gen.dart';
|
||||
export 'gen/pinball_fonts.dart';
|
||||
export 'gen/gen.dart';
|
||||
export 'src/pinball_components.dart';
|
||||
|
@ -1,42 +0,0 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
/// {@template flutter_sign_post}
|
||||
/// A sign, found in the Flutter Forest.
|
||||
/// {@endtemplate}
|
||||
class FlutterSignPost extends BodyComponent with InitialPosition {
|
||||
/// {@macro flutter_sign_post}
|
||||
FlutterSignPost()
|
||||
: super(
|
||||
children: [_FlutterSignPostSpriteComponent()],
|
||||
) {
|
||||
renderBody = false;
|
||||
}
|
||||
|
||||
@override
|
||||
Body createBody() {
|
||||
final shape = CircleShape()..radius = 0.25;
|
||||
final fixtureDef = FixtureDef(shape);
|
||||
final bodyDef = BodyDef(
|
||||
position: initialPosition,
|
||||
);
|
||||
|
||||
return world.createBody(bodyDef)..createFixture(fixtureDef);
|
||||
}
|
||||
}
|
||||
|
||||
class _FlutterSignPostSpriteComponent extends SpriteComponent with HasGameRef {
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
final sprite = await gameRef.loadSprite(
|
||||
Assets.images.flutterSignPost.keyName,
|
||||
);
|
||||
this.sprite = sprite;
|
||||
size = sprite.originalSize / 10;
|
||||
anchor = Anchor.bottomCenter;
|
||||
position = Vector2(0.65, 0.45);
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
// ignore_for_file: public_member_api_docs
|
||||
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
/// {@template render_priority}
|
||||
/// Priorities for the component rendering order in the pinball game.
|
||||
/// {@endtemplate}
|
||||
// TODO(allisonryan0002): find alternative to section comments.
|
||||
abstract class RenderPriority {
|
||||
static const _base = 0;
|
||||
static const _above = 1;
|
||||
static const _below = -1;
|
||||
|
||||
// Ball
|
||||
|
||||
/// Render priority for the [Ball] while it's on the board.
|
||||
static const int ballOnBoard = _base;
|
||||
|
||||
/// Render priority for the [Ball] while it's on the [SpaceshipRamp].
|
||||
static const int ballOnSpaceshipRamp =
|
||||
_above + spaceshipRampBackgroundRailing;
|
||||
|
||||
/// Render priority for the [Ball] while it's on the [Spaceship].
|
||||
static const int ballOnSpaceship = _above + spaceshipSaucer;
|
||||
|
||||
/// Render priority for the [Ball] while it's on the [SpaceshipRail].
|
||||
static const int ballOnSpaceshipRail = _below + spaceshipSaucer;
|
||||
|
||||
/// Render priority for the [Ball] while it's on the [LaunchRamp].
|
||||
static const int ballOnLaunchRamp = _above + launchRamp;
|
||||
|
||||
// Background
|
||||
|
||||
// TODO(allisonryan0002): fix this magic priority. Could bump all priorities
|
||||
// so there are no negatives.
|
||||
static const int background = 3 * _below + _base;
|
||||
|
||||
// Boundaries
|
||||
|
||||
static const int bottomBoundary = _above + dinoBottomWall;
|
||||
|
||||
static const int outerBoudary = _above + background;
|
||||
|
||||
// Bottom Group
|
||||
|
||||
static const int bottomGroup = _above + ballOnBoard;
|
||||
|
||||
// Launcher
|
||||
|
||||
static const int launchRamp = _above + outerBoudary;
|
||||
|
||||
static const int launchRampForegroundRailing = _above + ballOnLaunchRamp;
|
||||
|
||||
static const int plunger = _above + launchRamp;
|
||||
|
||||
static const int rocket = _above + bottomBoundary;
|
||||
|
||||
// Dino Land
|
||||
|
||||
static const int dinoTopWall = _above + ballOnBoard;
|
||||
|
||||
static const int dino = _above + dinoTopWall;
|
||||
|
||||
static const int dinoBottomWall = _above + dino;
|
||||
|
||||
static const int slingshot = _above + ballOnBoard;
|
||||
|
||||
// Flutter Forest
|
||||
|
||||
static const int signpost = _above + launchRampForegroundRailing;
|
||||
|
||||
static const int dashBumper = _above + ballOnBoard;
|
||||
|
||||
static const int dashAnimatronic = _above + launchRampForegroundRailing;
|
||||
|
||||
// Sparky Fire Zone
|
||||
|
||||
static const int computerBase = _below + ballOnBoard;
|
||||
|
||||
static const int computerTop = _above + ballOnBoard;
|
||||
|
||||
static const int sparkyAnimatronic = _above + spaceshipRampForegroundRailing;
|
||||
|
||||
static const int sparkyBumper = _above + ballOnBoard;
|
||||
|
||||
static const int turboChargeFlame = _above + ballOnBoard;
|
||||
|
||||
// Android Spaceship
|
||||
|
||||
static const int spaceshipRail = _above + bottomGroup;
|
||||
|
||||
static const int spaceshipRailForeground = _above + spaceshipRail;
|
||||
|
||||
static const int spaceshipSaucer = _above + spaceshipRail;
|
||||
|
||||
static const int spaceshipSaucerWall = _above + spaceshipSaucer;
|
||||
|
||||
static const int androidHead = _above + spaceshipSaucer;
|
||||
|
||||
static const int spaceshipRamp = _above + ballOnBoard;
|
||||
|
||||
static const int spaceshipRampBackgroundRailing = _above + spaceshipRamp;
|
||||
|
||||
static const int spaceshipRampForegroundRailing =
|
||||
_above + ballOnSpaceshipRamp;
|
||||
|
||||
static const int spaceshipRampBoardOpening = _below + ballOnBoard;
|
||||
|
||||
static const int alienBumper = _above + ballOnBoard;
|
||||
|
||||
// Score Text
|
||||
|
||||
static const int scoreText = _above + spaceshipRampForegroundRailing;
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
/// Represents the [Signpost]'s current [Sprite] state.
|
||||
@visibleForTesting
|
||||
enum SignpostSpriteState {
|
||||
/// Signpost with no active dashes.
|
||||
inactive,
|
||||
|
||||
/// Signpost with a single sign of active dashes.
|
||||
active1,
|
||||
|
||||
/// Signpost with two signs of active dashes.
|
||||
active2,
|
||||
|
||||
/// Signpost with all signs of active dashes.
|
||||
active3,
|
||||
}
|
||||
|
||||
extension on SignpostSpriteState {
|
||||
String get path {
|
||||
switch (this) {
|
||||
case SignpostSpriteState.inactive:
|
||||
return Assets.images.signpost.inactive.keyName;
|
||||
case SignpostSpriteState.active1:
|
||||
return Assets.images.signpost.active1.keyName;
|
||||
case SignpostSpriteState.active2:
|
||||
return Assets.images.signpost.active2.keyName;
|
||||
case SignpostSpriteState.active3:
|
||||
return Assets.images.signpost.active3.keyName;
|
||||
}
|
||||
}
|
||||
|
||||
SignpostSpriteState get next {
|
||||
return SignpostSpriteState
|
||||
.values[(index + 1) % SignpostSpriteState.values.length];
|
||||
}
|
||||
}
|
||||
|
||||
/// {@template signpost}
|
||||
/// A sign, found in the Flutter Forest.
|
||||
///
|
||||
/// Lights up a new sign whenever all three [DashNestBumper]s are hit.
|
||||
/// {@endtemplate}
|
||||
class Signpost extends BodyComponent with InitialPosition {
|
||||
/// {@macro signpost}
|
||||
Signpost()
|
||||
: super(
|
||||
priority: RenderPriority.signpost,
|
||||
children: [_SignpostSpriteComponent()],
|
||||
) {
|
||||
renderBody = false;
|
||||
}
|
||||
|
||||
/// Forwards the sprite to the next [SignpostSpriteState].
|
||||
///
|
||||
/// If the current state is the last one it cycles back to the initial state.
|
||||
void progress() => firstChild<_SignpostSpriteComponent>()!.progress();
|
||||
|
||||
@override
|
||||
Body createBody() {
|
||||
final shape = CircleShape()..radius = 0.25;
|
||||
final fixtureDef = FixtureDef(shape);
|
||||
final bodyDef = BodyDef(
|
||||
position: initialPosition,
|
||||
);
|
||||
|
||||
return world.createBody(bodyDef)..createFixture(fixtureDef);
|
||||
}
|
||||
}
|
||||
|
||||
class _SignpostSpriteComponent extends SpriteGroupComponent<SignpostSpriteState>
|
||||
with HasGameRef {
|
||||
_SignpostSpriteComponent()
|
||||
: super(
|
||||
anchor: Anchor.bottomCenter,
|
||||
position: Vector2(0.65, 0.45),
|
||||
);
|
||||
|
||||
void progress() => current = current?.next;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
final sprites = <SignpostSpriteState, Sprite>{};
|
||||
this.sprites = sprites;
|
||||
for (final spriteState in SignpostSpriteState.values) {
|
||||
// TODO(allisonryan0002): Support caching
|
||||
// https://github.com/VGVentures/pinball/pull/204
|
||||
// sprites[spriteState] = Sprite(
|
||||
// gameRef.images.fromCache(spriteState.path),
|
||||
// );
|
||||
sprites[spriteState] = await gameRef.loadSprite(spriteState.path);
|
||||
}
|
||||
|
||||
current = SignpostSpriteState.inactive;
|
||||
size = sprites[current]!.originalSize / 10;
|
||||
}
|
||||
}
|
@ -1,22 +1,30 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:flame/input.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
import 'package:sandbox/stories/ball/basic_ball_game.dart';
|
||||
|
||||
class FlutterSignPostGame extends BasicBallGame with Traceable {
|
||||
class SignpostGame extends BasicBallGame with Traceable, TapDetector {
|
||||
static const info = '''
|
||||
Shows how a FlutterSignPost is rendered.
|
||||
Shows how a Signpost is rendered.
|
||||
|
||||
- Activate the "trace" parameter to overlay the body.
|
||||
- Tap to progress the sprite.
|
||||
''';
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
await super.onLoad();
|
||||
|
||||
camera.followVector2(Vector2.zero());
|
||||
await add(FlutterSignPost()..priority = 1);
|
||||
await add(Signpost()..priority = 1);
|
||||
await traceAllBodies();
|
||||
}
|
||||
|
||||
@override
|
||||
void onTap() {
|
||||
super.onTap();
|
||||
firstChild<Signpost>()!.progress();
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
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';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final flameTester = FlameTester(TestGame.new);
|
||||
|
||||
group('FlutterSignPost', () {
|
||||
flameTester.testGameWidget(
|
||||
'renders correctly',
|
||||
setUp: (game, tester) async {
|
||||
await game.ensureAdd(FlutterSignPost());
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<TestGame>(),
|
||||
matchesGoldenFile('golden/flutter-sign-post.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'loads correctly',
|
||||
(game) async {
|
||||
final flutterSignPost = FlutterSignPost();
|
||||
await game.ready();
|
||||
await game.ensureAdd(flutterSignPost);
|
||||
|
||||
expect(game.contains(flutterSignPost), isTrue);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 466 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 216 KiB |
Before Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 41 KiB |
@ -0,0 +1,141 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
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';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final flameTester = FlameTester(TestGame.new);
|
||||
|
||||
group('Signpost', () {
|
||||
flameTester.test(
|
||||
'loads correctly',
|
||||
(game) async {
|
||||
final signpost = Signpost();
|
||||
await game.ready();
|
||||
await game.ensureAdd(signpost);
|
||||
|
||||
expect(game.contains(signpost), isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
group('renders correctly', () {
|
||||
flameTester.testGameWidget(
|
||||
'inactive sprite',
|
||||
setUp: (game, tester) async {
|
||||
final signpost = Signpost();
|
||||
await game.ensureAdd(signpost);
|
||||
|
||||
expect(
|
||||
signpost.firstChild<SpriteGroupComponent>()!.current,
|
||||
SignpostSpriteState.inactive,
|
||||
);
|
||||
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<TestGame>(),
|
||||
matchesGoldenFile('golden/signpost/inactive.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.testGameWidget(
|
||||
'active1 sprite',
|
||||
setUp: (game, tester) async {
|
||||
final signpost = Signpost();
|
||||
await game.ensureAdd(signpost);
|
||||
signpost.progress();
|
||||
|
||||
expect(
|
||||
signpost.firstChild<SpriteGroupComponent>()!.current,
|
||||
SignpostSpriteState.active1,
|
||||
);
|
||||
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<TestGame>(),
|
||||
matchesGoldenFile('golden/signpost/active1.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.testGameWidget(
|
||||
'active2 sprite',
|
||||
setUp: (game, tester) async {
|
||||
final signpost = Signpost();
|
||||
await game.ensureAdd(signpost);
|
||||
signpost
|
||||
..progress()
|
||||
..progress();
|
||||
|
||||
expect(
|
||||
signpost.firstChild<SpriteGroupComponent>()!.current,
|
||||
SignpostSpriteState.active2,
|
||||
);
|
||||
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<TestGame>(),
|
||||
matchesGoldenFile('golden/signpost/active2.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.testGameWidget(
|
||||
'active3 sprite',
|
||||
setUp: (game, tester) async {
|
||||
final signpost = Signpost();
|
||||
await game.ensureAdd(signpost);
|
||||
signpost
|
||||
..progress()
|
||||
..progress()
|
||||
..progress();
|
||||
|
||||
expect(
|
||||
signpost.firstChild<SpriteGroupComponent>()!.current,
|
||||
SignpostSpriteState.active3,
|
||||
);
|
||||
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<TestGame>(),
|
||||
matchesGoldenFile('golden/signpost/active3.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test(
|
||||
'progress correctly cycles through all sprites',
|
||||
(game) async {
|
||||
final signpost = Signpost();
|
||||
await game.ready();
|
||||
await game.ensureAdd(signpost);
|
||||
|
||||
final spriteComponent = signpost.firstChild<SpriteGroupComponent>()!;
|
||||
|
||||
expect(spriteComponent.current, SignpostSpriteState.inactive);
|
||||
signpost.progress();
|
||||
expect(spriteComponent.current, SignpostSpriteState.active1);
|
||||
signpost.progress();
|
||||
expect(spriteComponent.current, SignpostSpriteState.active2);
|
||||
signpost.progress();
|
||||
expect(spriteComponent.current, SignpostSpriteState.active3);
|
||||
signpost.progress();
|
||||
expect(spriteComponent.current, SignpostSpriteState.inactive);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockingjay/mockingjay.dart';
|
||||
import 'package:pinball/l10n/l10n.dart';
|
||||
import 'package:pinball/landing/landing.dart';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
group('LandingPage', () {
|
||||
testWidgets('renders correctly', (tester) async {
|
||||
final l10n = await AppLocalizations.delegate.load(Locale('en'));
|
||||
await tester.pumpApp(LandingPage());
|
||||
|
||||
expect(find.byType(TextButton), findsNWidgets(2));
|
||||
expect(find.text(l10n.play), findsOneWidget);
|
||||
expect(find.text(l10n.howToPlay), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('tapping on play button navigates to CharacterSelectionPage',
|
||||
(tester) async {
|
||||
final l10n = await AppLocalizations.delegate.load(Locale('en'));
|
||||
final navigator = MockNavigator();
|
||||
when(() => navigator.push<void>(any())).thenAnswer((_) async {});
|
||||
|
||||
await tester.pumpApp(
|
||||
LandingPage(),
|
||||
navigator: navigator,
|
||||
);
|
||||
|
||||
await tester.tap(find.widgetWithText(TextButton, l10n.play));
|
||||
|
||||
verify(() => navigator.push<void>(any())).called(1);
|
||||
});
|
||||
|
||||
testWidgets('tapping on how to play button displays dialog with controls',
|
||||
(tester) async {
|
||||
final l10n = await AppLocalizations.delegate.load(Locale('en'));
|
||||
await tester.pumpApp(LandingPage());
|
||||
|
||||
await tester.tap(find.widgetWithText(TextButton, l10n.howToPlay));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.byType(Dialog), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
group('KeyIndicator', () {
|
||||
testWidgets('fromKeyName renders correctly', (tester) async {
|
||||
const keyName = 'A';
|
||||
|
||||
await tester.pumpApp(
|
||||
KeyIndicator.fromKeyName(keyName: keyName),
|
||||
);
|
||||
|
||||
expect(find.text(keyName), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('fromIcon renders correctly', (tester) async {
|
||||
const keyIcon = Icons.keyboard_arrow_down;
|
||||
|
||||
await tester.pumpApp(
|
||||
KeyIndicator.fromIcon(keyIcon: keyIcon),
|
||||
);
|
||||
|
||||
expect(find.byIcon(keyIcon), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball/start_game/start_game.dart';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
group('HowToPlayDialog', () {
|
||||
testWidgets('displays dialog', (tester) async {
|
||||
await tester.pumpApp(HowToPlayDialog());
|
||||
|
||||
expect(find.byType(Dialog), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
group('KeyIndicator', () {
|
||||
testWidgets('fromKeyName renders correctly', (tester) async {
|
||||
const keyName = 'A';
|
||||
|
||||
await tester.pumpApp(
|
||||
KeyIndicator.fromKeyName(keyName: keyName),
|
||||
);
|
||||
|
||||
expect(find.text(keyName), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('fromIcon renders correctly', (tester) async {
|
||||
const keyIcon = Icons.keyboard_arrow_down;
|
||||
|
||||
await tester.pumpApp(
|
||||
KeyIndicator.fromIcon(keyIcon: keyIcon),
|
||||
);
|
||||
|
||||
expect(find.byIcon(keyIcon), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|