- testToggleReady: user was never marked verified, so toggleReady()
returned false before doing anything (an isVerified() gate was
added to the service after this test was written).
- testCheckAllPlayersReadyTransitionsStatus: entityManager mock
returned the same SessionSettingRepository for every getRepository()
call, but the service now also fetches a GameSettingRepository for
the session's total-time setting, causing a TypeError. Route the
mock by requested class instead.
- testChatRegeneratesVerifyCodesIfShared: two competing
method('getSetting') stubs were registered without with()
constraints; PHPUnit keeps the first one it sees active for every
call, so the (correct, more complete) willReturnCallback stub was
silently dead code and the regeneration path never actually ran.
Dropped the redundant first stub, and updated the flush() count now
that the real flow (chat tracking + code regeneration) executes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
128 lines
4.6 KiB
PHP
128 lines
4.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Game;
|
|
|
|
use App\Game\Entity\Game;
|
|
use App\Game\Entity\Player;
|
|
use App\Game\Entity\Session;
|
|
use App\Game\Entity\SessionSetting;
|
|
use App\Game\Enum\SessionSettingType;
|
|
use App\Game\Repository\SessionSettingRepository;
|
|
use App\Game\Service\GameResponseService;
|
|
use App\Game\Service\PlayerService;
|
|
use App\Game\Service\SessionActivityLogger;
|
|
use App\Tech\Entity\User;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Symfony\Bundle\SecurityBundle\Security;
|
|
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
|
|
|
class GameResponseServiceChatVerifyCodeTest extends TestCase
|
|
{
|
|
private string $tempDir;
|
|
private $security;
|
|
private $playerService;
|
|
private $sessionSettingRepository;
|
|
private $eventDispatcher;
|
|
private $entityManager;
|
|
private $service;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->tempDir = sys_get_temp_dir() . '/escapepage_test_' . uniqid();
|
|
mkdir($this->tempDir, 0777, true);
|
|
|
|
$this->security = $this->createMock(Security::class);
|
|
$this->playerService = $this->createMock(PlayerService::class);
|
|
$this->sessionSettingRepository = $this->createMock(SessionSettingRepository::class);
|
|
$this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
|
|
$this->entityManager = $this->createMock(EntityManagerInterface::class);
|
|
|
|
$this->service = new GameResponseService(
|
|
$this->security,
|
|
$this->playerService,
|
|
$this->sessionSettingRepository,
|
|
$this->entityManager,
|
|
$this->eventDispatcher,
|
|
new SessionActivityLogger($this->tempDir),
|
|
$this->tempDir
|
|
);
|
|
|
|
$_ENV['MERCURE_TOPIC_BASE'] = 'http://test';
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
$this->removeDir($this->tempDir);
|
|
}
|
|
|
|
private function removeDir(string $dir): void
|
|
{
|
|
if (!is_dir($dir)) return;
|
|
$files = array_diff(scandir($dir), ['.', '..']);
|
|
foreach ($files as $file) {
|
|
(is_dir("$dir/$file")) ? $this->removeDir("$dir/$file") : unlink("$dir/$file");
|
|
}
|
|
rmdir($dir);
|
|
}
|
|
|
|
public function testChatRegeneratesVerifyCodesIfShared(): void
|
|
{
|
|
$user = new User();
|
|
$user->setUsername('testuser');
|
|
|
|
$game = $this->createMock(Game::class);
|
|
$game->method('getNumberOfPlayers')->willReturn(4);
|
|
|
|
$session = $this->createMock(Session::class);
|
|
$session->method('getId')->willReturn(123);
|
|
$session->method('getGame')->willReturn($game);
|
|
|
|
$player = $this->createMock(Player::class);
|
|
$player->method('getUser')->willReturn($user);
|
|
$player->method('getScreen')->willReturn(1);
|
|
$player->method('getSession')->willReturn($session);
|
|
$player->method('getLogFileBasename')->willReturn('testuser');
|
|
|
|
$this->security->method('getUser')->willReturn($user);
|
|
$this->playerService->method('GetCurrentlyActiveAsPlayer')->willReturn($player);
|
|
|
|
// Mock rights
|
|
$rightsSetting = new SessionSetting();
|
|
$rightsSetting->setValue(json_encode(['chat']));
|
|
|
|
// Mock verify codes
|
|
$verifyCodesSetting = new SessionSetting();
|
|
$initialCodes = ['2' => 'secret123', '3' => 'secret456'];
|
|
$verifyCodesSetting->setValue(json_encode($initialCodes));
|
|
|
|
// Setting repository map for multiple calls
|
|
$this->sessionSettingRepository->method('getSetting')
|
|
->willReturnCallback(function($s, $t, $p = null) use ($rightsSetting, $verifyCodesSetting) {
|
|
if ($t === SessionSettingType::RIGHTS_FOR_PLAYER1) return $rightsSetting;
|
|
if ($t === SessionSettingType::VERIFY_CODES_FOR_PLAYER1) return $verifyCodesSetting;
|
|
return null;
|
|
});
|
|
|
|
// Expect 2 PushMercureMessageEvents dispatched: 1 for chat, 1 for the
|
|
// regenerated-code notification
|
|
$this->eventDispatcher->expects($this->exactly(2))
|
|
->method('dispatch')
|
|
->willReturnArgument(0);
|
|
|
|
// Flushed twice: once for the chat-tracking update, once for the code regeneration
|
|
$this->entityManager->expects($this->exactly(2))
|
|
->method('flush');
|
|
|
|
$raw = json_encode(['message' => '/chat Hello look at my code secret123', 'ts' => '123']);
|
|
$result = $this->service->getGameResponse($raw);
|
|
|
|
$this->assertEquals(['result' => ['succesfully send']], $result);
|
|
|
|
$newCodes = json_decode($verifyCodesSetting->getValue(), true);
|
|
$this->assertNotEquals('secret123', $newCodes['2']);
|
|
$this->assertEquals('secret456', $newCodes['3']);
|
|
}
|
|
}
|