Skip to content

thoughtbot/capybara_accessibility_audit

CapybaraAccessibilityAudit

Extend your Capybara-powered System Tests to automatically audit the page for WCAG Standards-based accessibility violations.

Usage

Failure:
Found 1 accessibility violation:

1) label: Form elements must have labels (critical)
    https://dequeuniversity.com/rules/axe/4.4/label?application=axeAPI
    The following 1 node violate this rule:

        Selector: input
        HTML: <input>
        Fix any of the following:
        - Form element does not have an implicit (wrapped) <label>
        - Form element does not have an explicit <label>
        - aria-label attribute does not exist or is empty
        - aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty
        - Element has no title attribute
        - Element has no placeholder attribute
        - Element's default semantics were not overridden with role="none" or role="presentation"

Invocation: axe.run({:exclude=>[]}, {}, callback);

Installing the gem will automatically configure your System Tests to audit for accessibility violations after common actions, including:

Under the hood, capybara_accessibility_audit relies on axe-core-rspec, which uses aXe to audit for accessibility violations. To configure which options are passed to the be_axe_clean matcher, override the class-level accessibility_audit_options. Supported keys include:

To override the class-level setting, wrap code in calls to the with_accessibility_audit_options method:

with_accessibility_audit_options according_to: :wcag21aaa do
  visit page_with_violations_path
end

Active Support instrumentation

Capybara Accessibility Audit integrates with Active Support's instrumentation through publishing ActiveSupport::Notifications.

audit.capybara_accessibility_audit notification

Subscribe to audit.capybara_accessibility_audit notifications emitted when an accessibility audit is automatically conducted. In addition to the metadata provided by default (like name, duration, and allocations, etc.), the payload includes additional information:

Payload Type Description
method Symbol The Capybara method that triggered the audit
options ActiveSupport::OrderedOptions The audit's configuration
test ActionDispatch::SystemTestCase The test case that triggered the audit

Note

The audit.capybara_accessibility_audit notifications are only published when an audit is conducted automatically. No audit.capybara_accessibility_audit notifications will be published when assert_no_accessibility_violations is invoked directly.

report.capybara_accessibility_audit notification

Subscribe to report.capybara_accessibility_audit notifications emitted when an accessibility audit detects violations. The payload includes:

Payload Type Description
report Axe::API::Results The underlying axe.js Results object
options ActiveSupport::OrderedOptions The audit's configuration
test ActionDispatch::SystemTestCase The test case that triggered the audit

Note

The report.capybara_accessibility_audit notifications are only published when config.capybara_accessibility_audit.reporter is configured with :notification or :log.

Frequently Asked Questions

My application already exists, automated accessibility audits are uncovering violations left and right. Do I have to fix them all at once?

Your suite has control over which rules are skipped and which rules are enforced through the accessibility_audit_options configuration.

Configuration overrides can occur at any scope, ranging from class-wide to block-wide.

For example, to skip a rule at the suite-level, override it in your ApplicationSystemTestCase:

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  accessibility_audit_options.skipping = %w[label button-name image-alt]
end

To skip a rule at the test-level, wrap the test in a with_accessibility_audit_options block:

class MySystemTest < ApplicationSystemTestCase
  test "with overridden accessibility audit options" do
    with_accessibility_audit_options skipping: %w[label button-name image-alt] do
      visit examples_path
      # ...
    end
  end
end

To skip a rule at the block-level, wrap the code in a with_accessibility_audit_options block:

class MySystemTest < ApplicationSystemTestCase
  test "with overridden accessibility audit options" do
    visit examples_path

    with_accessibility_audit_options skipping: %w[label button-name image-alt] do
      click_on "A link to a page with a violation"
    end

    # ...
  end
end

As you resolve the violations, you can remove entries from the list of skipped rules.

How many I conduct a preliminary audit that comprehensively exercises my system test suite without failing tests that result in violations?

You can configure the audit's reporting mechanism. By default, the config.capybara_accessibility_audit.reporter value is set to :raise, which will raise violation errors that will fail the test suite.

To log violations, rather than raise them, you can configure config.capybara_accessibility_audit.reporter to :log:

class MySystemTest < ApplicationSystemTestCase
  self.accessibility_audit_reporter = :log

  test "with overridden accessibility :log reporter" do
    visit examples_path
    # ...
  end
end

I've implemented a custom Capybara action to toggle a disclosure element. How can I automatically audit for violations after it's called?

You can add the method to the list of methods that will initiate an automated audit:

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  def toggle_disclosure(locator)
    # ...
  end

  accessibility_audit_after :toggle_disclosure
end

How can I turn off auditing for the entire suite?

You can disable automated auditing within your ApplicationSystemTestCase:

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  self.accessibility_audit_enabled = false
end

How can I turn off auditing for a block of code?

You can disable automated auditing temporarily by wrapping code in a skip_accessibility_audits block:

class MySystemTest < ApplicationSystemTestCase
  test "with overridden accessibility audit options" do
    skip_accessibility_audits do
      visit a_page_with_violations_path

      click_on "A link to a page with a violation"
    end

    # ...
  end
end

How can I turn off auditing hooks for a method?

You can remove the method from the test's Set of accessibility_audit_after_methods configuration by calling skip_accessibility_audit_after:

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  skip_accessibility_audit_after :visit
end

How can I turn off auditing for a test file?

You can disable automated auditing at the class-level:

class MySystemTest < ApplicationSystemTestCase
  self.accessibility_audit_enabled = false
end

As you gradually address violations, you can re-enable audits within with_accessibility_audits blocks:

class MySystemTest < ApplicationSystemTestCase
  self.accessibility_audit_enabled = false

  test "a test with a violation" do
    visit examples_path

    with_accessibility_audits do
      click_on "A link to a page with violations"
    end
  end
end

Installation

Add this line to your application's Gemfile:

gem "capybara_accessibility_audit"

And then execute:

$ bundle

Contributing

Please read CONTRIBUTING.md.

License

The gem is available as open source under the terms of the MIT License.

About thoughtbot

thoughtbot

This repo is maintained and funded by thoughtbot, inc. The names and logos for thoughtbot are trademarks of thoughtbot, inc.

We love open source software! See our other projects. We are available for hire.

About

Accessibility tooling for Capybara

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Contributors 6