lighthouse 9.5.0-dev.20220807 → 9.5.0-dev.20220810
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/cli/test/smokehouse/readme.md +6 -2
- package/cli/test/smokehouse/report-assert-test.js +34 -0
- package/cli/test/smokehouse/report-assert.js +28 -8
- package/core/audits/accessibility/accesskeys.js +1 -1
- package/core/audits/accessibility/aria-allowed-attr.js +1 -1
- package/core/audits/accessibility/aria-command-name.js +1 -1
- package/core/audits/accessibility/aria-hidden-body.js +1 -1
- package/core/audits/accessibility/aria-hidden-focus.js +1 -1
- package/core/audits/accessibility/aria-input-field-name.js +1 -1
- package/core/audits/accessibility/aria-meter-name.js +1 -1
- package/core/audits/accessibility/aria-progressbar-name.js +1 -1
- package/core/audits/accessibility/aria-required-attr.js +1 -1
- package/core/audits/accessibility/aria-required-children.js +1 -1
- package/core/audits/accessibility/aria-required-parent.js +1 -1
- package/core/audits/accessibility/aria-roles.js +1 -1
- package/core/audits/accessibility/aria-toggle-field-name.js +1 -1
- package/core/audits/accessibility/aria-tooltip-name.js +1 -1
- package/core/audits/accessibility/aria-treeitem-name.js +1 -1
- package/core/audits/accessibility/aria-valid-attr-value.js +1 -1
- package/core/audits/accessibility/aria-valid-attr.js +1 -1
- package/core/audits/accessibility/axe-audit.js +1 -1
- package/core/audits/accessibility/button-name.js +1 -1
- package/core/audits/accessibility/bypass.js +1 -1
- package/core/audits/accessibility/color-contrast.js +1 -1
- package/core/audits/accessibility/definition-list.js +1 -1
- package/core/audits/accessibility/dlitem.js +1 -1
- package/core/audits/accessibility/document-title.js +1 -1
- package/core/audits/accessibility/duplicate-id-active.js +1 -1
- package/core/audits/accessibility/duplicate-id-aria.js +1 -1
- package/core/audits/accessibility/form-field-multiple-labels.js +1 -1
- package/core/audits/accessibility/frame-title.js +1 -1
- package/core/audits/accessibility/heading-order.js +1 -1
- package/core/audits/accessibility/html-has-lang.js +1 -1
- package/core/audits/accessibility/html-lang-valid.js +1 -1
- package/core/audits/accessibility/image-alt.js +1 -1
- package/core/audits/accessibility/input-image-alt.js +1 -1
- package/core/audits/accessibility/label.js +1 -1
- package/core/audits/accessibility/link-name.js +1 -1
- package/core/audits/accessibility/list.js +1 -1
- package/core/audits/accessibility/listitem.js +1 -1
- package/core/audits/accessibility/meta-refresh.js +1 -1
- package/core/audits/accessibility/meta-viewport.js +1 -1
- package/core/audits/accessibility/object-alt.js +1 -1
- package/core/audits/accessibility/tabindex.js +1 -1
- package/core/audits/accessibility/td-headers-attr.js +1 -1
- package/core/audits/accessibility/th-has-data-cells.js +1 -1
- package/core/audits/accessibility/valid-lang.js +1 -1
- package/core/audits/accessibility/video-caption.js +1 -1
- package/core/audits/autocomplete.js +1 -1
- package/core/audits/bootup-time.js +1 -1
- package/core/audits/byte-efficiency/byte-efficiency-audit.js +1 -1
- package/core/audits/byte-efficiency/duplicated-javascript.js +1 -1
- package/core/audits/byte-efficiency/efficient-animated-content.js +1 -1
- package/core/audits/byte-efficiency/legacy-javascript.js +1 -1
- package/core/audits/byte-efficiency/modern-image-formats.js +1 -1
- package/core/audits/byte-efficiency/offscreen-images.js +1 -1
- package/core/audits/byte-efficiency/render-blocking-resources.js +1 -1
- package/core/audits/byte-efficiency/total-byte-weight.js +1 -1
- package/core/audits/byte-efficiency/unminified-css.js +1 -1
- package/core/audits/byte-efficiency/unminified-javascript.js +1 -1
- package/core/audits/byte-efficiency/unused-css-rules.js +1 -1
- package/core/audits/byte-efficiency/unused-javascript.js +1 -1
- package/core/audits/byte-efficiency/uses-long-cache-ttl.js +1 -1
- package/core/audits/byte-efficiency/uses-optimized-images.js +1 -1
- package/core/audits/byte-efficiency/uses-responsive-images-snapshot.js +1 -1
- package/core/audits/byte-efficiency/uses-responsive-images.js +1 -1
- package/core/audits/byte-efficiency/uses-text-compression.js +1 -1
- package/core/audits/content-width.js +1 -1
- package/core/audits/critical-request-chains.js +1 -1
- package/core/audits/csp-xss.js +1 -1
- package/core/audits/deprecations.js +1 -1
- package/core/audits/dobetterweb/charset.js +1 -1
- package/core/audits/dobetterweb/doctype.js +1 -1
- package/core/audits/dobetterweb/dom-size.js +1 -1
- package/core/audits/dobetterweb/geolocation-on-start.js +1 -1
- package/core/audits/dobetterweb/inspector-issues.js +1 -1
- package/core/audits/dobetterweb/js-libraries.js +1 -1
- package/core/audits/dobetterweb/no-document-write.js +1 -1
- package/core/audits/dobetterweb/no-vulnerable-libraries.js +1 -1
- package/core/audits/dobetterweb/notification-on-start.js +1 -1
- package/core/audits/dobetterweb/password-inputs-can-be-pasted-into.js +1 -1
- package/core/audits/dobetterweb/uses-http2.js +1 -1
- package/core/audits/dobetterweb/uses-passive-event-listeners.js +1 -1
- package/core/audits/errors-in-console.js +1 -1
- package/core/audits/font-display.js +1 -1
- package/core/audits/image-aspect-ratio.js +1 -1
- package/core/audits/image-size-responsive.js +1 -1
- package/core/audits/installable-manifest.js +1 -1
- package/core/audits/is-on-https.js +1 -1
- package/core/audits/largest-contentful-paint-element.js +1 -1
- package/core/audits/layout-shift-elements.js +1 -1
- package/core/audits/lcp-lazy-loaded.js +1 -1
- package/core/audits/long-tasks.js +1 -1
- package/core/audits/mainthread-work-breakdown.js +1 -1
- package/core/audits/manual/pwa-cross-browser.js +1 -1
- package/core/audits/manual/pwa-each-page-has-url.js +1 -1
- package/core/audits/manual/pwa-page-transitions.js +1 -1
- package/core/audits/maskable-icon.js +1 -1
- package/core/audits/metrics/cumulative-layout-shift.js +1 -1
- package/core/audits/metrics/experimental-interaction-to-next-paint.js +1 -1
- package/core/audits/metrics/first-contentful-paint.js +1 -1
- package/core/audits/metrics/first-meaningful-paint.js +1 -1
- package/core/audits/metrics/interactive.js +1 -1
- package/core/audits/metrics/largest-contentful-paint.js +1 -1
- package/core/audits/metrics/max-potential-fid.js +1 -1
- package/core/audits/metrics/speed-index.js +1 -1
- package/core/audits/metrics/total-blocking-time.js +1 -1
- package/core/audits/network-rtt.js +1 -1
- package/core/audits/network-server-latency.js +1 -1
- package/core/audits/no-unload-listeners.js +1 -1
- package/core/audits/non-composited-animations.js +1 -1
- package/core/audits/performance-budget.js +1 -1
- package/core/audits/predictive-perf.js +1 -1
- package/core/audits/preload-fonts.js +1 -1
- package/core/audits/preload-lcp-image.js +1 -1
- package/core/audits/redirects.js +1 -1
- package/core/audits/resource-summary.js +1 -1
- package/core/audits/seo/canonical.js +1 -1
- package/core/audits/seo/crawlable-anchors.js +1 -1
- package/core/audits/seo/font-size.js +1 -1
- package/core/audits/seo/hreflang.js +1 -1
- package/core/audits/seo/http-status-code.js +1 -1
- package/core/audits/seo/is-crawlable.js +1 -1
- package/core/audits/seo/link-text.js +1 -1
- package/core/audits/seo/manual/structured-data.js +1 -1
- package/core/audits/seo/meta-description.js +1 -1
- package/core/audits/seo/plugins.js +1 -1
- package/core/audits/seo/robots-txt.js +1 -1
- package/core/audits/seo/tap-targets.js +1 -1
- package/core/audits/server-response-time.js +1 -1
- package/core/audits/service-worker.js +1 -1
- package/core/audits/splash-screen.js +1 -1
- package/core/audits/themed-omnibox.js +1 -1
- package/core/audits/third-party-facades.js +1 -1
- package/core/audits/third-party-summary.js +1 -1
- package/core/audits/timing-budget.js +1 -1
- package/core/audits/unsized-images.js +1 -1
- package/core/audits/user-timings.js +1 -1
- package/core/audits/uses-rel-preconnect.js +1 -1
- package/core/audits/uses-rel-preload.js +1 -1
- package/core/audits/valid-source-maps.js +1 -1
- package/core/audits/viewport.js +1 -1
- package/core/audits/work-during-interaction.js +1 -1
- package/core/config/default-config.js +1 -1
- package/core/gather/driver/environment.js +1 -1
- package/core/gather/driver/navigation.js +1 -1
- package/core/gather/driver/storage.js +1 -1
- package/core/lib/csp-evaluator.js +1 -1
- package/core/lib/deprecations-strings.js +1 -1
- package/core/lib/i18n/i18n.js +0 -2
- package/core/lib/lh-error.js +1 -1
- package/core/lib/navigation-error.js +1 -1
- package/core/lib/stack-packs.js +1 -1
- package/package.json +4 -4
- package/shared/test/localization/format-test.js +8 -8
|
@@ -64,9 +64,11 @@ Individual elements of an array can be asserted by using numeric properties in a
|
|
|
64
64
|
|
|
65
65
|
However, if an array literal is used as the expectation, an extra condition is enforced that the actual array _must_ have the same length as the provided expected array.
|
|
66
66
|
|
|
67
|
-
Arrays can be checked against a subset of elements using the special `_includes` property. The value of `_includes` _must_ be an array. Each assertion in `_includes` will remove the matching item from consideration for the rest.
|
|
67
|
+
Arrays and objects can be checked against a subset of elements using the special `_includes` property. The value of `_includes` _must_ be an array. Each assertion in `_includes` will remove the matching item from consideration for the rest.
|
|
68
68
|
|
|
69
|
-
Arrays can be asserted to not match any elements using the special `_excludes` property. The value of `_excludes` _must_ be an array. If an `_includes` check is defined before an `_excludes` check, only the element not matched under the previous will be considered.
|
|
69
|
+
Arrays and objects can be asserted to not match any elements using the special `_excludes` property. The value of `_excludes` _must_ be an array. If an `_includes` check is defined before an `_excludes` check, only the element not matched under the previous will be considered.
|
|
70
|
+
|
|
71
|
+
If an object is checked using `_includes` or `_excludes`, it will be checked against the `Object.entries` array.
|
|
70
72
|
|
|
71
73
|
**Examples**:
|
|
72
74
|
| Actual | Expected | Result |
|
|
@@ -79,6 +81,8 @@ Arrays can be asserted to not match any elements using the special `_excludes` p
|
|
|
79
81
|
| `[{timeInMs: 5}, {timeInMs: 15}]` | `{_includes: [{timeInMs: 5}], _excludes: [{timeInMs: 15}]}` | ❌ FAIL |
|
|
80
82
|
| `[{timeInMs: 5}, {timeInMs: 15}]` | `{_includes: [{timeInMs: 5}], _excludes: [{}]}` | ❌ FAIL |
|
|
81
83
|
| `[{timeInMs: 5}, {timeInMs: 15}]` | `[{timeInMs: 5}]` | ❌ FAIL |
|
|
84
|
+
| `{'foo': 1}` | `{_includes: [['foo', 1]]}` | ✅ PASS |
|
|
85
|
+
| `{'foo': 1, 'bar': 2}` | `{_includes: [['foo', 1]], _excludes: [['bar', 2]]}` | ❌ FAIL |
|
|
82
86
|
|
|
83
87
|
### Special environment checks
|
|
84
88
|
|
|
@@ -133,6 +133,14 @@ describe('findDiffersences', () => {
|
|
|
133
133
|
expected: {prices: {_includes: [/\d/, /\d/, /\d/, /\d/, /\d/, /\d/]}},
|
|
134
134
|
diffs: null,
|
|
135
135
|
},
|
|
136
|
+
'_includes (object)': {
|
|
137
|
+
actual: {'0-alpha': 1, '1-beta': 2, '3-gamma': 3},
|
|
138
|
+
expected: {_includes: [
|
|
139
|
+
['0-alpha', '<2'],
|
|
140
|
+
[/[0-9]-beta/, 2],
|
|
141
|
+
]},
|
|
142
|
+
diffs: null,
|
|
143
|
+
},
|
|
136
144
|
|
|
137
145
|
'_excludes (1)': {
|
|
138
146
|
actual: {prices: [0, 1, 2, 3, 4, 5]},
|
|
@@ -147,6 +155,16 @@ describe('findDiffersences', () => {
|
|
|
147
155
|
message: 'Expected to not find matching entry via _excludes',
|
|
148
156
|
}}],
|
|
149
157
|
},
|
|
158
|
+
'_excludes (object)': {
|
|
159
|
+
actual: {'0-alpha': 1, '1-beta': 2, '3-gamma': 3},
|
|
160
|
+
expected: {_excludes: [
|
|
161
|
+
[/[0-9]-beta/, 2],
|
|
162
|
+
]},
|
|
163
|
+
diffs: [{path: '', actual: ['1-beta', 2], expected: {
|
|
164
|
+
expectedExclusion: [/[0-9]-beta/, 2],
|
|
165
|
+
message: 'Expected to not find matching entry via _excludes',
|
|
166
|
+
}}],
|
|
167
|
+
},
|
|
150
168
|
|
|
151
169
|
'_includes and _excludes (1)': {
|
|
152
170
|
actual: {prices: [0, 1, 2, 3, 4, 5]},
|
|
@@ -170,6 +188,22 @@ describe('findDiffersences', () => {
|
|
|
170
188
|
message: 'Expected to not find matching entry via _excludes',
|
|
171
189
|
}}],
|
|
172
190
|
},
|
|
191
|
+
'_includes and _excludes (object)': {
|
|
192
|
+
actual: {'0-alpha': 1, '1-beta': 2, '3-gamma': 3},
|
|
193
|
+
expected: {
|
|
194
|
+
_includes: [
|
|
195
|
+
['0-alpha', '<2'],
|
|
196
|
+
],
|
|
197
|
+
_excludes: [
|
|
198
|
+
[/[0-9]-alpha/, 1],
|
|
199
|
+
[/[0-9]-beta/, 2],
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
diffs: [{path: '', actual: ['1-beta', 2], expected: {
|
|
203
|
+
expectedExclusion: [/[0-9]-beta/, 2],
|
|
204
|
+
message: 'Expected to not find matching entry via _excludes',
|
|
205
|
+
}}],
|
|
206
|
+
},
|
|
173
207
|
};
|
|
174
208
|
|
|
175
209
|
for (const [testName, {actual, expected, diffs}] of Object.entries(testCases)) {
|
|
@@ -105,6 +105,8 @@ function findDifferences(path, actual, expected) {
|
|
|
105
105
|
|
|
106
106
|
/** @type {Difference[]} */
|
|
107
107
|
const diffs = [];
|
|
108
|
+
|
|
109
|
+
/** @type {any[]|undefined} */
|
|
108
110
|
let inclExclCopy;
|
|
109
111
|
|
|
110
112
|
// We only care that all expected's own properties are on actual (and not the other way around).
|
|
@@ -116,15 +118,20 @@ function findDifferences(path, actual, expected) {
|
|
|
116
118
|
const expectedValue = expected[key];
|
|
117
119
|
|
|
118
120
|
if (key === '_includes') {
|
|
119
|
-
|
|
121
|
+
if (Array.isArray(actual)) {
|
|
122
|
+
inclExclCopy = [...actual];
|
|
123
|
+
} else if (typeof actual === 'object') {
|
|
124
|
+
inclExclCopy = Object.entries(actual);
|
|
125
|
+
}
|
|
120
126
|
|
|
121
127
|
if (!Array.isArray(expectedValue)) throw new Error('Array subset must be array');
|
|
122
|
-
if (!
|
|
128
|
+
if (!inclExclCopy) {
|
|
123
129
|
diffs.push({
|
|
124
130
|
path,
|
|
125
|
-
actual: 'Actual value is not an array',
|
|
131
|
+
actual: 'Actual value is not an array or object',
|
|
126
132
|
expected,
|
|
127
133
|
});
|
|
134
|
+
continue;
|
|
128
135
|
}
|
|
129
136
|
|
|
130
137
|
for (const expectedEntry of expectedValue) {
|
|
@@ -148,20 +155,33 @@ function findDifferences(path, actual, expected) {
|
|
|
148
155
|
|
|
149
156
|
if (key === '_excludes') {
|
|
150
157
|
// Re-use state from `_includes` check, if there was one.
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
if (!inclExclCopy) {
|
|
159
|
+
if (Array.isArray(actual)) {
|
|
160
|
+
// We won't be removing items, so we can just copy the reference.
|
|
161
|
+
inclExclCopy = actual;
|
|
162
|
+
} else if (typeof actual === 'object') {
|
|
163
|
+
inclExclCopy = Object.entries(actual);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
153
166
|
|
|
154
167
|
if (!Array.isArray(expectedValue)) throw new Error('Array subset must be array');
|
|
155
|
-
if (!
|
|
168
|
+
if (!inclExclCopy) {
|
|
169
|
+
diffs.push({
|
|
170
|
+
path,
|
|
171
|
+
actual: 'Actual value is not an array or object',
|
|
172
|
+
expected,
|
|
173
|
+
});
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
156
176
|
|
|
157
177
|
const expectedExclusions = expectedValue;
|
|
158
178
|
for (const expectedExclusion of expectedExclusions) {
|
|
159
|
-
const matchingIndex =
|
|
179
|
+
const matchingIndex = inclExclCopy.findIndex(actualEntry =>
|
|
160
180
|
!findDifferences(keyPath, actualEntry, expectedExclusion));
|
|
161
181
|
if (matchingIndex !== -1) {
|
|
162
182
|
diffs.push({
|
|
163
183
|
path,
|
|
164
|
-
actual:
|
|
184
|
+
actual: inclExclCopy[matchingIndex],
|
|
165
185
|
expected: {
|
|
166
186
|
message: 'Expected to not find matching entry via _excludes',
|
|
167
187
|
expectedExclusion,
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'[Learn more about access keys](https://dequeuniversity.com/rules/axe/4.4/accesskeys).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class Accesskeys extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'how to match ARIA attributes to their roles](https://dequeuniversity.com/rules/axe/4.4/aria-allowed-attr).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class ARIAAllowedAttr extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'When an element doesn\'t have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn how to make command elements more accessible](https://dequeuniversity.com/rules/axe/4.4/aria-command-name).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class AriaCommandName extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'Assistive technologies, like screen readers, work inconsistently when `aria-hidden="true"` is set on the document `<body>`. [Learn how `aria-hidden` affects the document body](https://dequeuniversity.com/rules/axe/4.4/aria-hidden-body).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class AriaHiddenBody extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'Focusable descendents within an `[aria-hidden="true"]` element prevent those interactive elements from being available to users of assistive technologies like screen readers. [Learn how `aria-hidden` affects focusable elements](https://dequeuniversity.com/rules/axe/4.4/aria-hidden-focus).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class AriaHiddenFocus extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'When an input field doesn\'t have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn more about input field labels](https://dequeuniversity.com/rules/axe/4.4/aria-input-field-name).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class AriaInputFieldName extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'When an element doesn\'t have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn how to name `meter` elements](https://dequeuniversity.com/rules/axe/4.4/aria-meter-name).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class AriaMeterName extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'When a `progressbar` element doesn\'t have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn how to label `progressbar` elements](https://dequeuniversity.com/rules/axe/4.4/aria-progressbar-name).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class AriaProgressbarName extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -24,7 +24,7 @@ const UIStrings = {
|
|
|
24
24
|
'of the element to screen readers. [Learn more about roles and required attributes](https://dequeuniversity.com/rules/axe/4.4/aria-required-attr).',
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
const str_ = i18n.
|
|
27
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
28
28
|
|
|
29
29
|
class ARIARequiredAttr extends AxeAudit {
|
|
30
30
|
/**
|
|
@@ -28,7 +28,7 @@ const UIStrings = {
|
|
|
28
28
|
'[Learn more about roles and required children elements](https://dequeuniversity.com/rules/axe/4.4/aria-required-children).',
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
const str_ = i18n.
|
|
31
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
32
32
|
|
|
33
33
|
class AriaRequiredChildren extends AxeAudit {
|
|
34
34
|
/**
|
|
@@ -26,7 +26,7 @@ const UIStrings = {
|
|
|
26
26
|
'[Learn more about ARIA roles and required parent element](https://dequeuniversity.com/rules/axe/4.4/aria-required-parent).',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const str_ = i18n.
|
|
29
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
30
30
|
|
|
31
31
|
class AriaRequiredParent extends AxeAudit {
|
|
32
32
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'[Learn more about valid ARIA roles](https://dequeuniversity.com/rules/axe/4.4/aria-roles).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class AriaRoles extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'When a toggle field doesn\'t have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn more about toggle fields](https://dequeuniversity.com/rules/axe/4.4/aria-toggle-field-name).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class AriaToggleFieldName extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'When an element doesn\'t have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn how to name `tooltip` elements](https://dequeuniversity.com/rules/axe/4.4/aria-tooltip-name).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class AriaTooltipName extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'When a `treeitem` element doesn\'t have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn more about labeling `treeitem` elements](https://dequeuniversity.com/rules/axe/4.4/aria-treeitem-name).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class AriaTreeitemName extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'more about valid values for ARIA attributes](https://dequeuniversity.com/rules/axe/4.4/aria-valid-attr-value).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class ARIAValidAttr extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'more about valid ARIA attributes](https://dequeuniversity.com/rules/axe/4.4/aria-valid-attr).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class ARIAValidAttr extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -19,7 +19,7 @@ const UIStrings = {
|
|
|
19
19
|
failingElementsHeader: 'Failing Elements',
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const str_ = i18n.
|
|
22
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
23
23
|
|
|
24
24
|
class AxeAudit extends Audit {
|
|
25
25
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'[Learn how to make buttons more accessible](https://dequeuniversity.com/rules/axe/4.4/button-name).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class ButtonName extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -26,7 +26,7 @@ const UIStrings = {
|
|
|
26
26
|
'[Learn more about bypass blocks](https://dequeuniversity.com/rules/axe/4.4/bypass).',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const str_ = i18n.
|
|
29
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
30
30
|
|
|
31
31
|
class Bypass extends AxeAudit {
|
|
32
32
|
/**
|
|
@@ -26,7 +26,7 @@ const UIStrings = {
|
|
|
26
26
|
'[Learn how to provide sufficient color contrast](https://dequeuniversity.com/rules/axe/4.4/color-contrast).',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const str_ = i18n.
|
|
29
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
30
30
|
|
|
31
31
|
class ColorContrast extends AxeAudit {
|
|
32
32
|
/**
|
|
@@ -27,7 +27,7 @@ const UIStrings = {
|
|
|
27
27
|
'[Learn how to structure definition lists correctly](https://dequeuniversity.com/rules/axe/4.4/definition-list).',
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
const str_ = i18n.
|
|
30
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
31
31
|
|
|
32
32
|
class DefinitionList extends AxeAudit {
|
|
33
33
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'[Learn how to structure definition lists correctly](https://dequeuniversity.com/rules/axe/4.4/dlitem).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class DLItem extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'[Learn more about document titles](https://dequeuniversity.com/rules/axe/4.4/document-title).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class DocumentTitle extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'All focusable elements must have a unique `id` to ensure that they\'re visible to assistive technologies. [Learn how to fix duplicate `id`s](https://dequeuniversity.com/rules/axe/4.4/duplicate-id-active).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class DuplicateIdActive extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'The value of an ARIA ID must be unique to prevent other instances from being overlooked by assistive technologies. [Learn how to fix duplicate ARIA IDs](https://dequeuniversity.com/rules/axe/4.4/duplicate-id-aria).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class DuplicateIdAria extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'Form fields with multiple labels can be confusingly announced by assistive technologies like screen readers which use either the first, the last, or all of the labels. [Learn how to use form labels](https://dequeuniversity.com/rules/axe/4.4/form-field-multiple-labels).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class FormFieldMultipleLabels extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -24,7 +24,7 @@ const UIStrings = {
|
|
|
24
24
|
'[Learn more about frame titles](https://dequeuniversity.com/rules/axe/4.4/frame-title).',
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
const str_ = i18n.
|
|
27
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
28
28
|
|
|
29
29
|
class FrameTitle extends AxeAudit {
|
|
30
30
|
/**
|
|
@@ -23,7 +23,7 @@ const UIStrings = {
|
|
|
23
23
|
description: 'Properly ordered headings that do not skip levels convey the semantic structure of the page, making it easier to navigate and understand when using assistive technologies. [Learn more about heading order](https://dequeuniversity.com/rules/axe/4.4/heading-order).',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const str_ = i18n.
|
|
26
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
27
27
|
|
|
28
28
|
class HeadingOrder extends AxeAudit {
|
|
29
29
|
/**
|
|
@@ -27,7 +27,7 @@ const UIStrings = {
|
|
|
27
27
|
'[Learn more about the `lang` attribute](https://dequeuniversity.com/rules/axe/4.4/html-has-lang).',
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
const str_ = i18n.
|
|
30
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
31
31
|
|
|
32
32
|
class HTMLHasLang extends AxeAudit {
|
|
33
33
|
/**
|
|
@@ -26,7 +26,7 @@ const UIStrings = {
|
|
|
26
26
|
'[Learn how to use the `lang` attribute](https://dequeuniversity.com/rules/axe/4.4/html-lang-valid).',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const str_ = i18n.
|
|
29
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
30
30
|
|
|
31
31
|
class HTMLLangValid extends AxeAudit {
|
|
32
32
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'[Learn more about the `alt` attribute](https://dequeuniversity.com/rules/axe/4.4/image-alt).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class ImageAlt extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'[Learn about input image alt text](https://dequeuniversity.com/rules/axe/4.4/input-image-alt).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class InputImageAlt extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'more about form element labels](https://dequeuniversity.com/rules/axe/4.4/label).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class Label extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -26,7 +26,7 @@ const UIStrings = {
|
|
|
26
26
|
'[Learn how to make links accessible](https://dequeuniversity.com/rules/axe/4.4/link-name).',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const str_ = i18n.
|
|
29
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
30
30
|
|
|
31
31
|
class LinkName extends AxeAudit {
|
|
32
32
|
/**
|
|
@@ -27,7 +27,7 @@ const UIStrings = {
|
|
|
27
27
|
'[Learn more about proper list structure](https://dequeuniversity.com/rules/axe/4.4/list).',
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
const str_ = i18n.
|
|
30
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
31
31
|
|
|
32
32
|
class List extends AxeAudit {
|
|
33
33
|
/**
|
|
@@ -26,7 +26,7 @@ const UIStrings = {
|
|
|
26
26
|
'[Learn more about proper list structure](https://dequeuniversity.com/rules/axe/4.4/listitem).',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const str_ = i18n.
|
|
29
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
30
30
|
|
|
31
31
|
class ListItem extends AxeAudit {
|
|
32
32
|
/**
|
|
@@ -26,7 +26,7 @@ const UIStrings = {
|
|
|
26
26
|
'[Learn more about the refresh meta tag](https://dequeuniversity.com/rules/axe/4.4/meta-refresh).',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const str_ = i18n.
|
|
29
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
30
30
|
|
|
31
31
|
class MetaRefresh extends AxeAudit {
|
|
32
32
|
/**
|
|
@@ -27,7 +27,7 @@ const UIStrings = {
|
|
|
27
27
|
'[Learn more about the viewport meta tag](https://dequeuniversity.com/rules/axe/4.4/meta-viewport).',
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
const str_ = i18n.
|
|
30
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
31
31
|
|
|
32
32
|
class MetaViewport extends AxeAudit {
|
|
33
33
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'[Learn more about alt text for `object` elements](https://dequeuniversity.com/rules/axe/4.4/object-alt).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class ObjectAlt extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'for users who rely on assistive technologies. [Learn more about the `tabindex` attribute](https://dequeuniversity.com/rules/axe/4.4/tabindex).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class TabIndex extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -29,7 +29,7 @@ const UIStrings = {
|
|
|
29
29
|
'[Learn more about the `headers` attribute](https://dequeuniversity.com/rules/axe/4.4/td-headers-attr).',
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
const str_ = i18n.
|
|
32
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
33
33
|
|
|
34
34
|
class TDHeadersAttr extends AxeAudit {
|
|
35
35
|
/**
|
|
@@ -28,7 +28,7 @@ const UIStrings = {
|
|
|
28
28
|
'[Learn more about table headers](https://dequeuniversity.com/rules/axe/4.4/th-has-data-cells).',
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
const str_ = i18n.
|
|
31
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
32
32
|
|
|
33
33
|
class THHasDataCells extends AxeAudit {
|
|
34
34
|
/**
|
|
@@ -25,7 +25,7 @@ const UIStrings = {
|
|
|
25
25
|
'[Learn how to use the `lang` attribute](https://dequeuniversity.com/rules/axe/4.4/valid-lang).',
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const str_ = i18n.
|
|
28
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
29
29
|
|
|
30
30
|
class ValidLang extends AxeAudit {
|
|
31
31
|
/**
|
|
@@ -26,7 +26,7 @@ const UIStrings = {
|
|
|
26
26
|
'[Learn more about video captions](https://dequeuniversity.com/rules/axe/4.4/video-caption).',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const str_ = i18n.
|
|
29
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
30
30
|
|
|
31
31
|
class VideoCaption extends AxeAudit {
|
|
32
32
|
/**
|
|
@@ -48,7 +48,7 @@ const UIStrings = {
|
|
|
48
48
|
manualReview: 'Requires manual review',
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
const str_ = i18n.
|
|
51
|
+
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
52
52
|
|
|
53
53
|
/** @type {string[]} This array contains all acceptable autocomplete attributes from the WHATWG standard. More found at https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill */
|
|
54
54
|
const validAutocompleteTokens = ['name', 'honorific-prefix', 'given-name',
|