Fluffy

A friendly three-headed Fluffy asleep beside an Elixir wizard playing a flute, with the heads labeled Live, Static, and Playwright

Phoenix feature tests. Three drivers, one Playwright-shaped API.

Hex.pm HexDocs CI License

Fluffy runs tests through ConnTest, LiveViewTest, or a real browser. Its in-process drivers are checked against Playwright, grounding their behavior in browser reality.

Coming from PhoenixTest? Fluffy adds strict, composable locators, per-test backend selection within one module, and Playwright-style assertion retries and action waiting. See the differences →

start_session(:phoenix)
|> visit("/creatures")
|> fill(by_label("Name"), "Basilisk")
|> click(by_role(:button, name: "Register"))
|> expect(by_role(:heading, name: "Basilisk") |> to_be_visible())
|> expect(Page.to_have_url("/creatures/basilisk"))

Getting started

Add the dependency:

# mix.exs
defp deps do
[
{:fluffy, "~> 0.2.0", only: :test}
]
end

Configure the endpoint:

# config/test.exs
config :fluffy, endpoint: MyAppWeb.Endpoint

Every Fluffy test establishes a lifecycle scope and imports the shared API:

use ExUnit.Case, async: true
import Fluffy
import Fluffy.Expect
import Fluffy.Locator
alias Fluffy.Page
setup context do
Fluffy.Test.setup(context)
end

Start with start_session(:phoenix) for in-process Static and LiveView tests. Use start_session(:playwright) when a test needs a real browser. See Installation and runtime for Playwright and Ecto sandbox setup, then Usage for writing tests and a shared FluffyCase.

Migrating from PhoenixTest

The pipeline stays familiar; actions and expectations use composable locators:

PhoenixTest Fluffy
fill_in("Name", with: "Basilisk") fill(by_label("Name", exact: true), "Basilisk")
click_button("Register") click(by_role(:button, name: "Register"))
assert_path("/creatures") expect(Page.to_have_url(path: "/creatures"))

See Migrating from PhoenixTest for the full translation table and behavior differences.

Beyond page interactions

Capture downloads, open new tabs, handle dialogs, and observe network events with Fluffy's event API. See Advanced events and pages for examples and the Capability matrix for what each backend supports.

Guides

Developing Fluffy

The project pins the current local-development toolchain in .tool-versions. Fluffy's compatibility floor remains Elixir 1.18 and Node.js 20; development also requires pnpm 11.19.0 and PostgreSQL. From a clean checkout:

mix setup
mix test

Run the ordinary local gate—Styler-backed formatting, warnings-as-errors compilation, strict Credo, and the test suite—with:

mix check

Add test-environment Dialyzer analysis with:

mix quality

License

Fluffy is released under the MIT License.