CWAC is designed and developed by the Web Standards team at Te Pūnaha Matihiko | Government Digital Delivery Agency, New Zealand Government.
Note: "CWAC" is pronounced "quack", like a duck.
CWAC is a tool that can scan hundreds of websites for accessibility issues, automatically.
CWAC can be used as a mechanism to monitor the New Zealand Government's implementation of minimum accessibility standards and guidelines on its websites. The primary standard, is the NZ Government Web Accessibility Standard, which includes Web Content Accessibility Guidelines (WCAG) 2.2 Level AA conformance. CWAC enables the partial fulfillment of Article 9 of the United Nations Convention on the Rights of Persons with Disabilities (CRPD).
Provided a list of URLS to visit, CWAC will check each page for automatically-identifiable accessibility issues and store the results in an easy-to-read CSV file.
CWAC can also crawl each page as it goes to determine additional pages to check
(up to a set max number per URL), respecting robots.txt and server signals
when doing so. This makes it easy to check entire sites without knowing the all
paths beforehand.
CWAC is designed to be extensible, so new forms of web testing can be added over time. For instance, CWAC could also run The Nu Html Checker on web pages. Or, it could theoretically check other website requirements, such as website data usage and performance, or the existence of a privacy or copyright statement.
CWAC combines the following technologies:
- Python 3 (the primary scripting language CWAC is written in)
- Selenium (used to control web browsers)
- axe-core (the accessibility rules engine)
- Chrome for Testing (main browser CWAC uses)
CWAC uses several tools to maintain the quality and integrity of its source code, including:
- ruff, an uncompromising code formatter and linter
- bandit, for detecting potential security vulnerabilities
- flake8, for linting
- pylint, for linting
- mypy, for static type checking
You can run linters locally as follows:
source .venv/bin/activate
# prettier
npm run format-check
npm run format-fix
# ruff
ruff check # add --fix to auto fix
ruff format
mypy .
flake8 --max-line-length=120 .
bandit -r .
pylint -rn -sn $(git ls-files '*.py')CWAC is designed to be extensible with plugins. This enables CWAC to run multiple different types of audits against web pages.
The available audit plugins are described in
Understanding audits. The code for each plugin is located in
/src/audit_plugins/
To specify which audits run during testing, modify the audit_plugins object in
./config/config_default.json. The format of audit_plugins entries requires a
snake case name as the key, and a camel case name as the value for the
class_name property, e.g.:
{
"audit_plugins": {
"axe_core_audit": {
"class_name": "AxeCoreAudit",
"best-practice": true,
"enabled": true
},
"language_audit": {
"class_name": "LanguageAudit",
"enabled": true,
"viewport_to_test": "small",
"run_sentiment_analysis": false
},
"reflow_audit": {
"class_name": "ReflowAudit",
"enabled": true,
"viewport_to_test": "small",
"screenshot_failures": false
},
"title_audit": {
"class_name": "TitleAudit",
"enabled": true
},
"screenshot_audit": {
"class_name": "ScreenshotAudit",
"enabled": true,
"viewport_to_test": "small"
},
"focus_indicator_audit": {
"class_name": "FocusIndicatorAudit",
"enabled": true,
"root_element_css_selector": "main",
"pre_tab_key_presses": 0,
"max_tab_key_presses": 15
},
"element_audit": {
"class_name": "ElementAudit",
"target_element_css_selector": "input:not([type='search'])",
"enabled": true
}
}
}To add new audit plugins, first develop an appropriate test module/class within
./src/audit_plugins/, and then enable that audit plugin by adding an entry
within config_default.json.
Each plugin can have an optional viewport_to_test item, which allows you to
run a plugin only at particular viewport sizes, if multiple are being tested.
The value of this key must match a value within the viewport_sizes option.
CWAC will attempt to crawl sitemaps if the crawl_sitemaps configuration option
is true, which is the default.
This is done using the
ultimate-sitemap-parser
library which includes support for
- locating sitemaps via
robots.txt - sitemaps compressed with gunzip (
.gz) - various sitemap locations
sitemapindexs
It also comes with a CLI which can be useful in manually checking if sitemaps are set up correctly
$ usp ls https://example.org/
https://example.org/
https://example.org/robots.txt
https://example.org/sitemap.xml
https://example.org/page1.html
You can find the latest Chrome for Testing version manually by visiting https://googlechromelabs.github.io/chrome-for-testing/ or programmatically via:
curl --silent https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json | jq -r '.channels.Stable.version'The steps to upgrade are:
- Run the command above (or manually visit site) to get latest stable Chrome for Testing.
- Update
pacakge.jsonwith the new version. - Run
npm installto download Chrome for Testing and Chromedriver binaries corresponding to the new version frompackage.json. The binaries are downloaded tochrome/andchromedriver/respectively. - Run the
tests/e2e.shscript to verify that the new Chromedriver works in the Docker container.
[!TIP] macOS might come up with an error stating "chromedriver_mac_arm64" can't be opened because Apple cannot check it for malicious software." This is fixed by running
xattr -d com.apple.quarantine <path-to-executable-chromedriver>
Crown copyright (c) 2024, Department of Internal Affairs on behalf of the New Zealand Government.
This copyright, along with CWAC's GPL-3.0 license, does not extend to the
third-party chromedriver binaries located in the /drivers/ folder. Permission
to re-use third party copyright material cannot be given by the Department of
Internal Affairs.
CWAC includes chromedriver binaries at /drivers/. chromedriver licenses can be
found in the /drivers/ folder.
// Copyright 2015 The Chromium Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.