test-a11y-js 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -25
- package/dist/index.d.mts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +1793 -5
- package/dist/index.mjs +1793 -5
- package/dist/linter/eslint-plugin/index.js +1793 -5
- package/dist/linter/eslint-plugin/index.mjs +1793 -5
- package/package.json +17 -4
package/README.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
# test-a11y-js
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Catch accessibility issues in your editor, not in production.** Zero-config ESLint plugin + programmatic API for React, Vue, and JSX.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/test-a11y-js)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
|
|
9
|
+
**Why test-a11y-js?**
|
|
10
|
+
- ✅ **Zero config** - Works out of the box with React, Vue, and JSX
|
|
11
|
+
- ✅ **Real-time feedback** - Catch issues in your editor, not in production
|
|
12
|
+
- ✅ **16 accessibility rules** - Covers images, forms, buttons, landmarks, ARIA, semantic HTML, and more
|
|
13
|
+
- ✅ **Dual API** - Use as ESLint plugin OR programmatic API
|
|
14
|
+
- ✅ **Large project ready** - Minimal preset for incremental adoption
|
|
15
|
+
- ✅ **Framework agnostic** - Works with React, Vue, Preact, Solid, and more
|
|
4
16
|
|
|
5
17
|
## Installation
|
|
6
18
|
|
|
@@ -16,37 +28,62 @@ npm install --save-dev test-a11y-js
|
|
|
16
28
|
|
|
17
29
|
**Note:** jsdom is only required if you use HTML strings in your code. JSX and Vue templates work without jsdom. See [jsdom Guide](./docs/JSDOM.md) for details.
|
|
18
30
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
### Programmatic API
|
|
31
|
+
## Quick Start (30 seconds)
|
|
22
32
|
|
|
23
|
-
|
|
33
|
+
**Option 1: ESLint Plugin (Recommended)**
|
|
34
|
+
```javascript
|
|
35
|
+
// .eslintrc.js
|
|
36
|
+
module.exports = {
|
|
37
|
+
plugins: ['test-a11y-js'],
|
|
38
|
+
extends: ['plugin:test-a11y-js/recommended']
|
|
39
|
+
}
|
|
40
|
+
```
|
|
24
41
|
|
|
42
|
+
**Option 2: Programmatic API**
|
|
25
43
|
```typescript
|
|
26
44
|
import { A11yChecker } from 'test-a11y-js'
|
|
27
45
|
|
|
28
|
-
|
|
29
|
-
const results = await A11yChecker.check(element)
|
|
30
|
-
|
|
31
|
-
// Individual checks
|
|
32
|
-
const imageViolations = A11yChecker.checkImageAlt(element)
|
|
33
|
-
const linkViolations = A11yChecker.checkLinkText(element)
|
|
34
|
-
const buttonViolations = A11yChecker.checkButtonLabel(element)
|
|
35
|
-
const formViolations = A11yChecker.checkFormLabels(element)
|
|
36
|
-
const headingViolations = A11yChecker.checkHeadingOrder(element)
|
|
37
|
-
const iframeViolations = A11yChecker.checkIframeTitle(element)
|
|
38
|
-
const fieldsetViolations = A11yChecker.checkFieldsetLegend(element)
|
|
39
|
-
const tableViolations = A11yChecker.checkTableStructure(element)
|
|
40
|
-
const detailsViolations = A11yChecker.checkDetailsSummary(element)
|
|
41
|
-
const videoViolations = A11yChecker.checkVideoCaptions(element)
|
|
42
|
-
const audioViolations = A11yChecker.checkAudioCaptions(element)
|
|
43
|
-
const landmarkViolations = A11yChecker.checkLandmarks(element)
|
|
44
|
-
const dialogViolations = A11yChecker.checkDialogModal(element)
|
|
46
|
+
const violations = A11yChecker.checkImageAlt(element)
|
|
45
47
|
```
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
That's it! Start catching accessibility issues immediately.
|
|
50
|
+
|
|
51
|
+
## ESLint Plugin vs Programmatic API
|
|
52
|
+
|
|
53
|
+
**When to use the ESLint Plugin:**
|
|
54
|
+
- ✅ **Real-time feedback** - Catch issues as you type in your editor
|
|
55
|
+
- ✅ **CI/CD integration** - Prevent commits with accessibility violations
|
|
56
|
+
- ✅ **Team-wide enforcement** - Ensure all developers follow accessibility standards
|
|
57
|
+
- ✅ **Zero test code** - No need to write test cases, just configure ESLint
|
|
58
|
+
- ✅ **Best for:** Development workflow, code reviews, preventing regressions
|
|
59
|
+
|
|
60
|
+
**When to use the Programmatic API:**
|
|
61
|
+
- ✅ **Custom test scenarios** - Write specific accessibility tests in your test suite
|
|
62
|
+
- ✅ **Dynamic content** - Test accessibility of dynamically generated DOM
|
|
63
|
+
- ✅ **Integration testing** - Test accessibility in E2E or integration tests
|
|
64
|
+
- ✅ **Custom reporting** - Build custom violation reporting or analytics
|
|
65
|
+
- ✅ **Best for:** Unit tests, integration tests, custom testing workflows
|
|
66
|
+
|
|
67
|
+
**You can use both!** Many teams use ESLint plugin for development and programmatic API for comprehensive test coverage.
|
|
68
|
+
|
|
69
|
+
## What Problems Does This Solve?
|
|
70
|
+
|
|
71
|
+
❌ **Before:** Accessibility issues discovered in production or by users
|
|
72
|
+
✅ **After:** Issues caught in your editor before commit
|
|
73
|
+
|
|
74
|
+
❌ **Before:** Manual accessibility audits take hours
|
|
75
|
+
✅ **After:** Automated checks run in milliseconds
|
|
76
|
+
|
|
77
|
+
❌ **Before:** Complex setup with multiple tools
|
|
78
|
+
✅ **After:** One package, zero config, works everywhere
|
|
79
|
+
|
|
80
|
+
## Usage
|
|
48
81
|
|
|
49
|
-
|
|
82
|
+
> **Not sure which to use?** See [ESLint Plugin vs Programmatic API](#eslint-plugin-vs-programmatic-api) above for guidance.
|
|
83
|
+
|
|
84
|
+
### ESLint Plugin (Recommended for Most Cases)
|
|
85
|
+
|
|
86
|
+
The ESLint plugin provides real-time accessibility linting in your editor and CI/CD. It's the easiest way to catch issues during development.
|
|
50
87
|
|
|
51
88
|
#### Basic Setup
|
|
52
89
|
|
|
@@ -105,6 +142,32 @@ module.exports = {
|
|
|
105
142
|
|
|
106
143
|
See [Configuration Guide](./docs/CONFIGURATION.md) for more details and [Large Project Setup Guide](./docs/LARGE_PROJECTS.md) for incremental adoption strategies.
|
|
107
144
|
|
|
145
|
+
### Programmatic API
|
|
146
|
+
|
|
147
|
+
Use the `A11yChecker` class to test DOM elements programmatically in your test suites:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { A11yChecker } from 'test-a11y-js'
|
|
151
|
+
|
|
152
|
+
// Test a DOM element for accessibility violations
|
|
153
|
+
const results = await A11yChecker.check(element)
|
|
154
|
+
|
|
155
|
+
// Individual checks
|
|
156
|
+
const imageViolations = A11yChecker.checkImageAlt(element)
|
|
157
|
+
const linkViolations = A11yChecker.checkLinkText(element)
|
|
158
|
+
const buttonViolations = A11yChecker.checkButtonLabel(element)
|
|
159
|
+
const formViolations = A11yChecker.checkFormLabels(element)
|
|
160
|
+
const headingViolations = A11yChecker.checkHeadingOrder(element)
|
|
161
|
+
const iframeViolations = A11yChecker.checkIframeTitle(element)
|
|
162
|
+
const fieldsetViolations = A11yChecker.checkFieldsetLegend(element)
|
|
163
|
+
const tableViolations = A11yChecker.checkTableStructure(element)
|
|
164
|
+
const detailsViolations = A11yChecker.checkDetailsSummary(element)
|
|
165
|
+
const videoViolations = A11yChecker.checkVideoCaptions(element)
|
|
166
|
+
const audioViolations = A11yChecker.checkAudioCaptions(element)
|
|
167
|
+
const landmarkViolations = A11yChecker.checkLandmarks(element)
|
|
168
|
+
const dialogViolations = A11yChecker.checkDialogModal(element)
|
|
169
|
+
```
|
|
170
|
+
|
|
108
171
|
## API
|
|
109
172
|
|
|
110
173
|
### A11yChecker
|
|
@@ -151,6 +214,27 @@ Validates proper use of landmark elements.
|
|
|
151
214
|
#### `checkDialogModal(element: Element): A11yViolation[]`
|
|
152
215
|
Validates dialog elements have proper accessibility attributes.
|
|
153
216
|
|
|
217
|
+
#### `checkAriaRoles(element: Element): A11yViolation[]`
|
|
218
|
+
Validates ARIA roles for validity, appropriateness, and context.
|
|
219
|
+
|
|
220
|
+
#### `checkAriaProperties(element: Element): A11yViolation[]`
|
|
221
|
+
Validates ARIA properties for validity, appropriateness, and values.
|
|
222
|
+
|
|
223
|
+
#### `checkAriaRelationships(element: Element): A11yViolation[]`
|
|
224
|
+
Validates ARIA ID references with enhanced checks.
|
|
225
|
+
|
|
226
|
+
#### `checkAccessibleName(element: Element): A11yViolation[]`
|
|
227
|
+
Validates accessible name computation.
|
|
228
|
+
|
|
229
|
+
#### `checkCompositePatterns(element: Element): A11yViolation[]`
|
|
230
|
+
Validates composite ARIA patterns (tab/listbox/menu/tree).
|
|
231
|
+
|
|
232
|
+
#### `checkSemanticHTML(element: Element): A11yViolation[]`
|
|
233
|
+
Validates semantic HTML usage and structure.
|
|
234
|
+
|
|
235
|
+
#### `checkFormValidationMessages(element: Element): A11yViolation[]`
|
|
236
|
+
Validates form validation messages and error handling.
|
|
237
|
+
|
|
154
238
|
### Types
|
|
155
239
|
|
|
156
240
|
```typescript
|
|
@@ -182,6 +266,9 @@ interface A11yResults {
|
|
|
182
266
|
- **Audio captions validation** - Validates audio elements have tracks or transcripts
|
|
183
267
|
- **Landmark roles validation** - Checks proper use of semantic landmarks
|
|
184
268
|
- **Dialog/Modal validation** - Validates dialog accessibility patterns
|
|
269
|
+
- **Comprehensive ARIA validation** - Validates ARIA roles, properties, relationships, accessible names, and composite patterns
|
|
270
|
+
- **Semantic HTML validation** - Validates proper use of semantic HTML and detects misuse
|
|
271
|
+
- **Form validation messages** - Validates form validation and error handling
|
|
185
272
|
|
|
186
273
|
### ESLint Plugin
|
|
187
274
|
- Real-time accessibility linting in your editor
|
|
@@ -194,7 +281,7 @@ interface A11yResults {
|
|
|
194
281
|
|
|
195
282
|
## ESLint Rules
|
|
196
283
|
|
|
197
|
-
The plugin provides
|
|
284
|
+
The plugin provides 16 accessibility rules:
|
|
198
285
|
|
|
199
286
|
- `test-a11y-js/image-alt` - Enforce images have alt attributes
|
|
200
287
|
- `test-a11y-js/button-label` - Enforce buttons have labels
|
|
@@ -209,6 +296,9 @@ The plugin provides 13 accessibility rules:
|
|
|
209
296
|
- `test-a11y-js/audio-captions` - Enforce audio elements have tracks or transcripts
|
|
210
297
|
- `test-a11y-js/landmark-roles` - Enforce proper use of landmark elements (nav, main, header, footer, aside, section, article)
|
|
211
298
|
- `test-a11y-js/dialog-modal` - Enforce dialog elements have proper accessibility attributes
|
|
299
|
+
- `test-a11y-js/aria-validation` - Enforce valid ARIA roles, properties, relationships, and accessible names
|
|
300
|
+
- `test-a11y-js/semantic-html` - Enforce proper use of semantic HTML elements
|
|
301
|
+
- `test-a11y-js/form-validation` - Enforce proper form validation messages and error handling
|
|
212
302
|
|
|
213
303
|
See [`src/checks.json`](./src/checks.json) for a complete list of supported elements, ARIA attributes, and rules (including what's not yet supported).
|
|
214
304
|
|
|
@@ -272,6 +362,17 @@ function MyComponent() {
|
|
|
272
362
|
</template>
|
|
273
363
|
```
|
|
274
364
|
|
|
365
|
+
## How It Compares
|
|
366
|
+
|
|
367
|
+
| Feature | test-a11y-js | eslint-plugin-jsx-a11y | @axe-core/react |
|
|
368
|
+
|---------|--------------|------------------------|-----------------|
|
|
369
|
+
| Zero config | ✅ | ❌ | ❌ |
|
|
370
|
+
| Vue support | ✅ | ❌ | ❌ |
|
|
371
|
+
| Programmatic API | ✅ | ❌ | ✅ |
|
|
372
|
+
| Editor integration | ✅ | ✅ | ❌ |
|
|
373
|
+
| Large project ready | ✅ | ⚠️ | ⚠️ |
|
|
374
|
+
| Framework agnostic | ✅ | React only | React only |
|
|
375
|
+
|
|
275
376
|
## Framework Support
|
|
276
377
|
|
|
277
378
|
- ✅ **React/JSX** - Full support via JSX AST
|
|
@@ -289,6 +390,18 @@ npx eslint . --cache
|
|
|
289
390
|
|
|
290
391
|
See [Performance Guide](./docs/PERFORMANCE.md) for optimization tips and [Large Project Setup Guide](./docs/LARGE_PROJECTS.md) for incremental adoption strategies.
|
|
291
392
|
|
|
393
|
+
## Real Impact
|
|
394
|
+
|
|
395
|
+
**Before using test-a11y-js:**
|
|
396
|
+
- Accessibility violations discovered in production audits
|
|
397
|
+
- Weeks spent fixing issues after deployment
|
|
398
|
+
- High costs for accessibility audits
|
|
399
|
+
|
|
400
|
+
**After using test-a11y-js:**
|
|
401
|
+
- Issues caught during development in your editor
|
|
402
|
+
- Zero violations reach production
|
|
403
|
+
- Automated checks save time and money
|
|
404
|
+
|
|
292
405
|
## Publishing
|
|
293
406
|
|
|
294
407
|
This package uses GitHub Actions for automated publishing to npm. Publishing details are documented in [`.github/workflows/README.md`](.github/workflows/README.md) for maintainers.
|
package/dist/index.d.mts
CHANGED
|
@@ -25,6 +25,43 @@ declare class A11yChecker {
|
|
|
25
25
|
static checkLandmarks(element: Element): A11yViolation[];
|
|
26
26
|
static checkDialogModal(element: Element): A11yViolation[];
|
|
27
27
|
static check(element: Element): Promise<A11yResults>;
|
|
28
|
+
/**
|
|
29
|
+
* Check ARIA roles for validity, appropriateness, and context
|
|
30
|
+
*/
|
|
31
|
+
static checkAriaRoles(element: Element): A11yViolation[];
|
|
32
|
+
private static hasStrongNativeSemantics;
|
|
33
|
+
/**
|
|
34
|
+
* Check ARIA properties for validity, appropriateness, and values
|
|
35
|
+
*/
|
|
36
|
+
static checkAriaProperties(element: Element): A11yViolation[];
|
|
37
|
+
/**
|
|
38
|
+
* Validate ARIA property value based on type
|
|
39
|
+
*/
|
|
40
|
+
private static validateAriaPropertyValue;
|
|
41
|
+
/**
|
|
42
|
+
* Check ARIA relationships (ID references) with enhanced validation
|
|
43
|
+
*/
|
|
44
|
+
static checkAriaRelationships(element: Element): A11yViolation[];
|
|
45
|
+
/**
|
|
46
|
+
* Check if element is focusable
|
|
47
|
+
*/
|
|
48
|
+
private static isFocusable;
|
|
49
|
+
/**
|
|
50
|
+
* Check accessible name computation
|
|
51
|
+
*/
|
|
52
|
+
static checkAccessibleName(element: Element): A11yViolation[];
|
|
53
|
+
/**
|
|
54
|
+
* Check composite patterns (tab/listbox/menu/tree)
|
|
55
|
+
*/
|
|
56
|
+
static checkCompositePatterns(element: Element): A11yViolation[];
|
|
57
|
+
/**
|
|
58
|
+
* Check semantic HTML usage and structure
|
|
59
|
+
*/
|
|
60
|
+
static checkSemanticHTML(element: Element): A11yViolation[];
|
|
61
|
+
/**
|
|
62
|
+
* Check form validation messages
|
|
63
|
+
*/
|
|
64
|
+
static checkFormValidationMessages(element: Element): A11yViolation[];
|
|
28
65
|
}
|
|
29
66
|
|
|
30
67
|
export { A11yChecker, A11yResults, A11yViolation };
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,43 @@ declare class A11yChecker {
|
|
|
25
25
|
static checkLandmarks(element: Element): A11yViolation[];
|
|
26
26
|
static checkDialogModal(element: Element): A11yViolation[];
|
|
27
27
|
static check(element: Element): Promise<A11yResults>;
|
|
28
|
+
/**
|
|
29
|
+
* Check ARIA roles for validity, appropriateness, and context
|
|
30
|
+
*/
|
|
31
|
+
static checkAriaRoles(element: Element): A11yViolation[];
|
|
32
|
+
private static hasStrongNativeSemantics;
|
|
33
|
+
/**
|
|
34
|
+
* Check ARIA properties for validity, appropriateness, and values
|
|
35
|
+
*/
|
|
36
|
+
static checkAriaProperties(element: Element): A11yViolation[];
|
|
37
|
+
/**
|
|
38
|
+
* Validate ARIA property value based on type
|
|
39
|
+
*/
|
|
40
|
+
private static validateAriaPropertyValue;
|
|
41
|
+
/**
|
|
42
|
+
* Check ARIA relationships (ID references) with enhanced validation
|
|
43
|
+
*/
|
|
44
|
+
static checkAriaRelationships(element: Element): A11yViolation[];
|
|
45
|
+
/**
|
|
46
|
+
* Check if element is focusable
|
|
47
|
+
*/
|
|
48
|
+
private static isFocusable;
|
|
49
|
+
/**
|
|
50
|
+
* Check accessible name computation
|
|
51
|
+
*/
|
|
52
|
+
static checkAccessibleName(element: Element): A11yViolation[];
|
|
53
|
+
/**
|
|
54
|
+
* Check composite patterns (tab/listbox/menu/tree)
|
|
55
|
+
*/
|
|
56
|
+
static checkCompositePatterns(element: Element): A11yViolation[];
|
|
57
|
+
/**
|
|
58
|
+
* Check semantic HTML usage and structure
|
|
59
|
+
*/
|
|
60
|
+
static checkSemanticHTML(element: Element): A11yViolation[];
|
|
61
|
+
/**
|
|
62
|
+
* Check form validation messages
|
|
63
|
+
*/
|
|
64
|
+
static checkFormValidationMessages(element: Element): A11yViolation[];
|
|
28
65
|
}
|
|
29
66
|
|
|
30
67
|
export { A11yChecker, A11yResults, A11yViolation };
|