buildRequest(post: ['id' => 'demo']); $response = $handler->handle($request, ['id' => 'demo']); self::assertSame(403, $response->status); self::assertStringContainsString('Forbidden', $response->body); } public function testItRejectsARequestWithAnInvalidCsrfToken(): void { $handler = new PostTeamEditor(); $request = $this->buildRequest(post: ['id' => 'demo', '_csrf' => 'tampered']); $response = $handler->handle($request, ['id' => 'demo']); self::assertSame(403, $response->status); } public function testItSavesAValidScenarioAndReturnsTheLocalStorageSnippet(): void { [$token, $cookie] = CsrfToken::issue(self::SECRET); $handler = new PostTeamEditor(); $request = $this->buildRequest( post: $this->validPost($token), cookies: ['__csrf' => $cookie, '__csrf_token' => $token], server: ['__csrf_secret' => self::SECRET], ); $response = $handler->handle($request, ['id' => 'demo']); self::assertSame(200, $response->status); self::assertStringContainsString('localStorage.setItem', $response->body); self::assertStringContainsString('scenario:"demo"', $response->body); } public function testItRejectsAnOutOfBoundsStatAndReRendersTheForm(): void { [$token, $cookie] = CsrfToken::issue(self::SECRET); $handler = new PostTeamEditor(); $post = $this->validPost($token); $post['teamA']['units'][0]['maxHealth'] = '9999'; $request = $this->buildRequest( post: $post, cookies: ['__csrf' => $cookie, '__csrf_token' => $token], server: ['__csrf_secret' => self::SECRET], ); $response = $handler->handle($request, ['id' => 'demo']); self::assertSame(200, $response->status); self::assertStringContainsString('bf-errors', $response->body); self::assertStringContainsString('outside archetype bounds', $response->body); } public function testItEscapesAMaliciousIdSoItCannotBreakOutOfTheScriptBlock(): void { [$token, $cookie] = CsrfToken::issue(self::SECRET); $handler = new PostTeamEditor(); $post = $this->validPost($token); $post['id'] = ''; $request = $this->buildRequest( post: $post, cookies: ['__csrf' => $cookie, '__csrf_token' => $token], server: ['__csrf_secret' => self::SECRET], ); $response = $handler->handle($request, ['id' => $post['id']]); self::assertSame(200, $response->status); // The literal payload that would execute must NOT appear verbatim in the body. self::assertStringNotContainsString('', $response->body); // The JSON-encoded id is what we want to see, with the