testilo 3.6.3 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testilo",
3
- "version": "3.6.3",
3
+ "version": "3.8.0",
4
4
  "description": "Client that scores and digests Testaro reports",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -20,12 +20,12 @@
20
20
  <h2>Introduction</h2>
21
21
  <p>The table below compares __pageCount__ web pages on <a href="https://www.w3.org/WAI/fundamentals/accessibility-intro/">accessibility</a>. The page names link to the pages on the web. The scores link to digests that explain in detail how the scores were computed.</p>
22
22
  <p>The pages were:</p>
23
- <div id="summary">
24
- <p>Tested by <a href="https://www.npmjs.com/package/testaro">Testaro</a> with procedure <code>tp12</code></p>
25
- <p>Scored by <a href="https://www.npmjs.com/package/testilo">Testilo</a> with procedure <code>sp12a</code></p>
26
- <p>Digested by Testilo with procedure <code>dp12a</code></p>
27
- <p>Compared by Testilo with procedure <code>cp12a</code></p>
28
- </div>
23
+ <ol id="summary">
24
+ <li>Tested by <a href="https://www.npmjs.com/package/testaro">Testaro</a> with procedure <code>tp12</code></li>
25
+ <li>Scored by <a href="https://www.npmjs.com/package/testilo">Testilo</a> with procedure <code>sp12a</code></li>
26
+ <li>Digested by Testilo with procedure <code>dp12a</code></li>
27
+ <li>Compared by Testilo with procedure <code>cp12a</code></li>
28
+ </ol>
29
29
  <p>The Testaro procedure performs 808 tests on each page. Of these, 16 tests are custom tests defined by Testaro, and the others belong to packages of tests created by others.</p>
30
30
  <h2>Comparison</h2>
31
31
  <table class="allBorder">
@@ -19,9 +19,9 @@ const specialMessages = {
19
19
 
20
20
  // Makes strings HTML-safe.
21
21
  const htmlEscape = textOrNumber => textOrNumber
22
- .toString()
23
- .replace(/&/g, '&amp;')
24
- .replace(/</g, '&lt;');
22
+ .toString()
23
+ .replace(/&/g, '&amp;')
24
+ .replace(/</g, '&lt;');
25
25
  // Gets a row of the score-summary table.
26
26
  const getScoreRow = (component, score) => `<tr><th>${component}</th><td>${score}</td></tr>`;
27
27
  // Gets the start of a paragraph about a special score.
@@ -73,6 +73,10 @@ const groups = {
73
73
  'duplicate-id-active': {
74
74
  quality: 1,
75
75
  what: 'id attribute value of the active element is not unique'
76
+ },
77
+ 'duplicate-id-aria': {
78
+ quality: 1,
79
+ what: 'id attribute used in ARIA or in a label has a value that is not unique'
76
80
  }
77
81
  },
78
82
  htmlcs: {
@@ -89,6 +93,17 @@ const groups = {
89
93
  }
90
94
  }
91
95
  },
96
+ regionNoText: {
97
+ weight: 4,
98
+ packages: {
99
+ alfa: {
100
+ r40: {
101
+ quality: 1,
102
+ what: 'Region has no accessible name'
103
+ }
104
+ }
105
+ }
106
+ },
92
107
  formFieldNoText: {
93
108
  weight: 4,
94
109
  packages: {
@@ -118,9 +133,21 @@ const groups = {
118
133
  quality: 1,
119
134
  what: 'Email input has no accessible name'
120
135
  },
136
+ 'e:AA.4_1_2.H91.InputTel.Name': {
137
+ quality: 1,
138
+ what: 'Telephone input has no accessible name'
139
+ },
121
140
  'e:AA.4_1_2.H91.InputNumber.Name': {
122
141
  quality: 1,
123
142
  what: 'Number input has no accessible name'
143
+ },
144
+ 'e:AA.4_1_2.H91.InputSearch.Name': {
145
+ quality: 1,
146
+ what: 'Search input has no accessible name'
147
+ },
148
+ 'e:AA.4_1_2.H91.InputCheckbox.Name': {
149
+ quality: 1,
150
+ what: 'Checkbox input has no accessible name'
124
151
  }
125
152
  }
126
153
  }
