Playwright Symfony bridges the gap between high-fidelity browser automation and Symfony's in-process testing speed.
The bundle's architecture is built on the principle of Kernel Interception. Instead of the browser making network
requests to a web server, Playwright intercepts all outgoing requests and routes them directly into the Symfony
HttpKernel.
- Test Layer (
PlaywrightTestCase): Orchestrates the lifecycle. Manages a Shared Browser process that is launched once per class. - Client Layer (
PlaywrightKernelClient): The central hub. It implements theBrowserKitAPI and coordinates the interception. - Bridge Utilities:
RequestConverter: Translates Playwright requests (headers, body, cookies) to SymfonyHttpFoundationrequests.ResponseConverter: Translates Symfony responses back to Playwrightfulfilloptions.CookieJarSync: Keeps the browser's cookies in sync with Symfony'sCookieJar.
- Browser Registry (
BrowserRegistry): Browser lifecycle manager that handles process management andBrowserContextisolation. - Asset Layer (
AssetServer): A high-performance bypassing layer that serves static files and AssetMapper assets directly from the filesystem, avoiding Kernel overhead for non-application logic.
When you call $this->visit('/dashboard'):
- Navigation: The
PlaywrightKernelClientcallspage->goto('http://localhost/dashboard'). - Interception: Playwright triggers a route handler registered by the client.
- Asset Check: The
AssetServerchecks if the URL matches an asset prefix (e.g.,/assets/). If so, it fulfills the request immediately from disk. - Kernel Handling: If it's an application route:
RequestConverterbuilds a SymfonyRequest.beforeRequest()hooks are executed.- The
HttpKernelhandles the request and returns aResponse. afterResponse()hooks are executed.ResponseConverterencodes the response (including base64 for binaries).
- Fulfillment: The browser receives the response and renders the DOM.
- DomCrawler Sync: The client builds a fresh
Crawlerfrom the browser's livepage->content().
The bundle optimizes the DI container for testing:
- Autowiring:
BrowserContextInterfaceis automatically available for injection in your tests, aliased to the default configured browser. - Named Browsers: Every browser defined in
playwright.yamlis registered as a unique service (e.g.,playwright.browser.firefox_debug). - Prototypes: The
PlaywrightKernelClientis instantiated manually in the test case to ensure it always has the latest Kernel instance (crucial forWebTestCasestyle isolation).
Launching a browser process takes ~1000ms. By sharing the process across tests in the same class and only calling
restartContext() (~50ms), we achieve near-instant isolation.
By bypassing the network stack, we eliminate socket overhead and allow for advanced features like database transaction sharing and direct profiler inspection.
The AssetServer uses optimized locators to serve assets. This ensures that even if your application is slow, your CSS
and JS are served at lightning speed to the browser.