accented 0.0.2 → 1.0.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/NOTICE +14 -0
- package/README.md +44 -187
- package/dist/accented.d.ts +8 -8
- package/dist/accented.d.ts.map +1 -1
- package/dist/accented.js +37 -30
- package/dist/accented.js.map +1 -1
- package/dist/common/tokens.d.ts +7 -0
- package/dist/common/tokens.d.ts.map +1 -0
- package/dist/common/tokens.js +8 -0
- package/dist/common/tokens.js.map +1 -0
- package/dist/constants.d.ts +2 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -1
- package/dist/constants.js.map +1 -1
- package/dist/dom-updater.d.ts +1 -1
- package/dist/dom-updater.d.ts.map +1 -1
- package/dist/dom-updater.js +73 -31
- package/dist/dom-updater.js.map +1 -1
- package/dist/elements/accented-dialog.d.ts +13 -10
- package/dist/elements/accented-dialog.d.ts.map +1 -1
- package/dist/elements/accented-dialog.js +110 -94
- package/dist/elements/accented-dialog.js.map +1 -1
- package/dist/elements/accented-trigger.d.ts +14 -9
- package/dist/elements/accented-trigger.d.ts.map +1 -1
- package/dist/elements/accented-trigger.js +77 -22
- package/dist/elements/accented-trigger.js.map +1 -1
- package/dist/fullscreen-listener.d.ts +2 -0
- package/dist/fullscreen-listener.d.ts.map +1 -0
- package/dist/fullscreen-listener.js +17 -0
- package/dist/fullscreen-listener.js.map +1 -0
- package/dist/intersection-observer.d.ts +1 -1
- package/dist/intersection-observer.d.ts.map +1 -1
- package/dist/intersection-observer.js +12 -6
- package/dist/intersection-observer.js.map +1 -1
- package/dist/log-and-rethrow.d.ts +1 -1
- package/dist/log-and-rethrow.d.ts.map +1 -1
- package/dist/log-and-rethrow.js +2 -3
- package/dist/log-and-rethrow.js.map +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +6 -3
- package/dist/logger.js.map +1 -1
- package/dist/register-elements.d.ts +1 -1
- package/dist/register-elements.d.ts.map +1 -1
- package/dist/register-elements.js +6 -7
- package/dist/register-elements.js.map +1 -1
- package/dist/resize-listener.d.ts +1 -1
- package/dist/resize-listener.d.ts.map +1 -1
- package/dist/resize-listener.js +3 -4
- package/dist/resize-listener.js.map +1 -1
- package/dist/scanner.d.ts +2 -2
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +76 -43
- package/dist/scanner.js.map +1 -1
- package/dist/scroll-listeners.d.ts +1 -1
- package/dist/scroll-listeners.d.ts.map +1 -1
- package/dist/scroll-listeners.js +3 -4
- package/dist/scroll-listeners.js.map +1 -1
- package/dist/state.d.ts +3 -2
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +5 -3
- package/dist/state.js.map +1 -1
- package/dist/task-queue.d.ts +4 -4
- package/dist/task-queue.d.ts.map +1 -1
- package/dist/task-queue.js +3 -2
- package/dist/task-queue.js.map +1 -1
- package/dist/types.d.ts +140 -49
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/are-elements-with-issues-equal.d.ts +3 -0
- package/dist/utils/are-elements-with-issues-equal.d.ts.map +1 -0
- package/dist/utils/are-elements-with-issues-equal.js +5 -0
- package/dist/utils/are-elements-with-issues-equal.js.map +1 -0
- package/dist/utils/are-issue-sets-equal.d.ts +2 -2
- package/dist/utils/are-issue-sets-equal.d.ts.map +1 -1
- package/dist/utils/are-issue-sets-equal.js +3 -3
- package/dist/utils/are-issue-sets-equal.js.map +1 -1
- package/dist/utils/containing-blocks.d.ts +3 -0
- package/dist/utils/containing-blocks.d.ts.map +1 -0
- package/dist/utils/containing-blocks.js +46 -0
- package/dist/utils/containing-blocks.js.map +1 -0
- package/dist/utils/contains.d.ts +2 -0
- package/dist/utils/contains.d.ts.map +1 -0
- package/dist/utils/contains.js +19 -0
- package/dist/utils/contains.js.map +1 -0
- package/dist/utils/deduplicate-nodes.d.ts +2 -0
- package/dist/utils/deduplicate-nodes.d.ts.map +1 -0
- package/dist/utils/deduplicate-nodes.js +4 -0
- package/dist/utils/deduplicate-nodes.js.map +1 -0
- package/dist/utils/deep-merge.d.ts +1 -1
- package/dist/utils/deep-merge.d.ts.map +1 -1
- package/dist/utils/deep-merge.js +8 -5
- package/dist/utils/deep-merge.js.map +1 -1
- package/dist/utils/dom-helpers.d.ts +9 -0
- package/dist/utils/dom-helpers.d.ts.map +1 -0
- package/dist/utils/dom-helpers.js +34 -0
- package/dist/utils/dom-helpers.js.map +1 -0
- package/dist/utils/ensure-non-empty.d.ts +2 -0
- package/dist/utils/ensure-non-empty.d.ts.map +1 -0
- package/dist/utils/ensure-non-empty.js +7 -0
- package/dist/utils/ensure-non-empty.js.map +1 -0
- package/dist/utils/get-element-html.d.ts +1 -1
- package/dist/utils/get-element-html.d.ts.map +1 -1
- package/dist/utils/get-element-html.js +4 -2
- package/dist/utils/get-element-html.js.map +1 -1
- package/dist/utils/get-element-position.d.ts +10 -2
- package/dist/utils/get-element-position.d.ts.map +1 -1
- package/dist/utils/get-element-position.js +64 -16
- package/dist/utils/get-element-position.js.map +1 -1
- package/dist/utils/get-parent.d.ts +2 -0
- package/dist/utils/get-parent.d.ts.map +1 -0
- package/dist/utils/get-parent.js +12 -0
- package/dist/utils/get-parent.js.map +1 -0
- package/dist/utils/get-scan-context.d.ts +3 -0
- package/dist/utils/get-scan-context.d.ts.map +1 -0
- package/dist/utils/get-scan-context.js +28 -0
- package/dist/utils/get-scan-context.js.map +1 -0
- package/dist/utils/get-scrollable-ancestors.d.ts +1 -1
- package/dist/utils/get-scrollable-ancestors.d.ts.map +1 -1
- package/dist/utils/get-scrollable-ancestors.js +10 -6
- package/dist/utils/get-scrollable-ancestors.js.map +1 -1
- package/dist/utils/is-node-in-scan-context.d.ts +3 -0
- package/dist/utils/is-node-in-scan-context.d.ts.map +1 -0
- package/dist/utils/is-node-in-scan-context.js +26 -0
- package/dist/utils/is-node-in-scan-context.js.map +1 -0
- package/dist/utils/is-non-empty.d.ts +2 -0
- package/dist/utils/is-non-empty.d.ts.map +1 -0
- package/dist/utils/is-non-empty.js +4 -0
- package/dist/utils/is-non-empty.js.map +1 -0
- package/dist/utils/normalize-context.d.ts +3 -0
- package/dist/utils/normalize-context.d.ts.map +1 -0
- package/dist/utils/normalize-context.js +59 -0
- package/dist/utils/normalize-context.js.map +1 -0
- package/dist/utils/recalculate-positions.d.ts +1 -1
- package/dist/utils/recalculate-positions.d.ts.map +1 -1
- package/dist/utils/recalculate-positions.js +5 -5
- package/dist/utils/recalculate-positions.js.map +1 -1
- package/dist/utils/recalculate-scrollable-ancestors.d.ts +1 -1
- package/dist/utils/recalculate-scrollable-ancestors.d.ts.map +1 -1
- package/dist/utils/recalculate-scrollable-ancestors.js +4 -4
- package/dist/utils/recalculate-scrollable-ancestors.js.map +1 -1
- package/dist/utils/shadow-dom-aware-mutation-observer.d.ts +10 -0
- package/dist/utils/shadow-dom-aware-mutation-observer.d.ts.map +1 -0
- package/dist/utils/shadow-dom-aware-mutation-observer.js +61 -0
- package/dist/utils/shadow-dom-aware-mutation-observer.js.map +1 -0
- package/dist/utils/supports-anchor-positioning.d.ts +1 -1
- package/dist/utils/supports-anchor-positioning.d.ts.map +1 -1
- package/dist/utils/supports-anchor-positioning.js +1 -1
- package/dist/utils/supports-anchor-positioning.js.map +1 -1
- package/dist/utils/transform-violations.d.ts +2 -2
- package/dist/utils/transform-violations.d.ts.map +1 -1
- package/dist/utils/transform-violations.js +23 -10
- package/dist/utils/transform-violations.js.map +1 -1
- package/dist/utils/update-elements-with-issues.d.ts +11 -5
- package/dist/utils/update-elements-with-issues.d.ts.map +1 -1
- package/dist/utils/update-elements-with-issues.js +56 -24
- package/dist/utils/update-elements-with-issues.js.map +1 -1
- package/dist/validate-options.d.ts +2 -2
- package/dist/validate-options.d.ts.map +1 -1
- package/dist/validate-options.js +91 -4
- package/dist/validate-options.js.map +1 -1
- package/package.json +15 -7
- package/src/accented.test.ts +2 -2
- package/src/accented.ts +45 -34
- package/src/common/tokens.ts +10 -0
- package/src/constants.ts +2 -1
- package/src/dom-updater.ts +87 -34
- package/src/elements/accented-dialog.ts +157 -122
- package/src/elements/accented-trigger.ts +119 -47
- package/src/fullscreen-listener.ts +21 -0
- package/src/intersection-observer.ts +27 -16
- package/src/log-and-rethrow.ts +2 -3
- package/src/logger.ts +14 -4
- package/src/register-elements.ts +7 -7
- package/src/resize-listener.ts +15 -11
- package/src/scanner.ts +113 -57
- package/src/scroll-listeners.ts +27 -19
- package/src/state.ts +27 -16
- package/src/task-queue.test.ts +5 -4
- package/src/task-queue.ts +8 -6
- package/src/types.ts +179 -76
- package/src/utils/are-elements-with-issues-equal.ts +11 -0
- package/src/utils/are-issue-sets-equal.test.ts +10 -6
- package/src/utils/are-issue-sets-equal.ts +8 -6
- package/src/utils/containing-blocks.ts +60 -0
- package/src/utils/contains.test.ts +54 -0
- package/src/utils/contains.ts +19 -0
- package/src/utils/deduplicate-nodes.ts +3 -0
- package/src/utils/deep-merge.test.ts +8 -1
- package/src/utils/deep-merge.ts +14 -8
- package/src/utils/dom-helpers.ts +42 -0
- package/src/utils/ensure-non-empty.ts +6 -0
- package/src/utils/get-element-html.ts +4 -2
- package/src/utils/get-element-position.ts +84 -16
- package/src/utils/get-parent.ts +14 -0
- package/src/utils/get-scan-context.test.ts +85 -0
- package/src/utils/get-scan-context.ts +36 -0
- package/src/utils/get-scrollable-ancestors.ts +15 -7
- package/src/utils/is-node-in-scan-context.test.ts +70 -0
- package/src/utils/is-node-in-scan-context.ts +29 -0
- package/src/utils/is-non-empty.ts +3 -0
- package/src/utils/normalize-context.test.ts +105 -0
- package/src/utils/normalize-context.ts +65 -0
- package/src/utils/recalculate-positions.ts +5 -5
- package/src/utils/recalculate-scrollable-ancestors.ts +4 -4
- package/src/utils/shadow-dom-aware-mutation-observer.ts +75 -0
- package/src/utils/supports-anchor-positioning.ts +3 -3
- package/src/utils/transform-violations.test.ts +28 -24
- package/src/utils/transform-violations.ts +30 -12
- package/src/utils/update-elements-with-issues.test.ts +139 -51
- package/src/utils/update-elements-with-issues.ts +123 -54
- package/src/validate-options.ts +154 -14
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
type WindowWithCSS = Window & {
|
|
2
|
-
CSS: typeof CSS
|
|
3
|
-
}
|
|
2
|
+
CSS: typeof CSS;
|
|
3
|
+
};
|
|
4
4
|
|
|
5
|
-
export
|
|
5
|
+
export function supportsAnchorPositioning(win: WindowWithCSS) {
|
|
6
6
|
return win.CSS.supports('anchor-name: --foo') && win.CSS.supports('position-anchor: --foo');
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
|
-
import {suite, test} from 'node:test';
|
|
3
|
-
import transformViolations from './transform-violations';
|
|
2
|
+
import { suite, test } from 'node:test';
|
|
3
|
+
import { transformViolations } from './transform-violations';
|
|
4
4
|
|
|
5
5
|
import type { AxeResults } from 'axe-core';
|
|
6
6
|
type Violation = AxeResults['violations'][number];
|
|
@@ -12,7 +12,7 @@ const commonViolationProps1: Omit<Violation, 'nodes'> = {
|
|
|
12
12
|
helpUrl: 'http://example.com',
|
|
13
13
|
description: 'description1',
|
|
14
14
|
tags: [],
|
|
15
|
-
impact: 'serious'
|
|
15
|
+
impact: 'serious',
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
const commonViolationProps2: Omit<Violation, 'nodes'> = {
|
|
@@ -21,51 +21,53 @@ const commonViolationProps2: Omit<Violation, 'nodes'> = {
|
|
|
21
21
|
helpUrl: 'http://example.com',
|
|
22
22
|
description: 'description2',
|
|
23
23
|
tags: [],
|
|
24
|
-
impact: 'serious'
|
|
24
|
+
impact: 'serious',
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
const getRootNode = (): Node => ({}) as Node;
|
|
28
|
+
|
|
27
29
|
// @ts-expect-error element is not HTMLElement
|
|
28
|
-
const element1: HTMLElement = {};
|
|
30
|
+
const element1: HTMLElement = { getRootNode };
|
|
29
31
|
// @ts-expect-error element is not HTMLElement
|
|
30
|
-
const element2: HTMLElement = {};
|
|
32
|
+
const element2: HTMLElement = { getRootNode };
|
|
31
33
|
// @ts-expect-error element is not HTMLElement
|
|
32
|
-
const element3: HTMLElement = {};
|
|
34
|
+
const element3: HTMLElement = { getRootNode };
|
|
33
35
|
|
|
34
36
|
const commonNodeProps = {
|
|
35
37
|
html: '<div></div>',
|
|
36
38
|
any: [],
|
|
37
39
|
all: [],
|
|
38
|
-
none: []
|
|
40
|
+
none: [],
|
|
39
41
|
};
|
|
40
42
|
|
|
41
43
|
const node1: Node = {
|
|
42
44
|
...commonNodeProps,
|
|
43
45
|
element: element1,
|
|
44
46
|
target: ['div'],
|
|
45
|
-
failureSummary: 'summary1'
|
|
47
|
+
failureSummary: 'summary1',
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
const node2: Node = {
|
|
49
51
|
...commonNodeProps,
|
|
50
52
|
element: element2,
|
|
51
53
|
target: ['div'],
|
|
52
|
-
failureSummary: 'summary2'
|
|
54
|
+
failureSummary: 'summary2',
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
const node3: Node = {
|
|
56
58
|
...commonNodeProps,
|
|
57
59
|
element: element3,
|
|
58
60
|
target: ['div'],
|
|
59
|
-
failureSummary: 'summary3'
|
|
61
|
+
failureSummary: 'summary3',
|
|
60
62
|
};
|
|
61
63
|
|
|
62
64
|
suite('transformViolations', () => {
|
|
63
65
|
test('one violation, one element', () => {
|
|
64
66
|
const violation: Violation = {
|
|
65
67
|
...commonViolationProps1,
|
|
66
|
-
nodes: [node1]
|
|
68
|
+
nodes: [node1],
|
|
67
69
|
};
|
|
68
|
-
const elementsWithIssues = transformViolations([violation]);
|
|
70
|
+
const elementsWithIssues = transformViolations([violation], 'accented');
|
|
69
71
|
assert.equal(elementsWithIssues.length, 1);
|
|
70
72
|
assert.equal(elementsWithIssues[0]?.element, element1);
|
|
71
73
|
assert.equal(elementsWithIssues[0].issues.length, 1);
|
|
@@ -76,15 +78,17 @@ suite('transformViolations', () => {
|
|
|
76
78
|
test('two violations, two elements each', () => {
|
|
77
79
|
const violation1: Violation = {
|
|
78
80
|
...commonViolationProps1,
|
|
79
|
-
nodes: [node1, node2]
|
|
81
|
+
nodes: [node1, node2],
|
|
80
82
|
};
|
|
81
83
|
const violation2: Violation = {
|
|
82
84
|
...commonViolationProps2,
|
|
83
|
-
nodes: [node1, node3]
|
|
85
|
+
nodes: [node1, node3],
|
|
84
86
|
};
|
|
85
|
-
const elementsWithIssues = transformViolations([violation1, violation2]);
|
|
87
|
+
const elementsWithIssues = transformViolations([violation1, violation2], 'accented');
|
|
86
88
|
assert.equal(elementsWithIssues.length, 3);
|
|
87
|
-
const elementWithTwoIssues = elementsWithIssues.find(
|
|
89
|
+
const elementWithTwoIssues = elementsWithIssues.find(
|
|
90
|
+
(elementWithIssues) => elementWithIssues.element === element1,
|
|
91
|
+
);
|
|
88
92
|
assert.equal(elementWithTwoIssues?.issues.length, 2);
|
|
89
93
|
});
|
|
90
94
|
|
|
@@ -94,14 +98,14 @@ suite('transformViolations', () => {
|
|
|
94
98
|
element: element1,
|
|
95
99
|
// A target array whose length is > 1 signifies an element in an iframe
|
|
96
100
|
target: ['iframe', 'div'],
|
|
97
|
-
failureSummary: 'summary1'
|
|
101
|
+
failureSummary: 'summary1',
|
|
98
102
|
};
|
|
99
103
|
const violation: Violation = {
|
|
100
104
|
...commonViolationProps1,
|
|
101
|
-
nodes: [node]
|
|
105
|
+
nodes: [node],
|
|
102
106
|
};
|
|
103
107
|
|
|
104
|
-
const elementsWithIssues = transformViolations([violation]);
|
|
108
|
+
const elementsWithIssues = transformViolations([violation], 'accented');
|
|
105
109
|
assert.equal(elementsWithIssues.length, 0);
|
|
106
110
|
});
|
|
107
111
|
|
|
@@ -111,14 +115,14 @@ suite('transformViolations', () => {
|
|
|
111
115
|
element: element1,
|
|
112
116
|
// A target that contains an array within the outer array signifies an element in shadow DOM
|
|
113
117
|
target: [['div', 'div']],
|
|
114
|
-
failureSummary: 'summary1'
|
|
118
|
+
failureSummary: 'summary1',
|
|
115
119
|
};
|
|
116
120
|
const violation: Violation = {
|
|
117
121
|
...commonViolationProps1,
|
|
118
|
-
nodes: [node]
|
|
122
|
+
nodes: [node],
|
|
119
123
|
};
|
|
120
124
|
|
|
121
|
-
const elementsWithIssues = transformViolations([violation]);
|
|
122
|
-
assert.equal(elementsWithIssues.length,
|
|
125
|
+
const elementsWithIssues = transformViolations([violation], 'accented');
|
|
126
|
+
assert.equal(elementsWithIssues.length, 1);
|
|
123
127
|
});
|
|
124
128
|
});
|
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
import type { AxeResults, ImpactValue } from 'axe-core';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ElementWithIssues, Issue } from '../types.ts';
|
|
3
|
+
|
|
4
|
+
// This is a list of axe-core violations (their ids) that may be flagged by axe-core
|
|
5
|
+
// as false positives if an Accented trigger is a descendant of the element with the issue.
|
|
6
|
+
const violationsAffectedByAccentedTriggers = [
|
|
7
|
+
'aria-hidden-focus',
|
|
8
|
+
'aria-text',
|
|
9
|
+
'definition-list',
|
|
10
|
+
'label-content-name-mismatch',
|
|
11
|
+
'list',
|
|
12
|
+
'nested-interactive',
|
|
13
|
+
'scrollable-region-focusable', // The Accented trigger might make the content grow such that scrolling is required.
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
function maybeCausedByAccented(violationId: string, element: HTMLElement, name: string) {
|
|
17
|
+
return (
|
|
18
|
+
violationsAffectedByAccentedTriggers.includes(violationId) &&
|
|
19
|
+
Boolean(element.querySelector(`${name}-trigger`))
|
|
20
|
+
);
|
|
21
|
+
}
|
|
3
22
|
|
|
4
23
|
function impactCompare(a: ImpactValue, b: ImpactValue) {
|
|
5
24
|
const impactOrder = [null, 'minor', 'moderate', 'serious', 'critical'];
|
|
6
25
|
return impactOrder.indexOf(a) - impactOrder.indexOf(b);
|
|
7
26
|
}
|
|
8
27
|
|
|
9
|
-
export
|
|
28
|
+
export function transformViolations(violations: typeof AxeResults.violations, name: string) {
|
|
10
29
|
const elementsWithIssues: Array<ElementWithIssues> = [];
|
|
11
30
|
|
|
12
31
|
for (const violation of violations) {
|
|
@@ -21,26 +40,25 @@ export default function transformViolations(violations: typeof AxeResults.violat
|
|
|
21
40
|
// A consumer of Accented can instead scan the iframed document by calling Accented initialization from that document.
|
|
22
41
|
const isInIframe = target.length > 1;
|
|
23
42
|
|
|
24
|
-
|
|
25
|
-
// Until then, we don’t want such elements to be added to the set.
|
|
26
|
-
const isInShadowDOM = Array.isArray(target[0]);
|
|
27
|
-
|
|
28
|
-
if (element && !isInIframe && !isInShadowDOM) {
|
|
43
|
+
if (element && !isInIframe && !maybeCausedByAccented(violation.id, element, name)) {
|
|
29
44
|
const issue: Issue = {
|
|
30
45
|
id: violation.id,
|
|
31
46
|
title: violation.help,
|
|
32
47
|
description: node.failureSummary ?? violation.description,
|
|
33
48
|
url: violation.helpUrl,
|
|
34
|
-
impact: violation.impact ?? null
|
|
49
|
+
impact: violation.impact ?? null,
|
|
35
50
|
};
|
|
36
|
-
const
|
|
37
|
-
|
|
51
|
+
const existingElement = elementsWithIssues.find(
|
|
52
|
+
(elementWithIssues) => elementWithIssues.element === element,
|
|
53
|
+
);
|
|
54
|
+
if (existingElement === undefined) {
|
|
38
55
|
elementsWithIssues.push({
|
|
39
56
|
element,
|
|
40
|
-
|
|
57
|
+
rootNode: element.getRootNode(),
|
|
58
|
+
issues: [issue],
|
|
41
59
|
});
|
|
42
60
|
} else {
|
|
43
|
-
|
|
61
|
+
existingElement.issues.push(issue);
|
|
44
62
|
}
|
|
45
63
|
}
|
|
46
64
|
}
|
|
@@ -1,51 +1,68 @@
|
|
|
1
|
-
import {suite, test} from 'node:test';
|
|
2
1
|
import assert from 'node:assert/strict';
|
|
2
|
+
import { suite, test } from 'node:test';
|
|
3
3
|
import type { Signal } from '@preact/signals-core';
|
|
4
4
|
import { signal } from '@preact/signals-core';
|
|
5
5
|
import type { ExtendedElementWithIssues, Issue } from '../types';
|
|
6
|
-
import updateElementsWithIssues from './update-elements-with-issues';
|
|
6
|
+
import { updateElementsWithIssues } from './update-elements-with-issues';
|
|
7
7
|
|
|
8
8
|
import type { AxeResults, ImpactValue } from 'axe-core';
|
|
9
9
|
import type { AccentedTrigger } from '../elements/accented-trigger';
|
|
10
10
|
type Violation = AxeResults['violations'][number];
|
|
11
|
-
type
|
|
11
|
+
type AxeNode = Violation['nodes'][number];
|
|
12
12
|
|
|
13
13
|
const win: Window & { CSS: typeof CSS } = {
|
|
14
14
|
document: {
|
|
15
15
|
// @ts-expect-error the return value is of incorrect type.
|
|
16
16
|
createElement: () => ({
|
|
17
17
|
style: {
|
|
18
|
-
setProperty: () => {}
|
|
18
|
+
setProperty: () => {},
|
|
19
19
|
},
|
|
20
|
-
dataset: {}
|
|
21
|
-
})
|
|
20
|
+
dataset: {},
|
|
21
|
+
}),
|
|
22
|
+
contains: () => true,
|
|
22
23
|
},
|
|
23
24
|
// @ts-expect-error we're missing a lot of properties
|
|
24
25
|
getComputedStyle: () => ({
|
|
25
26
|
zIndex: '',
|
|
26
|
-
direction: 'ltr'
|
|
27
|
+
direction: 'ltr',
|
|
28
|
+
getPropertyValue: () => 'none',
|
|
27
29
|
}),
|
|
28
30
|
// @ts-expect-error we're missing a lot of properties
|
|
29
31
|
CSS: {
|
|
30
|
-
supports: () => true
|
|
31
|
-
}
|
|
32
|
-
}
|
|
32
|
+
supports: () => true,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
33
35
|
|
|
34
36
|
const getBoundingClientRect = () => ({});
|
|
35
37
|
|
|
38
|
+
const getRootNode = (): Node => ({}) as Node;
|
|
39
|
+
|
|
40
|
+
const baseElement = {
|
|
41
|
+
getBoundingClientRect,
|
|
42
|
+
getRootNode,
|
|
43
|
+
style: {
|
|
44
|
+
getPropertyValue: () => '',
|
|
45
|
+
},
|
|
46
|
+
closest: () => null,
|
|
47
|
+
};
|
|
48
|
+
|
|
36
49
|
// @ts-expect-error element is not HTMLElement
|
|
37
|
-
const element1: HTMLElement = {
|
|
50
|
+
const element1: HTMLElement = { ...baseElement, isConnected: true };
|
|
38
51
|
// @ts-expect-error element is not HTMLElement
|
|
39
|
-
const element2: HTMLElement = {
|
|
52
|
+
const element2: HTMLElement = { ...baseElement, isConnected: true };
|
|
40
53
|
// @ts-expect-error element is not HTMLElement
|
|
41
|
-
const element3: HTMLElement = {
|
|
54
|
+
const element3: HTMLElement = { ...baseElement, isConnected: false };
|
|
55
|
+
|
|
56
|
+
// @ts-expect-error rootNode is not Node
|
|
57
|
+
const rootNode: Node = {};
|
|
42
58
|
|
|
43
59
|
const trigger = win.document.createElement('accented-trigger') as AccentedTrigger;
|
|
44
60
|
|
|
45
61
|
const position = signal({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
left: 0,
|
|
63
|
+
width: 100,
|
|
64
|
+
top: 0,
|
|
65
|
+
height: 100,
|
|
49
66
|
});
|
|
50
67
|
|
|
51
68
|
const visible = signal(true);
|
|
@@ -57,20 +74,20 @@ const commonNodeProps = {
|
|
|
57
74
|
any: [],
|
|
58
75
|
all: [],
|
|
59
76
|
none: [],
|
|
60
|
-
target: ['div']
|
|
77
|
+
target: ['div'],
|
|
61
78
|
};
|
|
62
79
|
|
|
63
|
-
const node1:
|
|
80
|
+
const node1: AxeNode = {
|
|
64
81
|
...commonNodeProps,
|
|
65
82
|
element: element1,
|
|
66
83
|
};
|
|
67
84
|
|
|
68
|
-
const node2:
|
|
85
|
+
const node2: AxeNode = {
|
|
69
86
|
...commonNodeProps,
|
|
70
87
|
element: element2,
|
|
71
88
|
};
|
|
72
89
|
|
|
73
|
-
const node3:
|
|
90
|
+
const node3: AxeNode = {
|
|
74
91
|
...commonNodeProps,
|
|
75
92
|
element: element3,
|
|
76
93
|
};
|
|
@@ -80,53 +97,58 @@ const commonViolationProps = {
|
|
|
80
97
|
helpUrl: 'http://example.com',
|
|
81
98
|
description: 'description',
|
|
82
99
|
tags: [],
|
|
83
|
-
impact: 'serious' as ImpactValue
|
|
100
|
+
impact: 'serious' as ImpactValue,
|
|
84
101
|
};
|
|
85
102
|
|
|
86
103
|
const violation1: Violation = {
|
|
87
104
|
...commonViolationProps,
|
|
88
105
|
id: 'id1',
|
|
89
|
-
nodes: [node1]
|
|
106
|
+
nodes: [node1],
|
|
90
107
|
};
|
|
91
108
|
|
|
92
109
|
const violation2: Violation = {
|
|
93
110
|
...commonViolationProps,
|
|
94
111
|
id: 'id2',
|
|
95
|
-
nodes: [node2]
|
|
112
|
+
nodes: [node2],
|
|
96
113
|
};
|
|
97
114
|
|
|
98
115
|
const violation3: Violation = {
|
|
99
116
|
...commonViolationProps,
|
|
100
117
|
id: 'id3',
|
|
101
|
-
nodes: [node2]
|
|
118
|
+
nodes: [node2],
|
|
102
119
|
};
|
|
103
120
|
|
|
104
121
|
const violation4: Violation = {
|
|
105
122
|
...commonViolationProps,
|
|
106
123
|
id: 'id4',
|
|
107
|
-
nodes: [node3]
|
|
124
|
+
nodes: [node3],
|
|
108
125
|
};
|
|
109
126
|
|
|
110
127
|
const commonIssueProps = {
|
|
111
128
|
title: 'help',
|
|
112
129
|
description: 'description',
|
|
113
130
|
url: 'http://example.com',
|
|
114
|
-
impact: 'serious'
|
|
131
|
+
impact: 'serious',
|
|
115
132
|
} as const;
|
|
116
133
|
|
|
117
134
|
const issue1: Issue = {
|
|
118
135
|
id: 'id1',
|
|
119
|
-
...commonIssueProps
|
|
136
|
+
...commonIssueProps,
|
|
120
137
|
};
|
|
121
138
|
|
|
122
139
|
const issue2: Issue = {
|
|
123
140
|
id: 'id2',
|
|
124
|
-
...commonIssueProps
|
|
141
|
+
...commonIssueProps,
|
|
125
142
|
};
|
|
126
143
|
|
|
127
144
|
const issue3: Issue = {
|
|
128
145
|
id: 'id3',
|
|
129
|
-
...commonIssueProps
|
|
146
|
+
...commonIssueProps,
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const scanContext = {
|
|
150
|
+
include: [win.document],
|
|
151
|
+
exclude: [],
|
|
130
152
|
};
|
|
131
153
|
|
|
132
154
|
suite('updateElementsWithIssues', () => {
|
|
@@ -135,23 +157,35 @@ suite('updateElementsWithIssues', () => {
|
|
|
135
157
|
{
|
|
136
158
|
id: 1,
|
|
137
159
|
element: element1,
|
|
160
|
+
rootNode,
|
|
161
|
+
skipRender: false,
|
|
138
162
|
position,
|
|
139
163
|
visible,
|
|
140
164
|
trigger,
|
|
165
|
+
anchorNameValue: 'none',
|
|
141
166
|
scrollableAncestors,
|
|
142
|
-
issues: signal([issue1])
|
|
167
|
+
issues: signal([issue1]),
|
|
143
168
|
},
|
|
144
169
|
{
|
|
145
170
|
id: 2,
|
|
146
171
|
element: element2,
|
|
172
|
+
rootNode,
|
|
173
|
+
skipRender: false,
|
|
147
174
|
position,
|
|
148
175
|
visible,
|
|
149
176
|
trigger,
|
|
177
|
+
anchorNameValue: 'none',
|
|
150
178
|
scrollableAncestors,
|
|
151
|
-
issues: signal([issue2])
|
|
152
|
-
}
|
|
179
|
+
issues: signal([issue2]),
|
|
180
|
+
},
|
|
153
181
|
]);
|
|
154
|
-
updateElementsWithIssues(
|
|
182
|
+
updateElementsWithIssues({
|
|
183
|
+
extendedElementsWithIssues,
|
|
184
|
+
scanContext,
|
|
185
|
+
violations: [violation1, violation2],
|
|
186
|
+
win,
|
|
187
|
+
name: 'accented',
|
|
188
|
+
});
|
|
155
189
|
assert.equal(extendedElementsWithIssues.value.length, 2);
|
|
156
190
|
assert.equal(extendedElementsWithIssues.value[0]?.element, element1);
|
|
157
191
|
assert.equal(extendedElementsWithIssues.value[0]?.issues.value.length, 1);
|
|
@@ -164,23 +198,35 @@ suite('updateElementsWithIssues', () => {
|
|
|
164
198
|
{
|
|
165
199
|
id: 1,
|
|
166
200
|
element: element1,
|
|
201
|
+
rootNode,
|
|
202
|
+
skipRender: false,
|
|
167
203
|
position,
|
|
168
204
|
visible,
|
|
169
205
|
trigger,
|
|
206
|
+
anchorNameValue: 'none',
|
|
170
207
|
scrollableAncestors,
|
|
171
|
-
issues: signal([issue1])
|
|
208
|
+
issues: signal([issue1]),
|
|
172
209
|
},
|
|
173
210
|
{
|
|
174
211
|
id: 2,
|
|
175
212
|
element: element2,
|
|
213
|
+
rootNode,
|
|
214
|
+
skipRender: false,
|
|
176
215
|
position,
|
|
177
216
|
visible,
|
|
178
217
|
trigger,
|
|
218
|
+
anchorNameValue: 'none',
|
|
179
219
|
scrollableAncestors,
|
|
180
|
-
issues: signal([issue2])
|
|
181
|
-
}
|
|
220
|
+
issues: signal([issue2]),
|
|
221
|
+
},
|
|
182
222
|
]);
|
|
183
|
-
updateElementsWithIssues(
|
|
223
|
+
updateElementsWithIssues({
|
|
224
|
+
extendedElementsWithIssues,
|
|
225
|
+
scanContext,
|
|
226
|
+
violations: [violation1, violation2, violation3],
|
|
227
|
+
win,
|
|
228
|
+
name: 'accented',
|
|
229
|
+
});
|
|
184
230
|
assert.equal(extendedElementsWithIssues.value.length, 2);
|
|
185
231
|
assert.equal(extendedElementsWithIssues.value[0]?.element, element1);
|
|
186
232
|
assert.equal(extendedElementsWithIssues.value[0]?.issues.value.length, 1);
|
|
@@ -193,23 +239,35 @@ suite('updateElementsWithIssues', () => {
|
|
|
193
239
|
{
|
|
194
240
|
id: 1,
|
|
195
241
|
element: element1,
|
|
242
|
+
rootNode,
|
|
243
|
+
skipRender: false,
|
|
196
244
|
position,
|
|
197
245
|
visible,
|
|
198
246
|
trigger,
|
|
247
|
+
anchorNameValue: 'none',
|
|
199
248
|
scrollableAncestors,
|
|
200
|
-
issues: signal([issue1])
|
|
249
|
+
issues: signal([issue1]),
|
|
201
250
|
},
|
|
202
251
|
{
|
|
203
252
|
id: 2,
|
|
204
253
|
element: element2,
|
|
254
|
+
rootNode,
|
|
255
|
+
skipRender: false,
|
|
205
256
|
position,
|
|
206
257
|
visible,
|
|
207
258
|
trigger,
|
|
259
|
+
anchorNameValue: 'none',
|
|
208
260
|
scrollableAncestors,
|
|
209
|
-
issues: signal([issue2, issue3])
|
|
210
|
-
}
|
|
261
|
+
issues: signal([issue2, issue3]),
|
|
262
|
+
},
|
|
211
263
|
]);
|
|
212
|
-
updateElementsWithIssues(
|
|
264
|
+
updateElementsWithIssues({
|
|
265
|
+
extendedElementsWithIssues,
|
|
266
|
+
scanContext,
|
|
267
|
+
violations: [violation1, violation2],
|
|
268
|
+
win,
|
|
269
|
+
name: 'accented',
|
|
270
|
+
});
|
|
213
271
|
assert.equal(extendedElementsWithIssues.value.length, 2);
|
|
214
272
|
assert.equal(extendedElementsWithIssues.value[0]?.element, element1);
|
|
215
273
|
assert.equal(extendedElementsWithIssues.value[0]?.issues.value.length, 1);
|
|
@@ -222,14 +280,23 @@ suite('updateElementsWithIssues', () => {
|
|
|
222
280
|
{
|
|
223
281
|
id: 1,
|
|
224
282
|
element: element1,
|
|
283
|
+
rootNode,
|
|
284
|
+
skipRender: false,
|
|
225
285
|
position,
|
|
226
286
|
visible,
|
|
227
287
|
trigger,
|
|
288
|
+
anchorNameValue: 'none',
|
|
228
289
|
scrollableAncestors,
|
|
229
|
-
issues: signal([issue1])
|
|
230
|
-
}
|
|
290
|
+
issues: signal([issue1]),
|
|
291
|
+
},
|
|
231
292
|
]);
|
|
232
|
-
updateElementsWithIssues(
|
|
293
|
+
updateElementsWithIssues({
|
|
294
|
+
extendedElementsWithIssues,
|
|
295
|
+
scanContext,
|
|
296
|
+
violations: [violation1, violation2],
|
|
297
|
+
win,
|
|
298
|
+
name: 'accented',
|
|
299
|
+
});
|
|
233
300
|
assert.equal(extendedElementsWithIssues.value.length, 2);
|
|
234
301
|
assert.equal(extendedElementsWithIssues.value[0]?.element, element1);
|
|
235
302
|
assert.equal(extendedElementsWithIssues.value[0]?.issues.value.length, 1);
|
|
@@ -242,14 +309,23 @@ suite('updateElementsWithIssues', () => {
|
|
|
242
309
|
{
|
|
243
310
|
id: 1,
|
|
244
311
|
element: element1,
|
|
312
|
+
rootNode,
|
|
313
|
+
skipRender: false,
|
|
245
314
|
position,
|
|
246
315
|
visible,
|
|
247
316
|
trigger,
|
|
317
|
+
anchorNameValue: 'none',
|
|
248
318
|
scrollableAncestors,
|
|
249
|
-
issues: signal([issue1])
|
|
250
|
-
}
|
|
319
|
+
issues: signal([issue1]),
|
|
320
|
+
},
|
|
251
321
|
]);
|
|
252
|
-
updateElementsWithIssues(
|
|
322
|
+
updateElementsWithIssues({
|
|
323
|
+
extendedElementsWithIssues,
|
|
324
|
+
scanContext,
|
|
325
|
+
violations: [violation1, violation4],
|
|
326
|
+
win,
|
|
327
|
+
name: 'accented',
|
|
328
|
+
});
|
|
253
329
|
assert.equal(extendedElementsWithIssues.value.length, 1);
|
|
254
330
|
assert.equal(extendedElementsWithIssues.value[0]?.element, element1);
|
|
255
331
|
});
|
|
@@ -259,23 +335,35 @@ suite('updateElementsWithIssues', () => {
|
|
|
259
335
|
{
|
|
260
336
|
id: 1,
|
|
261
337
|
element: element1,
|
|
338
|
+
rootNode,
|
|
339
|
+
skipRender: false,
|
|
262
340
|
position,
|
|
263
341
|
visible,
|
|
264
342
|
trigger,
|
|
343
|
+
anchorNameValue: 'none',
|
|
265
344
|
scrollableAncestors,
|
|
266
|
-
issues: signal([issue1])
|
|
345
|
+
issues: signal([issue1]),
|
|
267
346
|
},
|
|
268
347
|
{
|
|
269
348
|
id: 2,
|
|
270
349
|
element: element2,
|
|
350
|
+
rootNode,
|
|
351
|
+
skipRender: false,
|
|
271
352
|
position,
|
|
272
353
|
visible,
|
|
273
354
|
trigger,
|
|
355
|
+
anchorNameValue: 'none',
|
|
274
356
|
scrollableAncestors,
|
|
275
|
-
issues: signal([issue2])
|
|
276
|
-
}
|
|
357
|
+
issues: signal([issue2]),
|
|
358
|
+
},
|
|
277
359
|
]);
|
|
278
|
-
updateElementsWithIssues(
|
|
360
|
+
updateElementsWithIssues({
|
|
361
|
+
extendedElementsWithIssues,
|
|
362
|
+
scanContext,
|
|
363
|
+
violations: [violation1],
|
|
364
|
+
win,
|
|
365
|
+
name: 'accented',
|
|
366
|
+
});
|
|
279
367
|
assert.equal(extendedElementsWithIssues.value.length, 1);
|
|
280
368
|
assert.equal(extendedElementsWithIssues.value[0]?.element, element1);
|
|
281
369
|
assert.equal(extendedElementsWithIssues.value[0]?.issues.value.length, 1);
|