{"id":18764466,"url":"https://github.com/theintern/intern-a11y","last_synced_at":"2025-07-08T19:41:31.254Z","repository":{"id":57165996,"uuid":"73105754","full_name":"theintern/intern-a11y","owner":"theintern","description":"Accessibility testing for Intern","archived":false,"fork":false,"pushed_at":"2018-01-19T04:56:43.000Z","size":115,"stargazers_count":21,"open_issues_count":0,"forks_count":4,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-26T21:47:38.051Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theintern.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-11-07T17:56:44.000Z","updated_at":"2023-10-20T13:17:31.000Z","dependencies_parsed_at":"2022-08-30T15:21:22.316Z","dependency_job_id":null,"html_url":"https://github.com/theintern/intern-a11y","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theintern%2Fintern-a11y","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theintern%2Fintern-a11y/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theintern%2Fintern-a11y/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theintern%2Fintern-a11y/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theintern","download_url":"https://codeload.github.com/theintern/intern-a11y/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248664695,"owners_count":21142012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T18:29:56.001Z","updated_at":"2025-04-13T04:33:32.152Z","avatar_url":"https://github.com/theintern.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# a11y\n\nAccessibility testing for [Intern](https://theintern.io/)\n\n[![Intern](https://theintern.io/images/intern-v4.svg)](https://github.com/theintern/intern/)\n\n## How it works\n\nAccessibility testing works by having a scanner check a page or page fragment for rule violations. The most commonly used rules are defined in the W3C's [Web Content Accessibility Guidelines](https://www.w3.org/WAI/intro/wcag.php) (WCAG) and the GSA's [Section 508 Standards](https://www.section508.gov/summary-section508-standards). There are twelve general WCAG guidelines at three levels of success criteria: A, AA, and AAA. Scanners can check for violations at any of the levels, and can typically be configured to only check a subset of rules.\n\n`a11y` is an addon for [Intern](https://github.com/theintern/intern) that lets users write tests targeting various accessibility testing systems. Currently it supports two scanners, [aXe](https://github.com/dequelabs/axe-core) and [Tenon](https://tenon.io). aXe is a JavaScript application that must be injected into the page being tested. The application is configured and executed, returning a report describing the test results. Tenon is a cloud-based testing service; a user requests that the service test a particular URL or page source, and the service returns a report of the results.\n\nBoth scanners are able to test entire pages and document fragments (or portions of a full page). In all cases, though, the scanners operate on a fully styled DOM. This means that if a user needs to test a single commponent in isolation, they'll need to create a test page with all the styles and supporting code required by the component, and use that page to run accessibility tests on the component.\n\nNote that because aXe must be injected into a loaded page, it can only be used in functional test suites (i.e., those listed in `functionalSuites` in an Intern config). Tenon makes HTTP calls to an external service and can be used in unit or functional tests.\n\n## Installation\n\nThe a11y module should be installed as a peer of Intern.\n\n```\n$ npm install intern --save-dev\n$ npm install @theintern/a11y --save-dev\n```\n\n## Getting started\n\nUsing either the aXe or Tenon modules is straightforward. The service modules can be accessed from the `services` property on the `@theintern/a11y` module.\n\n```js\nimport { services } from '@theintern/a11y';\nconst axe = services.axe;\n```\n\nor\n\n```js\nconst axe = require('@theintern/a11y').services.axe;\n```\n\nThe simplest Tenon test looks like:\n\n```js\n'check accessibility'() {\n\treturn tenon.check({\n\t\tsource: 'http://mypage.com'\n\t});\n}\n```\n\nSimilarly, the simplest aXe test looks like:\n\n```js\n'check accessibility'() {\n\treturn aXe.check({\n\t\t// aXe tests must be run in functional test suites\n\t\tremote: this.remote,\n\t\tsource: 'page.html'\n\t});\n}\n```\n\naXe may also be used inline in a Leadfoot Command chain:\n\n```js\n'check accessibility': function () {\n\treturn this.remote\n\t\t.get('page.html')\n\t\t.then(aXe.createChecker());\n}\n```\n\nIn all cases, the check is asynchronous and Promise-based. If the check fails (i.e., accessibility violations are detected), the returned Promise is rejected.\n\n## Examples\n\nThe repository contains two example projects that use `a11y`, one written in JavaScript and one written in TypeScript.\n\n### JavaScript\n\n1. cd into `examples/js`\n2. Run `npm install`\n3. Run `TENON_API_KEY=\u003cyour key\u003e npm test`\n\n### TypeScript\n\n1. cd into `examples/ts`\n2. Run `npm install`\n2. Run `npm run build`\n3. Run `TENON_API_KEY=\u003cyour key\u003e npm test`\n\n## API\n\nImporting the `@theintern/a11y` module will return an object with a `services` property. This property value is an object with `tenon` and `axe` properties. You can also import the service modules directly:\n\n```js\nimport { check } from '@theintern/a11y/services/axe';\n```\n\n### axe\n\nThe aXe checker must be injected into the page being analyzed, and therefore can only be used in functional test suites. The aXe checker provides two functions, `check` and `createChecker`.\n\n#### check\n\nThe `check` function performs an accessibility analysis on a given URL using a given Command object (typically `this.remote`).\n\n```typescript\ncheck({\n\t/** LeadFoot Command object */\n\tremote: Command\u003cany\u003e,\n\n\t/** URL to load for testing */\n\tsource: string,\n\n\t/** Number of milliseconds to wait before starting test */\n\twaitFor?: number,\n\n\t/** A selector to confine analysis to */\n\tcontext?: string\n\n\t/** aXe-specific configuration */\n\tconfig?: Object,\n}): PromiseLike\u003cAxeResults\u003e\n```\n\nThe two required parameters are `remote` and `source`. `remote` is a Leadfoot Command object, generally `this.remote` in a test. `source` is the URL that will be analyzed.\n\nThere are three optional parameters. `waitFor` is a number of milliseconds to wait after a page has loaded before starting the accessibility analysis. `context` is a CSS selector (ID or class name) that can be used to confine analysis to a specific part of a page. The `config` paramter contains [aXe configuration options](https://github.com/dequelabs/axe-core/blob/master/doc/API.md#api-name-axeconfigure).\n\n#### createChecker\n\nThe `createChecker` function returns a Leadfoot Command helper (a `then` callback). It assumes that a page has already been loaded and is ready to be tested, so it doesn't need a source or Command object.\n\n```typescript\ncreateChecker(config?: AxeTestOptions): Command\u003cA11yResults\u003e\n```\n\n### tenon\n\nThe Tenon checker works by making requests to a remote cloud service. It can be used in functional or unit test suites.\n\n#### check\n\nThe tenon `check` function works the same way as the axe module's, and takes a similar argument object.\n\n```typescript\ncheck({\n\t/** An external URL, file name, or a data string */\n\tsource: string,\n\n\t/** tenon.io API key */\n\tapiKey?: string,\n\n\t/** Number of milliseconds to wait before starting test */\n\twaitFor?: number,\n\n\t/** Tenon configuration options */\n\tconfig?: TenonConfig\n}): PromiseLike\u003cTenonResults\u003e\n```\n\n### A11yReporter\n\nThe A11yReporter class is an Intern reporter that will write test failure detail reports to a file or directory. The `check` methods will fail if accessibility failures are present, regardless of whether the A11yReporter reporter is in use. This reporter simply outputs more detailed information for any failures that are detected.\n\nThe reporter is loaded as an Intern plugin. It can be configured with a filename, which may name an HTML file, in which case all test reports will be written to a single file, or a directory name, in which case test reports will be written to individual HTML files in the given directory.\n\n```js\nplugins: [\n\t{\n\t\tscript: '@theintern/a11y/A11yReporter',\n\n\t\toptions: {\n\t\t\t// If this is a filename, all failures will be written to the given\n\t\t\t// file. If it's a directory name (no extension), each test failure\n\t\t\t// report will be written to an individual file in the given directory.\n\t\t\tfilename: 'somereport.html'\n\t\t}\n\t}\n]\n```\n\nThe A11yReporter class also exposes a `writeReport` static method. This method allows accessibility test results to be explicitly written to a file rather than relying on the reporter:\n\n```js\nreturn axe.check({ ... })\n\t.catch(error =\u003e {\n\t\tconst results = axe.toA11yResults(error.results);\n\t\treturn A11yReporter.writeReport('some_file.html', results);\n\t})\n```\n\n## Development\n\nFirst, clone this repo. Then:\n\n```\n$ npm install\n$ npm run build\n```\n\nOutput will be generated in the `_build/` directory. To clean up, run \n\n```\n$ npm run clean\n```\n\nTo run tests:\n\n```\n$ TENON_API_KEY=\u003cyour key\u003e npm test\n```\n\nYou can provide standard Intern arguments like `grep=foo`.\n\nNote that a Tenon API key must be provided to run Tenon self-tests. If no key is provided, the tests will be skipped.\n\n\u003c!-- start-github-only --\u003e\n## License\n\na11y is offered under the [New BSD license](LICENSE).\n\n© [SitePen, Inc.](http://sitepen.com) and its [contributors](https://github.com/theintern/intern-a11y/graphs/contributors)\n\u003c!-- end-github-only --\u003e\n\n\u003c!-- doc-viewer-config\n{\n    \"api\": \"docs/api.json\"\n}\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheintern%2Fintern-a11y","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheintern%2Fintern-a11y","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheintern%2Fintern-a11y/lists"}