axe DevTools RSpec

Link to axe DevTools RSpec copied to clipboard

The axe-devtools-rspec gem provides custom matchers to evaluate if a given page is axe clean.

This gem extends on top steps provided by the axe-core-rspec gem.

Setup and Usage

Ensure you have access to Deque's registry. If not, refer to the setup documentation.

To set up the RSpec gem, follow these steps:

  • Add axe-devtools-rspec to your Gemfile or gemspec file and run bundle install.
gem "axe-devtools-rspec"
spec.add_dependency "axe-devtools-rspec"
  • Require axe-rspec, which extends RSpec with custom matchers. Ideally, this would be specified in the file spec/spec_helper.rb.
require 'axe-rspec'

API

Matcher - Be axe Clean (be_axe_clean)

To construct an axe accessibility RSpec check, begin with expect(page).to be_axe_clean and append any clauses necessary. (The page object comes from your chosen WebDriver.)

Matcher - Be Audited for Accessibility (be_audited_for_accessibility)

To construct an axe accessibility RSpec check, begin with expect(page).to be_audited_for_accessibility and append any necessary chainable clauses.

expect(page).to be_audited_for_accessibility

Clauses

Clauses are chainable methods for the be_axe_clean custom matcher. Configurable clauses allows for greater granularity with testing and expectations.

within- Inclusion clause

The within clause specifies which elements of the page should be checked. A valid CSS selector must be provided. The within clause accepts a single selector, an array of selectors, or a hash describing iframes with selectors.

For more information, see the context parameter documentation.

Examples:

# Simple selector
expect(page).to be_axe_clean.within '#selector1'

# Compound selector
# Include all elements with the class 'selector2' inside the element with id 'selector1'
expect(page).to be_audited_for_accessibility.within '#selector1 .selector2'

# Multiple selectors
# Include the element with id 'selector1' *and* all elements with class 'selector2'
expect(page).to be_audited_for_accessibility.within '#selector1', '.selector2'

# IFrame selector
# Include the element with id 'selector1' inside the IFrame with id 'frame1'
expect(page).to be_axe_clean.within iframe: '#frame1', selector: '#selector1'

# Multiple IFrame selectors
# Include the element with id 'selector1' inside the IFrame with id 'frame1'
# Include the element with id 'selector2' inside the IFrame with id 'frame2'
expect(page).to be_audited_for_accessibility.within(
  {iframe: '#frame1', selector: '#selector1'},
  {iframe: '#frame2', selector: '#selector2'}
)

# Simple selectors *and* IFrame selector
# Include the element with id 'selector1' *and* all elements with class 'selector2'
# Include the element with id 'selector3' inside the IFrame with id 'frame'
expect(page).to be_audited_for_accessibility.within '#selector1', '.selector2', iframe: '#frame', selector: '#selector3'

# Nested IFrame selectors
# Include the element selector1 inside the IFrame with id 'frame2',
# inside the IFrame with id 'frame1'
expect(page).to be_axe_clean.within(iframe: '#frame1', selector:
  {iframe: '#frame2', selector: '#selector1'}
)
excluding- Exclusion clause

The excluding clause specifies which elements of the document should be ignored. A valid CSS selector must be provided. The excluding clause accepts a single selector, an array of selectors, or a hash describing iframes with selectors.

For more information, see the context parameter documentation.

Examples:

# Simple selector
expect(page).to be_audited_for_accessibility.excluding '#selector1'

# Compound selector
# Exclude all elements with the class 'selector2' inside the element with id 'selector1'
expect(page).to be_axe_clean.excluding '#selector1 .selector2'

# Multiple selectors
# Exclude the element with id 'selector1' *and* all elements with class 'selector2'
expect(page).to be_audited_for_accessibility.excluding '#selector1', '.selector2'

# IFrame selector
# Exclude the element with id 'selector1' inside the IFrame with id 'frame1'
expect(page).to be_axe_clean.excluding iframe: '#frame1', selector: '#selector1'

# Multiple IFrame selectors
# Exclude the element with id 'selector1' inside the IFrame with id 'frame1'
# Exclude the element with id 'selector2' inside the IFrame with id 'frame2'
expect(page).to be_axe_clean.excluding(
  {iframe: '#frame1', selector: '#selector1'},
  {iframe: '#frame2', selector: '#selector2'}
)

