jsonRequest($factory, 'POST', '/auth/register/step1', [ 'race_key' => 'human', ], $cookie); $response1 = $app->handle($step1); self::assertSame(200, $response1->getStatusCode()); $cookie = $this->extractCookie($response1, $cookie); $body1 = json_decode((string)$response1->getBody(), true); self::assertSame('human', $body1['draft']['race_key']); $step2 = $this->jsonRequest($factory, 'POST', '/auth/register/step2', [ 'avatar_key' => 'avatar-01', 'title' => 'Pionier', ], $cookie); $response2 = $app->handle($step2); self::assertSame(200, $response2->getStatusCode()); $cookie = $this->extractCookie($response2, $cookie); $body2 = json_decode((string)$response2->getBody(), true); self::assertSame('avatar-01', $body2['draft']['avatar_key']); $step3 = $this->jsonRequest($factory, 'POST', '/auth/register/step3', [ 'username' => 'neo', 'email' => 'neo@example.test', 'password' => 'change-me', ], $cookie); $response3 = $app->handle($step3); self::assertSame(201, $response3->getStatusCode()); $cookie = $this->extractCookie($response3, $cookie); $meRequest = $factory->createServerRequest('GET', '/me'); if ($cookie) { $meRequest = $meRequest->withHeader('Cookie', $cookie); } $meResponse = $app->handle($meRequest); self::assertSame(200, $meResponse->getStatusCode()); $meBody = json_decode((string)$meResponse->getBody(), true); self::assertSame('neo', $meBody['user']['username']); self::assertSame('human', $meBody['user']['race_key']); $draftCheck = $this->jsonRequest($factory, 'POST', '/auth/register/step2', [ 'avatar_key' => 'avatar-01', 'title' => 'Test', ], $cookie); $draftResponse = $app->handle($draftCheck); self::assertSame(409, $draftResponse->getStatusCode()); } public function testLoginSuccessAndFailure(): void { $pdo = TestDatabase::create(); TestDatabase::reset($pdo); TestDatabase::seedMinimal($pdo); $time = new FixedTimeProvider(new \DateTimeImmutable('2026-02-03 00:00:00')); $app = TestAppFactory::create($pdo, $time); $factory = new ServerRequestFactory(); $badLogin = $this->jsonRequest($factory, 'POST', '/auth/login', [ 'username_or_email' => 'tester', 'password' => 'wrong-pass', ]); $badResponse = $app->handle($badLogin); self::assertSame(401, $badResponse->getStatusCode()); $goodLogin = $this->jsonRequest($factory, 'POST', '/auth/login', [ 'username_or_email' => 'tester', 'password' => 'change-me', ]); $goodResponse = $app->handle($goodLogin); self::assertSame(200, $goodResponse->getStatusCode()); $cookie = $this->extractCookie($goodResponse, null); $meRequest = $factory->createServerRequest('GET', '/me'); if ($cookie) { $meRequest = $meRequest->withHeader('Cookie', $cookie); } $meResponse = $app->handle($meRequest); self::assertSame(200, $meResponse->getStatusCode()); } public function testRegistrationRejectsDuplicates(): void { $pdo = TestDatabase::create(); TestDatabase::reset($pdo); TestDatabase::seedMinimal($pdo); $time = new FixedTimeProvider(new \DateTimeImmutable('2026-02-03 00:00:00')); $app = TestAppFactory::create($pdo, $time); $factory = new ServerRequestFactory(); $cookie = null; $step1 = $this->jsonRequest($factory, 'POST', '/auth/register/step1', [ 'race_key' => 'human', ], $cookie); $response1 = $app->handle($step1); $cookie = $this->extractCookie($response1, $cookie); $step2 = $this->jsonRequest($factory, 'POST', '/auth/register/step2', [ 'avatar_key' => 'avatar-01', 'title' => 'Pilot', ], $cookie); $response2 = $app->handle($step2); $cookie = $this->extractCookie($response2, $cookie); $dupUsername = $this->jsonRequest($factory, 'POST', '/auth/register/step3', [ 'username' => 'tester', 'email' => 'unique@example.test', 'password' => 'change-me', ], $cookie); $dupResponse = $app->handle($dupUsername); self::assertSame(409, $dupResponse->getStatusCode()); $dupEmail = $this->jsonRequest($factory, 'POST', '/auth/register/step3', [ 'username' => 'unique-user', 'email' => 'tester@example.test', 'password' => 'change-me', ], $cookie); $dupEmailResponse = $app->handle($dupEmail); self::assertSame(409, $dupEmailResponse->getStatusCode()); } /** * @param array $payload */ private function jsonRequest(ServerRequestFactory $factory, string $method, string $path, array $payload = [], ?string $cookie = null): \Psr\Http\Message\ServerRequestInterface { $request = $factory->createServerRequest($method, $path) ->withHeader('Content-Type', 'application/json'); if ($cookie) { $request = $request->withHeader('Cookie', $cookie); } if ($payload !== []) { $request->getBody()->write(json_encode($payload)); $request->getBody()->rewind(); } return $request; } private function extractCookie(\Psr\Http\Message\ResponseInterface $response, ?string $fallback): ?string { $setCookie = $response->getHeaderLine('Set-Cookie'); if ($setCookie === '') { return $fallback; } $parts = explode(';', $setCookie); return trim($parts[0]); } }