playwright-php/playwright-symfony
Symfony integration for playwright-php, giving Symfony apps and test suites a clean way to drive real browsers with Playwright for end-to-end testing, scraping, and UI automation.
Architecture fit. This package targets Symfony's BrowserKit/DomCrawler/WebTestCase stack, not Laravel's. That distinction matters up front: the repository name and its WebTestCase integration point are Symfony-specific, and the "Laravel/PHP package" framing in the intake should be corrected before it reaches a roadmap. Architecturally it occupies the same slot as Symfony Panther — it swaps the default kernel-browser client (which fabricates requests and responses in-process, with no JavaScript) for a client that drives a real browser via Playwright. That is a genuinely useful seam: it preserves the Client/Crawler assertion idiom teams already know while adding JavaScript execution, auto-waiting, multi-browser (Chromium/Firefox/WebKit) and first-class traces, video and network interception. It is a test-time dependency only and should never appear in runtime code paths.
Integration feasibility. Feasible but with a non-trivial new runtime surface. Playwright is a Node project; the PHP side talks to a Node driver process, so every dev machine and CI image gains a Node runtime plus downloaded browser binaries (roughly 1–2 GB with dependencies). The integration is therefore not a Composer-only change — it is a Composer change plus an image change plus a CI change. For a Laravel codebase, the honest read is that Laravel's HTTP test client is BrowserKit-derived and a binding may be technically possible, but this package does not ship it, and Laravel Dusk already owns that niche; treat Laravel reuse as bespoke work, not a supported path.
Technical risk. High for the dependency, low for the concept.
NOASSERTION licensing is a hard blocker until cleared. Composer will install it, but legal cannot approve an uncharacterized license for a dependency embedded in the test pipeline. Resolve this before any engineering time is spent.Key questions to put to the maintainers (or answer by spike).
AbstractBrowser/HttpKernelBrowser semantics fully, or is it a parallel client with its own base class? This determines migration cost for existing tests.DomCrawler form submission mapped onto a real DOM? What breaks with shadow DOM or iframes?Stack fit. Best fit is a PHP 8.x / Symfony 6–7 application on PHPUnit with an existing functional test suite and a team that already uses Playwright (or wants to) for end-to-end coverage. The value case is strongest where the current kernel-browser tests are lying to you: anything driven by Stimulus/Turbo, AJAX form submission, client-side validation, third-party widgets, or auth flows with redirects. If the team has no Playwright footprint and no JS-heavy surfaces, Symfony Panther is the lower-risk default and this package is not worth the adoption cost.
Migration path. Do not attempt a suite-wide swap.
tests/Browser) with 5–10 tests ported from tests/Functional, run locally first.npx playwright install --with-deps; keep the existing fast PHPUnit job untouched so the fast feedback loop does not regress.Compatibility. Keep both clients alive behind a shared abstract test base class so the browser client is an implementation detail, not a hard fork of every test. Pin the Playwright npm version, the browser binaries, and the PHP client in lockstep and upgrade them as a single commit — never let them drift. Verify PHPUnit version support (10/11/12) and PHPUnit bridge behaviour with WebTestCase before scheduling work.
Sequencing. Legal → spike → CI image → pilot → gate → rollout. Roughly one sprint for the spike and CI work, one to two sprints of pilot before a go/no-go. The critical path is legal and CI, not the PHP code.
Maintenance. You are adopting a thin but load-bearing dependency that you may end up owning. Budget explicitly for: tracking Playwright releases (monthly-ish), rebuilding CI images when browser versions move, and reading upstream issues yourself because there is no vendor. Assume a 10–20% ongoing engineer allocation for as long as the suite exists; if nobody will hold that, do not adopt.
Support. No commercial support, no dependents to learn from, one maintainer-level bus factor. Internalize the source — it is small enough to read in an afternoon and small enough to vendor if it goes quiet. Document a fallback: Panther is the escape hatch, and the abstraction in the migration plan is what makes that escape cheap.
Scaling. Browser tests run roughly an order of magnitude slower than kernel-browser tests. Plan for sharding (PHPUnit --parallel, multiple CI runners each with its own browser) rather than trying to make a single runner fast. Each concurrent Chromium instance needs real memory (assume ~1–2 GB headroom) and its own port; CI runner sizing usually needs to go up a tier. Store traces, screenshots and videos as failure-only artifacts with a short retention window, or artifact storage costs will surprise you.
Failure modes to design against.
Ramp-up. The PHP side is familiar; the Node/Playwright side is new muscle for most Symfony teams. Realistic estimate: one engineer spends one to two weeks becoming the owner (driver lifecycle, tracing, CI image, upgrade procedure) and writes a short runbook; the wider team needs about half a day of onboarding to write and debug browser tests productively. Without a named owner and a runbook, expect the suite to decay into quarantined, skipped tests within two quarters.
How can I help you explore Laravel packages today?