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