ltbxd-actorle/tests/Controller/GameControllerTest.php
2026-04-11 12:47:52 +02:00

144 lines
5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Controller;
use App\Controller\GameController;
use App\Entity\Game;
use App\Provider\GameGridProvider;
use App\Repository\GameRepository;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\EntityManagerInterface;
class GameControllerTest extends TestCase
{
public function testStartPassesConfiguredPopularityRangeToGenerator(): void
{
$game = new Game();
$idProperty = new \ReflectionProperty(Game::class, 'id');
$idProperty->setValue($game, 42);
$generator = $this->createMock(GameGridProvider::class);
$generator
->expects($this->once())
->method('generate')
->with(
null,
$this->callback(function (array $config): bool {
$this->assertSame([
'minBucket' => 5,
'maxBucket' => 8,
], $config['popularityRange']);
$this->assertSame(['film', 'character', 'award'], $config['hintTypes']);
$this->assertArrayNotHasKey('watchedOnly', $config);
return true;
})
)
->willReturn($game);
$controller = new class extends GameController {
protected function isCsrfTokenValid(string $id, ?string $token): bool
{
return true;
}
public function getUser(): ?UserInterface
{
return null;
}
};
$controller->setContainer($this->createContainer());
$request = Request::create('/game/start', 'POST', [
'_token' => 'test-token',
'popularity_min_bucket' => '5',
'popularity_max_bucket' => '8',
]);
$request->setSession(new Session(new MockArraySessionStorage()));
$response = $controller->start(
$request,
$generator,
$this->createStub(GameRepository::class),
);
$this->assertInstanceOf(RedirectResponse::class, $response);
$this->assertSame('/', $response->getTargetUrl());
$this->assertSame(42, $request->getSession()->get('current_game_id'));
}
public function testAbandonStoresAttemptedLettersForReveal(): void
{
$game = new Game();
$idProperty = new \ReflectionProperty(Game::class, 'id');
$idProperty->setValue($game, 42);
$em = $this->createMock(EntityManagerInterface::class);
$em->expects($this->once())->method('flush');
$controller = new class extends GameController {
protected function isCsrfTokenValid(string $id, ?string $token): bool
{
return true;
}
public function getUser(): ?UserInterface
{
return null;
}
};
$controller->setContainer($this->createContainer());
$request = Request::create('/game/42/abandon', 'POST', [
'_token' => 'test-token',
'attempted_letters' => '{"0":{"2":"a","3":"!","4":"bc"},"4":{"1":" z "},"oops":"x"}',
]);
$request->setSession(new Session(new MockArraySessionStorage()));
$request->getSession()->set('current_game_id', 42);
$response = $controller->abandon($game, $request, $em);
$this->assertInstanceOf(RedirectResponse::class, $response);
$this->assertSame('/?revealed=1', $response->getTargetUrl());
$this->assertSame(Game::STATUS_ABANDONED, $game->getStatus());
$this->assertSame(42, $request->getSession()->get('revealed_game_id'));
$this->assertNull($request->getSession()->get('current_game_id'));
$this->assertSame([
0 => [
2 => 'A',
4 => 'B',
],
4 => [
1 => 'Z',
],
], $request->getSession()->get('revealed_attempted_letters'));
}
private function createContainer(): ContainerInterface
{
$router = $this->createStub(UrlGeneratorInterface::class);
$router->method('generate')->willReturn('/');
$container = $this->createStub(ContainerInterface::class);
$container->method('has')->willReturnCallback(static fn (string $id): bool => match ($id) {
'router' => true,
'security.token_storage' => false,
default => false,
});
$container->method('get')->willReturnCallback(static fn (string $id) => match ($id) {
'router' => $router,
default => null,
});
return $container;
}
}