testilo 17.0.0 → 17.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testilo",
3
- "version": "17.0.0",
3
+ "version": "17.0.1",
4
4
  "description": "Prepares and processes Testaro reports",
5
5
  "main": "aim.js",
6
6
  "scripts": {
@@ -0,0 +1,69 @@
1
+ /*
2
+ coverage.js
3
+ Checks coverage of Testaro tests in an issue classification.
4
+ */
5
+
6
+ // Returns a tabulation of the instance counts of issues reported by tools in scored reports.
7
+ const coverage = ticID => {
8
+ const evalRules = {
9
+ allCaps: 'leaf elements with entirely upper-case text longer than 7 characters',
10
+ allHidden: 'page that is entirely or mostly hidden',
11
+ allSlanted: 'leaf elements with entirely italic or oblique text longer than 39 characters',
12
+ autocomplete: 'name and email inputs without autocomplete attributes',
13
+ bulk: 'large count of visible elements',
14
+ buttonMenu: 'nonstandard keyboard navigation between items of button-controlled menus',
15
+ captionLoc: 'caption elements that are not first children of table elements',
16
+ distortion: 'distorted text',
17
+ docType: 'document without a doctype property',
18
+ dupAtt: 'elements with duplicate attributes',
19
+ embAc: 'active elements embedded in links or buttons',
20
+ filter: 'filter styles on elements',
21
+ focAll: 'discrepancies between focusable and Tab-focused elements',
22
+ focInd: 'missing and nonstandard focus indicators',
23
+ focOp: 'Tab-focusable elements that are not operable',
24
+ focVis: 'links that are invisible when focused',
25
+ headEl: 'invalid elements within the head',
26
+ headingAmb: 'same-level sibling headings with identical texts',
27
+ hover: 'hover-caused content changes',
28
+ hovInd: 'hover indication nonstandard',
29
+ hr: 'hr element instead of styles used for vertical segmentation',
30
+ labClash: 'labeling inconsistencies',
31
+ legendLoc: 'legend elements that are not first children of fieldset elements',
32
+ lineHeight: 'text with a line height less than 1.5 times its font size',
33
+ linkExt: 'links that automatically open new windows',
34
+ linkAmb: 'links with identical texts but different destinations',
35
+ linkOldAtt: 'links with deprecated attributes',
36
+ linkTitle: 'links with title attributes repeating text content',
37
+ linkTo: 'links without destinations',
38
+ linkUl: 'missing underlines on inline links',
39
+ miniText: 'text smaller than 11 pixels',
40
+ motion: 'motion without user request',
41
+ nonTable: 'table elements used for layout',
42
+ opFoc: 'Operable elements that are not Tab-focusable',
43
+ optRoleSel: 'Non-option elements with option roles that have no aria-selected attributes',
44
+ phOnly: 'input elements with placeholders but no accessible names',
45
+ pseudoP: 'adjacent br elements suspected of nonsemantically simulating p elements',
46
+ radioSet: 'radio buttons not grouped into standard field sets',
47
+ role: 'invalid and native-replacing explicit roles',
48
+ styleDiff: 'style inconsistencies',
49
+ tabNav: 'nonstandard keyboard navigation between elements with the tab role',
50
+ targetSize: 'buttons, inputs, and non-inline links smaller than 44 pixels wide and high',
51
+ titledEl: 'title attributes on inappropriate elements',
52
+ zIndex: 'non-default Z indexes'
53
+ };
54
+ const {issues} = require(`${__dirname}/../score/${ticID}`);
55
+ const testaroRuleIDs = new Set();
56
+ Object.values(issues).forEach(issue => {
57
+ if (issue.tools && issue.tools.testaro) {
58
+ Object.keys(issue.tools.testaro).forEach(ruleID => {
59
+ testaroRuleIDs.add(ruleID);
60
+ });
61
+ }
62
+ });
63
+ Object.keys(evalRules).forEach(ruleID => {
64
+ if (! testaroRuleIDs.has(ruleID)) {
65
+ console.log(`${ticID} is missing ${ruleID}`);
66
+ }
67
+ });
68
+ };
69
+ coverage('tic35');
@@ -17,7 +17,7 @@ exports.credit = reports => {
17
17
  // If it is valid:
18
18
  if (report.score && report.score.details && report.score.details.issue) {
19
19
  // For each issue:
20
- const issues = report.score.details.issue;
20
+ const issues = report.score.details && report.score.details.issue;
21
21
  Object.keys(issues).forEach(issueID => {
22
22
  // For each tool with any complaints about it:
23
23
  if (! counts[issueID]) {
@@ -28,19 +28,29 @@ exports.credit = reports => {
28
28
  Object.keys(issueTools).forEach(toolID => {
29
29
  // For each rule cited by any of those complaints:
30
30
  if (! counts[issueID][toolID]) {
31
- counts[issueID][toolID] = 0;
31
+ counts[issueID][toolID] = {
32
+ total: 0,
33
+ rules: {}
34
+ };
32
35
  }
33
36
  Object.keys(issueTools[toolID]).forEach(ruleID => {
34
37
  // If an instance count was recorded:
35
38
  const {complaints} = issueTools[toolID][ruleID];
36
39
  if (complaints && complaints.countTotal) {
37
40
  // Add it to the tally.
38
- counts[issueID][toolID] += complaints.countTotal;
41
+ counts[issueID][toolID].total += complaints.countTotal;
42
+ // Add a rule itemization to the tally.
43
+ if (! counts[issueID][toolID].rules[ruleID]) {
44
+ counts[issueID][toolID].rules[ruleID] = 0;
45
+ }
46
+ counts[issueID][toolID].rules[ruleID] += complaints.countTotal;
39
47
  }
40
48
  // Otherwise, i.e. if no instance count was recorded:
41
49
  else {
42
50
  // Report this.
43
- console.log(`ERROR: Missing countTotal for ${toolID} in ${issueID}`);
51
+ console.log(
52
+ `ERROR: Report ${report.id} missing countTotal for ${toolID} in ${issueID}`
53
+ );
44
54
  }
45
55
  });
46
56
  });
@@ -69,9 +79,9 @@ exports.credit = reports => {
69
79
  // Add the tools with the maximum instance count to the tally.
70
80
  const maxCount = Object
71
81
  .values(counts[issueID])
72
- .reduce((max, current) => Math.max(max, current));
82
+ .reduce((max, current) => Math.max(max, current ? current.total : 0), 0);
73
83
  Object.keys(counts[issueID]).forEach(toolID => {
74
- if (counts[issueID][toolID] === maxCount) {
84
+ if (maxCount && counts[issueID][toolID].total === maxCount) {
75
85
  if (! mosts[issueID]) {
76
86
  mosts[issueID] = [];
77
87
  }
@@ -354,7 +354,7 @@ exports.issues = {
354
354
  863: {
355
355
  variable: false,
356
356
  quality: 1,
357
- what: 'input has an accessible name that depends on a placeholder'
357
+ what: 'input element has an accessible name that depends on a placeholder'
358
358
  }
359
359
  }
360
360
  }
@@ -1,9 +1,8 @@
1
1
  /*
2
2
  tic35
3
- CONTINUUM NOT YET REMOVED
4
3
  Testilo issue classification 35
5
4
 
6
- Classifies approximately 650 rules of the tools of Testaro into 256 issues.
5
+ Classifies about 650 rules of the tools of Testaro into 256 issues.
7
6
 
8
7
  Issue properties:
9
8
  why: expected impact
@@ -351,11 +350,11 @@ exports.issues = {
351
350
  wcag: '4.1.2',
352
351
  weight: 3,
353
352
  tools: {
354
- continuum: {
355
- 863: {
353
+ testaro: {
354
+ phOnly: {
356
355
  variable: false,
357
356
  quality: 1,
358
- what: 'input element has an accessible name that depends on a placeholder'
357
+ what: 'input element has a placeholder but no accessible name'
359
358
  }
360
359
  }
361
360
  }
@@ -1365,8 +1364,8 @@ exports.issues = {
1365
1364
  wcag: '1.3.1',
1366
1365
  weight: 4,
1367
1366
  tools: {
1368
- continuum: {
1369
- 83: {
1367
+ testaro: {
1368
+ adbBadID: {
1370
1369
  variable: false,
1371
1370
  quality: 1,
1372
1371
  what: 'aria-describedby attribute references an invalid or duplicate ID'
@@ -1678,13 +1677,6 @@ exports.issues = {
1678
1677
  wcag: '1.3.1',
1679
1678
  weight: 4,
1680
1679
  tools: {
1681
- continuum: {
1682
- 872: {
1683
- variable: false,
1684
- quality: 1,
1685
- what: 'textarea element has no accessible name, but only a placeholder attribute'
1686
- }
1687
- },
1688
1680
  htmlcs: {
1689
1681
  'AAA.4_1_2.H91.Textarea.Name': {
1690
1682
  variable: false,
@@ -2081,13 +2073,6 @@ exports.issues = {
2081
2073
  what: 'svg element with an img role has no text alternative'
2082
2074
  }
2083
2075
  },
2084
- continuum: {
2085
- 123: {
2086
- variable: false,
2087
- quality: 1,
2088
- what: 'svg element has no machanism allowing an accessible name to be calculated'
2089
- }
2090
- },
2091
2076
  qualWeb: {
2092
2077
  'QW-ACT-R21': {
2093
2078
  variable: false,
@@ -2961,28 +2946,6 @@ exports.issues = {
2961
2946
  what: 'Element does not have all required states and properties'
2962
2947
  }
2963
2948
  },
2964
- continuum: {
2965
- 1039: {
2966
- variable: false,
2967
- quality: 1,
2968
- what: 'Element with a checkbox role has no aria-checked attribute'
2969
- },
2970
- 1040: {
2971
- variable: false,
2972
- quality: 1,
2973
- what: 'Element with a combobox role has no aria-controls or no aria-expanded attribute'
2974
- },
2975
- 1042: {
2976
- variable: false,
2977
- quality: 1,
2978
- what: 'Element with an option role has no aria-selected attribute'
2979
- },
2980
- 1043: {
2981
- variable: false,
2982
- quality: 1,
2983
- what: 'Element with a radio role has no aria-checked attribute'
2984
- }
2985
- },
2986
2949
  nuVal: {
2987
2950
  '^Element .+ is missing required attribute aria-.+$': {
2988
2951
  variable: true,
@@ -2999,6 +2962,20 @@ exports.issues = {
2999
2962
  }
3000
2963
  }
3001
2964
  },
2965
+ ariaMissingRisk: {
2966
+ why: 'Item may behave improperly',
2967
+ wcag: '4.1.2',
2968
+ weight: 2,
2969
+ tools: {
2970
+ testaro: {
2971
+ optRoleSel: {
2972
+ variable: false,
2973
+ quality: 1,
2974
+ what: 'Non-option element with an explicit option role has no aria-selected attribute'
2975
+ }
2976
+ }
2977
+ }
2978
+ },
3002
2979
  ariaAttributeBad: {
3003
2980
  why: 'Item behavior violates user expectations',
3004
2981
  wcag: '4.1.2',
@@ -3043,108 +3020,6 @@ exports.issues = {
3043
3020
  what: 'aria-roledescription is on an element with no semantic role'
3044
3021
  }
3045
3022
  },
3046
- continuum: {
3047
- 16: {
3048
- variable: false,
3049
- quality: 1,
3050
- what: 'Element has an aria-multiline attribute, which is not allowed'
3051
- },
3052
- 38: {
3053
- variable: false,
3054
- quality: 1,
3055
- what: 'Element has an aria-pressed attribute, which is not allowed'
3056
- },
3057
- 64: {
3058
- variable: false,
3059
- quality: 1,
3060
- what: 'Element has an aria-valuemax attribute that is not set to an integer'
3061
- },
3062
- 257: {
3063
- variable: false,
3064
- quality: 1,
3065
- what: 'Element has an aria-checked attribute, which is not allowed'
3066
- },
3067
- 260: {
3068
- variable: false,
3069
- quality: 1,
3070
- what: 'Element has an aria-level attribute, which is not allowed'
3071
- },
3072
- 261: {
3073
- variable: false,
3074
- quality: 1,
3075
- what: 'Element has an aria-multiselectable attribute, which is not allowed'
3076
- },
3077
- 264: {
3078
- variable: false,
3079
- quality: 1,
3080
- what: 'Element has an aria-selected attribute, which is not allowed'
3081
- },
3082
- 270: {
3083
- variable: false,
3084
- quality: 1,
3085
- what: 'Element has an aria-required attribute, which is not allowed'
3086
- },
3087
- 278: {
3088
- variable: false,
3089
- quality: 1,
3090
- what: 'Element has an aria-modal attribute, which is not allowed'
3091
- },
3092
- 279: {
3093
- variable: false,
3094
- quality: 1,
3095
- what: 'Element has an aria-posinset attribute without having a compatible role'
3096
- },
3097
- 280: {
3098
- variable: false,
3099
- quality: 1,
3100
- what: 'Element has aria-posinset and aria-setsize attributes without having a compatible role'
3101
- },
3102
- 281: {
3103
- variable: false,
3104
- quality: 1,
3105
- what: 'Element has an aria-expanded attribute, which is not allowed'
3106
- },
3107
- 282: {
3108
- variable: false,
3109
- quality: 1,
3110
- what: 'Element has an aria-autocomplete attribute, which is not allowed'
3111
- },
3112
- 283: {
3113
- variable: false,
3114
- quality: 1,
3115
- what: 'Element has an aria-activedescendant attribute, which is not allowed'
3116
- },
3117
- 331: {
3118
- variable: false,
3119
- quality: 1,
3120
- what: 'Element has an aria-owns attribute set to a non-null value'
3121
- },
3122
- 333: {
3123
- variable: false,
3124
- quality: 1,
3125
- what: 'Element with a textbox role has an aria-owns attribute, which is not allowed'
3126
- },
3127
- 334: {
3128
- variable: false,
3129
- quality: 1,
3130
- what: 'Element with a searchbox role has an aria-owns attribute, which is not allowed'
3131
- },
3132
- 609: {
3133
- variable: false,
3134
- quality: 1,
3135
- what: 'Element has an aria-setsize attribute but has no aria-posinset attribute'
3136
- },
3137
- 610: {
3138
- variable: false,
3139
- quality: 1,
3140
- what: 'Element has an aria-setsize attribute without having a compatible role'
3141
- },
3142
- 1066: {
3143
- variable: false,
3144
- quality: 1,
3145
- what: 'Element has an ARIA attribute which is not valid'
3146
- }
3147
- },
3148
3023
  ibm: {
3149
3024
  aria_semantics_attribute: {
3150
3025
  variable: false,
@@ -4336,18 +4211,6 @@ exports.issues = {
4336
4211
  quality: 1,
4337
4212
  what: 'li element is not contained by a ul or ol element'
4338
4213
  }
4339
- },
4340
- continuum: {
4341
- 99: {
4342
- variable: false,
4343
- quality: 1,
4344
- what: 'li element has no ul, ol, or list-role parent'
4345
- },
4346
- 385: {
4347
- variable: false,
4348
- quality: 1,
4349
- what: 'list item has no ul, ol, or list-role parent or owner'
4350
- }
4351
4214
  }
4352
4215
  }
4353
4216
  },
@@ -4583,8 +4446,8 @@ exports.issues = {
4583
4446
  wcag: '4.1.2',
4584
4447
  weight: 4,
4585
4448
  tools: {
4586
- continuum: {
4587
- 738: {
4449
+ testaro: {
4450
+ legendLoc: {
4588
4451
  variable: false,
4589
4452
  quality: 1,
4590
4453
  what: 'legend element is not the first child of its fieldset element'
@@ -4766,6 +4629,20 @@ exports.issues = {
4766
4629
  }
4767
4630
  }
4768
4631
  },
4632
+ tableCaptionLoc: {
4633
+ why: 'User cannot get help on the topic of a table',
4634
+ wcag: '1.3.1',
4635
+ weight: 3,
4636
+ tools: {
4637
+ testaro: {
4638
+ captionLoc: {
4639
+ variable: false,
4640
+ quality: 1,
4641
+ what: 'caption element is not the first child of a table element'
4642
+ }
4643
+ }
4644
+ }
4645
+ },
4769
4646
  cellHeadersNotInferrable: {
4770
4647
  why: 'User cannot get help on relationships in a table',
4771
4648
  wcag: '1.3.1',
@@ -4775,7 +4652,7 @@ exports.issues = {
4775
4652
  'AAA.1_3_1.H43.HeadersRequired': {
4776
4653
  variable: false,
4777
4654
  quality: 1,
4778
- what: 'Complex table requires headers attributes of cells'
4655
+ what: 'Complex table is missing headers attributes of cells'
4779
4656
  }
4780
4657
  },
4781
4658
  ibm: {
@@ -5752,18 +5629,6 @@ exports.issues = {
5752
5629
  wcag: '1.3.6',
5753
5630
  weight: 3,
5754
5631
  tools: {
5755
- continuum: {
5756
- 531: {
5757
- variable: false,
5758
- quality: 1,
5759
- what: 'nav element has an accessible name that is non-unique among the nav elements'
5760
- },
5761
- 533: {
5762
- variable: false,
5763
- quality: 1,
5764
- what: 'nav element is not the only nav element but has no accessible name'
5765
- }
5766
- },
5767
5632
  ibm: {
5768
5633
  Rpt_Aria_MultipleNavigationLandmarks_Implicit: {
5769
5634
  variable: false,
@@ -5884,7 +5749,7 @@ exports.issues = {
5884
5749
  weight: 4,
5885
5750
  tools: {
5886
5751
  testaro: {
5887
- focOp: {
5752
+ opFoc: {
5888
5753
  variable: false,
5889
5754
  quality: 1,
5890
5755
  what: 'Operable element is not Tab-focusable'
@@ -6207,8 +6072,8 @@ exports.issues = {
6207
6072
  wcag: '1.3.3',
6208
6073
  weight: 1,
6209
6074
  tools: {
6210
- continuum: {
6211
- 141: {
6075
+ testaro: {
6076
+ imageLink: {
6212
6077
  variable: false,
6213
6078
  quality: 1,
6214
6079
  what: 'a element has an href attribute set to an image file reference'
@@ -6445,7 +6310,7 @@ exports.issues = {
6445
6310
  weight: 1,
6446
6311
  tools: {
6447
6312
  testaro: {
6448
- filterStyle: {
6313
+ filter: {
6449
6314
  variable: false,
6450
6315
  quality: 1,
6451
6316
  what: 'Element styles include filter'
@@ -7034,6 +6899,13 @@ exports.issues = {
7034
6899
  what: 'HTML element is used to control the visual presentation of content'
7035
6900
  }
7036
6901
  },
6902
+ testaro: {
6903
+ linkOldAtt: {
6904
+ variable: false,
6905
+ quality: 1,
6906
+ what: 'a element has a deprecated attribute'
6907
+ }
6908
+ },
7037
6909
  wave: {
7038
6910
  longdesc: {
7039
6911
  variable: false,