@afixt/test-utils 1.3.0 → 2.0.1
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/BROWSER_TESTING.md +42 -22
- package/CHANGELOG.md +40 -0
- package/CLAUDE.md +10 -9
- package/package.json +1 -1
- package/src/constants.js +438 -1
- package/src/domUtils.js +17 -38
- package/src/formUtils.js +7 -24
- package/src/getAccessibleName.js +13 -71
- package/src/getCSSGeneratedContent.js +2 -0
- package/src/getFocusableElements.js +12 -21
- package/src/getGeneratedContent.js +18 -11
- package/src/getImageText.js +22 -7
- package/src/hasValidAriaRole.js +11 -19
- package/src/index.js +4 -4
- package/src/interactiveRoles.js +2 -19
- package/src/isA11yVisible.js +95 -0
- package/src/isAriaAttributesValid.js +5 -64
- package/src/isFocusable.js +30 -10
- package/src/isHidden.js +44 -8
- package/src/listEventListeners.js +115 -10
- package/src/stringUtils.js +54 -98
- package/src/tableUtils.js +4 -36
- package/test/domUtils.test.js +156 -0
- package/test/formUtils.test.js +0 -47
- package/test/getGeneratedContent.test.js +305 -241
- package/test/getImageText.test.js +158 -99
- package/test/index.test.js +54 -17
- package/test/{isVisible.test.js → isA11yVisible.test.js} +39 -33
- package/test/isFocusable.test.js +265 -272
- package/test/isHidden.test.js +257 -153
- package/test/listEventListeners.test.js +163 -44
- package/test/playwright/css-pseudo-elements.spec.js +3 -13
- package/test/stringUtils.test.js +115 -228
- package/todo.md +2 -2
- package/src/isVisible.js +0 -103
package/BROWSER_TESTING.md
CHANGED
|
@@ -6,19 +6,19 @@ This project uses **JSDOM** for the main test suite with **Playwright** for CSS
|
|
|
6
6
|
|
|
7
7
|
## Current Status
|
|
8
8
|
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **Total:
|
|
9
|
+
- **943 tests passing** in JSDOM environment (8 conditionally skipped)
|
|
10
|
+
- **20 tests passing** in Playwright for CSS pseudo-element support
|
|
11
|
+
- **Total: 963 tests passing** across both environments
|
|
12
12
|
|
|
13
13
|
### Implementation Complete
|
|
14
14
|
|
|
15
|
-
✅ JSDOM tests for all standard functionality (
|
|
16
|
-
✅ Standalone Playwright tests for CSS pseudo-elements (
|
|
17
|
-
✅
|
|
15
|
+
✅ JSDOM tests for all standard functionality (943 tests)
|
|
16
|
+
✅ Standalone Playwright tests for CSS pseudo-elements (20 tests)
|
|
17
|
+
✅ 8 CSS pseudo-element tests conditionally skipped in JSDOM, covered by Playwright
|
|
18
18
|
|
|
19
19
|
## Solution: Hybrid Testing Approach
|
|
20
20
|
|
|
21
|
-
The
|
|
21
|
+
The 20 CSS pseudo-element tests run with standalone Playwright tests that inject browser-compatible code directly into the page. This approach:
|
|
22
22
|
|
|
23
23
|
- ✅ Works with existing CommonJS source code
|
|
24
24
|
- ✅ Tests real browser CSS pseudo-element behavior
|
|
@@ -28,29 +28,33 @@ The 10 CSS pseudo-element tests now run with standalone Playwright tests that in
|
|
|
28
28
|
## Running Tests
|
|
29
29
|
|
|
30
30
|
### JSDOM Tests (Main Test Suite)
|
|
31
|
+
|
|
31
32
|
```bash
|
|
32
|
-
npm test # Run all
|
|
33
|
+
npm test # Run all 943 JSDOM tests
|
|
33
34
|
npm run test:coverage # Run with coverage
|
|
34
35
|
npm run test:watch # Watch mode
|
|
35
36
|
```
|
|
36
37
|
|
|
37
|
-
**Status:**
|
|
38
|
+
**Status:** 943 tests passing (8 conditionally skipped)
|
|
38
39
|
|
|
39
40
|
**Pros:**
|
|
41
|
+
|
|
40
42
|
- ⚡ Very fast execution (~3-4 seconds)
|
|
41
43
|
- 🔧 No browser dependencies needed
|
|
42
44
|
- ✅ Perfect for CI/CD and development
|
|
43
45
|
- ✅ Works with existing CommonJS code
|
|
44
46
|
|
|
45
47
|
### Playwright CSS Pseudo-element Tests
|
|
48
|
+
|
|
46
49
|
```bash
|
|
47
|
-
npm run test:playwright:css # Run
|
|
50
|
+
npm run test:playwright:css # Run 20 CSS pseudo-element tests
|
|
48
51
|
npm run test:all # Run both JSDOM + Playwright tests
|
|
49
52
|
```
|
|
50
53
|
|
|
51
|
-
**Status:**
|
|
54
|
+
**Status:** 20 tests passing
|
|
52
55
|
|
|
53
56
|
**Pros:**
|
|
57
|
+
|
|
54
58
|
- ✅ Real browser CSS pseudo-element support
|
|
55
59
|
- ✅ Tests `::before` and `::after` content properly
|
|
56
60
|
- ✅ Validates `getComputedStyle()` behavior
|
|
@@ -59,7 +63,8 @@ npm run test:all # Run both JSDOM + Playwright tests
|
|
|
59
63
|
|
|
60
64
|
The Playwright tests validate the following functionality:
|
|
61
65
|
|
|
62
|
-
#### getGeneratedContent
|
|
66
|
+
#### getGeneratedContent (8 tests)
|
|
67
|
+
|
|
63
68
|
- ✅ `should return ::before content when present`
|
|
64
69
|
- ✅ `should return ::after content when present`
|
|
65
70
|
- ✅ `should combine ::before, text content, and ::after`
|
|
@@ -69,7 +74,21 @@ The Playwright tests validate the following functionality:
|
|
|
69
74
|
- ✅ `should handle nested elements with generated content`
|
|
70
75
|
- ✅ `should handle content with HTML entities in CSS`
|
|
71
76
|
|
|
72
|
-
####
|
|
77
|
+
#### getCSSGeneratedContent (10 tests)
|
|
78
|
+
|
|
79
|
+
- ✅ `should get ::before content`
|
|
80
|
+
- ✅ `should get ::after content`
|
|
81
|
+
- ✅ `should get both ::before and ::after content`
|
|
82
|
+
- ✅ `should handle quoted content`
|
|
83
|
+
- ✅ `should handle URL content`
|
|
84
|
+
- ✅ `should default pseudoElement to both`
|
|
85
|
+
- ✅ `should return false for empty content`
|
|
86
|
+
- ✅ `should return false for content: none`
|
|
87
|
+
- ✅ `should return false for null element`
|
|
88
|
+
- ✅ `should return false for elements with no pseudo-element styles`
|
|
89
|
+
|
|
90
|
+
#### hasCSSGeneratedContent (2 tests)
|
|
91
|
+
|
|
73
92
|
- ✅ `should correctly identify elements with ::before content`
|
|
74
93
|
- ✅ `should correctly identify elements with ::after content`
|
|
75
94
|
|
|
@@ -83,7 +102,7 @@ The Playwright tests validate the following functionality:
|
|
|
83
102
|
|
|
84
103
|
### How It Works
|
|
85
104
|
|
|
86
|
-
The Playwright tests inject browser-compatible versions of `getGeneratedContent` and `hasCSSGeneratedContent` directly into the page using `page.addScriptTag()`. This approach:
|
|
105
|
+
The Playwright tests inject browser-compatible versions of `getGeneratedContent`, `getCSSGeneratedContent`, and `hasCSSGeneratedContent` directly into the page using `page.addScriptTag()`. This approach:
|
|
87
106
|
|
|
88
107
|
1. Loads an HTML fixture with CSS pseudo-element styles
|
|
89
108
|
2. Injects browser-compatible JavaScript functions
|
|
@@ -94,16 +113,17 @@ The Playwright tests inject browser-compatible versions of `getGeneratedContent`
|
|
|
94
113
|
|
|
95
114
|
```json
|
|
96
115
|
{
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
"test": "vitest run", // JSDOM tests (943 tests)
|
|
117
|
+
"test:coverage": "vitest run --coverage", // JSDOM with coverage
|
|
118
|
+
"test:playwright:css": "playwright test ...", // Playwright CSS tests (20 tests)
|
|
119
|
+
"test:all": "npm run test && npm run test:playwright:css" // All tests (963 tests)
|
|
101
120
|
}
|
|
102
121
|
```
|
|
103
122
|
|
|
104
123
|
## Test Coverage
|
|
105
124
|
|
|
106
|
-
- **
|
|
107
|
-
- **
|
|
108
|
-
- **
|
|
109
|
-
- **
|
|
125
|
+
- **87.75% statement coverage**
|
|
126
|
+
- **82.11% branch coverage**
|
|
127
|
+
- **95.58% function coverage**
|
|
128
|
+
- **87.69% line coverage**
|
|
129
|
+
- **963 total tests passing** (943 JSDOM + 20 Playwright)
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [2.0.0] - 2026-02-22
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- **`isVisible` renamed to `isA11yVisible`** (#26): The exported function `isVisible` has been renamed to `isA11yVisible` to clarify its AT-aware purpose. Update all imports from `isVisible` to `isA11yVisible`.
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- **isHidden**: Expand hidden detection with computed styles and configurable options (`checkAriaHidden`, `checkOpacity`, `checkDimensions`) (#31)
|
|
14
|
+
- **isFocusable**: Expand checks for visibility, `contenteditable`, and generic `tabindex` elements (#35)
|
|
15
|
+
- **listEventListeners**: Detect inline and property-based event handlers (#27)
|
|
16
|
+
- **domUtils**: Expand `hasInteractiveHandler` with additional event attributes (#32)
|
|
17
|
+
- **domUtils**: Expand `getSemanticContainer` tags and validate ARIA roles (#33)
|
|
18
|
+
- **stringUtils**: Expand `isGenericTitle` to detect more generic title patterns (#37)
|
|
19
|
+
- **getImageText**: Add language and options support for OCR (#30)
|
|
20
|
+
- **testContrast**: Skip contrast testing for elements with background images
|
|
21
|
+
|
|
22
|
+
### Refactoring
|
|
23
|
+
|
|
24
|
+
- **isA11yVisible**: Delegate element-level hidden check to `isHidden` to reduce code duplication (#26)
|
|
25
|
+
- **formUtils**: Remove redundant `hasAssociatedLabel` function (#25)
|
|
26
|
+
- **stringUtils**: Replace `getAllText` with `getAccessibleText` in `hasText` (#36)
|
|
27
|
+
- **constants**: Consolidate hardcoded constants into `constants.js` (#28)
|
|
28
|
+
|
|
29
|
+
### Fixes
|
|
30
|
+
|
|
31
|
+
- **getGeneratedContent**: Delegate pseudo-element retrieval to `getCSSGeneratedContent` (#29)
|
|
32
|
+
|
|
33
|
+
### Documentation
|
|
34
|
+
|
|
35
|
+
- **formUtils**: Clarify purpose of `hasExplicitAccessibleName` (#24)
|
|
36
|
+
- Update test counts and coverage stats to match actual values
|
|
37
|
+
|
|
38
|
+
## [1.2.0] - Previous release
|
|
39
|
+
|
|
40
|
+
See git history for earlier changes.
|
package/CLAUDE.md
CHANGED
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
## Git Workflow
|
|
26
26
|
|
|
27
27
|
- **Branching Strategy**: Git Flow must be used for all development
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
- **main/master**: Production-ready code only
|
|
29
|
+
- **develop**: Integration branch for features
|
|
30
|
+
- **feature/\***: New features (branch from develop, merge back to develop)
|
|
31
|
+
- **release/\***: Release preparation (branch from develop, merge to main and develop)
|
|
32
|
+
- **hotfix/\***: Emergency fixes (branch from main, merge to main and develop)
|
|
33
33
|
- **Branch Naming**: Use descriptive names (e.g., `feature/add-aria-validation`, `hotfix/fix-focus-trap`)
|
|
34
34
|
- **Commits**: Write clear, concise commit messages following conventional commits when possible
|
|
35
35
|
- **Pull Requests**: All features must go through PR review before merging to develop
|
|
@@ -44,12 +44,13 @@
|
|
|
44
44
|
|
|
45
45
|
### Test Status
|
|
46
46
|
|
|
47
|
-
- **
|
|
48
|
-
- **
|
|
49
|
-
-
|
|
47
|
+
- **943 tests passing** in JSDOM environment
|
|
48
|
+
- **8 tests skipped** - Conditionally skipped in JSDOM; require real browser CSS pseudo-element support
|
|
49
|
+
- **20 Playwright tests** cover CSS pseudo-element functionality in a real browser
|
|
50
|
+
- See `BROWSER_TESTING.md` for details on the hybrid testing approach
|
|
50
51
|
|
|
51
52
|
### Browser Testing Limitations
|
|
52
53
|
|
|
53
|
-
JSDOM does not fully support CSS pseudo-elements (`::before`, `::after`). Tests requiring these features are
|
|
54
|
+
JSDOM does not fully support CSS pseudo-elements (`::before`, `::after`). Tests requiring these features are conditionally skipped in JSDOM and covered by standalone Playwright tests instead. For details, see `BROWSER_TESTING.md`.
|
|
54
55
|
|
|
55
56
|
This codebase provides DOM and accessibility testing utilities
|
package/package.json
CHANGED
package/src/constants.js
CHANGED
|
@@ -96,7 +96,52 @@ const RTL_LANGUAGES = [
|
|
|
96
96
|
* Generic, non-descriptive, or meaningless frame/iframe titles.
|
|
97
97
|
* @type {string[]}
|
|
98
98
|
*/
|
|
99
|
-
const GENERIC_TITLES = [
|
|
99
|
+
const GENERIC_TITLES = [
|
|
100
|
+
'iframe',
|
|
101
|
+
'frame',
|
|
102
|
+
'untitled',
|
|
103
|
+
'title',
|
|
104
|
+
'content',
|
|
105
|
+
'main',
|
|
106
|
+
'page',
|
|
107
|
+
// Browser/authoring tool defaults
|
|
108
|
+
'untitled document',
|
|
109
|
+
'new page',
|
|
110
|
+
'blank',
|
|
111
|
+
'document',
|
|
112
|
+
'home',
|
|
113
|
+
'index',
|
|
114
|
+
'new document',
|
|
115
|
+
'no title',
|
|
116
|
+
'default',
|
|
117
|
+
'webpage',
|
|
118
|
+
'web page',
|
|
119
|
+
// CMS and editor defaults
|
|
120
|
+
'new tab',
|
|
121
|
+
'about blank',
|
|
122
|
+
'placeholder',
|
|
123
|
+
'sample page',
|
|
124
|
+
'test',
|
|
125
|
+
'example page',
|
|
126
|
+
'my page',
|
|
127
|
+
'welcome',
|
|
128
|
+
'landing page',
|
|
129
|
+
'site',
|
|
130
|
+
'header',
|
|
131
|
+
'footer',
|
|
132
|
+
'sidebar',
|
|
133
|
+
'banner',
|
|
134
|
+
'navigation',
|
|
135
|
+
'advertisement',
|
|
136
|
+
'ad',
|
|
137
|
+
'widget',
|
|
138
|
+
'module',
|
|
139
|
+
'section',
|
|
140
|
+
'region',
|
|
141
|
+
'form',
|
|
142
|
+
'search',
|
|
143
|
+
'menu',
|
|
144
|
+
];
|
|
100
145
|
|
|
101
146
|
/**
|
|
102
147
|
* Generic or useless table summaries commonly found in the wild.
|
|
@@ -214,6 +259,385 @@ const NEW_WINDOW_WARNINGS = [
|
|
|
214
259
|
'external site',
|
|
215
260
|
];
|
|
216
261
|
|
|
262
|
+
/**
|
|
263
|
+
* ARIA roles that represent interactive widgets.
|
|
264
|
+
* @type {string[]}
|
|
265
|
+
*/
|
|
266
|
+
const INTERACTIVE_ROLES = [
|
|
267
|
+
'button',
|
|
268
|
+
'checkbox',
|
|
269
|
+
'combobox',
|
|
270
|
+
'link',
|
|
271
|
+
'menu',
|
|
272
|
+
'menuitemcheckbox',
|
|
273
|
+
'menuitemradio',
|
|
274
|
+
'radio',
|
|
275
|
+
'scrollbar',
|
|
276
|
+
'slider',
|
|
277
|
+
'spinbutton',
|
|
278
|
+
'tablist',
|
|
279
|
+
'textbox',
|
|
280
|
+
'toolbar',
|
|
281
|
+
'switch',
|
|
282
|
+
'tree',
|
|
283
|
+
];
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* HTML tag names that are landmark elements.
|
|
287
|
+
* @type {string[]}
|
|
288
|
+
*/
|
|
289
|
+
const LANDMARK_TAGS = ['NAV', 'MAIN', 'HEADER', 'FOOTER', 'ASIDE', 'SECTION'];
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* ARIA landmark roles.
|
|
293
|
+
* @type {string[]}
|
|
294
|
+
*/
|
|
295
|
+
const LANDMARK_ROLES = [
|
|
296
|
+
'navigation',
|
|
297
|
+
'main',
|
|
298
|
+
'banner',
|
|
299
|
+
'contentinfo',
|
|
300
|
+
'complementary',
|
|
301
|
+
'region',
|
|
302
|
+
'search',
|
|
303
|
+
'form',
|
|
304
|
+
];
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Mapping of HTML tag names to their implicit landmark roles.
|
|
308
|
+
* @type {Object.<string, string>}
|
|
309
|
+
*/
|
|
310
|
+
const LANDMARK_ELEMENT_MAP = {
|
|
311
|
+
nav: 'navigation',
|
|
312
|
+
main: 'main',
|
|
313
|
+
aside: 'complementary',
|
|
314
|
+
header: 'banner',
|
|
315
|
+
footer: 'contentinfo',
|
|
316
|
+
section: 'region',
|
|
317
|
+
form: 'form',
|
|
318
|
+
search: 'search',
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Set of valid ARIA attributes per WAI-ARIA specification.
|
|
323
|
+
* @type {Set<string>}
|
|
324
|
+
*/
|
|
325
|
+
const VALID_ARIA_ATTRIBUTES = new Set([
|
|
326
|
+
'aria-activedescendant',
|
|
327
|
+
'aria-atomic',
|
|
328
|
+
'aria-autocomplete',
|
|
329
|
+
'aria-braillelabel',
|
|
330
|
+
'aria-brailleroledescription',
|
|
331
|
+
'aria-busy',
|
|
332
|
+
'aria-checked',
|
|
333
|
+
'aria-colcount',
|
|
334
|
+
'aria-colindex',
|
|
335
|
+
'aria-colindextext',
|
|
336
|
+
'aria-colspan',
|
|
337
|
+
'aria-controls',
|
|
338
|
+
'aria-current',
|
|
339
|
+
'aria-describedby',
|
|
340
|
+
'aria-description',
|
|
341
|
+
'aria-details',
|
|
342
|
+
'aria-disabled',
|
|
343
|
+
'aria-dropeffect',
|
|
344
|
+
'aria-errormessage',
|
|
345
|
+
'aria-expanded',
|
|
346
|
+
'aria-flowto',
|
|
347
|
+
'aria-grabbed',
|
|
348
|
+
'aria-haspopup',
|
|
349
|
+
'aria-hidden',
|
|
350
|
+
'aria-invalid',
|
|
351
|
+
'aria-keyshortcuts',
|
|
352
|
+
'aria-label',
|
|
353
|
+
'aria-labelledby',
|
|
354
|
+
'aria-level',
|
|
355
|
+
'aria-live',
|
|
356
|
+
'aria-modal',
|
|
357
|
+
'aria-multiline',
|
|
358
|
+
'aria-multiselectable',
|
|
359
|
+
'aria-orientation',
|
|
360
|
+
'aria-owns',
|
|
361
|
+
'aria-placeholder',
|
|
362
|
+
'aria-posinset',
|
|
363
|
+
'aria-pressed',
|
|
364
|
+
'aria-readonly',
|
|
365
|
+
'aria-relevant',
|
|
366
|
+
'aria-required',
|
|
367
|
+
'aria-roledescription',
|
|
368
|
+
'aria-rowcount',
|
|
369
|
+
'aria-rowindex',
|
|
370
|
+
'aria-rowindextext',
|
|
371
|
+
'aria-rowspan',
|
|
372
|
+
'aria-selected',
|
|
373
|
+
'aria-setsize',
|
|
374
|
+
'aria-sort',
|
|
375
|
+
'aria-valuemax',
|
|
376
|
+
'aria-valuemin',
|
|
377
|
+
'aria-valuenow',
|
|
378
|
+
'aria-valuetext',
|
|
379
|
+
]);
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* CSS selectors for elements that are inherently not visible in the accessibility tree.
|
|
383
|
+
* @type {string[]}
|
|
384
|
+
*/
|
|
385
|
+
const NON_VISIBLE_SELECTORS = [
|
|
386
|
+
'base',
|
|
387
|
+
'head',
|
|
388
|
+
'meta',
|
|
389
|
+
'title',
|
|
390
|
+
'link',
|
|
391
|
+
'style',
|
|
392
|
+
'script',
|
|
393
|
+
'br',
|
|
394
|
+
'nobr',
|
|
395
|
+
'col',
|
|
396
|
+
'embed',
|
|
397
|
+
'input[type="hidden"]',
|
|
398
|
+
'keygen',
|
|
399
|
+
'source',
|
|
400
|
+
'track',
|
|
401
|
+
'wbr',
|
|
402
|
+
'datalist',
|
|
403
|
+
'area',
|
|
404
|
+
'param',
|
|
405
|
+
'noframes',
|
|
406
|
+
'ruby > rp',
|
|
407
|
+
];
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* ARIA roles that derive their accessible name from text content.
|
|
411
|
+
* @type {string[]}
|
|
412
|
+
*/
|
|
413
|
+
const TEXT_ROLES = [
|
|
414
|
+
'button',
|
|
415
|
+
'checkbox',
|
|
416
|
+
'columnheader',
|
|
417
|
+
'gridcell',
|
|
418
|
+
'heading',
|
|
419
|
+
'link',
|
|
420
|
+
'listitem',
|
|
421
|
+
'menuitem',
|
|
422
|
+
'menuitemcheckbox',
|
|
423
|
+
'menuitemradio',
|
|
424
|
+
'option',
|
|
425
|
+
'radio',
|
|
426
|
+
'row',
|
|
427
|
+
'rowgroup',
|
|
428
|
+
'rowheader',
|
|
429
|
+
'tab',
|
|
430
|
+
'tooltip',
|
|
431
|
+
'treeitem',
|
|
432
|
+
];
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Raw array of CSS selectors for focusable elements (without :not([disabled]) filters).
|
|
436
|
+
* @type {string[]}
|
|
437
|
+
*/
|
|
438
|
+
const FOCUSABLE_SELECTORS = [
|
|
439
|
+
'a[href]',
|
|
440
|
+
'area',
|
|
441
|
+
'button',
|
|
442
|
+
'select',
|
|
443
|
+
'textarea',
|
|
444
|
+
'input:not([type="hidden"])',
|
|
445
|
+
'[tabindex]',
|
|
446
|
+
];
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Set of all valid WAI-ARIA roles.
|
|
450
|
+
* @type {Set<string>}
|
|
451
|
+
*/
|
|
452
|
+
const VALID_ARIA_ROLES = new Set([
|
|
453
|
+
'alert',
|
|
454
|
+
'alertdialog',
|
|
455
|
+
'button',
|
|
456
|
+
'checkbox',
|
|
457
|
+
'dialog',
|
|
458
|
+
'gridcell',
|
|
459
|
+
'link',
|
|
460
|
+
'log',
|
|
461
|
+
'marquee',
|
|
462
|
+
'menuitem',
|
|
463
|
+
'menuitemcheckbox',
|
|
464
|
+
'menuitemradio',
|
|
465
|
+
'option',
|
|
466
|
+
'progressbar',
|
|
467
|
+
'radio',
|
|
468
|
+
'scrollbar',
|
|
469
|
+
'searchbox',
|
|
470
|
+
'slider',
|
|
471
|
+
'spinbutton',
|
|
472
|
+
'status',
|
|
473
|
+
'switch',
|
|
474
|
+
'tab',
|
|
475
|
+
'tabpanel',
|
|
476
|
+
'textbox',
|
|
477
|
+
'tooltip',
|
|
478
|
+
'treeitem',
|
|
479
|
+
'combobox',
|
|
480
|
+
'grid',
|
|
481
|
+
'listbox',
|
|
482
|
+
'menu',
|
|
483
|
+
'menubar',
|
|
484
|
+
'radiogroup',
|
|
485
|
+
'tablist',
|
|
486
|
+
'tree',
|
|
487
|
+
'treegrid',
|
|
488
|
+
'article',
|
|
489
|
+
'cell',
|
|
490
|
+
'columnheader',
|
|
491
|
+
'definition',
|
|
492
|
+
'directory',
|
|
493
|
+
'document',
|
|
494
|
+
'feed',
|
|
495
|
+
'figure',
|
|
496
|
+
'group',
|
|
497
|
+
'heading',
|
|
498
|
+
'img',
|
|
499
|
+
'list',
|
|
500
|
+
'listitem',
|
|
501
|
+
'math',
|
|
502
|
+
'none',
|
|
503
|
+
'note',
|
|
504
|
+
'presentation',
|
|
505
|
+
'row',
|
|
506
|
+
'rowgroup',
|
|
507
|
+
'rowheader',
|
|
508
|
+
'separator',
|
|
509
|
+
'table',
|
|
510
|
+
'term',
|
|
511
|
+
'toolbar',
|
|
512
|
+
'application',
|
|
513
|
+
'banner',
|
|
514
|
+
'complementary',
|
|
515
|
+
'contentinfo',
|
|
516
|
+
'form',
|
|
517
|
+
'main',
|
|
518
|
+
'navigation',
|
|
519
|
+
'region',
|
|
520
|
+
'search',
|
|
521
|
+
'timer',
|
|
522
|
+
]);
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Generic/meaningless link text strings.
|
|
526
|
+
* @type {string[]}
|
|
527
|
+
*/
|
|
528
|
+
const GENERIC_LINK_TEXT = [
|
|
529
|
+
'click here',
|
|
530
|
+
'here',
|
|
531
|
+
'more',
|
|
532
|
+
'read more',
|
|
533
|
+
'learn more',
|
|
534
|
+
'click',
|
|
535
|
+
'link',
|
|
536
|
+
'this',
|
|
537
|
+
'page',
|
|
538
|
+
'article',
|
|
539
|
+
'continue',
|
|
540
|
+
'go',
|
|
541
|
+
'see more',
|
|
542
|
+
'view',
|
|
543
|
+
'download',
|
|
544
|
+
'pdf',
|
|
545
|
+
'document',
|
|
546
|
+
'form',
|
|
547
|
+
'submit',
|
|
548
|
+
'button',
|
|
549
|
+
'press',
|
|
550
|
+
'select',
|
|
551
|
+
'choose',
|
|
552
|
+
];
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* HTML tag names that act as semantic containers.
|
|
556
|
+
* @type {string[]}
|
|
557
|
+
*/
|
|
558
|
+
const SEMANTIC_CONTAINER_TAGS = [
|
|
559
|
+
'ARTICLE',
|
|
560
|
+
'ASIDE',
|
|
561
|
+
'BLOCKQUOTE',
|
|
562
|
+
'DETAILS',
|
|
563
|
+
'DIALOG',
|
|
564
|
+
'FIELDSET',
|
|
565
|
+
'FIGURE',
|
|
566
|
+
'FOOTER',
|
|
567
|
+
'FORM',
|
|
568
|
+
'HEADER',
|
|
569
|
+
'LI',
|
|
570
|
+
'MAIN',
|
|
571
|
+
'NAV',
|
|
572
|
+
'SECTION',
|
|
573
|
+
'TD',
|
|
574
|
+
'TH',
|
|
575
|
+
];
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* ARIA roles that represent semantic containers.
|
|
579
|
+
* @type {string[]}
|
|
580
|
+
*/
|
|
581
|
+
const SEMANTIC_CONTAINER_ROLES = [
|
|
582
|
+
'alert',
|
|
583
|
+
'alertdialog',
|
|
584
|
+
'application',
|
|
585
|
+
'banner',
|
|
586
|
+
'cell',
|
|
587
|
+
'complementary',
|
|
588
|
+
'contentinfo',
|
|
589
|
+
'dialog',
|
|
590
|
+
'document',
|
|
591
|
+
'feed',
|
|
592
|
+
'figure',
|
|
593
|
+
'form',
|
|
594
|
+
'grid',
|
|
595
|
+
'group',
|
|
596
|
+
'list',
|
|
597
|
+
'listbox',
|
|
598
|
+
'log',
|
|
599
|
+
'main',
|
|
600
|
+
'menu',
|
|
601
|
+
'menubar',
|
|
602
|
+
'navigation',
|
|
603
|
+
'note',
|
|
604
|
+
'region',
|
|
605
|
+
'row',
|
|
606
|
+
'rowgroup',
|
|
607
|
+
'search',
|
|
608
|
+
'status',
|
|
609
|
+
'table',
|
|
610
|
+
'tablist',
|
|
611
|
+
'tabpanel',
|
|
612
|
+
'toolbar',
|
|
613
|
+
'tree',
|
|
614
|
+
'treegrid',
|
|
615
|
+
];
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Inline event handler attributes that indicate user interactivity.
|
|
619
|
+
* @type {string[]}
|
|
620
|
+
*/
|
|
621
|
+
const INTERACTIVE_HANDLER_ATTRIBUTES = [
|
|
622
|
+
'onclick',
|
|
623
|
+
'ondblclick',
|
|
624
|
+
'oncontextmenu',
|
|
625
|
+
'onmousedown',
|
|
626
|
+
'onmouseup',
|
|
627
|
+
'onkeydown',
|
|
628
|
+
'onkeyup',
|
|
629
|
+
'onkeypress',
|
|
630
|
+
'onfocus',
|
|
631
|
+
'onblur',
|
|
632
|
+
'oninput',
|
|
633
|
+
'onchange',
|
|
634
|
+
'onsubmit',
|
|
635
|
+
'ontouchstart',
|
|
636
|
+
'ontouchend',
|
|
637
|
+
'onpointerdown',
|
|
638
|
+
'onpointerup',
|
|
639
|
+
];
|
|
640
|
+
|
|
217
641
|
module.exports = {
|
|
218
642
|
INTERACTIVE_SELECTOR,
|
|
219
643
|
FOCUSABLE_SELECTOR,
|
|
@@ -228,4 +652,17 @@ module.exports = {
|
|
|
228
652
|
COMPLEXITY_THRESHOLDS,
|
|
229
653
|
MIN_TARGET_SIZE,
|
|
230
654
|
NEW_WINDOW_WARNINGS,
|
|
655
|
+
INTERACTIVE_ROLES,
|
|
656
|
+
LANDMARK_TAGS,
|
|
657
|
+
LANDMARK_ROLES,
|
|
658
|
+
LANDMARK_ELEMENT_MAP,
|
|
659
|
+
VALID_ARIA_ATTRIBUTES,
|
|
660
|
+
NON_VISIBLE_SELECTORS,
|
|
661
|
+
TEXT_ROLES,
|
|
662
|
+
FOCUSABLE_SELECTORS,
|
|
663
|
+
VALID_ARIA_ROLES,
|
|
664
|
+
GENERIC_LINK_TEXT,
|
|
665
|
+
SEMANTIC_CONTAINER_TAGS,
|
|
666
|
+
SEMANTIC_CONTAINER_ROLES,
|
|
667
|
+
INTERACTIVE_HANDLER_ATTRIBUTES,
|
|
231
668
|
};
|