From 7b9868f04b6a7d3399dd4994406c8f756f9b7a1d Mon Sep 17 00:00:00 2001 From: NolwennD <32613839+NolwennD@users.noreply.github.com> Date: Wed, 11 Jan 2023 20:53:06 +0100 Subject: [PATCH] Improve responses payload (#42) * Deal with shitty php enum and related tools * Refactor RestStartGame --- .../app/Http/Controllers/DTO/RestGame.php | 43 ++++++++++++++++--- .../Http/Controllers/DTO/RestStartGame.php | 8 ++++ .../app/Http/Controllers/GamesController.php | 31 ++----------- .../Repositories/LaravelGamesRepository.php | 11 ++++- qvgds-back/src/Game/Domain/GameStart.php | 14 ++++++ qvgds-back/src/Game/Domain/GameStatus.php | 8 ++-- qvgds-back/src/Game/Service/GamesManager.php | 8 ++-- .../App/Http/Controllers/DTO/RestGameTest.php | 36 ++++++++++++++++ .../Controllers/DTO/RestStartGameTest.php | 36 ++++++++++++++++ qvgds-back/tests/Game/GameFixtures.php | 6 +++ .../tests/Game/Service/GamesManagerTest.php | 4 +- qvgds-back/tests/Json/JsonHelper.php | 36 ++++++++++++++++ 12 files changed, 196 insertions(+), 45 deletions(-) create mode 100644 qvgds-back/src/Game/Domain/GameStart.php create mode 100644 qvgds-back/tests/App/Http/Controllers/DTO/RestGameTest.php create mode 100644 qvgds-back/tests/App/Http/Controllers/DTO/RestStartGameTest.php create mode 100644 qvgds-back/tests/Json/JsonHelper.php diff --git a/qvgds-back/app/Http/Controllers/DTO/RestGame.php b/qvgds-back/app/Http/Controllers/DTO/RestGame.php index ef21415..4d248ab 100644 --- a/qvgds-back/app/Http/Controllers/DTO/RestGame.php +++ b/qvgds-back/app/Http/Controllers/DTO/RestGame.php @@ -19,26 +19,57 @@ */ private function __construct( #[OA\Property] - public string $id, + private string $id, #[OA\Property] - public string $player, + private string $player, #[OA\Property] - public int $step, + private int $step, #[OA\Property] - public int $shitcoins, + private int $shitcoins, #[OA\Property] - public GameStatus $status, + private GameStatus $status, #[OA\Property(items: new OA\Items(type: RestJoker::class))] - public array $jokers + private array $jokers ) { } + public function getId(): string + { + return $this->id; + } + + public function getPlayer(): string + { + return $this->player; + } + + public function getStep(): int + { + return $this->step; + } + + public function getShitcoins(): int + { + return $this->shitcoins; + } + + public function getStatus(): string + { + return $this->status->name; + } + + public function getJokers(): array + { + return $this->jokers; + } + + public static function from(Game $game): self { return new self( diff --git a/qvgds-back/app/Http/Controllers/DTO/RestStartGame.php b/qvgds-back/app/Http/Controllers/DTO/RestStartGame.php index 353ebc9..ccb0b3c 100644 --- a/qvgds-back/app/Http/Controllers/DTO/RestStartGame.php +++ b/qvgds-back/app/Http/Controllers/DTO/RestStartGame.php @@ -5,6 +5,9 @@ use OpenApi\Attributes\Property; use OpenApi\Attributes\Schema; +use QVGDS\Game\Domain\GameId; +use QVGDS\Game\Domain\GameStart; +use QVGDS\Session\Domain\SessionId; #[Schema( title: "Game start", @@ -20,4 +23,9 @@ public function __construct( ) { } + + public function toDomain(): GameStart + { + return new GameStart(GameId::newId(), SessionId::from($this->session), $this->player); + } } diff --git a/qvgds-back/app/Http/Controllers/GamesController.php b/qvgds-back/app/Http/Controllers/GamesController.php index 7edd636..811eb9c 100644 --- a/qvgds-back/app/Http/Controllers/GamesController.php +++ b/qvgds-back/app/Http/Controllers/GamesController.php @@ -16,7 +16,6 @@ use QVGDS\Game\Service\GamesManager; use QVGDS\Session\Domain\Question\Answer; use QVGDS\Session\Domain\Question\Question; -use QVGDS\Session\Domain\SessionId; use Ramsey\Uuid\Uuid; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; @@ -59,11 +58,7 @@ public function start(Request $request): Response /** @var RestStartGame $restStartGame */ $restStartGame = $this->serializer->deserialize($request->getContent(), RestStartGame::class, "json"); - $game = $this->games->start( - GameId::newId(), - new SessionId(Uuid::fromString($restStartGame->session)), - $restStartGame->player - ); + $game = $this->games->start($restStartGame->toDomain()); return new JsonResponse( $this->serializer->normalize(RestGame::from($game)) @@ -100,7 +95,7 @@ public function list(): Response { $games = $this->games->list(); $json = array_map( - fn(Game $game): array => $this->serializeWithQuestions($game), + fn(Game $game): array => $this->serializer->normalize(RestGame::from($game)), $games ); return new JsonResponse($json); @@ -133,7 +128,7 @@ public function guess(Request $request, string $gameId): Response [ "shitcoins" => $gameOrFail->game->shitCoins()->amount(), "goodAnswer" => $gameOrFail->game->currentQuestion()->goodAnswer()->text, - "gameStatus" => $gameOrFail->game->status()->value + "gameStatus" => $gameOrFail->game->status()->name ], Response::HTTP_BAD_REQUEST ); @@ -149,25 +144,6 @@ public function fiftyFifty(string $gameId): Response return new JsonResponse(["badAnswers" => $json]); } - /** - * @return array - */ - private function serializeWithQuestions(Game $game): array - { - return [ - "id" => $game->id()->get(), - "player" => $game->player(), - "step" => $game->step(), - "status" => $game->status(), - "questions" => [ - array_map( - fn(Question $q): array => ["question" => $q->text(), "answers" => $this->serializeAnswers($q)], - $game->session()->questions() - ) - ] - ]; - } - public function jokers(string $gameId): Response { $game = $this->getGame($gameId); @@ -194,5 +170,4 @@ private function serializeAnswers(Question $question): array return array_map(fn(Answer $a): array => ["answer" => $a->text], $answers); } - } diff --git a/qvgds-back/app/Repositories/LaravelGamesRepository.php b/qvgds-back/app/Repositories/LaravelGamesRepository.php index 1fa7aed..c17d9d7 100644 --- a/qvgds-back/app/Repositories/LaravelGamesRepository.php +++ b/qvgds-back/app/Repositories/LaravelGamesRepository.php @@ -82,7 +82,7 @@ private function toDomain(LaravelGame $laravelGame): Game $laravelGame->player, new Jokers(...$laravelGame->jokers()->get()->map(fn(LaravelJoker $joker) => $this->buildJoker($joker))->toArray()), $laravelGame->session()->get()->map(fn(LaravelSession $session): Session => LaravelSessionsRepository::toDomain($session))->first(), - GameStatus::from($laravelGame->status), + $this->buildGameStatus($laravelGame->status), $laravelGame->step ); } @@ -103,4 +103,13 @@ private function match(string $status): JokerStatus JokerStatus::ALREADY_USED->name => JokerStatus::ALREADY_USED, }; } + + private function buildGameStatus(string $status): GameStatus + { + return match ($status) { + GameStatus::IN_PROGRESS->name => GameStatus::IN_PROGRESS, + GameStatus::LOST->name => GameStatus::LOST, + GameStatus::FORGIVEN->name => GameStatus::FORGIVEN, + }; + } } diff --git a/qvgds-back/src/Game/Domain/GameStart.php b/qvgds-back/src/Game/Domain/GameStart.php new file mode 100644 index 0000000..dcbe5b1 --- /dev/null +++ b/qvgds-back/src/Game/Domain/GameStart.php @@ -0,0 +1,14 @@ +sessions->get($sessionId); + $session = $this->sessions->get($gameStart->sessionId); if ($session === null) { throw new SessionNotFoundException(); } - $game = Game::start($id, $player, $session); + $game = Game::start($gameStart->gameId, $gameStart->player, $session); $this->games->save($game); diff --git a/qvgds-back/tests/App/Http/Controllers/DTO/RestGameTest.php b/qvgds-back/tests/App/Http/Controllers/DTO/RestGameTest.php new file mode 100644 index 0000000..2f29b7b --- /dev/null +++ b/qvgds-back/tests/App/Http/Controllers/DTO/RestGameTest.php @@ -0,0 +1,36 @@ +json(), $json); + } + + private function json(): string + { + return + '{"id":"7cb03186-5430-45c2-9bdb-d5993a4ad209",' + . '"player":"Toto",' + . '"step":1,' + . '"shitcoins":0,' + . '"status":"IN_PROGRESS",' + . '"jokers":[' + . '{"type":"FIFTY_FIFTY","status":"AVAILABLE"},' + . '{"type":"CALL_A_FRIEND","status":"AVAILABLE"},' + . '{"type":"AUDIENCE_HELP","status":"AVAILABLE"}]' + . '}'; + } + +} diff --git a/qvgds-back/tests/App/Http/Controllers/DTO/RestStartGameTest.php b/qvgds-back/tests/App/Http/Controllers/DTO/RestStartGameTest.php new file mode 100644 index 0000000..79b9200 --- /dev/null +++ b/qvgds-back/tests/App/Http/Controllers/DTO/RestStartGameTest.php @@ -0,0 +1,36 @@ +json(), RestStartGame::class); + + $gameStart = $restStartGame->toDomain(); + + self::assertEquals($gameStart->player, "toto"); + self::assertEquals($gameStart->sessionId, SessionId::from("b72ff86d-20fc-47f6-bbce-cd931a1a925d")); + self::assertInstanceOf(GameId::class, $gameStart->gameId); + } + + private function json(): string + { + return <<<'JSON' + { + "player": "toto", + "session": "b72ff86d-20fc-47f6-bbce-cd931a1a925d" + } + JSON; + + } +} diff --git a/qvgds-back/tests/Game/GameFixtures.php b/qvgds-back/tests/Game/GameFixtures.php index 3c018f8..fe9ff7d 100644 --- a/qvgds-back/tests/Game/GameFixtures.php +++ b/qvgds-back/tests/Game/GameFixtures.php @@ -5,6 +5,7 @@ use QVGDS\Game\Domain\Game; use QVGDS\Game\Domain\GameId; +use QVGDS\Game\Domain\GameStart; use QVGDS\Tests\Session\SessionFixtures; use Ramsey\Uuid\Uuid; @@ -24,4 +25,9 @@ public static function player(): string { return "Toto"; } + + public static function gameStart(): GameStart + { + return new GameStart(self::gameId(), SessionFixtures::sessionId(), self::player()); + } } diff --git a/qvgds-back/tests/Game/Service/GamesManagerTest.php b/qvgds-back/tests/Game/Service/GamesManagerTest.php index c012745..750c7f8 100644 --- a/qvgds-back/tests/Game/Service/GamesManagerTest.php +++ b/qvgds-back/tests/Game/Service/GamesManagerTest.php @@ -38,7 +38,7 @@ protected function setUp(): void public function shouldNotStartAGameWithUnknownSession(): void { $this->expectException(SessionNotFoundException::class); - $this->service->start(GameId::newId(), SessionFixtures::sessionId(), "Toto"); + $this->service->start(GameFixtures::gameStart()); } /** @@ -128,6 +128,6 @@ public function shouldForgiveAGame(): void private function prepareGame(): void { $this->sessions->save(SessionFixtures::sessionWithQuestions()); - $this->service->start(GameFixtures::gameId(), SessionFixtures::sessionId(), "Toto"); + $this->service->start(GameFixtures::gameStart()); } } diff --git a/qvgds-back/tests/Json/JsonHelper.php b/qvgds-back/tests/Json/JsonHelper.php new file mode 100644 index 0000000..c71041b --- /dev/null +++ b/qvgds-back/tests/Json/JsonHelper.php @@ -0,0 +1,36 @@ +serialize($from, "json"); + } + + /** + * @template T of object + * @param class-string $className + * @return T + */ + public static function readFromJson(string $payload, string $className): object + { + return self::serializer()->deserialize($payload, $className, "json"); + } + + private static function serializer(): SerializerInterface + { + $encoders = [new JsonEncoder()]; + $normalizers = [new GetSetMethodNormalizer(), new PropertyNormalizer()]; + + return new Serializer($normalizers, $encoders); + } +}