axe DevTools RSpec
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 runbundle install
.
gem "axe-devtools-rspec"
spec.add_dependency "axe-devtools-rspec"
- Require
axe-rspec
, which extendsRSpec
with custom matchers. Ideally, this would be specified in the filespec/spec_helper.rb
.
require 'axe-rspec'
- Use the gem with the WebDriver of choice.
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