mirror of https://github.com/flutter/pinball.git
chore: StartGameBloc for control flow before launch the game (#184)
parent
e1bdb0e14b
commit
034c3719bf
@ -0,0 +1,58 @@
|
|||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:pinball/game/game.dart';
|
||||||
|
|
||||||
|
part 'start_game_event.dart';
|
||||||
|
part 'start_game_state.dart';
|
||||||
|
|
||||||
|
/// {@template start_game_bloc}
|
||||||
|
/// Bloc that manages the app flow before the game starts.
|
||||||
|
/// {@endtemplate}
|
||||||
|
class StartGameBloc extends Bloc<StartGameEvent, StartGameState> {
|
||||||
|
/// {@macro start_game_bloc}
|
||||||
|
StartGameBloc({
|
||||||
|
required PinballGame game,
|
||||||
|
}) : _game = game,
|
||||||
|
super(const StartGameState.initial()) {
|
||||||
|
on<PlayTapped>(_onPlayTapped);
|
||||||
|
on<CharacterSelected>(_onCharacterSelected);
|
||||||
|
on<HowToPlayFinished>(_onHowToPlayFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
final PinballGame _game;
|
||||||
|
|
||||||
|
void _onPlayTapped(
|
||||||
|
PlayTapped event,
|
||||||
|
Emitter<StartGameState> emit,
|
||||||
|
) {
|
||||||
|
_game.gameFlowController.start();
|
||||||
|
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
status: StartGameStatus.selectCharacter,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onCharacterSelected(
|
||||||
|
CharacterSelected event,
|
||||||
|
Emitter<StartGameState> emit,
|
||||||
|
) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
status: StartGameStatus.howToPlay,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onHowToPlayFinished(
|
||||||
|
HowToPlayFinished event,
|
||||||
|
Emitter<StartGameState> emit,
|
||||||
|
) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
status: StartGameStatus.play,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
part of 'start_game_bloc.dart';
|
||||||
|
|
||||||
|
/// {@template start_game_event}
|
||||||
|
/// Event added during the start game flow.
|
||||||
|
/// {@endtemplate}
|
||||||
|
abstract class StartGameEvent extends Equatable {
|
||||||
|
/// {@macro start_game_event}
|
||||||
|
const StartGameEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@template play_tapped}
|
||||||
|
/// Play tapped event.
|
||||||
|
/// {@endtemplate}
|
||||||
|
class PlayTapped extends StartGameEvent {
|
||||||
|
/// {@macro play_tapped}
|
||||||
|
const PlayTapped();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@template character_selected}
|
||||||
|
/// Character selected event.
|
||||||
|
/// {@endtemplate}
|
||||||
|
class CharacterSelected extends StartGameEvent {
|
||||||
|
/// {@macro character_selected}
|
||||||
|
const CharacterSelected();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@template how_to_play_finished}
|
||||||
|
/// How to play finished event.
|
||||||
|
/// {@endtemplate}
|
||||||
|
class HowToPlayFinished extends StartGameEvent {
|
||||||
|
/// {@macro how_to_play_finished}
|
||||||
|
const HowToPlayFinished();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
part of 'start_game_bloc.dart';
|
||||||
|
|
||||||
|
/// Defines status of start game flow.
|
||||||
|
enum StartGameStatus {
|
||||||
|
/// Initial status.
|
||||||
|
initial,
|
||||||
|
|
||||||
|
/// Selection characters status.
|
||||||
|
selectCharacter,
|
||||||
|
|
||||||
|
/// How to play status.
|
||||||
|
howToPlay,
|
||||||
|
|
||||||
|
/// Play status.
|
||||||
|
play,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@template start_game_state}
|
||||||
|
/// Represents the state of flow before the game starts.
|
||||||
|
/// {@endtemplate}
|
||||||
|
class StartGameState extends Equatable {
|
||||||
|
/// {@macro start_game_state}
|
||||||
|
const StartGameState({
|
||||||
|
required this.status,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Initial [StartGameState].
|
||||||
|
const StartGameState.initial() : this(status: StartGameStatus.initial);
|
||||||
|
|
||||||
|
/// Status of [StartGameState].
|
||||||
|
final StartGameStatus status;
|
||||||
|
|
||||||
|
/// Creates a copy of [StartGameState].
|
||||||
|
StartGameState copyWith({
|
||||||
|
StartGameStatus? status,
|
||||||
|
}) {
|
||||||
|
return StartGameState(
|
||||||
|
status: status ?? this.status,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [status];
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export 'bloc/start_game_bloc.dart';
|
@ -0,0 +1,62 @@
|
|||||||
|
import 'package:bloc_test/bloc_test.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:mocktail/mocktail.dart';
|
||||||
|
import 'package:pinball/game/game.dart';
|
||||||
|
import 'package:pinball/start_game/bloc/start_game_bloc.dart';
|
||||||
|
|
||||||
|
import '../../helpers/helpers.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
late PinballGame pinballGame;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
pinballGame = MockPinballGame();
|
||||||
|
|
||||||
|
when(
|
||||||
|
() => pinballGame.gameFlowController,
|
||||||
|
).thenReturn(
|
||||||
|
MockGameFlowController(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('StartGameBloc', () {
|
||||||
|
blocTest<StartGameBloc, StartGameState>(
|
||||||
|
'on PlayTapped changes status to selectCharacter',
|
||||||
|
build: () => StartGameBloc(
|
||||||
|
game: pinballGame,
|
||||||
|
),
|
||||||
|
act: (bloc) => bloc.add(const PlayTapped()),
|
||||||
|
expect: () => [
|
||||||
|
const StartGameState(
|
||||||
|
status: StartGameStatus.selectCharacter,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
blocTest<StartGameBloc, StartGameState>(
|
||||||
|
'on CharacterSelected changes status to howToPlay',
|
||||||
|
build: () => StartGameBloc(
|
||||||
|
game: pinballGame,
|
||||||
|
),
|
||||||
|
act: (bloc) => bloc.add(const CharacterSelected()),
|
||||||
|
expect: () => [
|
||||||
|
const StartGameState(
|
||||||
|
status: StartGameStatus.howToPlay,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
blocTest<StartGameBloc, StartGameState>(
|
||||||
|
'on HowToPlayFinished changes status to play',
|
||||||
|
build: () => StartGameBloc(
|
||||||
|
game: pinballGame,
|
||||||
|
),
|
||||||
|
act: (bloc) => bloc.add(const HowToPlayFinished()),
|
||||||
|
expect: () => [
|
||||||
|
const StartGameState(
|
||||||
|
status: StartGameStatus.play,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
// ignore_for_file: prefer_const_constructors
|
||||||
|
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:pinball/start_game/bloc/start_game_bloc.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('StartGameEvent', () {
|
||||||
|
test('PlayTapped supports value equality', () {
|
||||||
|
expect(
|
||||||
|
PlayTapped(),
|
||||||
|
equals(PlayTapped()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('CharacterSelected supports value equality', () {
|
||||||
|
expect(
|
||||||
|
CharacterSelected(),
|
||||||
|
equals(CharacterSelected()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('HowToPlayFinished supports value equality', () {
|
||||||
|
expect(
|
||||||
|
HowToPlayFinished(),
|
||||||
|
equals(HowToPlayFinished()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
// ignore_for_file: prefer_const_constructors
|
||||||
|
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:pinball/start_game/bloc/start_game_bloc.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('StartGameState', () {
|
||||||
|
final testState = StartGameState(
|
||||||
|
status: StartGameStatus.selectCharacter,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('initial state has correct values', () {
|
||||||
|
final state = StartGameState(
|
||||||
|
status: StartGameStatus.initial,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(state, StartGameState.initial());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('supports value equality', () {
|
||||||
|
final secondState = StartGameState(
|
||||||
|
status: StartGameStatus.selectCharacter,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(testState, secondState);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('supports copyWith', () {
|
||||||
|
final secondState = testState.copyWith();
|
||||||
|
|
||||||
|
expect(testState, secondState);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('has correct props', () {
|
||||||
|
expect(
|
||||||
|
testState.props,
|
||||||
|
equals([
|
||||||
|
StartGameStatus.selectCharacter,
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in new issue