Events

Use the normal HttpKernel event lifecycle and the bundle's before-request and after-response hooks.

An intercepted application request runs through the normal Symfony HttpKernel. Controllers, subscribers, security listeners, response listeners, and termination listeners participate in the request just as they do in a functional test.

Request lifecycle

For each request routed into the kernel, the bundle follows this order:

  1. Convert the Playwright request into a Symfony Request.
  2. Call the test case beforeRequest() hook.
  3. Handle the main request through HttpKernel.
  4. Call kernel.terminate when the kernel is terminable.
  5. Persist an enabled profiler profile.
  6. Call the test case afterResponse() hook.
  7. Fulfill the browser request with the Symfony response.

This means normal listeners for kernel.request, kernel.controller, kernel.response, and kernel.terminate continue to work for application requests.

Add a request hook

Override beforeRequest() when a test needs to add controlled request context before the kernel handles it:

php
use Symfony\Component\HttpFoundation\Request;

public function beforeRequest(Request $request): void
{
    $request->headers->set('X-Test-Tenant', 'acme');
}

The hook runs for every request routed through the kernel, including browser subresources that are not handled by the asset bridge. Keep the condition explicit when only one path should change:

php
public function beforeRequest(Request $request): void
{
    if ('/account' === $request->getPathInfo()) {
        $request->attributes->set('test_locale', 'fr');
    }
}

Inspect the response hook

afterResponse() runs after kernel termination and receives the Symfony response:

php
use Symfony\Component\HttpFoundation\Response;

public function afterResponse(Response $response): void
{
    self::assertTrue($response->headers->has('Content-Security-Policy'));
}

Use this hook for a rule that genuinely applies to every intercepted response. For a single scenario, getLastResponse() keeps the assertion closer to the behavior being tested.

Test application events

Application subscribers remain ordinary Symfony services. Prepare or retrieve a recording service from the test container, perform the browser action, then assert the recorded domain event or kernel event:

php
$events = static::getContainer()->get('app.test_event_recorder');

$page = $this->visit('/checkout');
$page->getByRole('button', ['name' => 'Confirm order'])->click();

self::assertSame(['order.confirmed'], iterator_to_array($events));

kernel.terminate listeners complete before afterResponse() and before the browser request is fulfilled. This also allows the profiler to load the profile written during termination.

Know the boundary

Requests served directly by the asset bridge do not enter HttpKernel, so they do not dispatch kernel events or invoke the request hooks. Requests to hosts outside intercepted_hosts remain normal browser network traffic. The boundary is visible and configurable: application URLs use Symfony, direct assets use the asset bridge, and external URLs use the network.