mirror of https://github.com/flutter/pinball.git
commit
900d8daaac
@ -1,8 +1 @@
|
||||
// Copyright (c) 2021, Very Good Ventures
|
||||
// https://verygood.ventures
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
export 'view/app.dart';
|
||||
|
@ -0,0 +1,2 @@
|
||||
export 'cubit/assets_manager_cubit.dart';
|
||||
export 'views/views.dart';
|
@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:pinball/assets_manager/assets_manager.dart';
|
||||
import 'package:pinball/l10n/l10n.dart';
|
||||
import 'package:pinball_ui/pinball_ui.dart';
|
||||
|
||||
/// {@template assets_loading_page}
|
||||
/// Widget used to indicate the loading progress of the different assets used
|
||||
/// in the game
|
||||
/// {@endtemplate}
|
||||
class AssetsLoadingPage extends StatelessWidget {
|
||||
/// {@macro assets_loading_page}
|
||||
const AssetsLoadingPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final headline1 = Theme.of(context).textTheme.headline1;
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
l10n.ioPinball,
|
||||
style: headline1!.copyWith(fontSize: 80),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
AnimatedEllipsisText(
|
||||
l10n.loading,
|
||||
style: headline1,
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
FractionallySizedBox(
|
||||
widthFactor: 0.8,
|
||||
child: BlocBuilder<AssetsManagerCubit, AssetsManagerState>(
|
||||
builder: (context, state) {
|
||||
return PinballLoadingIndicator(value: state.progress);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
export 'assets_loading_page.dart';
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,35 @@
|
||||
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
|
||||
with ParentIsA<Ball>, HasGameRef<Forge2DGame> {
|
||||
@override
|
||||
void update(double dt) {
|
||||
super.update(dt);
|
||||
final defaultGravity = gameRef.world.gravity.y;
|
||||
|
||||
final maxXDeviationFromCenter = BoardDimensions.bounds.width / 2;
|
||||
const maxXGravityPercentage =
|
||||
(1 - BoardDimensions.perspectiveShrinkFactor) / 2;
|
||||
final xDeviationFromCenter = parent.body.position.x;
|
||||
|
||||
final positionalXForce = ((xDeviationFromCenter / maxXDeviationFromCenter) *
|
||||
maxXGravityPercentage) *
|
||||
defaultGravity;
|
||||
final positionalYForce = math.sqrt(
|
||||
math.pow(defaultGravity, 2) - math.pow(positionalXForce, 2),
|
||||
);
|
||||
|
||||
final gravityOverride = parent.body.gravityOverride;
|
||||
if (gravityOverride != null) {
|
||||
gravityOverride.setValues(positionalXForce, positionalYForce);
|
||||
} else {
|
||||
parent.body.gravityOverride = Vector2(positionalXForce, positionalYForce);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
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<Ball> {
|
||||
@override
|
||||
void update(double dt) {
|
||||
super.update(dt);
|
||||
final boardHeight = BoardDimensions.bounds.height;
|
||||
const maxShrinkValue = BoardDimensions.perspectiveShrinkFactor;
|
||||
|
||||
final standardizedYPosition = parent.body.position.y + (boardHeight / 2);
|
||||
final scaleFactor = maxShrinkValue +
|
||||
((standardizedYPosition / boardHeight) * (1 - maxShrinkValue));
|
||||
|
||||
parent.body.fixtures.first.shape.radius = (Ball.size.x / 2) * scaleFactor;
|
||||
|
||||
parent.firstChild<SpriteComponent>()!.scale.setValues(
|
||||
scaleFactor,
|
||||
scaleFactor,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
export 'ball_gravitating_behavior.dart';
|
||||
export 'ball_scaling_behavior.dart';
|
@ -0,0 +1,63 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
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 'package:pinball_components/src/components/ball/behaviors/behaviors.dart';
|
||||
|
||||
import '../../../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final asset = Assets.images.ball.ball.keyName;
|
||||
final flameTester = FlameTester(() => TestGame([asset]));
|
||||
|
||||
group('BallGravitatingBehavior', () {
|
||||
const baseColor = Color(0xFFFFFFFF);
|
||||
test('can be instantiated', () {
|
||||
expect(
|
||||
BallGravitatingBehavior(),
|
||||
isA<BallGravitatingBehavior>(),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test('can be loaded', (game) async {
|
||||
final ball = Ball.test(baseColor: baseColor);
|
||||
final behavior = BallGravitatingBehavior();
|
||||
await ball.add(behavior);
|
||||
await game.ensureAdd(ball);
|
||||
expect(
|
||||
ball.firstChild<BallGravitatingBehavior>(),
|
||||
equals(behavior),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test(
|
||||
"overrides the body's horizontal gravity symmetrically",
|
||||
(game) async {
|
||||
final ball1 = Ball.test(baseColor: baseColor)
|
||||
..initialPosition = Vector2(10, 0);
|
||||
await ball1.add(BallGravitatingBehavior());
|
||||
|
||||
final ball2 = Ball.test(baseColor: baseColor)
|
||||
..initialPosition = Vector2(-10, 0);
|
||||
await ball2.add(BallGravitatingBehavior());
|
||||
|
||||
await game.ensureAddAll([ball1, ball2]);
|
||||
game.update(1);
|
||||
|
||||
expect(
|
||||
ball1.body.gravityOverride!.x,
|
||||
equals(-ball2.body.gravityOverride!.x),
|
||||
);
|
||||
expect(
|
||||
ball1.body.gravityOverride!.y,
|
||||
equals(ball2.body.gravityOverride!.y),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
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 'package:pinball_components/src/components/ball/behaviors/behaviors.dart';
|
||||
|
||||
import '../../../../helpers/helpers.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final asset = Assets.images.ball.ball.keyName;
|
||||
final flameTester = FlameTester(() => TestGame([asset]));
|
||||
|
||||
group('BallScalingBehavior', () {
|
||||
const baseColor = Color(0xFFFFFFFF);
|
||||
test('can be instantiated', () {
|
||||
expect(
|
||||
BallScalingBehavior(),
|
||||
isA<BallScalingBehavior>(),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test('can be loaded', (game) async {
|
||||
final ball = Ball.test(baseColor: baseColor);
|
||||
final behavior = BallScalingBehavior();
|
||||
await ball.add(behavior);
|
||||
await game.ensureAdd(ball);
|
||||
expect(
|
||||
ball.firstChild<BallScalingBehavior>(),
|
||||
equals(behavior),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test('scales the shape radius', (game) async {
|
||||
final ball1 = Ball.test(baseColor: baseColor)
|
||||
..initialPosition = Vector2(0, 10);
|
||||
await ball1.add(BallScalingBehavior());
|
||||
|
||||
final ball2 = Ball.test(baseColor: baseColor)
|
||||
..initialPosition = Vector2(0, -10);
|
||||
await ball2.add(BallScalingBehavior());
|
||||
|
||||
await game.ensureAddAll([ball1, ball2]);
|
||||
game.update(1);
|
||||
|
||||
final shape1 = ball1.body.fixtures.first.shape;
|
||||
final shape2 = ball2.body.fixtures.first.shape;
|
||||
expect(
|
||||
shape1.radius,
|
||||
greaterThan(shape2.radius),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test(
|
||||
'scales the sprite',
|
||||
(game) async {
|
||||
final ball1 = Ball.test(baseColor: baseColor)
|
||||
..initialPosition = Vector2(0, 10);
|
||||
await ball1.add(BallScalingBehavior());
|
||||
|
||||
final ball2 = Ball.test(baseColor: baseColor)
|
||||
..initialPosition = Vector2(0, -10);
|
||||
await ball2.add(BallScalingBehavior());
|
||||
|
||||
await game.ensureAddAll([ball1, ball2]);
|
||||
game.update(1);
|
||||
|
||||
final sprite1 = ball1.firstChild<SpriteComponent>()!;
|
||||
final sprite2 = ball2.firstChild<SpriteComponent>()!;
|
||||
expect(
|
||||
sprite1.scale.x,
|
||||
greaterThan(sprite2.scale.x),
|
||||
);
|
||||
expect(
|
||||
sprite1.scale.y,
|
||||
greaterThan(sprite2.scale.y),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:flame_forge2d/world_contact_listener.dart';
|
||||
|
||||
// NOTE(wolfen): 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(min(dt, 1 / 60));
|
||||
}
|
||||
|
||||
@override
|
||||
Vector2 screenToFlameWorld(Vector2 position) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Vector2 screenToWorld(Vector2 position) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Vector2 worldToScreen(Vector2 position) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
// 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 UnimpelementedError',
|
||||
(game) async {
|
||||
expect(
|
||||
() => game.screenToFlameWorld(Vector2.zero()),
|
||||
throwsUnimplementedError,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'screenToWorld throws UnimpelementedError',
|
||||
(game) async {
|
||||
expect(
|
||||
() => game.screenToWorld(Vector2.zero()),
|
||||
throwsUnimplementedError,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.test(
|
||||
'worldToScreen throws UnimpelementedError',
|
||||
(game) async {
|
||||
expect(
|
||||
() => game.worldToScreen(Vector2.zero()),
|
||||
throwsUnimplementedError,
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// {@tempalte animated_ellipsis_text}
|
||||
/// Every 500 milliseconds, it will add a new `.` at the end of the given
|
||||
/// [text]. Once 3 `.` have been added (e.g. `Loading...`), it will reset to
|
||||
/// zero ellipsis and start over again.
|
||||
/// {@endtemplate}
|
||||
class AnimatedEllipsisText extends StatefulWidget {
|
||||
/// {@macro animated_ellipsis_text}
|
||||
const AnimatedEllipsisText(
|
||||
this.text, {
|
||||
Key? key,
|
||||
this.style,
|
||||
}) : super(key: key);
|
||||
|
||||
/// The text that will be animated.
|
||||
final String text;
|
||||
|
||||
/// Optional [TextStyle] of the given [text].
|
||||
final TextStyle? style;
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _AnimatedEllipsisText();
|
||||
}
|
||||
|
||||
class _AnimatedEllipsisText extends State<AnimatedEllipsisText>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final Timer timer;
|
||||
var _numberOfEllipsis = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
timer = Timer.periodic(const Duration(milliseconds: 500), (_) {
|
||||
setState(() {
|
||||
_numberOfEllipsis++;
|
||||
_numberOfEllipsis = _numberOfEllipsis % 4;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (timer.isActive) timer.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
'${widget.text}${_numberOfEllipsis.toEllipsis()}',
|
||||
style: widget.style,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension on int {
|
||||
String toEllipsis() => '.' * this;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pinball_ui/pinball_ui.dart';
|
||||
|
||||
/// {@template crt_background}
|
||||
/// [BoxDecoration] that provides a CRT-like background efffect.
|
||||
/// {@endtemplate}
|
||||
class CrtBackground extends BoxDecoration {
|
||||
/// {@macro crt_background}
|
||||
const CrtBackground()
|
||||
: super(
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment(1, 0.015),
|
||||
stops: [0.0, 0.5, 0.5, 1],
|
||||
colors: [
|
||||
PinballColors.darkBlue,
|
||||
PinballColors.darkBlue,
|
||||
PinballColors.crtBackground,
|
||||
PinballColors.crtBackground,
|
||||
],
|
||||
tileMode: TileMode.repeated,
|
||||
),
|
||||
);
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pinball_ui/pinball_ui.dart';
|
||||
|
||||
/// {@template pinball_loading_indicator}
|
||||
/// Pixel-art loading indicator
|
||||
/// {@endtemplate}
|
||||
class PinballLoadingIndicator extends StatelessWidget {
|
||||
/// {@macro pinball_loading_indicator}
|
||||
const PinballLoadingIndicator({
|
||||
Key? key,
|
||||
required this.value,
|
||||
}) : assert(
|
||||
value >= 0.0 && value <= 1.0,
|
||||
'Progress must be between 0 and 1',
|
||||
),
|
||||
super(key: key);
|
||||
|
||||
/// Progress value
|
||||
final double value;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
_InnerIndicator(value: value, widthFactor: 0.95),
|
||||
_InnerIndicator(value: value, widthFactor: 0.98),
|
||||
_InnerIndicator(value: value),
|
||||
_InnerIndicator(value: value),
|
||||
_InnerIndicator(value: value, widthFactor: 0.98),
|
||||
_InnerIndicator(value: value, widthFactor: 0.95)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _InnerIndicator extends StatelessWidget {
|
||||
const _InnerIndicator({
|
||||
Key? key,
|
||||
required this.value,
|
||||
this.widthFactor = 1.0,
|
||||
}) : super(key: key);
|
||||
|
||||
final double value;
|
||||
final double widthFactor;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FractionallySizedBox(
|
||||
widthFactor: widthFactor,
|
||||
child: Column(
|
||||
children: [
|
||||
LinearProgressIndicator(
|
||||
backgroundColor: PinballColors.loadingDarkBlue,
|
||||
color: PinballColors.loadingDarkRed,
|
||||
value: value,
|
||||
),
|
||||
LinearProgressIndicator(
|
||||
backgroundColor: PinballColors.loadingLightBlue,
|
||||
color: PinballColors.loadingLightRed,
|
||||
value: value,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1 +1,4 @@
|
||||
export 'animated_ellipsis_text.dart';
|
||||
export 'crt_background.dart';
|
||||
export 'pinball_button.dart';
|
||||
export 'pinball_loading_indicator.dart';
|
||||
|
@ -0,0 +1,30 @@
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_ui/pinball_ui.dart';
|
||||
|
||||
void main() {
|
||||
group('AnimatedEllipsisText', () {
|
||||
testWidgets(
|
||||
'adds a new `.` every 500ms and '
|
||||
'resets back to zero after adding 3', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: AnimatedEllipsisText('test'),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.text('test'), findsOneWidget);
|
||||
await tester.pump(const Duration(milliseconds: 600));
|
||||
expect(find.text('test.'), findsOneWidget);
|
||||
await tester.pump(const Duration(milliseconds: 600));
|
||||
expect(find.text('test..'), findsOneWidget);
|
||||
await tester.pump(const Duration(milliseconds: 600));
|
||||
expect(find.text('test...'), findsOneWidget);
|
||||
await tester.pump(const Duration(milliseconds: 600));
|
||||
expect(find.text('test'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_ui/pinball_ui.dart';
|
||||
|
||||
void main() {
|
||||
group('CrtBackground', () {
|
||||
test('is a BoxDecoration with a LinearGradient', () {
|
||||
// ignore: prefer_const_constructors
|
||||
final crtBg = CrtBackground();
|
||||
const expectedGradient = LinearGradient(
|
||||
begin: Alignment(1, 0.015),
|
||||
stops: [0.0, 0.5, 0.5, 1],
|
||||
colors: [
|
||||
PinballColors.darkBlue,
|
||||
PinballColors.darkBlue,
|
||||
PinballColors.crtBackground,
|
||||
PinballColors.crtBackground,
|
||||
],
|
||||
tileMode: TileMode.repeated,
|
||||
);
|
||||
expect(crtBg, isA<BoxDecoration>());
|
||||
expect(crtBg.gradient, expectedGradient);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_ui/pinball_ui.dart';
|
||||
|
||||
void main() {
|
||||
group('PinballLoadingIndicator', () {
|
||||
group('assert value', () {
|
||||
test('throws error if value <= 0.0', () {
|
||||
expect(
|
||||
() => PinballLoadingIndicator(value: -0.5),
|
||||
throwsA(isA<AssertionError>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('throws error if value >= 1.0', () {
|
||||
expect(
|
||||
() => PinballLoadingIndicator(value: 1.5),
|
||||
throwsA(isA<AssertionError>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'renders 12 LinearProgressIndicators and '
|
||||
'6 FractionallySizedBox to indicate progress', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: PinballLoadingIndicator(value: 0.75),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.byType(FractionallySizedBox), findsNWidgets(6));
|
||||
expect(find.byType(LinearProgressIndicator), findsNWidgets(12));
|
||||
final progressIndicators = tester.widgetList<LinearProgressIndicator>(
|
||||
find.byType(LinearProgressIndicator),
|
||||
);
|
||||
for (final i in progressIndicators) {
|
||||
expect(i.value, 0.75);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball/game/game.dart';
|
||||
import 'package:pinball/assets_manager/assets_manager.dart';
|
||||
|
||||
void main() {
|
||||
group('AssetsManagerState', () {
|
@ -0,0 +1,38 @@
|
||||
import 'package:bloc_test/bloc_test.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:pinball/assets_manager/assets_manager.dart';
|
||||
import 'package:pinball_ui/pinball_ui.dart';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
class _MockAssetsManagerCubit extends Mock implements AssetsManagerCubit {}
|
||||
|
||||
void main() {
|
||||
late AssetsManagerCubit assetsManagerCubit;
|
||||
|
||||
setUp(() {
|
||||
final initialAssetsState = AssetsManagerState(
|
||||
loadables: [Future<void>.value()],
|
||||
loaded: const [],
|
||||
);
|
||||
assetsManagerCubit = _MockAssetsManagerCubit();
|
||||
whenListen(
|
||||
assetsManagerCubit,
|
||||
Stream.value(initialAssetsState),
|
||||
initialState: initialAssetsState,
|
||||
);
|
||||
});
|
||||
|
||||
group('AssetsLoadingPage', () {
|
||||
testWidgets('renders an animated text and a pinball loading indicator',
|
||||
(tester) async {
|
||||
await tester.pumpApp(
|
||||
const AssetsLoadingPage(),
|
||||
assetsManagerCubit: assetsManagerCubit,
|
||||
);
|
||||
expect(find.byType(AnimatedEllipsisText), findsOneWidget);
|
||||
expect(find.byType(PinballLoadingIndicator), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in new issue