diff --git a/.changeset/dull-rockets-wave.md b/.changeset/dull-rockets-wave.md new file mode 100644 index 00000000..83f6e240 --- /dev/null +++ b/.changeset/dull-rockets-wave.md @@ -0,0 +1,5 @@ +--- +"@chialab/vitest-axe": patch +--- + +First release. diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index 7b8ed63c..3097d087 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -101,6 +101,10 @@ export default defineConfig({ text: 'postcss-url-rebase', link: '/guide/postcss-url-rebase', }, + { + text: 'vitest-axe', + link: '/guide/vitest-axe', + }, // { // text: 'Write a plugin', // link: '/guide/write-a-plugin', diff --git a/docs/guide/vitest-axe.md b/docs/guide/vitest-axe.md new file mode 100644 index 00000000..3a7776f1 --- /dev/null +++ b/docs/guide/vitest-axe.md @@ -0,0 +1,58 @@ +# Vitest Axe matchers + +Axe violations matchers for Vitest. + +## Install + +::: code-group + +```sh[npm] +npm i -D axe-core @chialab/vitest-axe +``` + +```sh[yarn] +yarn add -D axe-core @chialab/vitest-axe +``` + +```sh[pnpm] +pnpm add -D axe-core @chialab/vitest-axe +``` + +::: + +## Usage + +Use a Vitest setup file to add the matchers to the test runner. + +::: code-group + +```ts[vitest.config.ts] +export default { + test: { + setupFiles: ['./test/setup.ts'], + }, +} +``` + +```ts[test/setup.ts] +import matchers from '@chialab/vitest-axe'; +import { expect } from 'vitest'; + +expect.extend(matchers); +``` + +::: + +## Example + +```ts +import { run as axe } from 'axe-core'; +import { describe, expect, test } from 'vitest'; + +describe('button', () => { + test('accessibility', async () => { + const button = document.createElement('button'); + expect(await axe(button)).toHaveNoViolations(); + }); +}); +``` diff --git a/packages/vitest-axe/LICENSE.md b/packages/vitest-axe/LICENSE.md new file mode 100644 index 00000000..cbaa0376 --- /dev/null +++ b/packages/vitest-axe/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Chialab + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/vitest-axe/README.md b/packages/vitest-axe/README.md new file mode 100644 index 00000000..918ab14f --- /dev/null +++ b/packages/vitest-axe/README.md @@ -0,0 +1,29 @@ +
+ vitest-axe • Axe matchers for Vitest. +
+ + + +--- + +## Install + +```sh +npm i @chialab/vitest-axe -D +``` + +```sh +yarn add @chialab/vitest-axe -D +``` + +## Documentation + +Read the documentation at [chialab.github.io/rna](https://chialab.github.io/rna/guide/vitest-axe). + +--- + +## License + +**vitest-axe** is released under the [MIT](https://github.com/chialab/rna/blob/main/packages/vitest-axe/LICENSE) license. diff --git a/packages/vitest-axe/lib/index.js b/packages/vitest-axe/lib/index.js new file mode 100644 index 00000000..3d224e74 --- /dev/null +++ b/packages/vitest-axe/lib/index.js @@ -0,0 +1,32 @@ +export * from './vitest-axe'; + +export default { + /** + * @param {import('axe-core').AxeResults} results + */ + toHaveNoViolations(results) { + const violations = results.violations ?? []; + + return { + pass: violations.length === 0, + actual: violations, + message() { + if (violations.length === 0) { + return ''; + } + + return `Expected no accessibility violations but received some. + +${violations + .map( + (violation) => `[${violation.impact}] ${violation.id} +${violation.description} +${violation.helpUrl} +` + ) + .join('\n')} +`; + }, + }; + }, +}; diff --git a/packages/vitest-axe/lib/vitest-axe.ts b/packages/vitest-axe/lib/vitest-axe.ts new file mode 100644 index 00000000..81d906d8 --- /dev/null +++ b/packages/vitest-axe/lib/vitest-axe.ts @@ -0,0 +1,10 @@ +interface AxeMatchers