@afixt/test-utils 1.0.2 → 1.1.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/.claude/settings.local.json +7 -1
- package/README.md +21 -1
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/coverage-final.json +51 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +161 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/coverage/test-utils/docs/scripts/core.js.html +2263 -0
- package/coverage/test-utils/docs/scripts/core.min.js.html +151 -0
- package/coverage/test-utils/docs/scripts/index.html +176 -0
- package/coverage/test-utils/docs/scripts/resize.js.html +355 -0
- package/coverage/test-utils/docs/scripts/search.js.html +880 -0
- package/coverage/test-utils/docs/scripts/search.min.js.html +100 -0
- package/coverage/test-utils/docs/scripts/third-party/fuse.js.html +109 -0
- package/coverage/test-utils/docs/scripts/third-party/hljs-line-num-original.js.html +1192 -0
- package/coverage/test-utils/docs/scripts/third-party/hljs-line-num.js.html +85 -0
- package/coverage/test-utils/docs/scripts/third-party/hljs-original.js.html +15598 -0
- package/coverage/test-utils/docs/scripts/third-party/hljs.js.html +85 -0
- package/coverage/test-utils/docs/scripts/third-party/index.html +236 -0
- package/coverage/test-utils/docs/scripts/third-party/popper.js.html +100 -0
- package/coverage/test-utils/docs/scripts/third-party/tippy.js.html +88 -0
- package/coverage/test-utils/docs/scripts/third-party/tocbot.js.html +2098 -0
- package/coverage/test-utils/docs/scripts/third-party/tocbot.min.js.html +85 -0
- package/coverage/test-utils/index.html +131 -0
- package/coverage/test-utils/src/arrayUtils.js.html +283 -0
- package/coverage/test-utils/src/domUtils.js.html +622 -0
- package/coverage/test-utils/src/getAccessibleName.js.html +1444 -0
- package/coverage/test-utils/src/getAccessibleText.js.html +271 -0
- package/coverage/test-utils/src/getAriaAttributesByElement.js.html +142 -0
- package/coverage/test-utils/src/getCSSGeneratedContent.js.html +265 -0
- package/coverage/test-utils/src/getComputedRole.js.html +592 -0
- package/coverage/test-utils/src/getFocusableElements.js.html +163 -0
- package/coverage/test-utils/src/getGeneratedContent.js.html +130 -0
- package/coverage/test-utils/src/getImageText.js.html +160 -0
- package/coverage/test-utils/src/getStyleObject.js.html +220 -0
- package/coverage/test-utils/src/hasAccessibleName.js.html +166 -0
- package/coverage/test-utils/src/hasAttribute.js.html +130 -0
- package/coverage/test-utils/src/hasCSSGeneratedContent.js.html +145 -0
- package/coverage/test-utils/src/hasHiddenParent.js.html +172 -0
- package/coverage/test-utils/src/hasParent.js.html +247 -0
- package/coverage/test-utils/src/hasValidAriaAttributes.js.html +175 -0
- package/coverage/test-utils/src/hasValidAriaRole.js.html +172 -0
- package/coverage/test-utils/src/index.html +611 -0
- package/coverage/test-utils/src/index.js.html +274 -0
- package/coverage/test-utils/src/interactiveRoles.js.html +145 -0
- package/coverage/test-utils/src/isAriaAttributesValid.js.html +304 -0
- package/coverage/test-utils/src/isComplexTable.js.html +412 -0
- package/coverage/test-utils/src/isDataTable.js.html +799 -0
- package/coverage/test-utils/src/isFocusable.js.html +187 -0
- package/coverage/test-utils/src/isHidden.js.html +136 -0
- package/coverage/test-utils/src/isOffScreen.js.html +133 -0
- package/coverage/test-utils/src/isValidUrl.js.html +124 -0
- package/coverage/test-utils/src/isVisible.js.html +271 -0
- package/coverage/test-utils/src/listEventListeners.js.html +370 -0
- package/coverage/test-utils/src/queryCache.js.html +1156 -0
- package/coverage/test-utils/src/stringUtils.js.html +535 -0
- package/coverage/test-utils/src/testContrast.js.html +784 -0
- package/coverage/test-utils/src/testLang.js.html +1810 -0
- package/coverage/test-utils/src/testOrder.js.html +355 -0
- package/coverage/test-utils/vitest.config.browser.js.html +133 -0
- package/coverage/test-utils/vitest.config.js.html +157 -0
- package/package.json +6 -1
- package/repairs-needed.md +84 -0
- package/src/arrayUtils.js +7 -12
- package/src/domUtils.js +1 -16
- package/src/getAccessibleName.js +10 -12
- package/src/getAccessibleText.js +10 -6
- package/src/getAriaAttributesByElement.js +1 -1
- package/src/getCSSGeneratedContent.js +6 -2
- package/src/getComputedRole.js +7 -2
- package/src/getFocusableElements.js +5 -1
- package/src/getGeneratedContent.js +5 -1
- package/src/getImageText.js +6 -2
- package/src/getStyleObject.js +5 -1
- package/src/hasAccessibleName.js +2 -10
- package/src/hasAttribute.js +5 -1
- package/src/hasCSSGeneratedContent.js +6 -2
- package/src/hasHiddenParent.js +2 -2
- package/src/hasParent.js +5 -1
- package/src/hasValidAriaAttributes.js +6 -2
- package/src/hasValidAriaRole.js +5 -1
- package/src/index.js +74 -31
- package/src/interactiveRoles.js +1 -1
- package/src/isAriaAttributesValid.js +6 -2
- package/src/isComplexTable.js +11 -4
- package/src/isDataTable.js +10 -5
- package/src/isFocusable.js +5 -1
- package/src/isHidden.js +1 -1
- package/src/isOffScreen.js +5 -1
- package/src/isValidUrl.js +5 -1
- package/src/isVisible.js +14 -2
- package/src/queryCache.js +358 -0
- package/src/testContrast.js +5 -1
- package/src/testLang.js +19 -7
- package/src/testOrder.js +8 -3
- package/test/hasCSSGeneratedContent.test.js +9 -7
- package/test/queryCache.test.js +465 -0
- package/test/setup.js +3 -1
- package/test/testOrder.test.js +10 -115
- package/todo.md +2 -0
- package/vitest.config.js +1 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
|
|
5
|
+
<head>
|
|
6
|
+
<title>Code coverage report for test-utils/vitest.config.js</title>
|
|
7
|
+
<meta charset="utf-8" />
|
|
8
|
+
<link rel="stylesheet" href="../prettify.css" />
|
|
9
|
+
<link rel="stylesheet" href="../base.css" />
|
|
10
|
+
<link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
+
<style type='text/css'>
|
|
13
|
+
.coverage-summary .sorter {
|
|
14
|
+
background-image: url(../sort-arrow-sprite.png);
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body>
|
|
20
|
+
<div class='wrapper'>
|
|
21
|
+
<div class='pad1'>
|
|
22
|
+
<h1><a href="../index.html">All files</a> / <a href="index.html">test-utils</a> vitest.config.js</h1>
|
|
23
|
+
<div class='clearfix'>
|
|
24
|
+
|
|
25
|
+
<div class='fl pad1y space-right2'>
|
|
26
|
+
<span class="strong">0% </span>
|
|
27
|
+
<span class="quiet">Statements</span>
|
|
28
|
+
<span class='fraction'>0/24</span>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<div class='fl pad1y space-right2'>
|
|
33
|
+
<span class="strong">0% </span>
|
|
34
|
+
<span class="quiet">Branches</span>
|
|
35
|
+
<span class='fraction'>0/1</span>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
<div class='fl pad1y space-right2'>
|
|
40
|
+
<span class="strong">0% </span>
|
|
41
|
+
<span class="quiet">Functions</span>
|
|
42
|
+
<span class='fraction'>0/1</span>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<div class='fl pad1y space-right2'>
|
|
47
|
+
<span class="strong">0% </span>
|
|
48
|
+
<span class="quiet">Lines</span>
|
|
49
|
+
<span class='fraction'>0/24</span>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
<p class="quiet">
|
|
55
|
+
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
|
56
|
+
</p>
|
|
57
|
+
<template id="filterTemplate">
|
|
58
|
+
<div class="quiet">
|
|
59
|
+
Filter:
|
|
60
|
+
<input type="search" id="fileSearch">
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
</div>
|
|
64
|
+
<div class='status-line low'></div>
|
|
65
|
+
<pre><table class="coverage">
|
|
66
|
+
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
|
+
<a name='L2'></a><a href='#L2'>2</a>
|
|
68
|
+
<a name='L3'></a><a href='#L3'>3</a>
|
|
69
|
+
<a name='L4'></a><a href='#L4'>4</a>
|
|
70
|
+
<a name='L5'></a><a href='#L5'>5</a>
|
|
71
|
+
<a name='L6'></a><a href='#L6'>6</a>
|
|
72
|
+
<a name='L7'></a><a href='#L7'>7</a>
|
|
73
|
+
<a name='L8'></a><a href='#L8'>8</a>
|
|
74
|
+
<a name='L9'></a><a href='#L9'>9</a>
|
|
75
|
+
<a name='L10'></a><a href='#L10'>10</a>
|
|
76
|
+
<a name='L11'></a><a href='#L11'>11</a>
|
|
77
|
+
<a name='L12'></a><a href='#L12'>12</a>
|
|
78
|
+
<a name='L13'></a><a href='#L13'>13</a>
|
|
79
|
+
<a name='L14'></a><a href='#L14'>14</a>
|
|
80
|
+
<a name='L15'></a><a href='#L15'>15</a>
|
|
81
|
+
<a name='L16'></a><a href='#L16'>16</a>
|
|
82
|
+
<a name='L17'></a><a href='#L17'>17</a>
|
|
83
|
+
<a name='L18'></a><a href='#L18'>18</a>
|
|
84
|
+
<a name='L19'></a><a href='#L19'>19</a>
|
|
85
|
+
<a name='L20'></a><a href='#L20'>20</a>
|
|
86
|
+
<a name='L21'></a><a href='#L21'>21</a>
|
|
87
|
+
<a name='L22'></a><a href='#L22'>22</a>
|
|
88
|
+
<a name='L23'></a><a href='#L23'>23</a>
|
|
89
|
+
<a name='L24'></a><a href='#L24'>24</a>
|
|
90
|
+
<a name='L25'></a><a href='#L25'>25</a></td><td class="line-coverage quiet"><span class="cline-any cline-no"> </span>
|
|
91
|
+
<span class="cline-any cline-neutral"> </span>
|
|
92
|
+
<span class="cline-any cline-no"> </span>
|
|
93
|
+
<span class="cline-any cline-no"> </span>
|
|
94
|
+
<span class="cline-any cline-no"> </span>
|
|
95
|
+
<span class="cline-any cline-no"> </span>
|
|
96
|
+
<span class="cline-any cline-no"> </span>
|
|
97
|
+
<span class="cline-any cline-no"> </span>
|
|
98
|
+
<span class="cline-any cline-no"> </span>
|
|
99
|
+
<span class="cline-any cline-no"> </span>
|
|
100
|
+
<span class="cline-any cline-no"> </span>
|
|
101
|
+
<span class="cline-any cline-no"> </span>
|
|
102
|
+
<span class="cline-any cline-no"> </span>
|
|
103
|
+
<span class="cline-any cline-no"> </span>
|
|
104
|
+
<span class="cline-any cline-no"> </span>
|
|
105
|
+
<span class="cline-any cline-no"> </span>
|
|
106
|
+
<span class="cline-any cline-no"> </span>
|
|
107
|
+
<span class="cline-any cline-no"> </span>
|
|
108
|
+
<span class="cline-any cline-no"> </span>
|
|
109
|
+
<span class="cline-any cline-no"> </span>
|
|
110
|
+
<span class="cline-any cline-no"> </span>
|
|
111
|
+
<span class="cline-any cline-no"> </span>
|
|
112
|
+
<span class="cline-any cline-no"> </span>
|
|
113
|
+
<span class="cline-any cline-no"> </span>
|
|
114
|
+
<span class="cline-any cline-no"> </span></td><td class="text"><pre class="prettyprint lang-js"><span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" ><span class="branch-0 cbranch-no" title="branch not covered" >import { defineConfig } from 'vitest/config';</span></span></span>
|
|
115
|
+
|
|
116
|
+
<span class="cstat-no" title="statement not covered" >export default defineConfig({</span>
|
|
117
|
+
<span class="cstat-no" title="statement not covered" > test: {</span>
|
|
118
|
+
<span class="cstat-no" title="statement not covered" > globals: true,</span>
|
|
119
|
+
<span class="cstat-no" title="statement not covered" > environment: 'jsdom',</span>
|
|
120
|
+
<span class="cstat-no" title="statement not covered" > setupFiles: './test/setup.js',</span>
|
|
121
|
+
<span class="cstat-no" title="statement not covered" > include: ['test/**/*.test.js'],</span>
|
|
122
|
+
<span class="cstat-no" title="statement not covered" > exclude: ['test/_template.test.js'],</span>
|
|
123
|
+
<span class="cstat-no" title="statement not covered" > deps: {</span>
|
|
124
|
+
<span class="cstat-no" title="statement not covered" > inline: [/^(?!.*vitest).*$/],</span>
|
|
125
|
+
<span class="cstat-no" title="statement not covered" > },</span>
|
|
126
|
+
<span class="cstat-no" title="statement not covered" > environmentOptions: {</span>
|
|
127
|
+
<span class="cstat-no" title="statement not covered" > jsdom: {</span>
|
|
128
|
+
<span class="cstat-no" title="statement not covered" > resources: 'usable',</span>
|
|
129
|
+
<span class="cstat-no" title="statement not covered" > },</span>
|
|
130
|
+
<span class="cstat-no" title="statement not covered" > },</span>
|
|
131
|
+
<span class="cstat-no" title="statement not covered" > coverage: {</span>
|
|
132
|
+
<span class="cstat-no" title="statement not covered" > provider: 'v8',</span>
|
|
133
|
+
<span class="cstat-no" title="statement not covered" > reporter: ['text', 'json', 'html'],</span>
|
|
134
|
+
<span class="cstat-no" title="statement not covered" > exclude: ['**/node_modules/**', 'test/**'],</span>
|
|
135
|
+
<span class="cstat-no" title="statement not covered" > reportsDirectory: './coverage',</span>
|
|
136
|
+
<span class="cstat-no" title="statement not covered" > },</span>
|
|
137
|
+
<span class="cstat-no" title="statement not covered" > },</span>
|
|
138
|
+
<span class="cstat-no" title="statement not covered" >});</span></pre></td></tr></table></pre>
|
|
139
|
+
|
|
140
|
+
<div class='push'></div><!-- for sticky footer -->
|
|
141
|
+
</div><!-- /wrapper -->
|
|
142
|
+
<div class='footer quiet pad2 space-top1 center small'>
|
|
143
|
+
Code coverage generated by
|
|
144
|
+
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
145
|
+
at 2025-06-23T19:41:12.391Z
|
|
146
|
+
</div>
|
|
147
|
+
<script src="../prettify.js"></script>
|
|
148
|
+
<script>
|
|
149
|
+
window.onload = function () {
|
|
150
|
+
prettyPrint();
|
|
151
|
+
};
|
|
152
|
+
</script>
|
|
153
|
+
<script src="../sorter.js"></script>
|
|
154
|
+
<script src="../block-navigation.js"></script>
|
|
155
|
+
</body>
|
|
156
|
+
</html>
|
|
157
|
+
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@afixt/test-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Various utilities for accessibility testing",
|
|
5
|
+
"main": "src/index.js",
|
|
5
6
|
"scripts": {
|
|
6
7
|
"test": "vitest run",
|
|
7
8
|
"test:watch": "vitest",
|
|
@@ -18,6 +19,10 @@
|
|
|
18
19
|
"type": "git",
|
|
19
20
|
"url": "git@github.com:AFixt/test-utils.git"
|
|
20
21
|
},
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/AFixt/test-utils/issues"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/AFixt/test-utils",
|
|
21
26
|
"author": "Karl Groves <karl.groves@afixt.com>",
|
|
22
27
|
"license": "UNLICENSED",
|
|
23
28
|
"engines": {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Required Changes for @afixt/test-utils Library
|
|
2
|
+
|
|
3
|
+
## Issue
|
|
4
|
+
|
|
5
|
+
The browser extension is throwing "Invalid input: element must be a DOM Element,
|
|
6
|
+
got: null" errors when viewing dynamic sites like CNN.com. The error originates
|
|
7
|
+
from the @afixt/test-utils library functions.
|
|
8
|
+
|
|
9
|
+
## Root Cause
|
|
10
|
+
|
|
11
|
+
The `isVisible()` function (and potentially other functions) in
|
|
12
|
+
@afixt/test-utils throws an error when passed null or non-Element arguments.
|
|
13
|
+
This happens frequently during DOM mutations when:
|
|
14
|
+
|
|
15
|
+
1. Elements are removed from the DOM during repair operations
|
|
16
|
+
2. Mutation observers fire on disconnected elements
|
|
17
|
+
3. Elements become stale between detection and processing
|
|
18
|
+
|
|
19
|
+
## Required Changes
|
|
20
|
+
|
|
21
|
+
### 1. isVisible() Function
|
|
22
|
+
|
|
23
|
+
The function needs to handle null/invalid inputs gracefully:
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
function isVisible(element, strict = false) {
|
|
27
|
+
// Add null check at the beginning
|
|
28
|
+
if (!element || !(element instanceof Element)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Check if element is still connected to the DOM
|
|
33
|
+
if (!element.isConnected) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ... rest of the existing function
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. getAccessibleText() Function
|
|
42
|
+
|
|
43
|
+
Should handle null elements:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
function getAccessibleText(element) {
|
|
47
|
+
if (!element || !(element instanceof Element)) {
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!element.isConnected) {
|
|
52
|
+
return '';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ... rest of the existing function
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 3. getAccessibleName() Function
|
|
60
|
+
|
|
61
|
+
Should handle null elements:
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
function getAccessibleName(element) {
|
|
65
|
+
if (!element || !(element instanceof Element)) {
|
|
66
|
+
return '';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!element.isConnected) {
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ... rest of the existing function
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Why These Changes Are Needed
|
|
78
|
+
|
|
79
|
+
1. **Defensive Programming**: DOM elements can become null or disconnected at
|
|
80
|
+
any time, especially in dynamic web applications
|
|
81
|
+
2. **Mutation Observer Behavior**: When observing DOM changes, elements can be
|
|
82
|
+
removed between the time a mutation is detected and when it's processed
|
|
83
|
+
3. **Library Robustness**: A utility library should handle invalid inputs
|
|
84
|
+
gracefully rather than throwing errors
|
package/src/arrayUtils.js
CHANGED
|
@@ -52,16 +52,11 @@ const arrayUtils = {
|
|
|
52
52
|
cleanBlank
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
// Export for ES modules
|
|
56
|
-
export { arrayUnique, arrayRemoveByValue, arrayCount, cleanBlank, arrayUtils };
|
|
57
|
-
|
|
58
55
|
// Export for CommonJS
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
};
|
|
67
|
-
}
|
|
56
|
+
module.exports = {
|
|
57
|
+
arrayUnique,
|
|
58
|
+
arrayRemoveByValue,
|
|
59
|
+
arrayCount,
|
|
60
|
+
cleanBlank,
|
|
61
|
+
arrayUtils
|
|
62
|
+
};
|
package/src/domUtils.js
CHANGED
|
@@ -57,7 +57,7 @@ const domUtils = {
|
|
|
57
57
|
* @returns {string|boolean} A JSON string representing the attributes of the element, or false if no attributes are found.
|
|
58
58
|
*/
|
|
59
59
|
getAttributesAsString(element) {
|
|
60
|
-
const attrs = getAttributes(element);
|
|
60
|
+
const attrs = domUtils.getAttributes(element);
|
|
61
61
|
return attrs ? JSON.stringify(attrs) : false;
|
|
62
62
|
},
|
|
63
63
|
|
|
@@ -161,19 +161,4 @@ const domUtils = {
|
|
|
161
161
|
},
|
|
162
162
|
};
|
|
163
163
|
|
|
164
|
-
module.exports = {
|
|
165
|
-
hasAttr: domUtils.hasAttr,
|
|
166
|
-
attrBegins: domUtils.attrBegins,
|
|
167
|
-
containsNoCase: domUtils.containsNoCase,
|
|
168
|
-
getAttributes: domUtils.getAttributes,
|
|
169
|
-
getAttributesAsString: domUtils.getAttributesAsString,
|
|
170
|
-
getConstructor: domUtils.getConstructor,
|
|
171
|
-
getDocumentSize: domUtils.getDocumentSize,
|
|
172
|
-
getElementsWithDuplicateIds: domUtils.getElementsWithDuplicateIds,
|
|
173
|
-
getOuterHTML: domUtils.getOuterHTML,
|
|
174
|
-
getXPath: domUtils.getXPath,
|
|
175
|
-
hasFocus: domUtils.hasFocus,
|
|
176
|
-
isFullyVisible: domUtils.isFullyVisible,
|
|
177
|
-
};
|
|
178
|
-
|
|
179
164
|
module.exports = domUtils;
|
package/src/getAccessibleName.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const { isEmpty } = require("./stringUtils.js");
|
|
2
|
+
const { getAccessibleText } = require("./getAccessibleText.js");
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Gets the accessible name of an element according to the accessible name calculation algorithm
|
|
@@ -7,7 +7,13 @@ import { getAccessibleText } from "./getAccessibleText.js";
|
|
|
7
7
|
* @returns {string|boolean} The accessible name or false if none exists
|
|
8
8
|
*/
|
|
9
9
|
function getAccessibleName(element) {
|
|
10
|
-
if (!element)
|
|
10
|
+
if (!element || !(element instanceof Element)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (!element.isConnected) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
11
17
|
|
|
12
18
|
// These are elements which are totally not able to be labeled at all.
|
|
13
19
|
// Even if the title attribute is valid per HTML for these elements,
|
|
@@ -442,13 +448,5 @@ function strlen(str) {
|
|
|
442
448
|
return typeof str === "string" && !isEmpty(str.trim()) ? str.trim().length : 0;
|
|
443
449
|
}
|
|
444
450
|
|
|
445
|
-
// Export as default for ES modules
|
|
446
|
-
export default getAccessibleName;
|
|
447
|
-
|
|
448
451
|
// Export the function for CommonJS module usage
|
|
449
|
-
|
|
450
|
-
module.exports = getAccessibleName;
|
|
451
|
-
} else if (typeof window !== 'undefined') {
|
|
452
|
-
// Add to window object for browser usage
|
|
453
|
-
window.getAccessibleName = getAccessibleName;
|
|
454
|
-
}
|
|
452
|
+
module.exports = getAccessibleName;
|
package/src/getAccessibleText.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
const { isEmpty } = require("./stringUtils.js");
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Get all accessible text for an element, including aria-labels and content from children.
|
|
5
5
|
* @param {Element} el - The DOM element.
|
|
6
6
|
* @returns {string} The accessible text.
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
if (!el)
|
|
8
|
+
function getAccessibleText(el) {
|
|
9
|
+
if (!el || !(el instanceof Element)) {
|
|
10
|
+
return '';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!el.isConnected) {
|
|
14
|
+
return '';
|
|
15
|
+
}
|
|
10
16
|
|
|
11
17
|
let textContent = "";
|
|
12
18
|
|
|
@@ -58,6 +64,4 @@ export function getAccessibleText(el) {
|
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
// Export for CommonJS module usage
|
|
61
|
-
|
|
62
|
-
module.exports = { getAccessibleText };
|
|
63
|
-
}
|
|
67
|
+
module.exports = { getAccessibleText };
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @param {string} [pseudoElement='both'] - Which pseudo-element to check ('before', 'after', or 'both')
|
|
8
8
|
* @returns {string|boolean} The generated content as a string or false if none exists
|
|
9
9
|
*/
|
|
10
|
-
|
|
10
|
+
function getCSSGeneratedContent(el, pseudoElement = 'both') {
|
|
11
11
|
if (!el) return false;
|
|
12
12
|
|
|
13
13
|
// jsdom doesn't fully support getComputedStyle for pseudo-elements
|
|
@@ -58,4 +58,8 @@ export function getCSSGeneratedContent(el, pseudoElement = 'both') {
|
|
|
58
58
|
} catch (error) {
|
|
59
59
|
return false;
|
|
60
60
|
}
|
|
61
|
-
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = {
|
|
64
|
+
getCSSGeneratedContent
|
|
65
|
+
};
|
package/src/getComputedRole.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const roleMapping = {
|
|
2
2
|
'a': {
|
|
3
3
|
'[href]': 'link',
|
|
4
4
|
':not([href])': 'text'
|
|
@@ -146,7 +146,7 @@ export const roleMapping = {
|
|
|
146
146
|
* @param {HTMLElement} element - The HTML element to get the role for.
|
|
147
147
|
* @returns {string|undefined} The computed role of the element, or undefined if no role is found.
|
|
148
148
|
*/
|
|
149
|
-
|
|
149
|
+
function getComputedRole(element) {
|
|
150
150
|
if (!element) return undefined;
|
|
151
151
|
|
|
152
152
|
const roleAttr = element.getAttribute('role');
|
|
@@ -167,3 +167,8 @@ export function getComputedRole(element) {
|
|
|
167
167
|
|
|
168
168
|
return undefined;
|
|
169
169
|
}
|
|
170
|
+
|
|
171
|
+
module.exports = {
|
|
172
|
+
roleMapping,
|
|
173
|
+
getComputedRole
|
|
174
|
+
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @param {Element} el - the element to be tested
|
|
4
4
|
* @returns {Array} - Array of focusable elements
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
function getFocusableElements(el) {
|
|
7
7
|
const focusableSelectors = [
|
|
8
8
|
"a[href]",
|
|
9
9
|
"area",
|
|
@@ -24,3 +24,7 @@ export function getFocusableElements(el) {
|
|
|
24
24
|
);
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
getFocusableElements
|
|
30
|
+
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @param {Element} el - The DOM element.
|
|
4
4
|
* @returns {string|boolean} The generated content or `false` if not available.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
function getGeneratedContent(el) {
|
|
7
7
|
if (!el) return false;
|
|
8
8
|
const computedStyle = getComputedStyle(el);
|
|
9
9
|
const before = computedStyle.getPropertyValue("content", "::before") || "";
|
|
@@ -13,3 +13,7 @@ export function getGeneratedContent(el) {
|
|
|
13
13
|
? `${before} ${inner} ${after}`.trim()
|
|
14
14
|
: false;
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
getGeneratedContent
|
|
19
|
+
};
|
package/src/getImageText.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
const Tesseract = require('tesseract.js');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Extracts text from an image using OCR.
|
|
5
5
|
* @param {string} imagePath - The path or URL of the image.
|
|
6
6
|
* @returns {Promise<string|false>} Extracted text if found, otherwise false.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
async function getImageText(imagePath) {
|
|
9
9
|
try {
|
|
10
10
|
const { data: { text } } = await Tesseract.recognize(
|
|
11
11
|
imagePath,
|
|
@@ -23,3 +23,7 @@ export async function getImageText(imagePath) {
|
|
|
23
23
|
|
|
24
24
|
// Example usage:
|
|
25
25
|
// getImageText('path/to/image.jpg').then(result => console.log(result));
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
getImageText
|
|
29
|
+
};
|
package/src/getStyleObject.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* with property names in camelCase. Returns false if the style object
|
|
8
8
|
* cannot be retrieved.
|
|
9
9
|
*/
|
|
10
|
-
|
|
10
|
+
function getStyleObject(el) {
|
|
11
11
|
// Ensure we have a valid DOM element
|
|
12
12
|
if (!el || !(el instanceof Element)) {
|
|
13
13
|
return false;
|
|
@@ -43,3 +43,7 @@ export function getStyleObject(el) {
|
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
|
|
47
|
+
module.exports = {
|
|
48
|
+
getStyleObject
|
|
49
|
+
};
|
package/src/hasAccessibleName.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const getAccessibleName = require("./getAccessibleName.js");
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Determines if an element has an accessible name
|
|
@@ -16,13 +16,5 @@ function hasAccessibleName(element) {
|
|
|
16
16
|
return accessibleName !== false;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
// Export for ES modules
|
|
20
|
-
export default hasAccessibleName;
|
|
21
|
-
|
|
22
19
|
// Export for CommonJS
|
|
23
|
-
|
|
24
|
-
module.exports = hasAccessibleName;
|
|
25
|
-
} else if (typeof window !== 'undefined') {
|
|
26
|
-
// Add to window object for browser usage
|
|
27
|
-
window.hasAccessibleName = hasAccessibleName;
|
|
28
|
-
}
|
|
20
|
+
module.exports = hasAccessibleName;
|
package/src/hasAttribute.js
CHANGED
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
* @param {Element} element - The DOM element to check the attribute on.
|
|
7
7
|
* @returns {boolean} - Returns true if the attribute exists on the element, otherwise false.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
function hasAttribute(attribute, element) {
|
|
10
10
|
if (!element || !(element instanceof Element) || typeof attribute !== 'string') {
|
|
11
11
|
return false;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
return element.hasAttribute(attribute);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
hasAttribute
|
|
15
19
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
2
|
+
const { getGeneratedContent } = require('./getGeneratedContent.js');
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Checks if an element has CSS generated content in its ::before or ::after pseudo-elements
|
|
@@ -8,7 +8,7 @@ import { getGeneratedContent } from './getGeneratedContent.js';
|
|
|
8
8
|
* @param {HTMLElement} el - The element to check for generated content.
|
|
9
9
|
* @returns {boolean} True if the element has any generated content, otherwise false.
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
function hasCSSGeneratedContent(el) {
|
|
12
12
|
if (!el) return false;
|
|
13
13
|
|
|
14
14
|
// Use getGeneratedContent and convert its result to a boolean
|
|
@@ -18,3 +18,7 @@ export function hasCSSGeneratedContent(el) {
|
|
|
18
18
|
// We want to return true if content exists, false otherwise
|
|
19
19
|
return content !== false;
|
|
20
20
|
}
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
hasCSSGeneratedContent
|
|
24
|
+
};
|
package/src/hasHiddenParent.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
2
|
+
const isHidden = require('./isHidden.js');
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Checks if the given element has a hidden parent element.
|
|
@@ -26,4 +26,4 @@ const hasHiddenParent = (element) => {
|
|
|
26
26
|
return !visible;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
module.exports = hasHiddenParent;
|
package/src/hasParent.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @param {string[]} selectors - An array of selectors to match against the element's parents.
|
|
6
6
|
* @returns {boolean} - Returns true if the element has a parent that matches any of the selectors, otherwise false.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
function hasParent(element, selectors) {
|
|
9
9
|
// Input validation
|
|
10
10
|
if (!element || !(element instanceof Element)) {
|
|
11
11
|
return false;
|
|
@@ -51,4 +51,8 @@ export function hasParent(element, selectors) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = {
|
|
57
|
+
hasParent
|
|
54
58
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const { isAriaAttributeValid } = require('./isAriaAttributesValid.js');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Checks if an element has any valid ARIA attributes.
|
|
@@ -6,7 +6,7 @@ import { isAriaAttributeValid } from './isAriaAttributesValid.js';
|
|
|
6
6
|
* @param {Element} element - The DOM element to check
|
|
7
7
|
* @returns {boolean} True if the element has at least one valid ARIA attribute, false otherwise
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
function hasValidAriaAttributes(element) {
|
|
10
10
|
if (!element || typeof element.hasAttributes !== 'function' || !element.attributes) {
|
|
11
11
|
return false;
|
|
12
12
|
}
|
|
@@ -28,3 +28,7 @@ export function hasValidAriaAttributes(element) {
|
|
|
28
28
|
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
hasValidAriaAttributes
|
|
34
|
+
};
|
package/src/hasValidAriaRole.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @param {HTMLElement} element - The DOM element to check.
|
|
5
5
|
* @returns {boolean} True if the element has a valid ARIA role, false otherwise.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
function hasValidAriaRole(element) {
|
|
8
8
|
const validAriaRoles = new Set([
|
|
9
9
|
"alert", "alertdialog", "button", "checkbox", "dialog", "gridcell", "link",
|
|
10
10
|
"log", "marquee", "menuitem", "menuitemcheckbox", "menuitemradio", "option",
|
|
@@ -27,3 +27,7 @@ export function hasValidAriaRole(element) {
|
|
|
27
27
|
const roles = roleAttr.trim().split(/\s+/);
|
|
28
28
|
return validAriaRoles.has(roles[0]); // Only check the first role
|
|
29
29
|
}
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
hasValidAriaRole
|
|
33
|
+
};
|