{"id":13667737,"url":"https://github.com/NickColley/jest-axe","last_synced_at":"2025-04-26T18:30:33.761Z","repository":{"id":29307304,"uuid":"121313859","full_name":"NickColley/jest-axe","owner":"NickColley","description":"Custom Jest matcher for aXe for testing accessibility ♿️🃏","archived":false,"fork":false,"pushed_at":"2025-03-03T21:16:31.000Z","size":846,"stargazers_count":1080,"open_issues_count":0,"forks_count":55,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-24T03:56:51.326Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NickColley.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-12T23:06:17.000Z","updated_at":"2025-04-15T11:57:16.000Z","dependencies_parsed_at":"2024-02-08T18:03:32.444Z","dependency_job_id":"2bb96a18-1039-4037-9631-ec46928afbcf","html_url":"https://github.com/NickColley/jest-axe","commit_stats":{"total_commits":215,"total_committers":39,"mean_commits":5.512820512820513,"dds":0.758139534883721,"last_synced_commit":"07e1ef0ee0c916203e16a862a1a702a7d057d422"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NickColley%2Fjest-axe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NickColley%2Fjest-axe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NickColley%2Fjest-axe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NickColley%2Fjest-axe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NickColley","download_url":"https://codeload.github.com/NickColley/jest-axe/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250560015,"owners_count":21450169,"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-08-02T07:00:48.465Z","updated_at":"2025-04-26T18:30:33.714Z","avatar_url":"https://github.com/NickColley.png","language":"JavaScript","funding_links":[],"categories":["Tools","Accessibility Testing \u0026 Validation"],"sub_categories":[],"readme":"# jest-axe\r\n\r\n[![npm version](https://img.shields.io/npm/v/jest-axe.svg)](http://npm.im/jest-axe)\r\n![node](https://img.shields.io/node/v/jest-axe)\r\n[![Repository CI Status](https://github.com/nickcolley/jest-axe/workflows/test/badge.svg)](https://github.com/nickcolley/jest-axe/actions?query=workflow%3Atest)\r\n\r\nCustom [Jest][Jest] matcher for [axe](https://github.com/dequelabs/axe-core) for testing accessibility\r\n\r\n## ⚠️✋ This project does not guarantee that what you build is accessible.\r\nThe GDS Accessibility team found that around [~30% of access barriers are missed by automated testing](https://accessibility.blog.gov.uk/2017/02/24/what-we-found-when-we-tested-tools-on-the-worlds-least-accessible-webpage).\r\n\r\nTools like axe are similar to [code linters](https://en.wikipedia.org/wiki/Lint_%28software%29) such as [eslint](https://eslint.org/) or [stylelint](https://stylelint.io/): they can find common issues but cannot guarantee that what you build works for users.\r\n\r\nYou'll also need to:\r\n- test your interface with the [assistive technologies that real users use](https://www.gov.uk/service-manual/technology/testing-with-assistive-technologies#when-to-test) (see also [WebAIM's survey results](https://webaim.org/projects/screenreadersurvey8/#primary)).\r\n- include disabled people in user research.\r\n\r\n### Checks that do not work in jest-axe\r\n\r\nColor contrast checks do not work in JSDOM so are turned off in jest-axe.\r\n\r\n## Installation:\r\n```bash\r\nnpm install --save-dev jest jest-axe jest-environment-jsdom\r\n```\r\n\r\n[TypeScript](https://www.typescriptlang.org/) users can install the community maintained types package:\r\n\r\n```bash\r\nnpm install --save-dev @types/jest-axe\r\n```\r\n\r\n## Usage:\r\n\r\n```javascript\r\n/**\r\n * @jest-environment jsdom\r\n */\r\nconst { axe, toHaveNoViolations } = require('jest-axe')\r\n\r\nexpect.extend(toHaveNoViolations)\r\n\r\nit('should demonstrate this matcher`s usage', async () =\u003e {\r\n  const render = () =\u003e '\u003cimg src=\"#\"/\u003e'\r\n\r\n  // pass anything that outputs html to axe\r\n  const html = render()\r\n\r\n  expect(await axe(html)).toHaveNoViolations()\r\n})\r\n```\r\n\r\n![Screenshot of the resulting output from the usage example](example-cli.png)\r\n\r\n\u003e Note, you can also require `'jest-axe/extend-expect'` which will call `expect.extend` for you.\r\n\u003e This is especially helpful when using the jest `setupFilesAfterEnv` configuration.\r\n\r\n### Testing React\r\n\r\n```javascript\r\nconst React = require('react')\r\nconst { render } =  require('react-dom')\r\nconst App = require('./app')\r\n\r\nconst { axe, toHaveNoViolations } = require('jest-axe')\r\nexpect.extend(toHaveNoViolations)\r\n\r\nit('should demonstrate this matcher`s usage with react', async () =\u003e {\r\n  render(\u003cApp/\u003e, document.body)\r\n  const results = await axe(document.body)\r\n  expect(results).toHaveNoViolations()\r\n})\r\n```\r\n\r\n### Testing React with [React Testing Library](https://testing-library.com/docs/react-testing-library/intro)\r\n\r\n```javascript\r\nconst React = require('react')\r\nconst App = require('./app')\r\n\r\nconst { render } = require('@testing-library/react')\r\nconst { axe, toHaveNoViolations } = require('jest-axe')\r\nexpect.extend(toHaveNoViolations)\r\n\r\nit('should demonstrate this matcher`s usage with react testing library', async () =\u003e {\r\n  const { container } = render(\u003cApp/\u003e)\r\n  const results = await axe(container)\r\n  \r\n  expect(results).toHaveNoViolations()\r\n})\r\n```\r\n\r\n\u003e Note: If you're using `react testing library` \u003c9.0.0 you should be using the\r\n\u003e [`cleanup`](https://testing-library.com/docs/react-testing-library/api#cleanup) method. This method removes the rendered application from the DOM and ensures a clean HTML Document for further testing.\r\n\r\nIf you're using [React Portals](https://reactjs.org/docs/portals.html), use the [`baseElement`](https://testing-library.com/docs/react-testing-library/api#baseelement) instead of `container`:\r\n\r\n```js\r\nit('should work with React Portals as well', async () =\u003e {\r\n  const { baseElement } = render(\u003cApp/\u003e)\r\n  const results = await axe(baseElement)\r\n  \r\n  expect(results).toHaveNoViolations()\r\n})\r\n```\r\n\r\n### Testing Vue with [Vue Test Utils](https://vue-test-utils.vuejs.org/)\r\n\r\n```javascript\r\nconst App = require('./App.vue')\r\n\r\nconst { mount } = require('@vue/test-utils')\r\nconst { axe, toHaveNoViolations } = require('jest-axe')\r\nexpect.extend(toHaveNoViolations)\r\n\r\nit('should demonstrate this matcher`s usage with vue test utils', async () =\u003e {\r\n  const wrapper = mount(Image)\r\n  const results = await axe(wrapper.element)\r\n\r\n  expect(results).toHaveNoViolations()\r\n})\r\n```\r\n\r\n### Testing Vue with [Vue Testing Library](https://testing-library.com/docs/vue-testing-library/intro)\r\n\r\n```javascript\r\nconst App = require('./app')\r\n\r\nconst { render } = require('@testing-library/vue')\r\nconst { axe, toHaveNoViolations } = require('jest-axe')\r\nexpect.extend(toHaveNoViolations)\r\n\r\nit('should demonstrate this matcher`s usage with react testing library', async () =\u003e {\r\n  const { container } = render(\u003cApp/\u003e)\r\n  const results = await axe(container)\r\n  \r\n  expect(results).toHaveNoViolations()\r\n})\r\n```\r\n\u003e Note: If you're using `vue testing library` \u003c3.0.0 you should be using the\r\n\u003e [`cleanup`](https://testing-library.com/docs/vue-testing-library/api#cleanup) method. This method removes the rendered application from the DOM and ensures a clean HTML Document for further testing.\r\n\r\n### Testing Angular with [Nx](https://nx.dev/)\r\n\r\n```typescript\r\nimport { ComponentFixture, TestBed } from \"@angular/core/testing\";\r\nimport { axe } from \"jest-axe\";\r\n\r\nimport { SomeComponent } from \"./some.component\";\r\n\r\ndescribe(\"SomeComponent\", () =\u003e {\r\n  let fixture: ComponentFixture\u003cSomeComponent\u003e;\r\n\r\n  beforeEach(() =\u003e {\r\n    TestBed.configureTestingModule({\r\n      declarations: [SomeComponent],\r\n    });\r\n\r\n    fixture = TestBed.createComponent(SomeComponent);\r\n  });\r\n\r\n  it(\"should create\", async () =\u003e {\r\n    const results = await axe(fixture.nativeElement);\r\n    expect(results).toHaveNoViolations();\r\n  });\r\n});\r\n```\r\n\r\n\u003e Note: You may need to extend jest by importing `jest-axe/extend-expect` at `test-setup.ts`\r\n\r\n### Usage with jest.useFakeTimers() or mocking setTimeout\r\n\r\n\u003e thrown: \"Exceeded timeout of 5000 ms for a test.\r\n\u003e Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test.\"\r\n\r\naXe core does not work when timers (setTimeout) are mocked. When using `jest.useFakeTimers()` aXe core will timeout often causing failing tests.\r\n\r\nWe recommend renabling the timers temporarily for aXe:\r\n\r\n```javascript\r\njest.useRealTimers();\r\nconst results = await axe(wrapper.element);\r\njest.useFakeTimers();\r\n```\r\n\r\n### Axe configuration\r\n\r\nThe `axe` function allows options to be set with the [same options as documented in axe-core](https://github.com/dequelabs/axe-core/blob/master/doc/API.md#options-parameter):\r\n\r\n```javascript\r\nconst { axe, toHaveNoViolations } = require('jest-axe')\r\n\r\nexpect.extend(toHaveNoViolations)\r\n\r\nit('should demonstrate this matcher`s usage with a custom config', async () =\u003e {\r\n  const render = () =\u003e `\r\n    \u003cdiv\u003e\r\n      \u003cimg src=\"#\"/\u003e\r\n    \u003c/div\u003e\r\n  `\r\n\r\n  // pass anything that outputs html to axe\r\n  const html = render()\r\n\r\n  const results = await axe(html, {\r\n    rules: {\r\n      // for demonstration only, don't disable rules that need fixing.\r\n      'image-alt': { enabled: false }\r\n    }\r\n  })\r\n\r\n  expect(results).toHaveNoViolations()\r\n})\r\n```\r\n\r\n### Testing isolated components\r\n\r\n\u003e All page content must be contained by landmarks (region)\r\n\r\nWhen testing with aXe sometimes it assumes you are testing a page. This then results in unexpected violations for landmarks for testing isolation components.\r\n\r\nYou can disable this behaviour with the `region` rule:\r\n\r\n```javascript\r\nconst { configureAxe } = require('jest-axe')\r\n\r\nconst axe = configureAxe({\r\n  rules: {\r\n    // disable landmark rules when testing isolated components.\r\n    'region': { enabled: false }\r\n  }\r\n})\r\n```\r\n\r\n## Setting global configuration\r\n\r\nIf you find yourself repeating the same options multiple times, you can export a version of the `axe` function with defaults set.\r\n\r\nNote: You can still pass additional options to this new instance; they will be merged with the defaults.\r\n\r\nThis could be done in [Jest's setup step](https://jestjs.io/docs/en/setup-teardown)\r\n\r\n```javascript\r\n// Global helper file (axe-helper.js)\r\nconst { configureAxe } = require('jest-axe')\r\n\r\nconst axe = configureAxe({\r\n  rules: {\r\n    // for demonstration only, don't disable rules that need fixing.\r\n    'image-alt': { enabled: false }\r\n  }\r\n})\r\n\r\nmodule.exports = axe\r\n```\r\n\r\n```javascript\r\n// Individual test file (test.js)\r\nconst { toHaveNoViolations } = require('jest-axe')\r\nconst axe = require('./axe-helper.js')\r\n\r\nexpect.extend(toHaveNoViolations)\r\n\r\nit('should demonstrate this matcher`s usage with a default config', async () =\u003e {\r\n  const render = () =\u003e `\r\n    \u003cdiv\u003e\r\n      \u003cimg src=\"#\"/\u003e\r\n    \u003c/div\u003e\r\n  `\r\n\r\n  // pass anything that outputs html to axe\r\n  const html = render()\r\n\r\n  expect(await axe(html)).toHaveNoViolations()\r\n})\r\n```\r\n\r\n### Setting custom rules and checks.\r\n\r\nThe configuration object passed to `configureAxe`, accepts a `globalOptions` property to configure the format of the data used by axe and to add custom checks and rules. The property value is the same as the parameter passed to [axe.configure](https://github.com/dequelabs/axe-core/blob/master/doc/API.md#parameters-1). \r\n\r\n```javascript\r\n// Global helper file (axe-helper.js)\r\nconst { configureAxe } = require('jest-axe')\r\n\r\nconst axe = configureAxe({\r\n  globalOptions: {\r\n    checks: [/* custom checks definitions */]\r\n  },\r\n  // ...\r\n})\r\n\r\nmodule.exports = axe\r\n```\r\n\r\n### Setting the level of user impact.\r\n\r\nAn array which defines which [impact](https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md) level should be considered. This ensures that only violations with a specific impact on the user are considered. The level of impact can be \"minor\", \"moderate\", \"serious\", or \"critical\".\r\n\r\n```javascript\r\n// Global helper file (axe-helper.js)\r\nconst { configureAxe } = require('jest-axe')\r\n\r\nconst axe = configureAxe({\r\n  impactLevels: ['critical'],\r\n  // ...\r\n})\r\n\r\nmodule.exports = axe\r\n```\r\n\r\nRefer to [Developing Axe-core Rules](https://github.com/dequelabs/axe-core/blob/master/doc/rule-development.md) for instructions on how to develop custom rules and checks.\r\n\r\n## Thanks\r\n- [Jest][Jest] for the great test runner that allows extending matchers.\r\n- [axe](https://www.deque.com/axe/) for the wonderful axe-core that makes it so easy to do this.\r\n- Government Digital Service for making coding in the open the default.\r\n  - GOV.UK Publishing Frontend team who published the [basis of the aXe reporter](https://github.com/alphagov/govuk_publishing_components/blob/581c22c9d35d85d5d985571d007f6397a4399f4c/spec/javascripts/govuk_publishing_components/AccessibilityTestSpec.js)\r\n- [jest-image-snapshot](https://github.com/americanexpress/jest-image-snapshot) for inspiration on README and repo setup\r\n\r\n[Jest]: https://jestjs.io/\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNickColley%2Fjest-axe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNickColley%2Fjest-axe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNickColley%2Fjest-axe/lists"}