Analyze Pages Using Spec Files

This page is not available in the language you requested. You have been redirected to the English version of the page.
Link to this page copied to clipboard

How to use the spec and bulk-spec subcommands to analyze pages using spec files

Not for use with personal data

A spec file is a JSON or YAML file that defines a list of web pages and the browser actions to run on each page before analyzing for accessibility issues. Use axe spec to run a single spec file, or axe bulk-spec to process a directory of spec files.

The axe spec Command

axe spec <spec-file> <output-dir> [options]

The <output-dir> is where JSON results are saved. If omitted, results are saved in the current working directory.

Example usage:

axe spec ./axe-workflow.yaml ./axe-results --format html

Spec File Structure

A spec file defines one or more projects, each with a list of pages to analyze and optional actions to perform on each page.

YAML Example

projects:
  - name: deque.com
    id: deque.com
    metadata:
      products:
        - CLI
      environment:
        - Prod
    globalActions:
      - dismiss modal "#CybotCookiebotDialog" with close button "#CybotCookiebotDialogBodyButtonAccept"
    pageList:
      - name: Deque search
        url: https://www.deque.com/
        actions:
          - type "axe" into element "#searchform input"
          - click element "#searchform button"
          - wait for element ".m-search-page" to be found
          - analyze
      - name: Axe Dashboard
        url: https://axe.deque.com/

Project

Property Type Description
name string Unique display name of the project.
id string Unique identifier of the project.
metadata object Optional. Arbitrary metadata for your use case (e.g., product name, environment).
globalActions array Optional. Actions that respond to state changes on every page in the project, for example, dismissing a cookie banner or survey pop-up. See Global Actions.
pageList array List of pages to analyze. See Page.

Page

Property Type Description
name string Display name of the page.
url string URL of the page.
actions array Optional. Actions to perform on the page before or after analysis. See Actions.

JSON/YAML Format

Spec files can be written in YAML or JSON. The following table shows the same values in each format. Note that in JSON, action strings that contain double quotes must escape them with a backslash.

YAML JSON
type "axe" into element "#searchform input" "type \"axe\" into element \"#searchform input\""
dismiss modal "#CybotCookiebotDialog" with close button "#CybotCookiebotDialogBodyButtonAccept" "dismiss modal \"#CybotCookiebotDialog\" with close button \"#CybotCookiebotDialogBodyButtonAccept\""

Actions

Actions are strings in the actions (or globalActions) array of a spec file. They perform tasks like clicking buttons, filling forms, dismissing dialogs, waiting for page states, and running accessibility analyses. Actions run in the order listed.

There are two types of actions:

  • Page actions run in sequence on a specific page. The analyze action must be called at least once per page.
  • Global actions run on every page in the project in response to state changes. See Global Actions.

Complete Action Example

The following example logs into Deque University and analyzes the dashboard:

projects:
  - name: Deque University login flow
    id: deque-university-login-flow
    pageList:
      - name: homepage
        url: https://dequeuniversity.com/
        actions:
          - click element ".loginLink"
          - wait for element ".loginUsername" to be found
          - type "user@example.com" into element ".loginUsername"
          - type "secretpassword" into element "#loginPassword"
          - click element "input[type=submit]"
          - wait for element ".logoutLink" to be found
          - analyze page

Selectors

Many actions take a selector argument that identifies an element on the page. A selector can be a CSS selector or XPath selector, specified as a single string or a list of strings.

To target elements inside iframes, you must use a list. All selectors in the list except the last one identify successive <iframe> elements to navigate into, and must be CSS selectors. The last selector in the list identifies the target element and can be CSS or XPath. Each selector in the list is evaluated relative to the document context established by the previous entry: the first selector is relative to the root document, and each subsequent iframe selector is relative to the document inside the preceding iframe.

Using a single string (not a list) cannot navigate into iframes.

Iframe Selector Example

Consider this HTML structure:

<body>
  <!-- root document -->
  <iframe class="payment-widget">
    <!-- document inside the payment-widget iframe -->
    <div class="form-wrapper">
      <iframe id="card-fields">
        <!-- document inside the card-fields iframe -->
        <form>
          <input type="text" name="card-number" class="card-input">
        </form>
      </iframe>
    </div>
  </iframe>
</body>

To click the card number input, use a selector list. Each CSS selector is evaluated within the document context established by the previous entry:

# "iframe.payment-widget" is evaluated in the root document
# "#card-fields" is evaluated in the document inside iframe.payment-widget
# ".card-input" is evaluated in the document inside #card-fields
click element [ "iframe.payment-widget", "#card-fields", ".card-input" ]

To use XPath for the final target element (the iframe selectors must still be CSS):

click element [ "iframe.payment-widget", "#card-fields", "//input[@name='card-number']" ]

In JSON:

"click element [\"iframe.payment-widget\", \"#card-fields\", \".card-input\"]"

Page Actions

