From 5b4b0723c5a86807f9e2b4db18e1c8a9d323e636 Mon Sep 17 00:00:00 2001 From: arturplaczek Date: Wed, 13 Apr 2022 10:40:27 +0200 Subject: [PATCH] chore: create StartGameBloc --- lib/game/bloc/start_game_bloc.dart | 58 ++++++++++++++++++++ lib/game/bloc/start_game_event.dart | 21 ++++++++ lib/game/bloc/start_game_state.dart | 46 ++++++++++++++++ test/game/bloc/start_game_bloc_test.dart | 64 +++++++++++++++++++++++ test/game/bloc/start_game_event_test.dart | 27 ++++++++++ test/game/bloc/start_game_state_test.dart | 43 +++++++++++++++ 6 files changed, 259 insertions(+) create mode 100644 lib/game/bloc/start_game_bloc.dart create mode 100644 lib/game/bloc/start_game_event.dart create mode 100644 lib/game/bloc/start_game_state.dart create mode 100644 test/game/bloc/start_game_bloc_test.dart create mode 100644 test/game/bloc/start_game_event_test.dart create mode 100644 test/game/bloc/start_game_state_test.dart diff --git a/lib/game/bloc/start_game_bloc.dart b/lib/game/bloc/start_game_bloc.dart new file mode 100644 index 00000000..3f04e33f --- /dev/null +++ b/lib/game/bloc/start_game_bloc.dart @@ -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 which allows to control user state before launch the game. +/// {@endtemplate} +class StartGameBloc extends Bloc { + /// {@macro start_game_bloc} + StartGameBloc({ + required PinballGame game, + }) : _game = game, + super(const StartGameState.initial()) { + on(_onSelectCharacter); + on(_onHowToPlay); + on(_onPlay); + } + + final PinballGame _game; + + Future _onSelectCharacter( + SelectCharacter event, + Emitter emit, + ) async { + _game.gameFlowController.start(); + + emit( + state.copyWith( + status: StartGameStatus.selectCharacter, + ), + ); + } + + Future _onHowToPlay( + HowToPlay event, + Emitter emit, + ) async { + emit( + state.copyWith( + status: StartGameStatus.howToPlay, + ), + ); + } + + Future _onPlay( + Play event, + Emitter emit, + ) async { + emit( + state.copyWith( + status: StartGameStatus.play, + ), + ); + } +} diff --git a/lib/game/bloc/start_game_event.dart b/lib/game/bloc/start_game_event.dart new file mode 100644 index 00000000..e3da0afe --- /dev/null +++ b/lib/game/bloc/start_game_event.dart @@ -0,0 +1,21 @@ +part of 'start_game_bloc.dart'; + +/// {@template start_game_event} +/// Event added when user is staring the game. +/// {@endtemplate} +abstract class StartGameEvent extends Equatable { + /// {@macro start_game_event} + const StartGameEvent(); + + @override + List get props => []; +} + +/// Select character event. +class SelectCharacter extends StartGameEvent {} + +/// How to play event. +class HowToPlay extends StartGameEvent {} + +/// Play event. +class Play extends StartGameEvent {} diff --git a/lib/game/bloc/start_game_state.dart b/lib/game/bloc/start_game_state.dart new file mode 100644 index 00000000..72402e81 --- /dev/null +++ b/lib/game/bloc/start_game_state.dart @@ -0,0 +1,46 @@ +part of 'start_game_bloc.dart'; + +/// Defines status of start game flow. +enum StartGameStatus { + /// Starting status. + initial, + + /// Selection characters status. + selectCharacter, + + /// How to play status. + howToPlay, + + /// Play status. + play, +} + +/// {@template start_game_state} +/// Represents the state of flow before launch the game. +/// {@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 get props => [ + status, + ]; +} diff --git a/test/game/bloc/start_game_bloc_test.dart b/test/game/bloc/start_game_bloc_test.dart new file mode 100644 index 00000000..d3d30634 --- /dev/null +++ b/test/game/bloc/start_game_bloc_test.dart @@ -0,0 +1,64 @@ +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:pinball/game/bloc/start_game_bloc.dart'; +import 'package:pinball/game/game.dart'; + +class MockPinballGame extends Mock implements PinballGame {} + +class MockGameFlowController extends Mock implements GameFlowController {} + +void main() { + late PinballGame pinballGame; + + setUp(() { + pinballGame = MockPinballGame(); + + when( + () => pinballGame.gameFlowController, + ).thenReturn( + MockGameFlowController(), + ); + }); + + group('StartGameBloc', () { + blocTest( + 'on SelectCharacter changes status to selectCharacter', + build: () => StartGameBloc( + game: pinballGame, + ), + act: (bloc) => bloc.add(SelectCharacter()), + expect: () => [ + const StartGameState( + status: StartGameStatus.selectCharacter, + ) + ], + ); + + blocTest( + 'on HowToPlay changes status to howToPlay', + build: () => StartGameBloc( + game: pinballGame, + ), + act: (bloc) => bloc.add(HowToPlay()), + expect: () => [ + const StartGameState( + status: StartGameStatus.howToPlay, + ) + ], + ); + + blocTest( + 'on Play changes status to play', + build: () => StartGameBloc( + game: pinballGame, + ), + act: (bloc) => bloc.add(Play()), + expect: () => [ + const StartGameState( + status: StartGameStatus.play, + ) + ], + ); + }); +} diff --git a/test/game/bloc/start_game_event_test.dart b/test/game/bloc/start_game_event_test.dart new file mode 100644 index 00000000..00ddf741 --- /dev/null +++ b/test/game/bloc/start_game_event_test.dart @@ -0,0 +1,27 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball/game/bloc/start_game_bloc.dart'; + +void main() { + group('StartGameEvent', () { + test('SelectCharacter supports value equality', () { + expect( + SelectCharacter(), + equals(SelectCharacter()), + ); + }); + + test('HowToPlay supports value equality', () { + expect( + HowToPlay(), + equals(HowToPlay()), + ); + }); + + test('Play supports value equality', () { + expect( + Play(), + equals(Play()), + ); + }); + }); +} diff --git a/test/game/bloc/start_game_state_test.dart b/test/game/bloc/start_game_state_test.dart new file mode 100644 index 00000000..b59c5c2c --- /dev/null +++ b/test/game/bloc/start_game_state_test.dart @@ -0,0 +1,43 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:flutter_test/flutter_test.dart'; +import 'package:pinball/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, + ]), + ); + }); + }); +}