testilo 13.6.1 → 13.7.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,7 +1,7 @@
1
1
  {
2
2
  "name": "testilo",
3
- "version": "13.6.1",
4
- "description": "Client that scores and digests Testaro reports",
3
+ "version": "13.7.0",
4
+ "description": "Prepares and processes Testaro reports",
5
5
  "main": "aim.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -70,13 +70,13 @@ const populateQuery = (report, query) => {
70
70
  issueDetailRows.push(`<h4>Complaints by <code>${toolID}</code></h5>`);
71
71
  const ruleIDs = Object.keys(issueData.tools[toolID]);
72
72
  ruleIDs.forEach(ruleID => {
73
+ const ruleData = issueData.tools[toolID][ruleID];
73
74
  issueDetailRows.push(`<h5>Rule <code>${ruleID}</code></h5>`);
74
- issueDetailRows.push(
75
- `<p>Count of instances: ${issueData.tools[toolID][ruleID].complaints.countTotal}</p>`
76
- );
75
+ issueDetailRows.push(`<p>Description: ${ruleData.what}</p>`);
76
+ issueDetailRows.push(`<p>Count of instances: ${ruleData.complaints.countTotal}</p>`);
77
77
  issueDetailRows.push('<h6>Complaint specifics</h6>');
78
78
  issueDetailRows.push('<ul>');
79
- issueData.tools[toolID][ruleID].complaints.texts.forEach(text => {
79
+ ruleData.complaints.texts.forEach(text => {
80
80
  issueDetailRows.push(` <li>${htmlEscape(text || '')}</li>`);
81
81
  });
82
82
  issueDetailRows.push('</ul>');
@@ -52,6 +52,13 @@ exports.issueClasses = {
52
52
  wcag: '4.1.1',
53
53
  weight: 2,
54
54
  tools: {
55
+ nuVal: {
56
+ '^Duplicate attribute.*$': {
57
+ variable: true,
58
+ quality: 1,
59
+ what: 'Source code of the element contains 2 or more of the same attribute'
60
+ }
61
+ },
55
62
  testaro: {
56
63
  dupAtt: {
57
64
  variable: false,
@@ -140,6 +147,11 @@ exports.issueClasses = {
140
147
  variable: false,
141
148
  quality: 1,
142
149
  what: 'Interactive component has no programmatically associated name'
150
+ },
151
+ aria_widget_labelled: {
152
+ variable: false,
153
+ quality: 1,
154
+ what: 'Interactive component has no programmatically associated name'
143
155
  }
144
156
  }
145
157
  }
@@ -159,7 +171,7 @@ exports.issueClasses = {
159
171
  1010: {
160
172
  variable: false,
161
173
  quality: 1,
162
- what: 'Element with a region role has no mechanism that allows an accessible name to be calculated'
174
+ what: 'Element with a region role has no machanism allowing an accessible name to be calculated'
163
175
  }
164
176
  },
165
177
  ibm: {
@@ -167,6 +179,11 @@ exports.issueClasses = {
167
179
  variable: false,
168
180
  quality: 1,
169
181
  what: 'Element with a region role has no label that describes its purpose'
182
+ },
183
+ aria_region_labelled: {
184
+ variable: false,
185
+ quality: 1,
186
+ what: 'Element with a region role has no label'
170
187
  }
171
188
  }
172
189
  }
@@ -217,37 +234,42 @@ exports.issueClasses = {
217
234
  118: {
218
235
  variable: false,
219
236
  quality: 1,
220
- what: 'Text input element has no mechanism that allows an accessible name to be calculated'
237
+ what: 'Text input element has no machanism allowing an accessible name to be calculated'
221
238
  },
222
239
  370: {
223
240
  variable: false,
224
241
  quality: 1,
225
- what: 'Search input element has no mechanism that allows an accessible name to be calculated'
242
+ what: 'Search input element has no machanism allowing an accessible name to be calculated'
243
+ },
244
+ 372: {
245
+ variable: false,
246
+ quality: 1,
247
+ what: 'email input element has no machanism allowing an accessible name to be calculated'
226
248
  },
227
249
  375: {
228
250
  variable: false,
229
251
  quality: 1,
230
- what: 'input element with type="checkbox" has no mechanism that allows an accessible name to be calculated'
252
+ what: 'input element with type="checkbox" has no machanism allowing an accessible name to be calculated'
231
253
  },
232
254
  376: {
233
255
  variable: false,
234
256
  quality: 1,
235
- what: 'input element has no mechanism that allows an accessible name to be calculated'
257
+ what: 'input element has no machanism allowing an accessible name to be calculated'
236
258
  },
237
259
  507: {
238
260
  variable: false,
239
261
  quality: 1,
240
- what: 'element with a radio role has no mechanism that allows an accessible name to be calculated'
262
+ what: 'Element with a radio role has no machanism allowing an accessible name to be calculated'
241
263
  },
242
264
  509: {
243
265
  variable: false,
244
266
  quality: 1,
245
- what: 'element with a textbox role has no mechanism that allows an accessible name to be calculated'
267
+ what: 'Element with a textbox role has no machanism allowing an accessible name to be calculated'
246
268
  },
247
269
  510: {
248
270
  variable: false,
249
271
  quality: 1,
250
- what: 'element with a combobox role has no mechanism that allows an accessible name to be calculated'
272
+ what: 'Element with a combobox role has no machanism allowing an accessible name to be calculated'
251
273
  }
252
274
  },
253
275
  htmlcs: {
@@ -317,17 +339,10 @@ exports.issueClasses = {
317
339
  }
318
340
  }
319
341
  },
320
- imageInputNoText: {
342
+ imageButtonNoText: {
321
343
  wcag: '1.1.1',
322
344
  weight: 4,
323
345
  tools: {
324
- alfa: {
325
- r28: {
326
- variable: false,
327
- quality: 1,
328
- what: 'Image input element has no accessible name'
329
- }
330
- },
331
346
  axe: {
332
347
  'input-image-alt': {
333
348
  variable: false,
@@ -340,13 +355,11 @@ exports.issueClasses = {
340
355
  variable: false,
341
356
  quality: 1,
342
357
  what: 'Image submit button has no alt attribute'
343
- }
344
- },
345
- ibm: {
346
- WCAG20_Input_ExplicitLabelImage: {
358
+ },
359
+ 'AAA.1_1_1.H36': {
347
360
  variable: false,
348
361
  quality: 1,
349
- what: 'Input element of type image has no text alternative'
362
+ what: 'Image submit button has no alt attribute'
350
363
  }
351
364
  },
352
365
  qualWeb: {
@@ -370,6 +383,45 @@ exports.issueClasses = {
370
383
  }
371
384
  }
372
385
  },
386
+ imageInputNoText: {
387
+ wcag: '1.1.1',
388
+ weight: 4,
389
+ tools: {
390
+ alfa: {
391
+ r28: {
392
+ variable: false,
393
+ quality: 1,
394
+ what: 'image input element has no accessible name'
395
+ }
396
+ },
397
+ continuum: {
398
+ 131: {
399
+ variable: false,
400
+ quality: 1,
401
+ what: 'image input has no machanism allowing an accessible name to be calculated'
402
+ }
403
+ },
404
+ htmlcs: {
405
+ 'AAA.4_1_2.H91.InputImage.Name': {
406
+ variable: false,
407
+ quality: 1,
408
+ what: 'image input has no accessible name'
409
+ }
410
+ },
411
+ ibm: {
412
+ WCAG20_Input_ExplicitLabelImage: {
413
+ variable: false,
414
+ quality: 1,
415
+ what: 'input element of type image has no text alternative'
416
+ },
417
+ imagebutton_alt_exists: {
418
+ variable: false,
419
+ quality: 1,
420
+ what: 'input element of type image has no text alternative'
421
+ }
422
+ }
423
+ }
424
+ },
373
425
  figureNoText: {
374
426
  wcag: '1.1.1',
375
427
  weight: 4,
@@ -415,12 +467,12 @@ exports.issueClasses = {
415
467
  87: {
416
468
  variable: false,
417
469
  quality: 1,
418
- what: 'element with an image, graphics-symbol, or graphics-document role has no mechanism to calculate an accessible name'
470
+ what: 'Element with an image, graphics-symbol, or graphics-document role has no mechanism to calculate an accessible name'
419
471
  },
420
472
  89: {
421
473
  variable: false,
422
474
  quality: 1,
423
- what: 'img element has no mechanism that allows an accessible name to be calculated'
475
+ what: 'img element has no machanism allowing an accessible name to be calculated'
424
476
  }
425
477
  },
426
478
  htmlcs: {
@@ -450,6 +502,11 @@ exports.issueClasses = {
450
502
  variable: false,
451
503
  quality: 1,
452
504
  what: 'Image has neither an alt attribute nor an ARIA label or title'
505
+ },
506
+ img_alt_null: {
507
+ variable: false,
508
+ quality: 1,
509
+ what: 'Image has a title attribute but an empty alt attribute'
453
510
  }
454
511
  },
455
512
  nuVal: {
@@ -658,7 +715,7 @@ exports.issueClasses = {
658
715
  235: {
659
716
  variable: false,
660
717
  quality: 1,
661
- what: 'element with an img, graphics-symbol, or graphics-document role has a suspicious calculated accessible name'
718
+ what: 'Element with an img, graphics-symbol, or graphics-document role has a suspicious calculated accessible name'
662
719
  }
663
720
  },
664
721
  qualWeb: {
@@ -759,6 +816,11 @@ exports.issueClasses = {
759
816
  variable: false,
760
817
  quality: 1,
761
818
  what: 'Page detected as HTML, but has no lang attribute'
819
+ },
820
+ html_lang_exists: {
821
+ variable: false,
822
+ quality: 1,
823
+ what: 'Page detected as HTML, but has no lang attribute'
762
824
  }
763
825
  },
764
826
  nuVal: {
@@ -911,7 +973,7 @@ exports.issueClasses = {
911
973
  736: {
912
974
  variable: false,
913
975
  quality: 1,
914
- what: 'Element with a dialog role has no mechanism that allows an accessible name to be calculated'
976
+ what: 'Element with a dialog role has no machanism allowing an accessible name to be calculated'
915
977
  }
916
978
  }
917
979
  }
@@ -951,7 +1013,7 @@ exports.issueClasses = {
951
1013
  249: {
952
1014
  variable: false,
953
1015
  quality: 1,
954
- what: 'object element has no mechanism that allows an accessible name to be calculated'
1016
+ what: 'object element has no machanism allowing an accessible name to be calculated'
955
1017
  }
956
1018
  },
957
1019
  htmlcs: {
@@ -1005,7 +1067,7 @@ exports.issueClasses = {
1005
1067
  252: {
1006
1068
  variable: false,
1007
1069
  quality: 1,
1008
- what: 'video element has no mechanism that allows an accessible name to be calculated'
1070
+ what: 'video element has no machanism allowing an accessible name to be calculated'
1009
1071
  }
1010
1072
  }
1011
1073
  }
@@ -1277,6 +1339,11 @@ exports.issueClasses = {
1277
1339
  quality: 1,
1278
1340
  what: 'Text input or select element label follows the input control'
1279
1341
  },
1342
+ input_label_before: {
1343
+ variable: false,
1344
+ quality: 1,
1345
+ what: 'Label text is after its text input or select element'
1346
+ },
1280
1347
  WCAG20_Input_LabelAfter: {
1281
1348
  variable: false,
1282
1349
  quality: 1,
@@ -1305,7 +1372,7 @@ exports.issueClasses = {
1305
1372
  95: {
1306
1373
  variable: false,
1307
1374
  quality: 1,
1308
- what: 'element has an aria-labelledby value that includes an invalid or duplicate id'
1375
+ what: 'Element has an aria-labelledby value that includes an invalid or duplicate id'
1309
1376
  }
1310
1377
  },
1311
1378
  htmlcs: {
@@ -1406,7 +1473,12 @@ exports.issueClasses = {
1406
1473
  237: {
1407
1474
  variable: false,
1408
1475
  quality: 1,
1409
- what: 'a element has no mechanism that allows an accessible name value to be calculated'
1476
+ what: 'a element has no machanism allowing an accessible name value to be calculated'
1477
+ },
1478
+ 238: {
1479
+ variable: false,
1480
+ quality: 1,
1481
+ what: 'Element with a link role has no machanism allowing an accessible name value to be calculated'
1410
1482
  }
1411
1483
  },
1412
1484
  htmlcs: {
@@ -1836,17 +1908,17 @@ exports.issueClasses = {
1836
1908
  116: {
1837
1909
  variable: false,
1838
1910
  quality: 1,
1839
- what: 'input element with type=button has no mechanism that allows an accessible name to be calculated'
1911
+ what: 'input element with type=button has no machanism allowing an accessible name to be calculated'
1840
1912
  },
1841
1913
  224: {
1842
1914
  variable: false,
1843
1915
  quality: 1,
1844
- what: 'button element has no mechanism that allows an accessible name to be calculated'
1916
+ what: 'button element has no machanism allowing an accessible name to be calculated'
1845
1917
  },
1846
1918
  511: {
1847
1919
  variable: false,
1848
1920
  quality: 1,
1849
- what: 'Element with a button role has no mechanism that allows an accessible name to be calculated'
1921
+ what: 'Element with a button role has no machanism allowing an accessible name to be calculated'
1850
1922
  }
1851
1923
  },
1852
1924
  htmlcs: {
@@ -1912,14 +1984,14 @@ exports.issueClasses = {
1912
1984
  r94: {
1913
1985
  variable: false,
1914
1986
  quality: 1,
1915
- what: 'element with a menuitem role has no accessible name'
1987
+ what: 'Element with a menuitem role has no accessible name'
1916
1988
  }
1917
1989
  },
1918
1990
  qualWeb: {
1919
1991
  'QW-ACT-R66': {
1920
1992
  variable: false,
1921
1993
  quality: 1,
1922
- what: 'Menuitem has no non-empty accessible name'
1994
+ what: 'menuitem element has no non-empty accessible name'
1923
1995
  }
1924
1996
  }
1925
1997
  }
@@ -2027,7 +2099,7 @@ exports.issueClasses = {
2027
2099
  123: {
2028
2100
  variable: false,
2029
2101
  quality: 1,
2030
- what: 'svg element has no mechanism that allows an accessible name to be calculated'
2102
+ what: 'svg element has no machanism allowing an accessible name to be calculated'
2031
2103
  }
2032
2104
  },
2033
2105
  qualWeb: {
@@ -2080,7 +2152,7 @@ exports.issueClasses = {
2080
2152
  r47: {
2081
2153
  variable: false,
2082
2154
  quality: 1,
2083
- what: 'Meta element restricts zooming'
2155
+ what: 'meta element restricts zooming'
2084
2156
  }
2085
2157
  },
2086
2158
  axe: {
@@ -2393,7 +2465,7 @@ exports.issueClasses = {
2393
2465
  '^Bad value .+ for attribute .+ on element meta.*$': {
2394
2466
  variable: true,
2395
2467
  quality: 1,
2396
- what: 'attribute of a meta element has an invalid value'
2468
+ what: 'Attribute of a meta element has an invalid value'
2397
2469
  }
2398
2470
  }
2399
2471
  }
@@ -2456,7 +2528,7 @@ exports.issueClasses = {
2456
2528
  228: {
2457
2529
  variable: false,
2458
2530
  quality: 1,
2459
- what: 'iframe has no mechanism that allows an accessible name to be calculated'
2531
+ what: 'iframe has no machanism allowing an accessible name to be calculated'
2460
2532
  }
2461
2533
  },
2462
2534
  htmlcs: {
@@ -2471,6 +2543,11 @@ exports.issueClasses = {
2471
2543
  variable: false,
2472
2544
  quality: 1,
2473
2545
  what: 'Inline frame has an empty or nonunique title attribute'
2546
+ },
2547
+ frame_title_exists: {
2548
+ variable: false,
2549
+ quality: 1,
2550
+ what: 'Inline frame has no title attribute'
2474
2551
  }
2475
2552
  },
2476
2553
  qualWeb: {
@@ -2496,6 +2573,11 @@ exports.issueClasses = {
2496
2573
  variable: false,
2497
2574
  quality: 1,
2498
2575
  what: 'Element does not have a valid role'
2576
+ },
2577
+ r110: {
2578
+ variable: false,
2579
+ quality: 1,
2580
+ what: 'No token in the value of the role attribute is valid'
2499
2581
  }
2500
2582
  },
2501
2583
  axe: {
@@ -2569,7 +2651,7 @@ exports.issueClasses = {
2569
2651
  412: {
2570
2652
  variable: false,
2571
2653
  quality: 1,
2572
- what: 'element has a role attribute set to an invalid ARIA role value'
2654
+ what: 'Element has a role attribute set to an invalid ARIA role value'
2573
2655
  }
2574
2656
  },
2575
2657
  ibm: {
@@ -2603,6 +2685,11 @@ exports.issueClasses = {
2603
2685
  quality: 1,
2604
2686
  what: 'Element has an invalid role'
2605
2687
  },
2688
+ aria_role_allowed: {
2689
+ variable: false,
2690
+ quality: 1,
2691
+ what: 'Element has an invalid role'
2692
+ },
2606
2693
  aria_eventhandler_role_valid: {
2607
2694
  variable: false,
2608
2695
  quality: 1,
@@ -2711,6 +2798,11 @@ exports.issueClasses = {
2711
2798
  variable: false,
2712
2799
  quality: 1,
2713
2800
  what: 'ARIA attribute is invalid for the role of its element'
2801
+ },
2802
+ aria_attribute_value_valid: {
2803
+ variable: false,
2804
+ quality: 1,
2805
+ what: 'Value of an attribute on the element is not valid'
2714
2806
  }
2715
2807
  },
2716
2808
  nuVal: {
@@ -2727,17 +2819,17 @@ exports.issueClasses = {
2727
2819
  '^Attribute .+ not allowed on element .+ at this point.*$': {
2728
2820
  variable: true,
2729
2821
  quality: 1,
2730
- what: 'attribute not allowed on this element'
2822
+ what: 'Attribute not allowed on this element'
2731
2823
  },
2732
2824
  '^Bad value .* for attribute .+ on element .+$': {
2733
2825
  variable: true,
2734
2826
  quality: 1,
2735
- what: 'attribute on this element has an invalid value'
2827
+ what: 'Attribute on this element has an invalid value'
2736
2828
  },
2737
2829
  '^Bad value .+ for the attribute .+$': {
2738
2830
  variable: true,
2739
2831
  quality: 1,
2740
- what: 'attribute has an invalid value'
2832
+ what: 'Attribute has an invalid value'
2741
2833
  },
2742
2834
  '^Attribute .+ not allowed here.*$': {
2743
2835
  variable: true,
@@ -2769,20 +2861,30 @@ exports.issueClasses = {
2769
2861
  quality: 1,
2770
2862
  what: 'link element has a sizes attribute but no icon-type rel attribute'
2771
2863
  },
2864
+ 'An input element with a type attribute whose value is hidden must not have any aria-* attributes.': {
2865
+ variable: false,
2866
+ quality: 1,
2867
+ what: 'hidden-type input element has an ARIA attribute'
2868
+ },
2772
2869
  'The sizes attribute may be specified only if the srcset attribute is also present.': {
2773
2870
  variable: false,
2774
2871
  quality: 1,
2775
- what: 'element has a sizes attribute but no srcset attribute'
2872
+ what: 'Element has a sizes attribute but no srcset attribute'
2873
+ },
2874
+ 'The sizes attribute must only be specified if the srcset attribute is also specified.': {
2875
+ variable: false,
2876
+ quality: 1,
2877
+ what: 'Element has a sizes attribute but no srcset attribute'
2776
2878
  },
2777
2879
  '^Bad value for attribute (?:width|height) on element img: The empty string is not a valid non-negative integer.*$': {
2778
2880
  variable: true,
2779
2881
  quality: 1,
2780
- what: 'attribute has an empty value'
2882
+ what: 'Attribute has an empty value'
2781
2883
  },
2782
2884
  '^.+ in an unquoted attribute value. Probable causes: Attributes running together or a URL query string in an unquoted attribute value.*$': {
2783
2885
  variable: true,
2784
2886
  quality: 1,
2785
- what: 'attribute has a value containing invalid punctuation'
2887
+ what: 'Attribute has a value containing invalid punctuation'
2786
2888
  }
2787
2889
  }
2788
2890
  }
@@ -3006,12 +3108,12 @@ exports.issueClasses = {
3006
3108
  279: {
3007
3109
  variable: false,
3008
3110
  quality: 1,
3009
- what: 'element has an aria-posinset attribute without having a compatible role'
3111
+ what: 'Element has an aria-posinset attribute without having a compatible role'
3010
3112
  },
3011
3113
  280: {
3012
3114
  variable: false,
3013
3115
  quality: 1,
3014
- what: 'element has aria-posinset and aria-setsize attributes without having a compatible role'
3116
+ what: 'Element has aria-posinset and aria-setsize attributes without having a compatible role'
3015
3117
  },
3016
3118
  281: {
3017
3119
  variable: false,
@@ -3051,7 +3153,7 @@ exports.issueClasses = {
3051
3153
  610: {
3052
3154
  variable: false,
3053
3155
  quality: 1,
3054
- what: 'element has an aria-setsize attribute without having a compatible role'
3156
+ what: 'Element has an aria-setsize attribute without having a compatible role'
3055
3157
  },
3056
3158
  1066: {
3057
3159
  variable: false,
@@ -3090,17 +3192,17 @@ exports.issueClasses = {
3090
3192
  'Attribute aria-activedescendant value should either refer to a descendant element, or should be accompanied by attribute aria-owns.': {
3091
3193
  variable: false,
3092
3194
  quality: 1,
3093
- what: 'element has no aria-owns attribute but its aria-activedescendant attribute references a non-descendant'
3195
+ what: 'Element has no aria-owns attribute but its aria-activedescendant attribute references a non-descendant'
3094
3196
  },
3095
3197
  '^Bad value for attribute .+ on element .+: Must be non-empty.*$': {
3096
3198
  variable: true,
3097
3199
  quality: 1,
3098
- what: 'attribute value is empty'
3200
+ what: 'Attribute value is empty'
3099
3201
  },
3100
3202
  '^Bad value for attribute aria-hidden on element .+$': {
3101
3203
  variable: true,
3102
3204
  quality: 1,
3103
- what: 'attribute aria-hidden has an empty value'
3205
+ what: 'aria-hidden attribute has an empty value'
3104
3206
  },
3105
3207
  'The form attribute must refer to a form element.': {
3106
3208
  variable: false,
@@ -3110,7 +3212,12 @@ exports.issueClasses = {
3110
3212
  'The aria-checked attribute should not be used on an input element which has a type attribute whose value is checkbox.': {
3111
3213
  variable: false,
3112
3214
  quality: 1,
3113
- what: 'input element with type="checkbox" has an aria-checked attribute'
3215
+ what: 'input element with type checkbox has an aria-checked attribute'
3216
+ },
3217
+ 'The aria-checked attribute must not be used on an input element which has a type attribute whose value is checkbox.': {
3218
+ variable: false,
3219
+ quality: 1,
3220
+ what: 'input element with type checkbox has an aria-checked attribute'
3114
3221
  },
3115
3222
  'An img element with no alt attribute must not have any aria-* attributes other than aria-hidden.': {
3116
3223
  variable: false,
@@ -3224,6 +3331,11 @@ exports.issueClasses = {
3224
3331
  variable: false,
3225
3332
  quality: 1,
3226
3333
  what: 'autocomplete attribute token is not appropriate for the input form field'
3334
+ },
3335
+ input_autocomplete_valid: {
3336
+ variable: false,
3337
+ quality: 1,
3338
+ what: 'autocomplete attribute has an incorrect value'
3227
3339
  }
3228
3340
  },
3229
3341
  nuVal: {
@@ -3847,7 +3959,7 @@ exports.issueClasses = {
3847
3959
  71: {
3848
3960
  variable: false,
3849
3961
  quality: 1,
3850
- what: 'element with a heading role has no aria-level attribute'
3962
+ what: 'Element with a heading role has no aria-level attribute'
3851
3963
  }
3852
3964
  }
3853
3965
  }
@@ -4182,7 +4294,14 @@ exports.issueClasses = {
4182
4294
  'Element dl is missing a required child element.': {
4183
4295
  variable: false,
4184
4296
  quality: 1,
4185
- what: 'dl element has no child element.'
4297
+ what: 'dl element has no child element'
4298
+ }
4299
+ },
4300
+ qualWeb: {
4301
+ 'QW-BP24': {
4302
+ variable: false,
4303
+ quality: 1,
4304
+ what: 'ul or ol element has a child other than li, script, or template'
4186
4305
  }
4187
4306
  }
4188
4307
  }
@@ -4280,7 +4399,7 @@ exports.issueClasses = {
4280
4399
  114: {
4281
4400
  variable: false,
4282
4401
  quality: 1,
4283
- what: 'select element has no mechanism that allows an accessible name to be calculated'
4402
+ what: 'select element has no machanism allowing an accessible name to be calculated'
4284
4403
  }
4285
4404
  },
4286
4405
  htmlcs: {
@@ -4386,6 +4505,11 @@ exports.issueClasses = {
4386
4505
  variable: false,
4387
4506
  quality: 1,
4388
4507
  what: 'Input is in a different group than another with the name'
4508
+ },
4509
+ input_checkboxes_grouped: {
4510
+ variable: false,
4511
+ quality: 1,
4512
+ what: 'checkbox input is not grouped with others with the same name'
4389
4513
  }
4390
4514
  },
4391
4515
  testaro: {
@@ -4438,7 +4562,7 @@ exports.issueClasses = {
4438
4562
  221: {
4439
4563
  variable: false,
4440
4564
  quality: 1,
4441
- what: 'Element with a radiogroup role has no mechanism that allows an accessible name to be calculated'
4565
+ what: 'Element with a radiogroup role has no machanism allowing an accessible name to be calculated'
4442
4566
  }
4443
4567
  },
4444
4568
  htmlcs: {
@@ -5197,6 +5321,18 @@ exports.issueClasses = {
5197
5321
  quality: 1,
5198
5322
  what: 'complementary landmark (aside) is contained in another landmark'
5199
5323
  }
5324
+ },
5325
+ qualWeb: {
5326
+ 'QW-BP25': {
5327
+ variable: false,
5328
+ quality: 1,
5329
+ what: 'complementary landmark is not at the top level'
5330
+ },
5331
+ 'QW-BP26': {
5332
+ variable: false,
5333
+ quality: 1,
5334
+ what: 'complementary landmark is not at the top level'
5335
+ }
5200
5336
  }
5201
5337
  }
5202
5338
  },
@@ -5210,6 +5346,13 @@ exports.issueClasses = {
5210
5346
  quality: 1,
5211
5347
  what: 'main landmark is contained in another landmark'
5212
5348
  }
5349
+ },
5350
+ qualWeb: {
5351
+ 'QW-BP27': {
5352
+ variable: false,
5353
+ quality: 1,
5354
+ what: 'main landmark is not at the top level'
5355
+ }
5213
5356
  }
5214
5357
  }
5215
5358
  },
@@ -5294,6 +5437,11 @@ exports.issueClasses = {
5294
5437
  variable: false,
5295
5438
  quality: 1,
5296
5439
  what: 'Multiple elements with a banner role are on the page'
5440
+ },
5441
+ aria_banner_single: {
5442
+ variable: false,
5443
+ quality: 1,
5444
+ what: 'More than one element with a banner role is on the page'
5297
5445
  }
5298
5446
  },
5299
5447
  qualWeb: {
@@ -5334,6 +5482,11 @@ exports.issueClasses = {
5334
5482
  variable: false,
5335
5483
  quality: 1,
5336
5484
  what: 'Element with a contentinfo role has no unique purpose label among the contentinfo-role elements'
5485
+ },
5486
+ aria_contentinfo_label_unique: {
5487
+ variable: false,
5488
+ quality: 1,
5489
+ what: 'Multiple elements with a contentinfo role have no unique labels'
5337
5490
  }
5338
5491
  }
5339
5492
  }
@@ -5354,6 +5507,18 @@ exports.issueClasses = {
5354
5507
  variable: false,
5355
5508
  quality: 1,
5356
5509
  what: 'Page, document, or application has more than one element with a contentinfo role'
5510
+ },
5511
+ aria_contentinfo_single: {
5512
+ variable: false,
5513
+ quality: 1,
5514
+ what: 'Multiple elements with a contentinfo role are on the page'
5515
+ }
5516
+ },
5517
+ qualWeb: {
5518
+ 'QW-BP21': {
5519
+ variable: false,
5520
+ quality: 0.5,
5521
+ what: 'There are multiple contentinfo or banner landmarks'
5357
5522
  }
5358
5523
  }
5359
5524
  }
@@ -5443,6 +5608,11 @@ exports.issueClasses = {
5443
5608
  variable: false,
5444
5609
  quality: 1,
5445
5610
  what: 'Element with a complementary role has no unique purpose label among the complementary-role elements'
5611
+ },
5612
+ aria_complementary_label_unique: {
5613
+ variable: false,
5614
+ quality: 1,
5615
+ what: 'Multiple elements with a complementary role have no unique labels'
5446
5616
  }
5447
5617
  }
5448
5618
  }
@@ -5456,6 +5626,11 @@ exports.issueClasses = {
5456
5626
  variable: false,
5457
5627
  quality: 1,
5458
5628
  what: 'Element with a banner role has no unique purpose label among the banner-role elements'
5629
+ },
5630
+ aria_banner_label_unique: {
5631
+ variable: false,
5632
+ quality: 1,
5633
+ what: 'Multiple elements with a banner role have no unique labels'
5459
5634
  }
5460
5635
  }
5461
5636
  }
@@ -5542,12 +5717,22 @@ exports.issueClasses = {
5542
5717
  Rpt_Aria_ComplementaryRequiredLabel_Implicit: {
5543
5718
  variable: false,
5544
5719
  quality: 1,
5545
- what: 'Element has a complementary role but has no label'
5720
+ what: 'Element with a complementary role has no label'
5721
+ },
5722
+ aria_complementary_labelled: {
5723
+ variable: false,
5724
+ quality: 1,
5725
+ what: 'Element with a complementary role has no label'
5546
5726
  },
5547
5727
  Rpt_Aria_ComplementaryLandmarkLabel_Implicit: {
5548
5728
  variable: false,
5549
5729
  quality: 1,
5550
5730
  what: 'Element with a complementary role has no visible purpose label'
5731
+ },
5732
+ aria_complementary_label_visible: {
5733
+ variable: false,
5734
+ quality: 1,
5735
+ what: 'Element with a complementary role has no visible label'
5551
5736
  }
5552
5737
  }
5553
5738
  }
@@ -5836,6 +6021,11 @@ exports.issueClasses = {
5836
6021
  variable: false,
5837
6022
  quality: 1,
5838
6023
  what: 'Form control does not have exactly one label'
6024
+ },
6025
+ form_label_unique: {
6026
+ variable: false,
6027
+ quality: 1,
6028
+ what: 'Form control has more than one label'
5839
6029
  }
5840
6030
  },
5841
6031
  wave: {
@@ -6473,6 +6663,11 @@ exports.issueClasses = {
6473
6663
  variable: false,
6474
6664
  quality: 0.5,
6475
6665
  what: 'Page provides no way to skip directly to the main content'
6666
+ },
6667
+ skip_main_exists: {
6668
+ variable: false,
6669
+ quality: 0.5,
6670
+ what: 'Page provides no way to quickly navigate to the main content'
6476
6671
  }
6477
6672
  },
6478
6673
  qualWeb: {
@@ -6736,6 +6931,16 @@ exports.issueClasses = {
6736
6931
  weight: 3,
6737
6932
  tools: {
6738
6933
  nuVal: {
6934
+ 'CSS: z-index: This number should be an integer.': {
6935
+ variable: false,
6936
+ quality: 1,
6937
+ what: 'z-index style property has a non-integer value'
6938
+ },
6939
+ '^CSS: .+: Character .+ is neither a decimal digit number.*$': {
6940
+ variable: true,
6941
+ quality: 1,
6942
+ what: 'Nonnumeric character in a numeric style property'
6943
+ },
6739
6944
  'CSS: Parse Error. Style sheets should not include HTML syntax.': {
6740
6945
  variable: false,
6741
6946
  quality: 1,
@@ -6894,6 +7099,11 @@ exports.issueClasses = {
6894
7099
  quality: 1,
6895
7100
  what: 'Element is closed while an element within it is unclosed'
6896
7101
  },
7102
+ '^End tag .+ implied, but there were open elements.*$': {
7103
+ variable: true,
7104
+ quality: 1,
7105
+ what: 'Element is implicitly closed while an element within it is unclosed'
7106
+ },
6897
7107
  '^Unclosed element .+$': {
6898
7108
  variable: true,
6899
7109
  quality: 1,
@@ -6937,11 +7147,26 @@ exports.issueClasses = {
6937
7147
  }
6938
7148
  },
6939
7149
  nuVal: {
6940
- 'No space between attributes.': {
7150
+ 'End tag clippath did not match the name of the current open element (path).': {
6941
7151
  variable: false,
6942
7152
  quality: 1,
7153
+ what: 'End tag clippath conflicts with the current open element.'
7154
+ },
7155
+ '^Self-closing syntax .+ used on a non-void HTML element.*$': {
7156
+ variable: true,
7157
+ quality: 1,
7158
+ what: 'Self-closing syntax used on a non-void element'
7159
+ },
7160
+ 'No space between attributes.': {
7161
+ variable: true,
7162
+ quality: 1,
6943
7163
  what: 'No space between attributes'
6944
7164
  },
7165
+ '^Bad value [^\ufffd]+ Tab, new line or carriage return found.*$': {
7166
+ variable: true,
7167
+ quality: 1,
7168
+ what: 'Attribute value contains an illegal spacing character'
7169
+ },
6945
7170
  'Saw <?. Probable cause: Attempt to use an XML processing instruction in HTML. (XML processing instructions are not supported in HTML.)': {
6946
7171
  variable: false,
6947
7172
  quality: 1,
@@ -7070,7 +7295,7 @@ exports.issueClasses = {
7070
7295
  'When the srcset attribute has any image candidate string with a width descriptor, the sizes attribute must also be present.': {
7071
7296
  variable: false,
7072
7297
  quality: 1,
7073
- what: 'element with a srcset attribute with a width has no sizes attribute'
7298
+ what: 'Element with a srcset attribute with a width has no sizes attribute'
7074
7299
  },
7075
7300
  '^The text content of element .+ was not in the required format: Expected .+ but found .+ instead.*$': {
7076
7301
  variable: true,
@@ -120,8 +120,10 @@ exports.scorer = report => {
120
120
  details.issue[issueID].tools[which] = {};
121
121
  }
122
122
  if (! details.issue[issueID].tools[which][ruleID]) {
123
+ const ruleData = issueClasses[issueID].tools[which][ruleID];
123
124
  details.issue[issueID].tools[which][ruleID] = {
124
- quality: issueClasses[issueID].tools[which][ruleID].quality,
125
+ quality: ruleData.quality,
126
+ what: ruleData.what,
125
127
  complaints: {
126
128
  countTotal: 0,
127
129
  texts: []
@@ -172,7 +174,7 @@ exports.scorer = report => {
172
174
  }
173
175
  });
174
176
  // Get the score for the issue.
175
- issueData.score = issueData.weight * issueData.maxCount;
177
+ issueData.score = Math.round(issueData.weight * issueData.maxCount);
176
178
  });
177
179
  // Add the severity detail totals to the score.
178
180
  details.severity.total = Object.keys(details.severity.byTool).reduce((severityTotals, toolID) => {
@@ -195,18 +197,20 @@ exports.scorer = report => {
195
197
  );
196
198
  // Add the summary log score to the score.
197
199
  const {jobData} = report;
198
- summary.log = Math.max(0, Math.round(
199
- logWeights.logCount * jobData.logCount
200
- + logWeights.logSize * jobData.logSize +
201
- + logWeights.errorLogCount * jobData.errorLogCount
202
- + logWeights.errorLogSize * jobData.errorLogSize
203
- + logWeights.prohibitedCount * jobData.prohibitedCount +
204
- + logWeights.visitRejectionCount * jobData.visitRejectionCount
205
- ));
206
- // Add the summary latency score to the score.
207
- summary.latency = Math.round(
208
- latencyWeight * (Math.max(0, jobData.visitLatency - normalLatency))
209
- );
200
+ if (jobData) {
201
+ summary.log = Math.max(0, Math.round(
202
+ logWeights.logCount * jobData.logCount
203
+ + logWeights.logSize * jobData.logSize +
204
+ + logWeights.errorLogCount * jobData.errorLogCount
205
+ + logWeights.errorLogSize * jobData.errorLogSize
206
+ + logWeights.prohibitedCount * jobData.prohibitedCount +
207
+ + logWeights.visitRejectionCount * jobData.visitRejectionCount
208
+ ));
209
+ // Add the summary latency score to the score.
210
+ summary.latency = Math.round(
211
+ latencyWeight * (Math.max(0, jobData.visitLatency - normalLatency))
212
+ );
213
+ }
210
214
  // Round the unrounded scores.
211
215
  Object.keys(summary).forEach(summaryTypeName => {
212
216
  summary[summaryTypeName] = Math.round(summary[summaryTypeName]);