fix: fixed bloc error on behavior with tests

pull/235/head
RuiAlonso 3 years ago
parent 40526bf0fe
commit ff909394ae

@ -1,40 +1,26 @@
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
with HasGameRef<PinballGame>, ParentIsA<Multiballs> {
with
HasGameRef<PinballGame>,
ParentIsA<Multiballs>,
BlocComponent<GameBloc, GameState> {
@override
void onMount() {
super.onMount();
var _previousMultiballBonus = 0;
gameRef.read<GameBloc>().stream.listen((state) {
// TODO(ruimiguel): only when state.bonusHistory dashNest has changed
final multiballBonus = state.bonusHistory.fold<int>(
0,
(previousValue, bonus) {
if (bonus == GameBonus.dashNest) {
previousValue++;
bool listenWhen(GameState? previousState, GameState newState) {
final hasMultiball = newState.bonusHistory.contains(GameBonus.dashNest);
final hasChanged = previousState?.bonusHistory != newState.bonusHistory;
return hasChanged && hasMultiball;
}
return previousValue;
},
);
if (_previousMultiballBonus != multiballBonus) {
_previousMultiballBonus = multiballBonus;
final hasMultiball = state.bonusHistory.contains(GameBonus.dashNest);
if (hasMultiball) {
@override
void onNewState(GameState state) {
parent.children.whereType<Multiball>().forEach((multiball) {
multiball.bloc.onAnimate();
});
}
}
});
}
}

@ -24,6 +24,11 @@ void main() {
setUp(() {
gameBloc = MockGameBloc();
whenListen(
gameBloc,
const Stream<GameState>.empty(),
initialState: const GameState.initial(),
);
});
final flameBlocTester = FlameBlocTester<PinballGame, GameBloc>(
@ -32,74 +37,99 @@ void main() {
assets: assets,
);
flameBlocTester.testGameWidget(
'animate multiballs when new GameBonus.dashNest received',
setUp: (game, tester) async {
final streamController = StreamController<GameState>();
whenListen(
gameBloc,
streamController.stream,
initialState: const GameState.initial(),
group('listenWhen', () {
test(
'is true when the bonusHistory has changed '
'with a new GameBonus.dashNest', () {
final previous = GameState.initial();
final state = previous.copyWith(
bonusHistory: [GameBonus.dashNest],
);
final behavior = MultiballsBehavior();
final parent = Multiballs.test();
final multiballs = [
Multiball.test(bloc: MockMultiballCubit()),
Multiball.test(bloc: MockMultiballCubit()),
Multiball.test(bloc: MockMultiballCubit()),
Multiball.test(bloc: MockMultiballCubit()),
];
expect(
MultiballsBehavior().listenWhen(previous, state),
isTrue,
);
});
await parent.addAll(multiballs);
await game.ensureAdd(parent);
await parent.ensureAdd(behavior);
test(
'is false when the bonusHistory has changed '
'with a bonus different than GameBonus.dashNest', () {
final previous = GameState.initial();
final state = previous.copyWith(
bonusHistory: [GameBonus.androidSpaceship],
);
streamController.add(
GameState.initial().copyWith(bonusHistory: [GameBonus.dashNest]),
expect(
MultiballsBehavior().listenWhen(previous, state),
isFalse,
);
await tester.pump();
});
for (final multiball in multiballs) {
verify(multiball.bloc.onAnimate).called(1);
}
},
test('is false when the bonusHistory state is the same', () {
final state = GameState(
score: 10,
multiplier: 1,
rounds: 0,
bonusHistory: const [],
);
flameBlocTester.testGameWidget(
"don't animate multiballs when now new GameBonus.dashNest received",
setUp: (game, tester) async {
final streamController = StreamController<GameState>();
whenListen(
gameBloc,
streamController.stream,
initialState: const GameState.initial(),
final previous = GameState.initial();
expect(
MultiballsBehavior().listenWhen(previous, state),
isFalse,
);
});
});
group('onNewState', () {
flameBlocTester.testGameWidget(
"calls 'onAnimate' once per each multiball when GameBloc emit state",
setUp: (game, tester) async {
final behavior = MultiballsBehavior();
final parent = Multiballs.test();
final multiballCubit = MockMultiballCubit();
final otherMultiballCubit = MockMultiballCubit();
final multiballs = [
Multiball.test(bloc: MockMultiballCubit()),
Multiball.test(bloc: MockMultiballCubit()),
Multiball.test(bloc: MockMultiballCubit()),
Multiball.test(bloc: MockMultiballCubit()),
Multiball.test(
bloc: multiballCubit,
),
Multiball.test(
bloc: otherMultiballCubit,
),
];
whenListen(
multiballCubit,
const Stream<MultiballState>.empty(),
initialState: MultiballState.initial(),
);
when(multiballCubit.onAnimate).thenAnswer((_) async {});
whenListen(
otherMultiballCubit,
const Stream<MultiballState>.empty(),
initialState: MultiballState.initial(),
);
when(otherMultiballCubit.onAnimate).thenAnswer((_) async {});
await parent.addAll(multiballs);
await game.ensureAdd(parent);
await parent.ensureAdd(behavior);
streamController.add(
GameState.initial().copyWith(
bonusHistory: [GameBonus.sparkyTurboCharge],
),
);
await tester.pump();
behavior.onNewState(
GameState.initial().copyWith(bonusHistory: [GameBonus.dashNest]),
);
for (final multiball in multiballs) {
verifyNever(multiball.bloc.onAnimate);
verify(
multiball.bloc.onAnimate,
).called(1);
}
},
);
});
});
}

Loading…
Cancel
Save