├── .github └── workflows │ └── test.yml ├── .gitignore ├── .nvmrc ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── __tests__ ├── __snapshots__ │ ├── index.test.js.snap │ ├── reactjs.test.js.snap │ └── vuejs.test.js.snap ├── index.test.js ├── reactjs.test.js └── vuejs.test.js ├── example-cli.png ├── extend-expect.js ├── index.js ├── package-lock.json └── package.json /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: test 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | pull_request: 10 | branches: [ main ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [16, 18, 20, 22] 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v1 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | - run: npm ci 28 | - run: npm test 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 20 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 10.0.0 2 | 3 | - Update axe-core to version 4.10.2 - thanks [@daniel-nagy](https://github.com/daniel-nagy). 4 | 5 | # 9.0.0 6 | 7 | - Update axe-core to version 4.9.1 - thanks [@1Copenut](https://github.com/1Copenut) and [@longmatthewh](https://github.com/longmatthewh). 8 | - Update minimum Node.js version to 16 9 | 10 | # 8.0.0 11 | 12 | - Update axe-core to version 4.7.2 - thanks [@hpinkos](https://github.com/hpinkos) and [@philcon93](https://github.com/philcon93). 13 | 14 | # 7.0.0 15 | 16 | Update main dependencies: 17 | - axe-core from version 4.4.1 to 4.5.1 - thanks [@jbchr](https://github.com/jbchr). 18 | - chalk updated from version 4.1.0 to 4.1.2 19 | - jest-matcher-utils updated from version 27.0.2 to 29.2.2 20 | 21 | Breaking changes: 22 | - axe-core includes new rules and checks which may need to be fixed or turned off 23 | - axe-core help messages updates will change your snapshot output 24 | - no longer support Node.js 10 and 12 25 | 26 | # 6.0.1 27 | 28 | - [Fix "Not implemented: window.computedStyle(elt, pseudoElt)" errors](https://github.com/NickColley/jest-axe/pull/252/commits/48824b2400b23bf2ff11bcccd090cf868b4fd8ec). 29 | 30 | # 6.0.0 31 | 32 | - Update axe-core to version 4.4.1 - thanks [@dafnem1](https://github.com/dafnem1). 33 | 34 | # 5.0.1 35 | 36 | - Pin axe-core to version 4.2.1 to prevent unintentional breaking changes from patch versions. 37 | 38 | # 5.0.0 39 | 40 | - Update [axe-core to version 4.2.1](https://github.com/nickcolley/jest-axe/pull/169) - thanks [@lpelypenko](https://github.com/lpelypenko). 41 | 42 | # 4.1.0 43 | 44 | - You can now [filter violations by user impact](https://github.com/nickcolley/jest-axe#setting-the-level-of-user-impact) - thanks [@martiL](https://github.com/martiL). 45 | 46 | # 4.0.0 47 | 48 | - Update [axe-core to version 4](https://github.com/dequelabs/axe-core/releases/tag/v4.0.0). 49 | 50 | # 3.5.0 51 | 52 | - [Add a globalOptions configuration property to setup custom rules and checks](https://github.com/nickcolley/jest-axe/pull/114) - thanks [@dwightjack](https://github.com/@dwightjack) 53 | 54 | See [setting custom rules and checks](https://github.com/nickcolley/jest-axe#setting-custom-rules-and-checks) for usage. 55 | 56 | # 3.4.0 57 | 58 | - Update axe-core to 3.5.0 59 | 60 | # 3.3.0 61 | 62 | - [Update axe-core to 3.4.1](https://github.com/nickcolley/jest-axe/pull/83) - thanks [@mohanraj-r](https://github.com/mohanraj-r) 63 | 64 | # 3.2.0 65 | 66 | - Improved support for using DOM nodes which makes jest-axe work better with testing libraries such as @testing-library, React and Vue - thanks to [@dakebl](https://github.com/dakebl) for contributing this, and everyone for helping review this. 67 | - Improved help text output including colour highlighting - thanks to [@dakebl](https://github.com/dakebl) 68 | - Update axe-core to 3.3.1, you may need to update any snapshot tests. 69 | - Update dependencies to avoid vulnerability warnings - thanks to [@chimericdream](https://github.com/chimericdream) for the prompt 70 | 71 | See the [full 3.2.0 milestone](https://github.com/nickcolley/jest-axe/milestone/1) for all related issues and pull requests. 72 | 73 | # 3.1.1 74 | 75 | - Ensure that jest-axe cleans up the document after it runs [(Issue #50)](https://github.com/nickcolley/jest-axe/issues/50) Thanks @thomasheyenbrock and @camdub ! 76 | - Update axe-core to 3.1.2 77 | 78 | # 3.1.0 79 | 80 | - Add extend-expect file - [(PR #44)](https://github.com/nickcolley/jest-axe/pull/44) Thanks @kentcdodds 81 | - Update axe-core to v3.1.1, update jest-matcher-utils to 23.5.0 82 | 83 | # 3.0.0 84 | 85 | - Allow Node.js 6.x to use jest-axe - [(PR #40)](https://github.com/nickcolley/jest-axe/pull/40) 86 | 87 | Breaking changes: 88 | - Update axe-core to 3.x - [(PR #39)](https://github.com/nickcolley/jest-axe/pull/39) 89 | 90 | # 2.1.4 91 | 92 | - Only publish index.js - [(PR #22)](https://github.com/nickcolley/jest-axe/pull/22) 93 | 94 | # 2.1.3 95 | 96 | - Loosen Node engines requirement to 8.x - [(PR #20)](https://github.com/nickcolley/jest-axe/pull/20) 97 | 98 | # 2.1.2 99 | 100 | - Allow Node.js versions higher than LTS to run jest-axe - [(PR #13)](https://github.com/nickcolley/jest-axe/pull/13) Thanks @connor-baer 101 | 102 | # 2.1.1 103 | 104 | - Fixed a bug with default options being mutated - [(Commit)](https://github.com/nickcolley/jest-axe/commit/60412a52461e610ab6d2391441edda0a803d0dc5) 105 | 106 | # 2.1.0 107 | (Made a mistake publishing, so is a minor version when should have been a patch) 108 | 109 | - Nit: replaced 'var' with 'const' - [(PR #2)](https://github.com/nickcolley/jest-axe/pull/2) Thanks @JoshuaKGoldberg 110 | 111 | # 2.0.0 112 | Breaking changes: 113 | - Fixed typo in matcher which will require you to update any tests that depend on this incorrect spelling. 114 | 115 | # 1.0.0 116 | 117 | Initial project 118 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (C) 2017 Crown Copyright (Government Digital Service) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jest-axe 2 | 3 | [![npm version](https://img.shields.io/npm/v/jest-axe.svg)](http://npm.im/jest-axe) 4 | ![node](https://img.shields.io/node/v/jest-axe) 5 | [![Repository CI Status](https://github.com/nickcolley/jest-axe/workflows/test/badge.svg)](https://github.com/nickcolley/jest-axe/actions?query=workflow%3Atest) 6 | 7 | Custom [Jest][Jest] matcher for [axe](https://github.com/dequelabs/axe-core) for testing accessibility 8 | 9 | ## ⚠️✋ This project does not guarantee that what you build is accessible. 10 | The 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). 11 | 12 | Tools 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. 13 | 14 | You'll also need to: 15 | - 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)). 16 | - include disabled people in user research. 17 | 18 | ### Checks that do not work in jest-axe 19 | 20 | Color contrast checks do not work in JSDOM so are turned off in jest-axe. 21 | 22 | ## Installation: 23 | ```bash 24 | npm install --save-dev jest jest-axe jest-environment-jsdom 25 | ``` 26 | 27 | [TypeScript](https://www.typescriptlang.org/) users can install the community maintained types package: 28 | 29 | ```bash 30 | npm install --save-dev @types/jest-axe 31 | ``` 32 | 33 | ## Usage: 34 | 35 | ```javascript 36 | /** 37 | * @jest-environment jsdom 38 | */ 39 | const { axe, toHaveNoViolations } = require('jest-axe') 40 | 41 | expect.extend(toHaveNoViolations) 42 | 43 | it('should demonstrate this matcher`s usage', async () => { 44 | const render = () => '' 45 | 46 | // pass anything that outputs html to axe 47 | const html = render() 48 | 49 | expect(await axe(html)).toHaveNoViolations() 50 | }) 51 | ``` 52 | 53 | ![Screenshot of the resulting output from the usage example](example-cli.png) 54 | 55 | > Note, you can also require `'jest-axe/extend-expect'` which will call `expect.extend` for you. 56 | > This is especially helpful when using the jest `setupFilesAfterEnv` configuration. 57 | 58 | ### Testing React 59 | 60 | ```javascript 61 | const React = require('react') 62 | const { render } = require('react-dom') 63 | const App = require('./app') 64 | 65 | const { axe, toHaveNoViolations } = require('jest-axe') 66 | expect.extend(toHaveNoViolations) 67 | 68 | it('should demonstrate this matcher`s usage with react', async () => { 69 | render(, document.body) 70 | const results = await axe(document.body) 71 | expect(results).toHaveNoViolations() 72 | }) 73 | ``` 74 | 75 | ### Testing React with [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) 76 | 77 | ```javascript 78 | const React = require('react') 79 | const App = require('./app') 80 | 81 | const { render } = require('@testing-library/react') 82 | const { axe, toHaveNoViolations } = require('jest-axe') 83 | expect.extend(toHaveNoViolations) 84 | 85 | it('should demonstrate this matcher`s usage with react testing library', async () => { 86 | const { container } = render() 87 | const results = await axe(container) 88 | 89 | expect(results).toHaveNoViolations() 90 | }) 91 | ``` 92 | 93 | > Note: If you're using `react testing library` <9.0.0 you should be using the 94 | > [`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. 95 | 96 | If 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`: 97 | 98 | ```js 99 | it('should work with React Portals as well', async () => { 100 | const { baseElement } = render() 101 | const results = await axe(baseElement) 102 | 103 | expect(results).toHaveNoViolations() 104 | }) 105 | ``` 106 | 107 | ### Testing Vue with [Vue Test Utils](https://vue-test-utils.vuejs.org/) 108 | 109 | ```javascript 110 | const App = require('./App.vue') 111 | 112 | const { mount } = require('@vue/test-utils') 113 | const { axe, toHaveNoViolations } = require('jest-axe') 114 | expect.extend(toHaveNoViolations) 115 | 116 | it('should demonstrate this matcher`s usage with vue test utils', async () => { 117 | const wrapper = mount(Image) 118 | const results = await axe(wrapper.element) 119 | 120 | expect(results).toHaveNoViolations() 121 | }) 122 | ``` 123 | 124 | ### Testing Vue with [Vue Testing Library](https://testing-library.com/docs/vue-testing-library/intro) 125 | 126 | ```javascript 127 | const App = require('./app') 128 | 129 | const { render } = require('@testing-library/vue') 130 | const { axe, toHaveNoViolations } = require('jest-axe') 131 | expect.extend(toHaveNoViolations) 132 | 133 | it('should demonstrate this matcher`s usage with react testing library', async () => { 134 | const { container } = render() 135 | const results = await axe(container) 136 | 137 | expect(results).toHaveNoViolations() 138 | }) 139 | ``` 140 | > Note: If you're using `vue testing library` <3.0.0 you should be using the 141 | > [`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. 142 | 143 | ### Testing Angular with [Nx](https://nx.dev/) 144 | 145 | ```typescript 146 | import { ComponentFixture, TestBed } from "@angular/core/testing"; 147 | import { axe } from "jest-axe"; 148 | 149 | import { SomeComponent } from "./some.component"; 150 | 151 | describe("SomeComponent", () => { 152 | let fixture: ComponentFixture; 153 | 154 | beforeEach(() => { 155 | TestBed.configureTestingModule({ 156 | declarations: [SomeComponent], 157 | }); 158 | 159 | fixture = TestBed.createComponent(SomeComponent); 160 | }); 161 | 162 | it("should create", async () => { 163 | const results = await axe(fixture.nativeElement); 164 | expect(results).toHaveNoViolations(); 165 | }); 166 | }); 167 | ``` 168 | 169 | > Note: You may need to extend jest by importing `jest-axe/extend-expect` at `test-setup.ts` 170 | 171 | ### Usage with jest.useFakeTimers() or mocking setTimeout 172 | 173 | > thrown: "Exceeded timeout of 5000 ms for a test. 174 | > Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test." 175 | 176 | aXe core does not work when timers (setTimeout) are mocked. When using `jest.useFakeTimers()` aXe core will timeout often causing failing tests. 177 | 178 | We recommend renabling the timers temporarily for aXe: 179 | 180 | ```javascript 181 | jest.useRealTimers(); 182 | const results = await axe(wrapper.element); 183 | jest.useFakeTimers(); 184 | ``` 185 | 186 | ### Axe configuration 187 | 188 | The `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): 189 | 190 | ```javascript 191 | const { axe, toHaveNoViolations } = require('jest-axe') 192 | 193 | expect.extend(toHaveNoViolations) 194 | 195 | it('should demonstrate this matcher`s usage with a custom config', async () => { 196 | const render = () => ` 197 |
198 | 199 |
200 | ` 201 | 202 | // pass anything that outputs html to axe 203 | const html = render() 204 | 205 | const results = await axe(html, { 206 | rules: { 207 | // for demonstration only, don't disable rules that need fixing. 208 | 'image-alt': { enabled: false } 209 | } 210 | }) 211 | 212 | expect(results).toHaveNoViolations() 213 | }) 214 | ``` 215 | 216 | ### Testing isolated components 217 | 218 | > All page content must be contained by landmarks (region) 219 | 220 | When testing with aXe sometimes it assumes you are testing a page. This then results in unexpected violations for landmarks for testing isolation components. 221 | 222 | You can disable this behaviour with the `region` rule: 223 | 224 | ```javascript 225 | const { configureAxe } = require('jest-axe') 226 | 227 | const axe = configureAxe({ 228 | rules: { 229 | // disable landmark rules when testing isolated components. 230 | 'region': { enabled: false } 231 | } 232 | }) 233 | ``` 234 | 235 | ## Setting global configuration 236 | 237 | If you find yourself repeating the same options multiple times, you can export a version of the `axe` function with defaults set. 238 | 239 | Note: You can still pass additional options to this new instance; they will be merged with the defaults. 240 | 241 | This could be done in [Jest's setup step](https://jestjs.io/docs/en/setup-teardown) 242 | 243 | ```javascript 244 | // Global helper file (axe-helper.js) 245 | const { configureAxe } = require('jest-axe') 246 | 247 | const axe = configureAxe({ 248 | rules: { 249 | // for demonstration only, don't disable rules that need fixing. 250 | 'image-alt': { enabled: false } 251 | } 252 | }) 253 | 254 | module.exports = axe 255 | ``` 256 | 257 | ```javascript 258 | // Individual test file (test.js) 259 | const { toHaveNoViolations } = require('jest-axe') 260 | const axe = require('./axe-helper.js') 261 | 262 | expect.extend(toHaveNoViolations) 263 | 264 | it('should demonstrate this matcher`s usage with a default config', async () => { 265 | const render = () => ` 266 |
267 | 268 |
269 | ` 270 | 271 | // pass anything that outputs html to axe 272 | const html = render() 273 | 274 | expect(await axe(html)).toHaveNoViolations() 275 | }) 276 | ``` 277 | 278 | ### Setting custom rules and checks. 279 | 280 | The 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). 281 | 282 | ```javascript 283 | // Global helper file (axe-helper.js) 284 | const { configureAxe } = require('jest-axe') 285 | 286 | const axe = configureAxe({ 287 | globalOptions: { 288 | checks: [/* custom checks definitions */] 289 | }, 290 | // ... 291 | }) 292 | 293 | module.exports = axe 294 | ``` 295 | 296 | ### Setting the level of user impact. 297 | 298 | An 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". 299 | 300 | ```javascript 301 | // Global helper file (axe-helper.js) 302 | const { configureAxe } = require('jest-axe') 303 | 304 | const axe = configureAxe({ 305 | impactLevels: ['critical'], 306 | // ... 307 | }) 308 | 309 | module.exports = axe 310 | ``` 311 | 312 | Refer 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. 313 | 314 | ## Thanks 315 | - [Jest][Jest] for the great test runner that allows extending matchers. 316 | - [axe](https://www.deque.com/axe/) for the wonderful axe-core that makes it so easy to do this. 317 | - Government Digital Service for making coding in the open the default. 318 | - 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) 319 | - [jest-image-snapshot](https://github.com/americanexpress/jest-image-snapshot) for inspiration on README and repo setup 320 | 321 | [Jest]: https://jestjs.io/ 322 | -------------------------------------------------------------------------------- /__tests__/__snapshots__/index.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`jest-axe readme first readme example should demonstrate this matcher\`s usage 1`] = ` 4 | "expect(received).toHaveNoViolations(expected) 5 | 6 | Expected the HTML found at $('img') to have no violations: 7 | 8 | 9 | 10 | Received: 11 | 12 | "Images must have alternative text (image-alt)" 13 | 14 | Fix any of the following: 15 | Element does not have an alt attribute 16 | aria-label attribute does not exist or is empty 17 | aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty 18 | Element has no title attribute 19 | Element's default semantics were not overridden with role="none" or role="presentation" 20 | 21 | You can find more information on this issue here: 22 | https://dequeuniversity.com/rules/axe/4.10/image-alt?application=axeAPI 23 | 24 | ──────── 25 | 26 | Expected the HTML found at $('img') to have no violations: 27 | 28 | 29 | 30 | Received: 31 | 32 | "All page content should be contained by landmarks (region)" 33 | 34 | Fix any of the following: 35 | Some page content is not contained by landmarks 36 | 37 | You can find more information on this issue here: 38 | https://dequeuniversity.com/rules/axe/4.10/region?application=axeAPI" 39 | `; 40 | 41 | exports[`jest-axe toHaveNoViolations returns correctly formatted message when violations are present 1`] = ` 42 | "expect(received).toHaveNoViolations(expected) 43 | 44 | Expected the HTML found at $('body > img') to have no violations: 45 | 46 | 47 | 48 | Received: 49 | 50 | "Images must have alternate text (image-alt)" 51 | 52 | Fix any of the following: 53 | Element does not have an alt attribute 54 | aria-label attribute does not exist or is empty 55 | aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty or not visible 56 | Element has no title attribute or the title attribute is empty 57 | Element's default semantics were not overridden with role="presentation" 58 | Element's default semantics were not overridden with role="none" 59 | 60 | You can find more information on this issue here: 61 | https://dequeuniversity.com/rules/axe/2.6/image-alt?application=axeAPI" 62 | `; 63 | 64 | exports[`jest-axe toHaveNoViolations returns properly formatted text with more complex example 1`] = ` 65 | "expect(received).toHaveNoViolations(expected) 66 | 67 | Expected the HTML found at $('img[src$="example.com"]') to have no violations: 68 | 69 | 70 | 71 | Received: 72 | 73 | "Images must have alternative text (image-alt)" 74 | 75 | Fix any of the following: 76 | Element does not have an alt attribute 77 | aria-label attribute does not exist or is empty 78 | aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty 79 | Element has no title attribute 80 | Element's default semantics were not overridden with role="none" or role="presentation" 81 | 82 | You can find more information on this issue here: 83 | https://dequeuniversity.com/rules/axe/4.10/image-alt?application=axeAPI 84 | 85 | Expected the HTML found at $('img[src="http://example.com/2"]') to have no violations: 86 | 87 | 88 | 89 | Received: 90 | 91 | "Images must have alternative text (image-alt)" 92 | 93 | Fix any of the following: 94 | Element does not have an alt attribute 95 | aria-label attribute does not exist or is empty 96 | aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty 97 | Element has no title attribute 98 | Element's default semantics were not overridden with role="none" or role="presentation" 99 | 100 | You can find more information on this issue here: 101 | https://dequeuniversity.com/rules/axe/4.10/image-alt?application=axeAPI 102 | 103 | ──────── 104 | 105 | Expected the HTML found at $('input') to have no violations: 106 | 107 | 108 | 109 | Received: 110 | 111 | "Form elements must have labels (label)" 112 | 113 | Fix any of the following: 114 | Element does not have an implicit (wrapped)