# Simple selectors with IFrame selector
# Exclude the element with id 'selector1' *and* all elements with class 'selector2'
# Exclude the element with id 'selector3' inside the IFrame with id 'frame'
expect(page).to be_audited_for_accessibility.excluding '#selector1', '.selector2', iframe: '#frame', selector: '#selector3'

# Nested IFrame selectors
# Exclude the element selector1 inside the IFrame with id 'frame2',
# inside the IFrame with id 'frame1'
expect(page).to be_axe_clean.excluding(iframe: '#frame1', selector:
  {iframe: '#frame2', selector: '#selector1'}
)
according_to- Accessibility Standard (Tag) clause

The according_to clause specifies which accessibility standard (or standards) should be used to check the page. The accessibility standards are specified by name. The according_to clause accepts a single tag, or an array of tags.

The acceptable tag names are documented as well as a complete listing of rules that correspond to each tag.

# Single standard
expect(page).to be_audited_for_accessibility.according_to :wcag2a

# Multiple standards
expect(page).to be_axe_clean.according_to :wcag2a, :section508
checking- Checking Rules clause

The checking clause specifies which additional rules to check in addition to the specified tags (if any) or the default ruleset. The checking clause accepts a single rule, or an array of rules.

For more information, see the rules documentation for a list of valid rule IDs.

# Checking a single rule
expect(page).to be_axe_clean.checking :label

# Checking multiple rules
expect(page).to be_axe_clean.checking :label, :tabindex

# Example specifying an additional best practice rule in addition to all rules in the WCAG2A standard
expect(page).to be_audited_for_accessibility.according_to(:wcag2a).checking(:tabindex)
checking_only- Exclusive Rules clause

The checking_only clause specifies which rules to exclusively check. Using this matcher excludes all rules outside of the list.

# Checking a single rule
expect(page).to be_axe_clean.checking_only :label

# Checking multiple rules
expect(page).to be_audited_for_accessibility.checking_only :label, :tabindex
skipping- Skipping Rules clause

The skipping clause specifies which rules to skip. This allows an accessibility standard to be provided (via the tag clause) while ignoring a particular rule. The rules are specified by comma-separated rule IDs.

For more information, see the rules documentation for a list of valid rule IDs.

# Skipping a single rule
expect(page).to be_axe_clean.skipping :label

# Skipping multiple rules
expect(page).to be_audited_for_accessibility.skipping :label, :tabindex

# Example specifying an additional best practice rule in addition to all rules in the WCAG2A standard
expect(page).to be_axe_clean.according_to(:wcag2a).skipping(:label)
Clauses available only to matcher - Be Audited for accessibility

The be_audited_for_accessibility matcher provides support for two additional clauses.

according_to_ruleset- Ruleset clause

The ruleset clause according_to_ruleset helps specify a single ruleset (for example, 508, wcag2, wcag2.1) to be used to check the page.

 expect(page)
      .to be_audited_for_accessibility
      .according_to_ruleset('wcag2.1')
logging_results- Logging results clause

To log results from the base matcher and clauses, invoke the chainable method logging_results as shown below.

expect(page)
  .to be_audited_for_accessibility
  .logging_results({
    output_directory: 'attest-results',
    test_machine: 'Jenkins CI Server',
    test_suite_name: 'Landing Page',
    ui_state: 'Page Load',
    user_agent: 'Headless Chrome'
  })
Interoperability between clauses

All of the described clauses may be mixed and matched with method chaining. Below are some examples.

expect(page).to be_axe_clean.within('.main', '.header').excluding('.footer')

expect(page).to be_audited_for_accessibility.excluding('#sidebar').according_to(:wcag2a, :wcag2aa).skipping(:color-contrast)

expect(page).to be_axe_clean.within('.main').checking_only :document-title, :label

expect(page).to be_audited_for_accessibility.according_to(:best-practice).checking(:aria-roles, :definition-list)

Advanced API usage

Refer to advanced usage to see how to configure the API for:

  • Custom rules
  • Custom path to axe source
  • Usage recording
  • Reporting