The CLI supports nine page actions:

  1. analyze: run an accessibility analysis
  2. change: change the value of an <input>, <textarea>, or <select> via JavaScript
  3. click: click an element
  4. dismiss: dismiss a popup or modal
  5. eval: evaluate arbitrary JavaScript
  6. press: press a key (with or without modifiers)
  7. select: select an option in a <select>
  8. type: type into an <input>
  9. wait: wait for a specific state or sleep

analyze

The analyze action runs an accessibility analysis. It must be called at least once per page. You may call it multiple times to analyze a page at different points in a workflow (use the with title variant to distinguish results).

The optional ruleset parameter specifies which ruleset to use. The default is WCAG 2.1 AA. Available rulesets:

Ruleset ID Standard
wcag2 WCAG 2.0 AA
wcag2.1 WCAG 2.1 AA (default)
wcag2.2 WCAG 2.2 AA
wcag2aaa WCAG 2.0 AAA
wcag2.1aaa WCAG 2.1 AAA
wcag2.2aaa WCAG 2.2 AAA
508 Section 508
ttv5 Trusted Tester v5
en301549 EN 301 549
rgaav4 RGAA v4

For information on including or excluding elements, see the axe-core API documentation on the Context parameter.

# Analyze using the WCAG 2.1 AA ruleset (default) — all three forms are equivalent
analyze
analyze the page
analyze page

# Analyze using the Section 508 ruleset
analyze page with ruleset "508"

# Analyze with a custom title (useful when analyzing a page multiple times)
analyze the page with title "after login"

# Analyze only a specific element
analyze only element "#main-content"

# Analyze only specific elements
analyze only element "#idOfElement" and element ".classToAnalyze"

# Analyze everything except images that are immediate children of paragraphs
analyze the page excluding element "p > img"

# Analyze everything except elements inside a frame with a specific class
analyze the page excluding element [ ".classOfFrameToExclude", "#idOfElement" ]

# Save results to a specific directory
analyze the page and save in "./homepage-team/"

# Save a copy to an additional directory while also saving to the default location
analyze the page and save a copy in "./homepage-team/"

# Use the axe-core library's built-in default ruleset
analyze the page with the source default ruleset

Example combining multiple options: Analyze only images within elements with the class third-party and forms that aren't validated on submission, excluding elements with the class old-api, using the 508 ruleset, with a custom title and a custom save location.

analyze only element [ ".third-party", "img"] and element "form[novalidate]" excluding element ".old-api" with ruleset "508" with title "What is this testing" and save in "Results for Some test"

In JSON:

"analyze only element [\".third-party\", \"img\"] and element \"form[novalidate]\" excluding element \".old-api\" with ruleset \"508\" with title \"What is this testing\" and save in \"Results for Some test\""

change

The change action changes the value of an <input>, <textarea>, or <select> element via JavaScript. Use change when normal DOM events are not available.

# Change the value of an input
change the value of "input[name=song]" to "too many puppies"

click

The click action clicks the first element that matches the given selector.

# Click a button by class selector
click element ".myButton"

# Click the body element
click "body"

dismiss

The dismiss action closes a popup or modal by clicking its close button. Provide a CSS selector for the modal container and another for the close button. The action fails gracefully if either element is not present.

note

This action does not dismiss native alert() or confirm() dialogs.

# Dismiss a modal using separate selectors for the container and close button
dismiss modal ".myModal" with close button ".myModal .close"

eval

The eval action executes arbitrary JavaScript on the page. Use it to manipulate the DOM or perform custom actions.

# Change the page title
eval "document.title = 'hello world'"

# Scroll an element into view
eval "document.querySelector('.someElement').scrollIntoView()"

# Scroll to the bottom of the page
eval "window.scrollTo(0, document.body.scrollHeight)"

press

The press action sends a key press to an element (optionally with modifier keys). For supported key names, see the Selenium key documentation.

# Press H on the body element
press "H" on "body"

# Press Shift+Tab on the navigation element
press "shift+tab" on element ".navigation"

# Press Shift+Control+7 on an element
press "shift+control+7" on element ".foo"

select

The select action selects an <option> of a <select> element by its visible text (not its value attribute).

Given this HTML:

<select class="mySelect">
  <option></option>
  <option value="1">dog</option>
  <option value="2">cat</option>
  <option value="3">fish</option>
</select>
# Select by visible option text
select the "dog" option in ".mySelect"
select the "cat" option in element ".mySelect"

type

The type action types a string into an <input> or <textarea> element. Use it to fill out forms and populate search fields.

# Type into an email input
type "user@example.com" into element "input[type=email]"

# Type into a textarea
type "hello world" into "textarea.Message"

# Type with a delay between keystrokes to simulate human typing
type "sloth" into "input[type=search]" with a 150ms key delay

wait

The wait action either waits for an element to reach a specified state, or sleeps for a given duration.

Supported element states: visible, hidden, selected, enabled, disabled, found.

