feat: removed FlutterForestCubit

pull/234/head
alestiago 3 years ago
parent 4c0d33596d
commit c5865a4252

@ -10,35 +10,29 @@ class FlutterForestBonusBehavior extends Component
@override
void onMount() {
super.onMount();
// TODO(alestiago): Refactor subscription management once the following is
// merged:
// https://github.com/flame-engine/flame/pull/1538
parent.bloc.stream.listen(_onNewState);
final bumpers = parent.children.whereType<DashNestBumper>();
for (final bumper in bumpers) {
bumper.bloc.stream.listen((state) {
if (state == DashNestBumperState.active) {
parent.bloc.onBumperActivated(bumper);
}
});
}
}
void _onNewState(FlutterForestState state) {
if (state.hasBonus) {
gameRef.read<GameBloc>().add(const BonusActivated(GameBonus.dashNest));
final hasBonus = bumpers.every(
(bumper) => bumper.bloc.state == DashNestBumperState.active,
);
if (hasBonus) {
gameRef
.read<GameBloc>()
.add(const BonusActivated(GameBonus.dashNest));
gameRef.add(
ControlledBall.bonus(theme: gameRef.theme)
..initialPosition = Vector2(17.2, -52.7),
);
parent.firstChild<DashAnimatronic>()?.playing = true;
for (final bumper in state.activatedBumpers) {
for (final bumper in bumpers) {
bumper.bloc.onReset();
}
parent.bloc.onBonusApplied();
}
});
}
}
}

@ -1,29 +0,0 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:pinball_components/pinball_components.dart';
part 'flutter_forest_state.dart';
// TODO(alestiago): Evaluate if there is any useful documentation that could
// be added to this class.
// ignore: public_member_api_docs
class FlutterForestCubit extends Cubit<FlutterForestState> {
// ignore: public_member_api_docs
FlutterForestCubit() : super(const FlutterForestState.initial());
/// Event added when a bumper contacts with a ball.
void onBumperActivated(DashNestBumper dashNestBumper) {
emit(
state.copyWith(
activatedBumpers: state.activatedBumpers.union({dashNestBumper}),
),
);
}
/// Event added after the bonus is activated.
void onBonusApplied() {
emit(
state.copyWith(activatedBumpers: const {}),
);
}
}

@ -1,26 +0,0 @@
// ignore_for_file: public_member_api_docs
part of 'flutter_forest_cubit.dart';
class FlutterForestState extends Equatable {
const FlutterForestState({
required this.activatedBumpers,
});
const FlutterForestState.initial() : this(activatedBumpers: const {});
final Set<DashNestBumper> activatedBumpers;
bool get hasBonus => activatedBumpers.length == 3;
FlutterForestState copyWith({
Set<DashNestBumper>? activatedBumpers,
}) {
return FlutterForestState(
activatedBumpers: activatedBumpers ?? this.activatedBumpers,
);
}
@override
List<Object> get props => [activatedBumpers];
}