@@ -137,7 +164,7 @@ const groups = {
137
164
  axe: {
138
165
  'input-image-alt': {
139
166
  quality: 1,
140
- what: 'Image buttons must have alternate text'
167
+ what: 'Image button has no text alternative'
141
168
  }
142
169
  },
143
170
  htmlcs: {
@@ -172,7 +199,7 @@ const groups = {
172
199
  axe: {
173
200
  'image-alt': {
174
201
  quality: 1,
175
- what: 'Images must have alternate text'
202
+ what: 'Image has no text alternative'
176
203
  }
177
204
  },
178
205
  htmlcs: {
@@ -184,13 +211,17 @@ const groups = {
184
211
  ibm: {
185
212
  'v:WCAG20_Img_HasAlt': {
186
213
  quality: 1,
187
- what: 'Images must have an alt attribute if they convey meaning, or alt="" if decorative'
214
+ what: 'Image has no alt attribute conveying its meaning, or alt="" if decorative'
188
215
  }
189
216
  },
190
217
  wave: {
191
218
  'e:alt_missing': {
192
219
  quality: 1,
193
- what: 'Missing alternative text'
220
+ what: 'Text alternative is missing'
221
+ },
222
+ 'e:alt_spacer_missing': {
223
+ quality: 1,
224
+ what: 'Spacer image has no text alternative'
194
225
  }
195
226
  }
196
227
  }
@@ -206,6 +237,17 @@ const groups = {
206
237
  }
207
238
  }
208
239
  },
240
+ imagesSameAlt: {
241
+ weight: 1,
242
+ packages: {
243
+ wave: {
244
+ 'a:alt_duplicate': {
245
+ quality: 1,
246
+ what: 'Two images near each other have the same text alternative'
247
+ }
248
+ }
249
+ }
250
+ },
209
251
  imageTextLong: {
210
252
  weight: 2,
211
253
  packages: {
@@ -239,17 +281,6 @@ const groups = {
239
281
  }
240
282
  }
241
283
  },
242
- presentationConflict: {
243
- weight: 4,
244
- packages: {
245
- axe: {
246
- 'presentation-role-conflict': {
247
- quality: 1,
248
- what: 'Element has a none/presentation role but is focusable or has a global ARIA state or property'
249
- }
250
- }
251
- }
252
- },
253
284
  decorativeElementExposed: {
254
285
  weight: 1,
255
286
  packages: {
@@ -277,7 +308,7 @@ const groups = {
277
308
  axe: {
278
309
  'html-has-lang': {
279
310
  quality: 1,
280
- what: 'html element must have a lang attribute'
311
+ what: 'html element has no lang attribute'
281
312
  }
282
313
  },
283
314
  htmlcs: {
@@ -312,7 +343,13 @@ const groups = {
312
343
  axe: {
313
344
  'html-lang-valid': {
314
345
  quality: 1,
315
- what: 'html element must have a valid value for the lang attribute'
346
+ what: 'html element has no valid value for the lang attribute'
347
+ }
348
+ },
349
+ htmlcs: {
350
+ 'e:AA.3_1_1.H57.3.Lang': {
351
+ quality: 1,
352
+ what: 'Language specified in the lang attribute of the document does not appear to be well-formed'
316
353
  }
317
354
  },
318
355
  ibm: {
@@ -323,6 +360,17 @@ const groups = {
323
360
  }
324
361
  }
325
362
  },
363
+ elementLanguageBad: {
364
+ weight: 4,
365
+ packages: {
366
+ htmlcs: {
367
+ 'e:AA.3_1_2.H58.1.Lang': {
368
+ quality: 1,
369
+ what: 'Language specified in the lang attribute of the element does not appear to be well-formed'
370
+ }
371
+ }
372
+ }
373
+ },
326
374
  languageChange: {
327
375
  weight: 3,
328
376
  packages: {
@@ -335,7 +383,7 @@ const groups = {
335
383
  axe: {
336
384
  'valid-lang': {
337
385
  quality: 1,
338
- what: 'lang attribute must have a valid value'
386
+ what: 'lang attribute has no valid value'
339
387
  }
340
388
  },
341
389
  htmlcs: {
@@ -346,25 +394,36 @@ const groups = {
346
394
  }
347
395
  }
348
396
  },
397
+ dialogNoText: {
398
+ weight: 4,
399
+ packages: {
400
+ axe: {
401
+ 'aria-dialog-name': {
402
+ quality: 1,
403
+ what: 'ARIA dialog or alertdialog node has no accessible name'
404
+ }
405
+ }
406
+ }
407
+ },
349
408
  objectNoText: {
350
409
  weight: 4,
351
410
  packages: {
352
411
  axe: {
353
412
  'object-alt': {
354
413
  quality: 1,
355
- what: 'Object elements must have alternate text'
414
+ what: 'Object element has no text alternative'
356
415
  }
357
416
  },
358
417
  htmlcs: {
359
418
  'e:ARIA6+H53': {
360
419
  quality: 1,
361
- what: 'Object elements must contain a text alternative'
420
+ what: 'Object element contains no text alternative'
362
421
  }
363
422
  },
364
423
  ibm: {
365
424
  'v:WCAG20_Object_HasText': {
366
425
  quality: 1,
367
- what: 'Object elements must have a text alternative'
426
+ what: 'Object element has no text alternative'
368
427
  }
369
428
  },
370
429
  wave: {
@@ -381,7 +440,7 @@ const groups = {
381
440
  axe: {
382
441
  'area-alt': {
383
442
  quality: 1,
384
- what: 'Active area elements must have alternate text'
443
+ what: 'Active area elements has no text alternative'
385
444
  }
386
445
  },
387
446
  htmlcs: {
@@ -446,13 +505,32 @@ const groups = {
446
505
  }
447
506
  }
448
507
  },
449
- labelForBadID: {
508
+ labelForWrongRisk: {
509
+ weight: 1,
510
+ packages: {
511
+ htmlcs: {
512
+ 'w:AA.1_3_1.H44.NotFormControl': {
513
+ quality: 1,
514
+ what: 'Label for attribute may reference the wrong element, because it is not a form control'
515
+ }
516
+ }
517
+ }
518
+ },
519
+ labelBadID: {
450
520
  weight: 4,
451
521
  packages: {
452
522
  htmlcs: {
453
523
  'w:AA.1_3_1.H44.NonExistentFragment': {
454
524
  quality: 1,
455
525
  what: 'Label for attribute references a nonexistent element'
526
+ },
527
+ 'w:AA.1_3_1.ARIA16,ARIA9': {
528
+ quality: 1,
529
+ what: 'aria-labelledby attribute references a nonexistent element'
530
+ },
531
+ 'w:AA.4_1_2.ARIA16,ARIA9': {
532
+ quality: 1,
533
+ what: 'aria-labelledby attribute references a nonexistent element'
456
534
  }
457
535
  },
458
536
  wave: {
@@ -475,7 +553,7 @@ const groups = {
475
553
  axe: {
476
554
  'link-name': {
477
555
  quality: 1,
478
- what: 'Links must have discernible text'
556
+ what: 'Link has no discernible text'
479
557
  }
480
558
  },
481
559
  htmlcs: {
@@ -510,6 +588,10 @@ const groups = {
510
588
  57: {
511
589
  quality: 1,
512
590
  what: 'Link has no text inside it'
591
+ },
592
+ 91: {
593
+ quality: 1,
594
+ what: 'Link has a background image but no text inside it'
513
595
  }
514
596
  },
515
597
  wave: {
@@ -552,7 +634,7 @@ const groups = {
552
634
  htmlcs: {
553
635
  'w:AA.4_1_2.H91.A.NoHref': {
554
636
  quality: 1,
555
- what: 'Link misused as link destination'
637
+ what: 'Link is misused as a link destination'
556
638
  }
557
639
  }
558
640
  }
@@ -694,7 +776,7 @@ const groups = {
694
776
  axe: {
695
777
  'aria-required-parent': {
696
778
  quality: 1,
697
- what: 'Certain ARIA roles must be contained by particular parents'
779
+ what: 'ARIA role is not contained by a required parent'
698
780
  }
699
781
  }
700
782
  }
@@ -711,7 +793,7 @@ const groups = {
711
793
  axe: {
712
794
  'svg-img-alt': {
713
795
  quality: 1,
714
- what: 'SVG elements with an img role must have an alternative text'
796
+ what: 'SVG element with an img role has no text alternative'
715
797
  }
716
798
  }
717
799
  }
@@ -765,13 +847,13 @@ const groups = {
765
847
  alfa: {
766
848
  r68: {
767
849
  quality: 1,
768
- what: 'Element owns no elements as required by its semantic role'
850
+ what: 'Element does not own an element required by its semantic role'
769
851
  }
770
852
  },
771
853
  axe: {
772
854
  'aria-required-children': {
773
855
  quality: 1,
774
- what: 'Certain ARIA roles must contain particular children'
856
+ what: 'ARIA role does not contain a required child'
775
857
  }
776
858
  }
777
859
  }
@@ -793,7 +875,7 @@ const groups = {
793
875
  alfa: {
794
876
  r74: {
795
877
  quality: 1,
796
- what: 'Paragraph text has absolute font size'
878
+ what: 'Paragraph text has an absolute font size'
797
879
  }
798
880
  }
799
881
  }
@@ -801,6 +883,12 @@ const groups = {
801
883
  fontSmall: {
802
884
  weight: 3,
803
885
  packages: {
886
+ alfa: {
887
+ r75: {
888
+ quality: 1,
889
+ what: 'Font size is smaller than 9 pixels'
890
+ }
891
+ },
804
892
  tenon: {
805
893
  134: {
806
894
  quality: 1,
@@ -827,7 +915,7 @@ const groups = {
827
915
  axe: {
828
916
  'avoid-inline-spacing': {
829
917
  quality: 1,
830
- what: 'Inline text spacing must be adjustable with custom stylesheets'
918
+ what: 'Inline text spacing is not adjustable with a custom stylesheet'
831
919
  }
832
920
  }
833
921
  }
@@ -838,7 +926,7 @@ const groups = {
838
926
  alfa: {
839
927
  r80: {
840
928
  quality: 1,
841
- what: 'Paragraph text has absolute line height'
929
+ what: 'Paragraph text has an absolute line height'
842
930
  }
843
931
  }
844
932
  }
@@ -849,7 +937,7 @@ const groups = {
849
937
  alfa: {
850
938
  r73: {
851
939
  quality: 1,
852
- what: 'Paragraphs of text have insufficient line height'
940
+ what: 'Paragraph of text has insufficient line height'
853
941
  }
854
942
  }
855
943
  }
@@ -898,7 +986,7 @@ const groups = {
898
986
  htmlcs: {
899
987
  'e:AA.2_4_1.H64.1': {
900
988
  quality: 1,
901
- what: 'iframe element requires a non-empty title attribute'
989
+ what: 'iframe element has no non-empty title attribute'
902
990
  }
903
991
  },
904
992
  ibm: {
@@ -912,16 +1000,22 @@ const groups = {
912
1000
  roleBad: {
913
1001
  weight: 3,
914
1002
  packages: {
1003
+ alfa: {
1004
+ r21: {
1005
+ quality: 1,
1006
+ what: 'Element does not have a valid role'
1007
+ }
1008
+ },
915
1009
  axe: {
916
1010
  'aria-allowed-role': {
917
1011
  quality: 1,
918
- what: 'ARIA role should be appropriate for the element'
1012
+ what: 'ARIA role is not appropriate for the element'
919
1013
  }
920
1014
  },
921
1015
  ibm: {
922
1016
  'v:aria_semantics_role': {
923
1017
  quality: 1,
924
- what: 'ARIA roles must be valid for the element to which they are assigned'
1018
+ what: 'ARIA role is not valid for the element to which it is assigned'
925
1019
  }
926
1020
  },
927
1021
  testaro: {
@@ -938,13 +1032,13 @@ const groups = {
938
1032
  axe: {
939
1033
  'aria-required-attr': {
940
1034
  quality: 1,
941
- what: 'Required ARIA attributes must be provided'
1035
+ what: 'Required ARIA attribute is not provided'
942
1036
  }
943
1037
  },
944
1038
  ibm: {
945
1039
  'v:Rpt_Aria_RequiredProperties': {
946
1040
  quality: 1,
947
- what: 'ARIA role on an element must have required attributes'
1041
+ what: 'ARIA role on an element does not have a required attribute'
948
1042
  }
949
1043
  }
950
1044
  }
@@ -953,6 +1047,14 @@ const groups = {
953
1047
  weight: 4,
954
1048
  packages: {
955
1049
  alfa: {
1050
+ r18: {
1051
+ quality: 1,
1052
+ what: 'ARIA state or property is not allowed for the element on which it is specified'
1053
+ },
1054
+ r19: {
1055
+ quality: 1,
1056
+ what: 'ARIA state or property has an invalid value'
1057
+ },
956
1058
  r20: {
957
1059
  quality: 1,
958
1060
  what: 'ARIA attribute is not defined'
@@ -986,7 +1088,7 @@ const groups = {
986
1088
  ibm: {
987
1089
  'v:Rpt_Aria_ValidIdRef': {
988
1090
  quality: 1,
989
- what: 'ARIA property must reference non-empty unique id of visible element'
1091
+ what: 'ARIA property does not reference the non-empty unique id of a visible element'
990
1092
  }
991
1093
  },
992
1094
  wave: {
@@ -1020,7 +1122,7 @@ const groups = {
1020
1122
  axe: {
1021
1123
  'autocomplete-valid': {
1022
1124
  quality: 1,
1023
- what: 'Autocomplete attribute must be used correctly'
1125
+ what: 'Autocomplete attribute is used incorrectly'
1024
1126
  }
1025
1127
  },
1026
1128
  htmlcs: {
@@ -1032,7 +1134,18 @@ const groups = {
1032
1134
  ibm: {
1033
1135
  'v:WCAG21_Input_Autocomplete': {
1034
1136
  quality: 1,
1035
- what: 'Autocomplete attribute token(s) must be appropriate for the input form field'
1137
+ what: 'Autocomplete attribute token is not appropriate for the input form field'
1138
+ }
1139
+ }
1140
+ }
1141
+ },
1142
+ autocompleteRisk: {
1143
+ weight: 1,
1144
+ packages: {
1145
+ htmlcs: {
1146
+ 'w:AA.1_3_5.H98': {
1147
+ quality: 1,
1148
+ what: 'Element contains a potentially faulty value in its autocomplete attribute'
1036
1149
  }
1037
1150
  }
1038
1151
  }
@@ -1049,7 +1162,7 @@ const groups = {
1049
1162
  axe: {
1050
1163
  'color-contrast': {
1051
1164
  quality: 1,
1052
- what: 'Elements must have sufficient color contrast'
1165
+ what: 'Element has insufficient color contrast'
1053
1166
  }
1054
1167
  },
1055
1168
  htmlcs: {
@@ -1065,7 +1178,7 @@ const groups = {
1065
1178
  ibm: {
1066
1179
  'v:IBMA_Color_Contrast_WCAG2AA': {
1067
1180
  quality: 1,
1068
- what: 'Contrast ratio of text with background must meet WCAG 2.1 AA'
1181
+ what: 'Contrast ratio of text with background does not meet WCAG 2.1 AA'
1069
1182
  }
1070
1183
  },
1071
1184
  wave: {
@@ -1088,7 +1201,7 @@ const groups = {
1088
1201
  axe: {
1089
1202
  'color-contrast-enhanced': {
1090
1203
  quality: 1,
1091
- what: 'Elements must have sufficient color contrast (Level AAA)'
1204
+ what: 'Element has insufficient color contrast (Level AAA)'
1092
1205
  }
1093
1206
  },
1094
1207
  htmlcs: {
@@ -1168,7 +1281,7 @@ const groups = {
1168
1281
  ibm: {
1169
1282
  'v:RPT_Header_HasContent': {
1170
1283
  quality: 1,
1171
- what: 'Heading elements must provide descriptive text'
1284
+ what: 'Heading element provides no descriptive text'
1172
1285
  }
1173
1286
  },
1174
1287
  wave: {
@@ -1196,7 +1309,7 @@ const groups = {
1196
1309
  axe: {
1197
1310
  'image-redundant-alt': {
1198
1311
  quality: 1,
1199
- what: 'Text of buttons and links should not be repeated in the image alternative'
1312
+ what: 'Text of a button or link is repeated in the image alternative'
1200
1313
  }
1201
1314
  },
1202
1315
  ibm: {
@@ -1219,6 +1332,23 @@ const groups = {
1219
1332
  }
1220
1333
  }
1221
1334
  },
1335
+ decorativeTitle: {
1336
+ weight: 1,
1337
+ packages: {
1338
+ htmlcs: {
1339
+ 'e:AA.1_1_1.H67.1': {
1340
+ quality: 1,
1341
+ what: 'img element has an empty alt attribute but has a nonempty title attribute'
1342
+ }
1343
+ },
1344
+ wave: {
1345
+ 'a:image_title': {
1346
+ quality: 1,
1347
+ what: 'Image has a title attribute value but no alt value'
1348
+ }
1349
+ }
1350
+ }
1351
+ },
1222
1352
  titleRedundant: {
1223
1353
  weight: 1,
1224
1354
  packages: {
@@ -1254,10 +1384,22 @@ const groups = {
1254
1384
  pageTitle: {
1255
1385
  weight: 3,
1256
1386
  packages: {
1387
+ alfa: {
1388
+ r1: {
1389
+ quality: 1,
1390
+ what: 'Document has no valid title element'
1391
+ }
1392
+ },
1257
1393
  axe: {
1258
1394
  'document-title': {
1259
1395
  quality: 1,
1260
- what: 'Documents must contain a title element'
1396
+ what: 'Document contains no title element'
1397
+ }
1398
+ },
1399
+ htmlcs: {
1400
+ 'e:AA.2_4_2.H25.1.NoTitleEl': {
1401
+ quality: 1,
1402
+ what: 'Document head element contains no non-empty title element'
1261
1403
  }
1262
1404
  },
1263
1405
  wave: {
@@ -1280,7 +1422,7 @@ const groups = {
1280
1422
  axe: {
1281
1423
  'heading-order': {
1282
1424
  quality: 1,
1283
- what: 'Heading levels should only increase by one'
1425
+ what: 'Heading levels do not increase by only one'
1284
1426
  }
1285
1427
  },
1286
1428
  htmlcs: {
@@ -1292,7 +1434,7 @@ const groups = {
1292
1434
  tenon: {
1293
1435
  155: {
1294
1436
  quality: 1,
1295
- what: 'These headings are not structured in a hierarchical manner'
1437
+ what: 'Headings are not structured in a hierarchical manner'
1296
1438
  }
1297
1439
  },
1298
1440
  wave: {
@@ -1303,11 +1445,22 @@ const groups = {
1303
1445
  }
1304
1446
  }
1305
1447
  },
1448
+ noHeading: {
1449
+ weight: 3,
1450
+ packages: {
1451
+ alfa: {
1452
+ r59: {
1453
+ quality: 1,
1454
+ what: 'Document has no headings'
1455
+ }
1456
+ }
1457
+ }
1458
+ },
1306
1459
  h1Missing: {
1307
1460
  weight: 2,
1308
1461
  packages: {
1309
1462
  alfa: {
1310
- 'r61': {
1463
+ r61: {
1311
1464
  quality: 1,
1312
1465
  what: 'First heading is not h1'
1313
1466
  }
@@ -1315,7 +1468,7 @@ const groups = {
1315
1468
  axe: {
1316
1469
  'page-has-heading-one': {
1317
1470
  quality: 1,
1318
- what: 'Page should contain a level-one heading'
1471
+ what: 'Page contains no level-one heading'
1319
1472
  }
1320
1473
  },
1321
1474
  wave: {
@@ -1326,6 +1479,60 @@ const groups = {
1326
1479
  }
1327
1480
  }
1328
1481
  },
1482
+ justification: {
1483
+ weight: 1,
1484
+ packages: {
1485
+ alfa: {
1486
+ r71: {
1487
+ quality: 1,
1488
+ what: 'Paragraph text is fully justified'
1489
+ }
1490
+ },
1491
+ tenon: {
1492
+ 36: {
1493
+ quality: 1,
1494
+ what: 'Text is fully justified'
1495
+ }
1496
+ },
1497
+ wave: {
1498
+ 'a:text_justified': {
1499
+ quality: 1,
1500
+ what: 'Text is justified'
1501
+ }
1502
+ }
1503
+ }
1504
+ },
1505
+ nonSemanticText: {
1506
+ weight: 2,
1507
+ packages: {
1508
+ htmlcs: {
1509
+ 'w:AA.1_3_1.H49.AlignAttr': {
1510
+ quality: 1,
1511
+ what: 'Special text is aligned nonsemantically'
1512
+ },
1513
+ 'w:AA.1_3_1.H49.B': {
1514
+ quality: 1,
1515
+ what: 'Special text is bolded nonsemantically'
1516
+ },
1517
+ 'w:AA.1_3_1.H49.I': {
1518
+ quality: 1,
1519
+ what: 'Special text is italicized nonsemantically'
1520
+ },
1521
+ 'w:AA.1_3_1.H49.Big': {
1522
+ quality: 1,
1523
+ what: 'Special text is enlarged nonsemantically'
1524
+ },
1525
+ 'w:AA.1_3_1.H49.Small': {
1526
+ quality: 1,
1527
+ what: 'Special text is made small nonsemantically'
1528
+ },
1529
+ 'w:AA.1_3_1.H49.U': {
1530
+ quality: 1,
1531
+ what: 'Special text is underlined nonsemantically'
1532
+ }
1533
+ }
1534
+ }
1535
+ },
1329
1536
  pseudoParagraphRisk: {
1330
1537
  weight: 1,
1331
1538
  packages: {
@@ -1368,6 +1575,12 @@ const groups = {
1368
1575
  quality: 1,
1369
1576
  what: 'CSS underline on text that is not a link'
1370
1577
  }
1578
+ },
1579
+ wave: {
1580
+ 'a:underline': {
1581
+ quality: 1,
1582
+ what: 'CSS underline on text that is not a link'
1583
+ }
1371
1584
  }
1372
1585
  }
1373
1586
  },
@@ -1375,9 +1588,13 @@ const groups = {
1375
1588
  weight: 4,
1376
1589
  packages: {
1377
1590
  axe: {
1378
- 'list': {
1591
+ list: {
1379
1592
  quality: 1,
1380
1593
  what: 'List element ul or ol has a child element other than li, script, and template'
1594
+ },
1595
+ 'definition-list': {
1596
+ quality: 1,
1597
+ what: 'List element dl has a child element other than properly ordered dt and dt group, script, template, and div'
1381
1598
  }
1382
1599
  }
1383
1600
  }
@@ -1410,7 +1627,7 @@ const groups = {
1410
1627
  htmlcs: {
1411
1628
  'w:AA.1_3_1.H48': {
1412
1629
  quality: 1,
1413
- what: 'Navigation links should best be coded as a list'
1630
+ what: 'Navigation links are not coded as a list'
1414
1631
  }
1415
1632
  }
1416
1633
  }
@@ -1448,7 +1665,7 @@ const groups = {
1448
1665
  htmlcs: {
1449
1666
  'w:AA.1_3_1.H85.2': {
1450
1667
  quality: 1,
1451
- what: 'If selection list contains groups of related options, they should be grouped with optgroup'
1668
+ what: 'Selection list may contain groups of related options that are not grouped with optgroup'
1452
1669
  }
1453
1670
  }
1454
1671
  }
@@ -1459,7 +1676,7 @@ const groups = {
1459
1676
  ibm: {
1460
1677
  'v:WCAG20_Elem_UniqueAccessKey': {
1461
1678
  quality: 1,
1462
- what: 'Accesskey attribute values on each element must be unique for the page'
1679
+ what: 'Accesskey attribute value on an element is not unique for the page'
1463
1680
  }
1464
1681
  },
1465
1682
  wave: {
@@ -1493,6 +1710,17 @@ const groups = {
1493
1710
  }
1494
1711
  }
1495
1712
  },
1713
+ fieldSetRisk: {
1714
+ weight: 1,
1715
+ packages: {
1716
+ htmlcs: {
1717
+ 'w:AA.1_3_1.H71.SameName': {
1718
+ quality: 1,
1719
+ what: 'Radio buttons or check boxes may require a group description via a fieldset element'
1720
+ }
1721
+ }
1722
+ }
1723
+ },
1496
1724
  legendMissing: {
1497
1725
  weight: 2,
1498
1726
  packages: {
@@ -1527,6 +1755,17 @@ const groups = {
1527
1755
  }
1528
1756
  }
1529
1757
  },
1758
+ layoutTable: {
1759
+ weight: 2,
1760
+ packages: {
1761
+ wave: {
1762
+ 'a:table_layout': {
1763
+ quality: 1,
1764
+ what: 'Table element is misused to arrange content'
1765
+ }
1766
+ }
1767
+ }
1768
+ },
1530
1769
  tableCaption: {
1531
1770
  weight: 1,
1532
1771
  packages: {
@@ -1538,9 +1777,48 @@ const groups = {
1538
1777
  }
1539
1778
  }
1540
1779
  },
1541
- nameValue: {
1780
+ tableCellHeaderless: {
1781
+ weight: 4,
1782
+ packages: {
1783
+ alfa: {
1784
+ r77: {
1785
+ quality: 1,
1786
+ what: 'Table cell has no header'
1787
+ }
1788
+ }
1789
+ }
1790
+ },
1791
+ TableHeaderScopeRisk: {
1792
+ weight: 1,
1793
+ packages: {
1794
+ htmlcs: {
1795
+ 'e:AA.1_3_1.H63.1': {
1796
+ quality: 1,
1797
+ what: 'Not all th elements in the table have a scope attribute, so an inferred scope may be incorrect'
1798
+ }
1799
+ }
1800
+ }
1801
+ },
1802
+ tableHeaderEmpty: {
1803
+ weight: 2,
1804
+ packages: {
1805
+ wave: {
1806
+ 'e:th_empty': {
1807
+ quality: 1,
1808
+ what: 'th (table header) contains no text'
1809
+ }
1810
+ }
1811
+ }
1812
+ },
1813
+ controlLabel: {
1542
1814
  weight: 4,
1543
1815
  packages: {
1816
+ axe: {
1817
+ label: {
1818
+ quality: 1,
1819
+ what: 'Form element has no label'
1820
+ }
1821
+ },
1544
1822
  htmlcs: {
1545
1823
  'e:AA.1_3_1.F68': {
1546
1824
  quality: 1,
@@ -1555,6 +1833,17 @@ const groups = {
1555
1833
  }
1556
1834
  }
1557
1835
  },
1836
+ titleAsLabel: {
1837
+ weight: 3,
1838
+ packages: {
1839
+ wave: {
1840
+ 'a:label_title': {
1841
+ quality: 1,
1842
+ what: 'Form control has a title but no label'
1843
+ }
1844
+ }
1845
+ }
1846
+ },
1558
1847
  invisibleLabel: {
1559
1848
  weight: 3,
1560
1849
  packages: {
@@ -1603,10 +1892,16 @@ const groups = {
1603
1892
  activeEmbedding: {
1604
1893
  weight: 3,
1605
1894
  packages: {
1895
+ axe: {
1896
+ 'nested-interactive': {
1897
+ quality: 1,
1898
+ what: 'Interactive controls are nested'
1899
+ }
1900
+ },
1606
1901
  testaro: {
1607
1902
  embAc: {
1608
1903
  quality: 1,
1609
- what: 'Active elements embedded in links or buttons'
1904
+ what: 'Active element is embedded in a link or button'
1610
1905
  }
1611
1906
  }
1612
1907
  }
@@ -1659,6 +1954,12 @@ const groups = {
1659
1954
  allItalics: {
1660
1955
  weight: 1,
1661
1956
  packages: {
1957
+ alfa: {
1958
+ r85: {
1959
+ quality: 1,
1960
+ what: 'Text of the paragraph is all italic'
1961
+ }
1962
+ },
1662
1963
  tenon: {
1663
1964
  154: {
1664
1965
  quality: 1,
@@ -1667,6 +1968,17 @@ const groups = {
1667
1968
  }
1668
1969
  }
1669
1970
  },
1971
+ noLandmarks: {
1972
+ weight: 2,
1973
+ packages: {
1974
+ wave: {
1975
+ 'a:region_missing': {
1976
+ quality: 1,
1977
+ what: 'Page has no regions or ARIA landmarks'
1978
+ }
1979
+ }
1980
+ }
1981
+ },
1670
1982
  contentBeyondLandmarks: {
1671
1983
  weight: 2,
1672
1984
  packages: {
@@ -1732,6 +2044,17 @@ const groups = {
1732
2044
  }
1733
2045
  }
1734
2046
  },
2047
+ bannerLandmark: {
2048
+ weight: 2,
2049
+ packages: {
2050
+ axe: {
2051
+ 'landmark-no-duplicate-banner': {
2052
+ quality: 1,
2053
+ what: 'page has more than 1 banner landmark'
2054
+ }
2055
+ }
2056
+ }
2057
+ },
1735
2058
  footerMultiple: {
1736
2059
  weight: 2,
1737
2060
  packages: {
@@ -1789,6 +2112,31 @@ const groups = {
1789
2112
  'aria-hidden-focus': {
1790
2113
  quality: 1,
1791
2114
  what: 'ARIA hidden element is focusable or contains a focusable element'
2115
+ },
2116
+ 'presentation-role-conflict': {
2117
+ quality: 1,
2118
+ what: 'Element has a none/presentation role but is focusable or has a global ARIA state or property'
2119
+ }
2120
+ },
2121
+ tenon: {
2122
+ 189: {
2123
+ quality: 1,
2124
+ what: 'Element is typically used for interaction but has a presentation role'
2125
+ },
2126
+ 194: {
2127
+ quality: 1,
2128
+ what: 'Visible element is focusable but has a presentation role or aria-hidden=true attribute'
2129
+ }
2130
+ }
2131
+ }
2132
+ },
2133
+ focusableDescendants: {
2134
+ weight: 4,
2135
+ packages: {
2136
+ alfa: {
2137
+ r90: {
2138
+ quality: 1,
2139
+ what: 'Element has a role making its children presentational but contains a focusable element'
1792
2140
  }
1793
2141
  }
1794
2142
  }
@@ -1855,6 +2203,16 @@ const groups = {
1855
2203
  'w:AA.1_3_1.ARIA6': {
1856
2204
  quality: 1,
1857
2205
  what: 'Value of the aria-label attribute of the form control is empty or only whitespace'
2206
+ },
2207
+ 'w:AA.4_1_2.ARIA6': {
2208
+ quality: 1,
2209
+ what: 'Value of the aria-label attribute of the form control is empty or only whitespace'
2210
+ }
2211
+ },
2212
+ wave: {
2213
+ 'e:label_empty': {
2214
+ quality: 1,
2215
+ what: 'Empty form label'
1858
2216
  }
1859
2217
  }
1860
2218
  }
@@ -1915,6 +2273,17 @@ const groups = {
1915
2273
  }
1916
2274
  }
1917
2275
  },
2276
+ menuItemless: {
2277
+ weight: 4,
2278
+ packages: {
2279
+ wave: {
2280
+ 'e:aria_menu_broken': {
2281
+ quality: 1,
2282
+ what: 'ARIA menu does not contain required menu items'
2283
+ }
2284
+ }
2285
+ }
2286
+ },
1918
2287
  tabNavigation: {
1919
2288
  weight: 2,
1920
2289
  packages: {
@@ -2002,9 +2371,13 @@ const groups = {
2002
2371
  weight: 1,
2003
2372
  packages: {
2004
2373
  wave: {
2374
+ 'a:html5_video_audio': {
2375
+ quality: 1,
2376
+ what: 'video or audio element may have no or incorrect captions, transcript, or audio description'
2377
+ },
2005
2378
  'a:youtube_video': {
2006
2379
  quality: 1,
2007
- what: 'YouTube video may fail to be captioned'
2380
+ what: 'YouTube video may have no or incorrect captions'
2008
2381
  }
2009
2382
  }
2010
2383
  }
@@ -2050,6 +2423,18 @@ const groups = {
2050
2423
  quality: 0.5,
2051
2424
  what: 'First focusable element is not a link to the main content'
2052
2425
  }
2426
+ },
2427
+ axe: {
2428
+ 'skip-link': {
2429
+ quality: 1,
2430
+ what: 'Skip-link target is not focusable or does not exist'
2431
+ }
2432
+ },
2433
+ wave: {
2434
+ 'e:link_skip_broken': {
2435
+ quality: 1,
2436
+ what: 'Skip-navigation link has no target or is not keyboard accessible'
2437
+ }
2053
2438
  }
2054
2439
  }
2055
2440
  },
@@ -2064,6 +2449,17 @@ const groups = {
2064
2449
  }
2065
2450
  }
2066
2451
  },
2452
+ fragmentaryNoticeRisk: {
2453
+ weight: 2,
2454
+ packages: {
2455
+ alfa: {
2456
+ r54: {
2457
+ quality: 1,
2458
+ what: 'Assertive region is not atomic'
2459
+ }
2460
+ }
2461
+ }
2462
+ },
2067
2463
  noScriptRisk: {
2068
2464
  weight: 1,
2069
2465
  packages: {
@@ -2087,19 +2483,29 @@ const groups = {
2087
2483
  htmlcs: {
2088
2484
  'e:AA.1_3_1.H49.Center': {
2089
2485
  quality: 1,
2090
- what: 'Element is obsolete'
2486
+ what: 'center element is obsolete'
2487
+ },
2488
+ 'e:AA.1_3_1.H49.Font': {
2489
+ quality: 1,
2490
+ what: 'font element is obsolete'
2091
2491
  }
2092
2492
  }
2093
2493
  }
2094
2494
  },
2095
2495
  obsoleteAttribute: {
2096
- weight: 1,
2496
+ weight: 3,
2097
2497
  packages: {
2098
2498
  htmlcs: {
2099
2499
  'e:AA.1_3_1.H49.AlignAttr': {
2100
2500
  quality: 1,
2101
2501
  what: 'The align attribute is obsolete'
2102
2502
  }
2503
+ },
2504
+ wave: {
2505
+ 'a:longdesc': {
2506
+ quality: 1,
2507
+ what: 'The longdesc attribute is obsolete'
2508
+ }
2103
2509
  }
2104
2510
  }
2105
2511
  }