For sleep duration, numeric values are interpreted as milliseconds. Strings are converted using the ms package — for example, 1m = 60,000 ms, 1s = 1,000 ms.

# Wait for an element to appear
wait for element ".myElement" to be found

# Wait for an element to become hidden
wait for element ".myElement" to be hidden

# Sleep for 1 minute
wait for 1m

# Sleep for 1 second
wait for 1s

# Sleep for 30 milliseconds
wait for 30

Global Actions

Global actions run on every page in a project in response to state changes, rather than running procedurally like page actions. Only one global action is currently supported: dismiss modal.

  • Global actions work in both spec mode and headless URI mode.
  • Global actions are not procedural — they trigger in response to page events, not in a fixed sequence.
  • The dismiss modal global action waits for a specified modal to appear and dismisses it before page actions continue.

Add global actions to a project after name/id and before pageList:

projects:
  - id: demo
    name: CLI demo
    globalActions:
      - dismiss modal "#__next .survey" with close button ".survey button.close"
    pageList:
      - name: homepage
        url: https://dequelabs.github.io/aget-demo-site
      - name: popup
        url: https://dequelabs.github.io/aget-demo-site
        actions:
          - wait for element "#__next header nav" to be visible
          - click element "#__next header nav a[href*=popup]"
          - wait for element ".content button" to be found
          - analyze with title "before popup"
          - click element ".content button"
          - analyze with title "with popup"
          - dismiss modal ".ReactModal__Content" with close button ".ReactModal__Content .close"
          - analyze with title "after popup"
      - name: contact
        url: https://dequelabs.github.io/aget-demo-site/contact
        actions:
          - analyze with title "form disabled"
          - wait for element "#__next .toggle" to be found
          - click element ".toggle button"
          - wait for element "input[name=name]" to be enabled
          - analyze with title "form enabled"
          - type "stephen" into element "input[name=name]"
          - type "555-555-5555" into element "input[name=phone]"
          - type "stephen@deque.com" into element "input[name=email]"
          - type "hello world" into element "textarea[name=message]"
          - click element "button[type=submit]"
          - wait for element ".thanks" to be found
          - analyze with title "thanks message"

Batch Processing with axe bulk-spec

To process multiple spec files in a single run, use axe bulk-spec with a directory containing spec files. The CLI recursively searches the directory and its subdirectories for spec files.

axe bulk-spec <spec-files-directory> <output-directory>

The <output-directory> is optional — if omitted, results are saved in the current working directory.

Progress updates are printed to stdout during the run.

Results are written to the output directory: one JSON file per analyze action, plus a log file listing any spec files that failed and the reason for failure.

Options

The following options are available for axe spec:

--axe-devhub-api-key <api-key>

Specifies the Axe Developer Hub API key. Required (along with --axe-devhub-project-id) to send results to Axe Developer Hub. See Send Results to Axe Developer Hub.

--axe-devhub-project-id <project-id>

Specifies the Axe Developer Hub project ID. Required (along with --axe-devhub-api-key) to send results to Axe Developer Hub. See Send Results to Axe Developer Hub.

--axe-devhub-server-url <url>

Specifies the URL of the Axe Developer Hub server. Defaults to https://axe.deque.com. Equivalent to the AXE_DEVHUB_SERVER_URL environment variable. See Send Results to Axe Developer Hub.

-c, --custom <path>

Specifies a custom ruleset file, overriding the default ruleset.

Collects the links on each page and appends them to the results. Requires --verbose.

--dismiss-alerts

Automatically dismisses browser alert(), confirm(), and prompt() dialogs before scanning.

--enable-tracking <state>

Enables sending data to the metrics library.

--filter <type(s)>

Filters result types from output: passes, violations, incomplete, inapplicable. Requires --format csv.

-f, --format <type(s)>

Report format(s): html, junit, csv, or a comma-separated combination. Default: html.

--no-git-data

Excludes Git branch and commit information when sending results to Axe Developer Hub. See Send Results to Axe Developer Hub.

--page-name <name>

Runs only the page with the specified name from the spec file's pageList.

--page-source

Appends the scanned HTML source to results. Requires --verbose.

--page-title

Appends the page title to results. Requires --verbose.

--remote-proxy <proxy-server>

Routes traffic through the specified remote proxy server.

--resume-from <name>

Skips all pages before the named page in the spec file's pageList.

--scanned-url

Adds the base URL and current scan URL to verbose results. Chrome only. Requires --verbose.

--set-distinct-id <id>

Overrides the distinct ID value.

--set-tracking-url <url>

Overrides the URL where metrics data is sent.

-t, --tags

Filters the standard ruleset by tag.

--user-agent

Sets a custom user agent string for the browser.

--validate

Validates your spec file without running it.

-v, --verbose

Includes additional output: Axe results and metadata such as tool name, version, and environment.

For additional configuration options, see Configure.