@ -6,8 +6,6 @@ import 'package:pinball/game/components/flutter_forest/behaviors/behaviors.dart'
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
export 'cubit/flutter_forest_cubit.dart';
/// {@template flutter_forest}
/// Area positioned at the top right of the [Board] where the [Ball]
/// can bounce off [DashNestBumper]s.
@ -15,8 +13,7 @@ export 'cubit/flutter_forest_cubit.dart';
class FlutterForest extends Component {
/// {@macro flutter_forest}
FlutterForest()
: bloc = FlutterForestCubit(),
super(
: super(
children: [
Signpost(
children: [
@ -43,20 +40,9 @@ class FlutterForest extends Component {
],
);
/// {@macro flutter_forest}
/// Creates a [FlutterForest] without any children.
///
/// This can be used for testing [FlutterForest]'s behaviors in isolation.
@visibleForTesting
FlutterForest.test({
required this.bloc,
});
// TODO(alestiago): Consider refactoring once the following is merged:
// https://github.com/flame-engine/flame/pull/1538
// ignore: public_member_api_docs
final FlutterForestCubit bloc;
@override
void onRemove() {
bloc.close();
super.onRemove();
}
FlutterForest.test();
}

@ -80,8 +80,9 @@ class DashNestBumper extends BodyComponent with InitialPosition {
/// {@macro dash_nest_bumper}
@visibleForTesting
DashNestBumper.test({required this.bloc})
: _majorRadius = 3,
DashNestBumper.test({DashNestBumperCubit? bloc})
: bloc = bloc ?? DashNestBumperCubit(),
_majorRadius = 3,
_minorRadius = 2.5;
final double _majorRadius;

@ -0,0 +1,84 @@
// ignore_for_file: cascade_invocations
import 'dart:async';
import 'package:bloc_test/bloc_test.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/components/flutter_forest/behaviors/behaviors.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
import '../../../../helpers/helpers.dart';
void main() {
group('FlutterForestBonusBehavior', () {
late GameBloc gameBloc;
setUp(() {
gameBloc = MockGameBloc();
whenListen(
gameBloc,
const Stream<GameState>.empty(),
initialState: const GameState.initial(),
);
});
final flameBlocTester = FlameBlocTester<PinballGame, GameBloc>(
gameBuilder: EmptyPinballTestGame.new,
blocBuilder: () => gameBloc,
);
flameBlocTester.testGameWidget(
'adds GameBonus.dashNest to the game when all bumpers are active',
setUp: (game, tester) async {
final behavior = FlutterForestBonusBehavior();
final parent = FlutterForest.test();
final bumpers = [
DashNestBumper.test(),
DashNestBumper.test(),
DashNestBumper.test(),
];
await parent.addAll(bumpers);
await game.ensureAdd(parent);
await parent.ensureAdd(behavior);
for (final bumper in bumpers) {
bumper.bloc.onBallContacted();
}
await tester.pump();
verify(
() => gameBloc.add(const BonusActivated(GameBonus.dashNest)),
).called(1);
},
);
flameBlocTester.testGameWidget(
'adds a new ball to the game when all bumpers are active',
setUp: (game, tester) async {
final behavior = FlutterForestBonusBehavior();
final parent = FlutterForest.test();
final bumpers = [
DashNestBumper.test(),
DashNestBumper.test(),
DashNestBumper.test(),
];
await parent.addAll(bumpers);
await game.ensureAdd(parent);
await parent.ensureAdd(behavior);
for (final bumper in bumpers) {
bumper.bloc.onBallContacted();
}
await game.ready();
expect(
game.descendants().whereType<Ball>().single,
isNotNull,
);
},
);
});
}

@ -1,9 +1,7 @@
// ignore_for_file: cascade_invocations
import 'package:bloc_test/bloc_test.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:pinball/game/game.dart';
import 'package:pinball_components/pinball_components.dart';
@ -78,25 +76,5 @@ void main() {
},
);
});
// TODO(alestiago): Consider refactoring once the following is merged:
// https://github.com/flame-engine/flame/pull/1538
// ignore: public_member_api_docs
flameTester.test('closes bloc when removed', (game) async {
final bloc = MockFlutterForestCubit();
whenListen(
bloc,
const Stream<FlutterForestState>.empty(),
initialState: const FlutterForestState.initial(),
);
when(bloc.close).thenAnswer((_) async {});
final flutterForest = FlutterForest.test(bloc: bloc);
await game.ensureAdd(flutterForest);
game.remove(flutterForest);
await game.ready();
verify(bloc.close).called(1);
});
});
}

@ -85,5 +85,3 @@ class MockGameFlowController extends Mock implements GameFlowController {}
class MockAlienBumper extends Mock implements AlienBumper {}
class MockSparkyBumper extends Mock implements SparkyBumper {}
class MockFlutterForestCubit extends Mock implements FlutterForestCubit {}

Loading…
Cancel
Save