createMock(CsrfTokenManagerInterface::class); return new CsrfProtectionSubscriber($csrfManager); } public function testSubscribedEvents(): void { $events = CsrfProtectionSubscriber::getSubscribedEvents(); self::assertArrayHasKey(KernelEvents::REQUEST, $events); self::assertArrayHasKey(KernelEvents::RESPONSE, $events); } public function testIgnoresGetRequests(): void { $subscriber = $this->createSubscriber(); $request = Request::create('/test', 'GET'); $request->attributes->set('_route', 'app_test'); $kernel = $this->createMock(HttpKernelInterface::class); $event = new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST); $subscriber->onKernelRequest($event); self::assertNull($event->getResponse()); } public function testIgnoresExcludedRoutes(): void { $subscriber = $this->createSubscriber(); $request = Request::create('/webhooks/stripe/insta', 'POST'); $request->attributes->set('_route', 'app_stripe_webhook_insta'); $kernel = $this->createMock(HttpKernelInterface::class); $event = new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST); $subscriber->onKernelRequest($event); self::assertNull($event->getResponse()); } public function testIgnoresJsonRequests(): void { $subscriber = $this->createSubscriber(); $request = Request::create('/test', 'POST', [], [], [], ['CONTENT_TYPE' => 'application/json']); $request->attributes->set('_route', 'app_test'); $kernel = $this->createMock(HttpKernelInterface::class); $event = new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST); $subscriber->onKernelRequest($event); self::assertNull($event->getResponse()); } public function testIgnoresPostWithoutToken(): void { $subscriber = $this->createSubscriber(); $request = Request::create('/test', 'POST'); $request->attributes->set('_route', 'app_test'); $kernel = $this->createMock(HttpKernelInterface::class); $event = new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST); $subscriber->onKernelRequest($event); self::assertNull($event->getResponse()); } public function testRejectsInvalidToken(): void { $csrfManager = $this->createMock(CsrfTokenManagerInterface::class); $csrfManager->method('isTokenValid')->willReturn(false); $subscriber = $this->createSubscriber($csrfManager); $request = Request::create('/test', 'POST', ['_csrf_token' => 'bad']); $request->attributes->set('_route', 'app_test'); $kernel = $this->createMock(HttpKernelInterface::class); $event = new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST); $subscriber->onKernelRequest($event); self::assertNotNull($event->getResponse()); self::assertSame(403, $event->getResponse()->getStatusCode()); } public function testAcceptsValidToken(): void { $csrfManager = $this->createMock(CsrfTokenManagerInterface::class); $csrfManager->method('isTokenValid')->willReturn(true); $subscriber = $this->createSubscriber($csrfManager); $request = Request::create('/test', 'POST', ['_csrf_token' => 'valid']); $request->attributes->set('_route', 'app_test'); $kernel = $this->createMock(HttpKernelInterface::class); $event = new RequestEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST); $subscriber->onKernelRequest($event); self::assertNull($event->getResponse()); } public function testInjectsTokenInHtmlResponse(): void { $csrfManager = $this->createMock(CsrfTokenManagerInterface::class); $csrfManager->method('getToken')->willReturn(new CsrfToken('form_protection', 'abc123')); $subscriber = $this->createSubscriber($csrfManager); $response = new Response('
'); $response->headers->set('Content-Type', 'text/html'); $request = Request::create('/test'); $kernel = $this->createMock(HttpKernelInterface::class); $event = new ResponseEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $response); $subscriber->onKernelResponse($event); self::assertStringContainsString('name="_csrf_token"', $response->getContent()); self::assertStringContainsString('value="abc123"', $response->getContent()); } public function testDoesNotInjectInNonHtml(): void { $subscriber = $this->createSubscriber(); $response = new Response('{"ok":true}'); $response->headers->set('Content-Type', 'application/json'); $request = Request::create('/test'); $kernel = $this->createMock(HttpKernelInterface::class); $event = new ResponseEvent($kernel, $request, HttpKernelInterface::MAIN_REQUEST, $response); $subscriber->onKernelResponse($event); self::assertStringNotContainsString('_csrf_token', $response->getContent()); } }