The table compares Fluffy's Phoenix and Playwright backends within the boundaries described below.
- equivalent — matching behavior verified against Playwright;
- structural subset — supports HTML-represented state, with browser-only behavior excluded;
- - — unavailable or not applicable.
| Feature | Phoenix | Playwright |
|---|---|---|
| Frame locators and traversal | - | equivalent |
| Documented CSS locator subset | equivalent | equivalent |
| Text, label, and attribute locators | equivalent | equivalent |
| Structural role and accessible-name subset | structural subset | equivalent |
| DOM assertions and strictness | equivalent | equivalent |
| Page title assertions | equivalent | equivalent |
| Indeterminate checkbox/radio DOM property | - | equivalent |
| Focus, blur, and focus assertions | - | equivalent |
| Structural element actions | structural subset | equivalent |
| Visits, reloads, links, redirects, cookies, and HTTP forms | equivalent | equivalent |
| Phoenix.HTML data-method/data-to actions | structural subset | equivalent |
| LiveView events, patches, navigation, and structural action retry | equivalent | equivalent |
| LiveView form-change delivery and timing | structural subset | equivalent |
| Declarative LiveView keyboard events | structural subset | equivalent |
| Supported mutable form state and ordered submission | equivalent | equivalent |
| Enter implicit form submission | - | equivalent |
| Native constraint validation | - | equivalent |
| Specialized scalar input values | structural subset | equivalent |
| Computed style, layout, and browser accessibility tree | - | equivalent |
| Downloads | equivalent | equivalent |
| Named pages and new tabs | - | equivalent |
| Browser history navigation | - | equivalent |
| Browser cookie helpers and storage-state export | - | equivalent |
| Hover, drag-and-drop, and sequential typing | - | equivalent |
| Dialogs, frame navigation, and browser request/response events | - | equivalent |
| Active-page JavaScript evaluation | - | equivalent |
| JavaScript-owned DOM and default actions | - | equivalent |
| Native invalid, submit, and formdata event ordering | - | equivalent |
| Hard-wrapped textarea, object, and custom-element entries | - | equivalent |
| Per-test sessions, cleanup, and Ecto sandbox propagation | equivalent | equivalent |
| Regex URL matching | equivalent | equivalent |
| Structured path, query, and fragment URL matching | equivalent | equivalent |
| Typed file selection and supported upload lifecycle | equivalent | equivalent |
| Script-opened file chooser events | - | equivalent |
Boundaries
When to choose Playwright
Use Playwright for computed style, layout, browser accessibility, native validation, arbitrary JavaScript, and browser network events. Phoenix operates on parsed HTML and mutable form state. Even Phoenix checks structural visibility; see Visibility and DOM presence for the distinction from browser rendering and DOM absence.
LiveView timing and keyboard events
LiveView eagerly dispatches each applicable form-control phx-change and
ignores phx-debounce/phx-throttle scheduling, including phx-debounce="blur".
Phoenix does not model focus; its change delivery is independent of focus. Use
Playwright for delay, blur-only delivery, coalescing, cancellation, and throttle
suppression.
Fluffy.press/4 has a driver-specific contract:
- Static: unsupported; raises
Fluffy.CapabilityErrorfor every key. - LiveView: passes the supplied key unchanged to LiveViewTest keydown/keyup
handlers bound to the selected element. This includes window bindings on that
element, without discovering handlers elsewhere in the document. LiveViewTest
supplies event values and targeting. Fluffy does not apply
phx-keyfilters, translate keys or modifier combinations, synthesize field values, or simulate focus movement, editing, activation, or implicit submission. An element with no keyboard binding raises. Callers supply the intended key value. - Playwright: native browser key presses, including default actions and Playwright modifier syntax.
Filling contenteditable elements requires Playwright. Static and LiveView fill input and textarea controls; they do not emulate editing element text.
Focus and client state
Fluffy.Playwright.focus/3, Fluffy.Playwright.blur/3, and focus assertions
require Playwright. Static and LiveView do not track or simulate focus.
On a changed LiveView render, local text values adopt the rendered value,
except during phx-trigger-action handoff. Unchanged document renders preserve
local values. Changes are detected across the document, not per control, so an
unrelated update can discard local text. Checkbox/radio state survives while the
rendered checked attribute is unchanged. Selected options survive while the
option signature is unchanged; files survive while the matched control remains
a file input. Use Playwright for focused input protection and exact browser patch
behavior.
LiveView document and patch boundaries
LiveView locators and actions see the current Phoenix.LiveViewTest.View, not the
surrounding dead layout. Use Phoenix.ConnTest for initial outer-layout HTML assertions
or Playwright for full-document interactions. LiveView Fluffy.unwrap/2 receives only
the View.
Tabs, windows, and iframes
The Playwright backend exposes page handles for browser tabs and popup windows.
All public page-management helpers live in Fluffy.Playwright and reject Phoenix
sessions. Phoenix retains one current document internally; use shared page URL,
title, and status assertions to inspect it.
Fluffy.Playwright.new_page/1 returns a handle; Fluffy.Playwright.switch_page/2 selects it for subsequent actions.
Use frame locators to query iframe contents with
Playwright. Page switching does not select an iframe, and frame locators do not
change the active page.
Static and LiveView can query the iframe element in their current markup, but
do not load its src or parse its srcdoc as a child document. They do not
flatten iframe contents into the parent document or ignore frame boundaries:
executing a frame-traversing query raises Fluffy.CapabilityError. Visit the
embedded route directly to test it independently with Phoenix; use Playwright
to test the embedding behavior. See
Pages, popups, and frames
for how pages, browser contexts, and frames relate.
Browser baseline
Fluffy verifies compatibility against pinned Chromium. Firefox and WebKit are available through Playwright but are not covered by Fluffy's conformance suite.
Phoenix.HTML actions and dialogs
For a Static or LiveView target with data-confirm, Fluffy.click/2 ignores the
attribute and continues with the normal structural action. It does not create, inspect,
accept, or dismiss a browser dialog; use Playwright whenever the prompt or its
cancellation path is part of the assertion. Both in-process drivers model the pinned
Phoenix.HTML data-method/data-to hidden-form action for plain elements, including
links and buttons. Custom phoenix.link.click listeners, cancellation, and competing
LiveView actions remain browser-only.
Forms and files
Static and LiveView bypass native validation and retain specialized scalar input values as supplied strings. Use Playwright for validation events and blocking, browser sanitization/defaults, and custom or form-associated elements.
Native reset-button behavior requires Playwright. Static and LiveView clicks do
not restore form defaults or clear file selections. LiveView reset buttons with
phx-click still dispatch their server event.
File selection supports bounded local paths and typed in-memory payloads, ordered multiple selection, clearing, and ordinary multipart forms, including empty-file entries. Managed LiveView uploads support validation, progress, cancellation, replacement, auto-upload, and submission.
Native picker UI, external uploaders, directories, drag-and-drop, and arbitrary
FileList mutation are unsupported. Fluffy.Event.file_chooser/1 requires Playwright
because application JavaScript opens the chooser.
Native escape hatch
Fluffy.unwrap/2 exposes driver-specific APIs: Plug.Conn,
Phoenix.LiveViewTest.View, or Fluffy.Playwright.Handle. Use the shared event
and page APIs for lifecycle operations. See
Native escape hatch for callback behavior.