# Excessibility
[](https://hex.pm/packages/excessibility)
[](https://hexdocs.pm/excessibility)
[](https://github.com/your-org/excessibility/actions)
[](LICENSE)
**Accessibility Snapshot Testing for Elixir + Phoenix**
Excessibility helps you test your Phoenix apps for accessibility (WCAG compliance) by taking HTML snapshots during tests and running them through Pa11y.
It integrates with Plug.Conn, Wallaby.Session, Phoenix.LiveViewTest.View, and more. You can also diff snapshots against a baseline, auto-open mismatches, and interactively approve changes.
✨ Features
✅ Snapshot HTML from Conn/LiveView/Wallaby
✅ Save and manage snapshot files
✅ Automatically diff against saved baselines
✅ Interactive approval (good/bad) when snapshots change
✅ Mockable system/browser calls for CI
✅ Clean test output and file organization
🛠 Installation
Add to mix.exs:
def deps do
[
{:excessibility, github: "your-org/excessibility"}
]
end
Run `mix excessibility.install` once after fetching deps so Pa11y is installed under `assets/node_modules/`.
### Configuration
Add the endpoint and optional overrides to your config or test helper:
```elixir
config :excessibility,
:endpoint, MyAppWeb.Endpoint,
:system_mod, Excessibility.System,
:browser_mod, Wallaby.Browser,
:live_view_mod, Excessibility.LiveView,
:excessibility_output_path, "test/excessibility"
```
If you enable `screenshot?: true`, ensure `ChromicPDF` is supervised in your application (e.g., `{ChromicPDF, name: ChromicPDF}`) so the library can render PNGs of each snapshot.
📸 Usage
In your test:
import Excessibility
html_snapshot(conn, __ENV__, __MODULE__)
You can snapshot from:
Plug.Conn
Wallaby.Session
Phoenix.LiveViewTest.View
Phoenix.LiveViewTest.Element
Options
html_snapshot(source, env, mod, [
open_browser?: true,
cleanup?: true,
tag_on_diff: true,
prompt_on_diff: true,
name: "homepage.html",
screenshot?: true
])
🔍 Snapshot Diffing
Snapshots are saved to: test/excessibility/html_snapshots/
Baselines live in: test/excessibility/baseline/
If a snapshot differs:
You’ll be shown .good.html (baseline) and .bad.html (new).
You're prompted to keep the good or bad version.
The baseline is updated accordingly.
🧪 Testing
Set up mocks in test/test_helper.exs:
Mox.defmock(Excessibility.SystemMock, for: Excessibility.SystemBehaviour)
Application.put_env(:excessibility, :system_mod, Excessibility.SystemMock)
Then define expectations in your test:
SystemMock
|> expect(:open_with_system_cmd, fn path -> ... end)
🧼 Cleaning Up
To remove old snapshots for a test module:
html_snapshot(conn, env, mod, cleanup?: true)
🧰 Mix Tasks
- `mix excessibility.install` – installs Pa11y into `assets/node_modules/`.
- `mix excessibility` – runs Pa11y against every generated snapshot (fails fast if Pa11y is missing).
- `mix excessibility.approve [--keep good|bad]` – promotes `.good/.bad.html` diffs back into the `baseline/` directory without rerunning the test suite.
🧩 Coming Soon
mix excessibility.lint — run Pa11y on snapshots
mix excessibility.approve — promote diffs to baseline
Visual snapshot diffing
📄 License
MIT © Andrew Moore