Swing the A11y Axe as an Elixir Playwright
Accessibility testing without Wallaby.
While working on the PhoenixTest Playwright driver, I was worried I might lose a11y_audit along the way.
This wonderful library wraps axe-core, a JavaScript accessibility testing engine, for ExUnit. Usage with Wallaby and Hound is documented. And then there is the ominous sounding section "For other environments":
get_audit_result =
fn ->
execute_script(A11yAudit.JS.axe_core())
axe_result_map = execute_script(A11yAudit.JS.await_audit_results())
A11yAudit.Results.from_json(axe_result_map)
end
A11yAudit.Assertions.assert_no_violations(get_audit_result.())
And now for Playwright
So mainly, we need the ability to execute some JavaScript in the browser. Since Playwright exposes this functionality via the SDKs, it should be possible with a custom Elixir wrapper also.
And it is! Here are two short snippets showing how:
defmodule MyTest do
use PhoenixTest.Playwright.Case, async: true
alias PhoenixTest.Playwright.Frame
test "is accessible", %{conn: conn} do
conn
|> visit("/")
|> unwrap(&assert_a11y/1)
end
defp assert_a11y(%{frame_id: frame_id}) do
Frame.evaluate(frame_id, A11yAudit.JS.axe_core())
frame_id
|> Frame.evaluate("axe.run()")
|> A11yAudit.Results.from_json()
|> A11yAudit.Assertions.assert_no_violations()
end
end
Notice that we use axe.run()
instead of A11yAudit.JS.await_audit_results()
.
Playwright automatically awaits the Promise returned by axe.run()
, but doesn't support top-level await
s
as used by await_audit_results()
.
And that's it!