@jrpool/kilotest 46.0.2 → 46.0.4

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/openapi.yaml CHANGED
@@ -254,9 +254,9 @@ paths:
254
254
  type: object
255
255
  properties:
256
256
  name:
257
- anyOf:
258
- - type: string
259
- - type: 'null'
257
+ type:
258
+ - string
259
+ - 'null'
260
260
  reason for failure:
261
261
  description: Copied verbatim from the Testaro report; shape may vary.
262
262
  required:
@@ -266,9 +266,9 @@ paths:
266
266
  names of rule engines that reported rule violations:
267
267
  type: array
268
268
  items:
269
- anyOf:
270
- - type: string
271
- - type: 'null'
269
+ type:
270
+ - string
271
+ - 'null'
272
272
  counts of issues by priority:
273
273
  type: object
274
274
  properties:
@@ -782,9 +782,9 @@ paths:
782
782
  type: object
783
783
  properties:
784
784
  size of the report in bytes:
785
- anyOf:
786
- - type: number
787
- - type: string
785
+ type:
786
+ - number
787
+ - string
788
788
  full report:
789
789
  description: The full raw Testaro/Testilo report JSON, copied verbatim, or an error object if it could not be retrieved.
790
790
  required:
@@ -1224,9 +1224,9 @@ components:
1224
1224
  type: string
1225
1225
  description: URL of the equivalent web UI page for this request.
1226
1226
  closest ancestor request:
1227
- anyOf:
1228
- - type: string
1229
- - type: 'null'
1227
+ type:
1228
+ - string
1229
+ - 'null'
1230
1230
  required:
1231
1231
  - this request
1232
1232
  - closest ancestor request
@@ -1290,13 +1290,13 @@ components:
1290
1290
  identifier:
1291
1291
  type: string
1292
1292
  name:
1293
- anyOf:
1294
- - type: string
1295
- - type: 'null'
1293
+ type:
1294
+ - string
1295
+ - 'null'
1296
1296
  sponsor:
1297
- anyOf:
1298
- - type: string
1299
- - type: 'null'
1297
+ type:
1298
+ - string
1299
+ - 'null'
1300
1300
  required:
1301
1301
  - identifier
1302
1302
  - name
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jrpool/kilotest",
3
- "version": "46.0.2",
3
+ "version": "46.0.4",
4
4
  "description": "Ensemble testing for front-end web quality",
5
5
  "main": "index.js",
6
6
  "engines": {
@@ -0,0 +1,245 @@
1
+ /*
2
+ buildFixtures.js
3
+ Builds the fixture corpus for Kilotest tests.
4
+
5
+ Each fixture is a minimal Testaro report in the current format, crafted so that the expected API response can be hand-computed and hard-coded into tests. The fixtures collectively cover the `outcome` property values (`failed`, `cantTell`, and missing/undefined), superseded reports, empty reports, and prevented rule engines.
6
+
7
+ Run with: node test/fixtures/buildFixtures.js [targetDir]
8
+ */
9
+
10
+ // IMPORTS
11
+
12
+ const fs = require('fs/promises');
13
+ const path = require('path');
14
+
15
+ // CONSTANTS
16
+
17
+ // Issue IDs with known specs in testaro-issues, chosen for different weights.
18
+ // weight 4 (highest)
19
+ const issueLinkNoText = 'linkNoText';
20
+ // weight 4
21
+ const issueFocusIndication = 'focusIndicationBad';
22
+ // weight 1 (lowest)
23
+ const issueAllCaps = 'allCaps';
24
+
25
+ // Rule engine IDs that exist in util.js ruleEngines.
26
+ const engineAxe = 'axe';
27
+ const engineAlfa = 'alfa';
28
+ const engineIbm = 'ibm';
29
+
30
+ // FUNCTIONS
31
+
32
+ // Returns a minimal catalog item.
33
+ const catalogItem = (tagName, text, pathID = '/html', boxID = '0:0:100:50') => ({
34
+ tagName,
35
+ id: '',
36
+ startTag: `<${tagName.toLowerCase()}>`,
37
+ text,
38
+ textLinkable: false,
39
+ boxID,
40
+ pathID,
41
+ headingIndex: '',
42
+ checkpoint: 0
43
+ });
44
+
45
+ // Returns a minimal standard instance.
46
+ const instance = (
47
+ ruleID, what, outcome, issueID, catalogIndex, ordinalSeverity = 2, count = 1
48
+ ) => ({
49
+ ruleID,
50
+ what,
51
+ ordinalSeverity,
52
+ outcome,
53
+ count,
54
+ catalogIndex: String(catalogIndex),
55
+ checkpoint: 0,
56
+ issueID
57
+ });
58
+
59
+ // Returns a minimal test act.
60
+ const testAct = (which, instances) => ({
61
+ type: 'test',
62
+ which,
63
+ startTime: '26-01-01T00:00',
64
+ endTime: '26-01-01T00:01',
65
+ result: {
66
+ standardResult: {
67
+ instances,
68
+ outcomeTotals: {
69
+ failed: instances.filter(i => i.outcome === 'failed').length,
70
+ cantTell: instances.filter(i => i.outcome === 'cantTell').length
71
+ }
72
+ }
73
+ }
74
+ });
75
+
76
+ // Returns a minimal valid report.
77
+ const report = (id, what, url, acts, catalog, endTime = '26-01-01T00:10') => ({
78
+ id,
79
+ what,
80
+ strict: false,
81
+ standard: 'only',
82
+ device: {id: 'default'},
83
+ browserID: 'chromium',
84
+ creationTimeStamp: id.slice(0, 11),
85
+ executionTimeStamp: id.slice(0, 11),
86
+ target: {what, url},
87
+ sources: {worker: 'test-worker'},
88
+ acts,
89
+ jobData: {
90
+ startTime: '26-01-01T00:00',
91
+ endTime,
92
+ elapsedSeconds: 600,
93
+ preventions: {},
94
+ issuelessRules: []
95
+ },
96
+ catalog,
97
+ images: {},
98
+ checkpoints: []
99
+ });
100
+
101
+ // Writes a JSON file with a trailing newline.
102
+ const writeJSON = async (filePath, object) => {
103
+ await fs.writeFile(filePath, `${JSON.stringify(object, null, 2)}\n`);
104
+ };
105
+
106
+ // MAIN
107
+
108
+ const main = async () => {
109
+ const targetDir = process.argv[2] || path.join(__dirname, 'db');
110
+ const reportsDir = path.join(targetDir, 'reports');
111
+ await fs.mkdir(reportsDir, {recursive: true});
112
+ await fs.mkdir(path.join(targetDir, 'jobs', 'queue'), {recursive: true});
113
+ await fs.mkdir(path.join(targetDir, 'jobs', 'claimed'), {recursive: true});
114
+ await fs.mkdir(path.join(targetDir, 'jobs', 'failed'), {recursive: true});
115
+ await fs.mkdir(path.join(targetDir, 'hiddenReports'), {recursive: true});
116
+
117
+ // Fixture 1: mixedOutcomes. Two rule engines, four instances: two failed (same issue, same violator, two engines), one cantTell (excluded from counts), one failed (different issue, different violator). Two distinct issues (linkNoText weight 4, allCaps weight 1) and two distinct violator catalog indexes (0 and 1).
118
+ const mixedCatalog = {
119
+ '0': catalogItem('A', 'About Us', '/html/body/a[1]', '10:20:80:30'),
120
+ '1': catalogItem('P', 'ALL ABOUT US', '/html/body/p[1]', '10:60:80:20')
121
+ };
122
+ const mixedActs = [
123
+ testAct(engineAxe, [
124
+ instance('r11', 'The link does not have an accessible name', 'failed',
125
+ issueLinkNoText, 0, 2, 1),
126
+ instance('r65', 'Focus Visible', 'cantTell',
127
+ issueFocusIndication, 0, 0, 1)
128
+ ]),
129
+ testAct(engineAlfa, [
130
+ instance('r11', 'The link does not have an accessible name', 'failed',
131
+ issueLinkNoText, 0, 2, 1),
132
+ instance('r3', 'Text is all-capital', 'failed',
133
+ issueAllCaps, 1, 1, 1)
134
+ ])
135
+ ];
136
+ await writeJSON(
137
+ path.join(reportsDir, '260101T0000-mix.json'),
138
+ report('260101T0000-mix', 'Mixed Outcomes Page',
139
+ 'https://example.com/mixed', mixedActs, mixedCatalog)
140
+ );
141
+
142
+ // Fixture 2: allCantTell. All instances have outcome cantTell, so no issues or violators should be reported by listIssues, listViolators, or listDiagnoses.
143
+ const cantTellCatalog = {
144
+ '0': catalogItem('A', 'Click here', '/html/body/a[1]', '5:10:60:20')
145
+ };
146
+ const cantTellActs = [
147
+ testAct(engineAxe, [
148
+ instance('r65', 'Focus Visible', 'cantTell',
149
+ issueFocusIndication, 0, 0, 1)
150
+ ])
151
+ ];
152
+ await writeJSON(
153
+ path.join(reportsDir, '260101T0001-ct.json'),
154
+ report('260101T0001-ct', 'All CantTell Page',
155
+ 'https://example.com/canttell', cantTellActs, cantTellCatalog)
156
+ );
157
+
158
+ // Fixture 3: noOutcomes. Instances with no outcome property. Testaro defaults to 'failed', but Kilotest code checks `outcome !== 'cantTell'`, so missing outcome (undefined) is treated as a violation. This verifies that behavior.
159
+ const noOutcomeCatalog = {
160
+ '0': catalogItem('BUTTON', 'Submit', '/html/body/button[1]', '15:25:70:30')
161
+ };
162
+ const noOutcomeActs = [
163
+ testAct(engineIbm, [
164
+ {
165
+ ruleID: 'r1',
166
+ what: 'Button has no accessible name',
167
+ ordinalSeverity: 3,
168
+ count: 1,
169
+ catalogIndex: '0',
170
+ checkpoint: 0,
171
+ issueID: issueLinkNoText
172
+ }
173
+ ])
174
+ ];
175
+ await writeJSON(
176
+ path.join(reportsDir, '260101T0002-no.json'),
177
+ report('260101T0002-no', 'No Outcomes Page',
178
+ 'https://example.com/nooutcomes', noOutcomeActs, noOutcomeCatalog)
179
+ );
180
+
181
+ // Fixture 4: superseded. A report about the same page as mixedOutcomes but with a later timestamp, so mixedOutcomes is superseded by this one.
182
+ const newerActs = [
183
+ testAct(engineAxe, [
184
+ instance('r11', 'The link does not have an accessible name', 'failed',
185
+ issueLinkNoText, 0, 2, 1)
186
+ ])
187
+ ];
188
+ await writeJSON(
189
+ path.join(reportsDir, '260202T0000-new.json'),
190
+ report('260202T0000-new', 'Mixed Outcomes Page',
191
+ 'https://example.com/mixed', newerActs, mixedCatalog, '26-02-02T00:10')
192
+ );
193
+
194
+ // Fixture 5: empty. A valid report with no test acts that have instances, so listIssues returns zero issues.
195
+ await writeJSON(
196
+ path.join(reportsDir, '260101T0005-emp.json'),
197
+ report('260101T0005-emp', 'Empty Results Page',
198
+ 'https://example.com/empty', [testAct(engineAxe, [])], {})
199
+ );
200
+
201
+ // Fixture 6: prevented. A report where one rule engine was prevented from testing.
202
+ const preventedCatalog = {
203
+ '0': catalogItem('IMG', 'An image', '/html/body/img[1]', '0:0:200:100')
204
+ };
205
+ const preventedActs = [
206
+ testAct(engineAxe, [
207
+ instance('r11', 'The image has no alt text', 'failed',
208
+ issueLinkNoText, 0, 2, 1)
209
+ ])
210
+ ];
211
+ const preventedReport = report('260101T0006-prv', 'Prevented Page',
212
+ 'https://example.com/prevented', preventedActs, preventedCatalog);
213
+ preventedReport.jobData.preventions = {alfa: 'page timed out'};
214
+ await writeJSON(
215
+ path.join(reportsDir, '260101T0006-prv.json'),
216
+ preventedReport
217
+ );
218
+
219
+ // Fixture 7: hidden. A report placed in hiddenReports/ instead of reports/, so it must not appear in listReports, listIssues, listViolators, listDiagnoses, or getReport API responses. The reportsExtract must not include it.
220
+ const hiddenCatalog = {
221
+ '0': catalogItem('A', 'Secret link', '/html/body/a[1]', '5:10:60:20')
222
+ };
223
+ const hiddenActs = [
224
+ testAct(engineAxe, [
225
+ instance('r11', 'The link does not have an accessible name', 'failed',
226
+ issueLinkNoText, 0, 2, 1)
227
+ ])
228
+ ];
229
+ const hiddenReport = report('260101T0007-hid', 'Hidden Page',
230
+ 'https://example.com/hidden', hiddenActs, hiddenCatalog);
231
+ await writeJSON(
232
+ path.join(targetDir, 'hiddenReports', '260101T0007-hid.json'),
233
+ hiddenReport
234
+ );
235
+
236
+ // Write an empty recs.json so getRecs does not try to create one.
237
+ await writeJSON(path.join(targetDir, 'jobs', 'recs.json'), {});
238
+
239
+ console.log(`Fixtures built in ${targetDir}`);
240
+ };
241
+
242
+ main().catch(error => {
243
+ console.error(error);
244
+ process.exit(1);
245
+ });
@@ -0,0 +1,69 @@
1
+ {
2
+ "id": "260101T0007-hid",
3
+ "what": "Hidden Page",
4
+ "strict": false,
5
+ "standard": "only",
6
+ "device": {
7
+ "id": "default"
8
+ },
9
+ "browserID": "chromium",
10
+ "creationTimeStamp": "260101T0007",
11
+ "executionTimeStamp": "260101T0007",
12
+ "target": {
13
+ "what": "Hidden Page",
14
+ "url": "https://example.com/hidden"
15
+ },
16
+ "sources": {
17
+ "worker": "test-worker"
18
+ },
19
+ "acts": [
20
+ {
21
+ "type": "test",
22
+ "which": "axe",
23
+ "startTime": "26-01-01T00:00",
24
+ "endTime": "26-01-01T00:01",
25
+ "result": {
26
+ "standardResult": {
27
+ "instances": [
28
+ {
29
+ "ruleID": "r11",
30
+ "what": "The link does not have an accessible name",
31
+ "ordinalSeverity": 2,
32
+ "outcome": "failed",
33
+ "count": 1,
34
+ "catalogIndex": "0",
35
+ "checkpoint": 0,
36
+ "issueID": "linkNoText"
37
+ }
38
+ ],
39
+ "outcomeTotals": {
40
+ "failed": 1,
41
+ "cantTell": 0
42
+ }
43
+ }
44
+ }
45
+ }
46
+ ],
47
+ "jobData": {
48
+ "startTime": "26-01-01T00:00",
49
+ "endTime": "26-01-01T00:10",
50
+ "elapsedSeconds": 600,
51
+ "preventions": {},
52
+ "issuelessRules": []
53
+ },
54
+ "catalog": {
55
+ "0": {
56
+ "tagName": "A",
57
+ "id": "",
58
+ "startTag": "<a>",
59
+ "text": "Secret link",
60
+ "textLinkable": false,
61
+ "boxID": "5:10:60:20",
62
+ "pathID": "/html/body/a[1]",
63
+ "headingIndex": "",
64
+ "checkpoint": 0
65
+ }
66
+ },
67
+ "images": {},
68
+ "checkpoints": []
69
+ }
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,126 @@
1
+ {
2
+ "id": "260101T0000-mix",
3
+ "what": "Mixed Outcomes Page",
4
+ "strict": false,
5
+ "standard": "only",
6
+ "device": {
7
+ "id": "default"
8
+ },
9
+ "browserID": "chromium",
10
+ "creationTimeStamp": "260101T0000",
11
+ "executionTimeStamp": "260101T0000",
12
+ "target": {
13
+ "what": "Mixed Outcomes Page",
14
+ "url": "https://example.com/mixed"
15
+ },
16
+ "sources": {
17
+ "worker": "test-worker"
18
+ },
19
+ "acts": [
20
+ {
21
+ "type": "test",
22
+ "which": "axe",
23
+ "startTime": "26-01-01T00:00",
24
+ "endTime": "26-01-01T00:01",
25
+ "result": {
26
+ "standardResult": {
27
+ "instances": [
28
+ {
29
+ "ruleID": "r11",
30
+ "what": "The link does not have an accessible name",
31
+ "ordinalSeverity": 2,
32
+ "outcome": "failed",
33
+ "count": 1,
34
+ "catalogIndex": "0",
35
+ "checkpoint": 0,
36
+ "issueID": "linkNoText"
37
+ },
38
+ {
39
+ "ruleID": "r65",
40
+ "what": "Focus Visible",
41
+ "ordinalSeverity": 0,
42
+ "outcome": "cantTell",
43
+ "count": 1,
44
+ "catalogIndex": "0",
45
+ "checkpoint": 0,
46
+ "issueID": "focusIndicationBad"
47
+ }
48
+ ],
49
+ "outcomeTotals": {
50
+ "failed": 1,
51
+ "cantTell": 1
52
+ }
53
+ }
54
+ }
55
+ },
56
+ {
57
+ "type": "test",
58
+ "which": "alfa",
59
+ "startTime": "26-01-01T00:00",
60
+ "endTime": "26-01-01T00:01",
61
+ "result": {
62
+ "standardResult": {
63
+ "instances": [
64
+ {
65
+ "ruleID": "r11",
66
+ "what": "The link does not have an accessible name",
67
+ "ordinalSeverity": 2,
68
+ "outcome": "failed",
69
+ "count": 1,
70
+ "catalogIndex": "0",
71
+ "checkpoint": 0,
72
+ "issueID": "linkNoText"
73
+ },
74
+ {
75
+ "ruleID": "r3",
76
+ "what": "Text is all-capital",
77
+ "ordinalSeverity": 1,
78
+ "outcome": "failed",
79
+ "count": 1,
80
+ "catalogIndex": "1",
81
+ "checkpoint": 0,
82
+ "issueID": "allCaps"
83
+ }
84
+ ],
85
+ "outcomeTotals": {
86
+ "failed": 2,
87
+ "cantTell": 0
88
+ }
89
+ }
90
+ }
91
+ }
92
+ ],
93
+ "jobData": {
94
+ "startTime": "26-01-01T00:00",
95
+ "endTime": "26-01-01T00:10",
96
+ "elapsedSeconds": 600,
97
+ "preventions": {},
98
+ "issuelessRules": []
99
+ },
100
+ "catalog": {
101
+ "0": {
102
+ "tagName": "A",
103
+ "id": "",
104
+ "startTag": "<a>",
105
+ "text": "About Us",
106
+ "textLinkable": false,
107
+ "boxID": "10:20:80:30",
108
+ "pathID": "/html/body/a[1]",
109
+ "headingIndex": "",
110
+ "checkpoint": 0
111
+ },
112
+ "1": {
113
+ "tagName": "P",
114
+ "id": "",
115
+ "startTag": "<p>",
116
+ "text": "ALL ABOUT US",
117
+ "textLinkable": false,
118
+ "boxID": "10:60:80:20",
119
+ "pathID": "/html/body/p[1]",
120
+ "headingIndex": "",
121
+ "checkpoint": 0
122
+ }
123
+ },
124
+ "images": {},
125
+ "checkpoints": []
126
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "id": "260101T0001-ct",
3
+ "what": "All CantTell Page",
4
+ "strict": false,
5
+ "standard": "only",
6
+ "device": {
7
+ "id": "default"
8
+ },
9
+ "browserID": "chromium",
10
+ "creationTimeStamp": "260101T0001",
11
+ "executionTimeStamp": "260101T0001",
12
+ "target": {
13
+ "what": "All CantTell Page",
14
+ "url": "https://example.com/canttell"
15
+ },
16
+ "sources": {
17
+ "worker": "test-worker"
18
+ },
19
+ "acts": [
20
+ {
21
+ "type": "test",
22
+ "which": "axe",
23
+ "startTime": "26-01-01T00:00",
24
+ "endTime": "26-01-01T00:01",
25
+ "result": {
26
+ "standardResult": {
27
+ "instances": [
28
+ {
29
+ "ruleID": "r65",
30
+ "what": "Focus Visible",
31
+ "ordinalSeverity": 0,
32
+ "outcome": "cantTell",
33
+ "count": 1,
34
+ "catalogIndex": "0",
35
+ "checkpoint": 0,
36
+ "issueID": "focusIndicationBad"
37
+ }
38
+ ],
39
+ "outcomeTotals": {
40
+ "failed": 0,
41
+ "cantTell": 1
42
+ }
43
+ }
44
+ }
45
+ }
46
+ ],
47
+ "jobData": {
48
+ "startTime": "26-01-01T00:00",
49
+ "endTime": "26-01-01T00:10",
50
+ "elapsedSeconds": 600,
51
+ "preventions": {},
52
+ "issuelessRules": []
53
+ },
54
+ "catalog": {
55
+ "0": {
56
+ "tagName": "A",
57
+ "id": "",
58
+ "startTag": "<a>",
59
+ "text": "Click here",
60
+ "textLinkable": false,
61
+ "boxID": "5:10:60:20",
62
+ "pathID": "/html/body/a[1]",
63
+ "headingIndex": "",
64
+ "checkpoint": 0
65
+ }
66
+ },
67
+ "images": {},
68
+ "checkpoints": []
69
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "id": "260101T0002-no",
3
+ "what": "No Outcomes Page",
4
+ "strict": false,
5
+ "standard": "only",
6
+ "device": {
7
+ "id": "default"
8
+ },
9
+ "browserID": "chromium",
10
+ "creationTimeStamp": "260101T0002",
11
+ "executionTimeStamp": "260101T0002",
12
+ "target": {
13
+ "what": "No Outcomes Page",
14
+ "url": "https://example.com/nooutcomes"
15
+ },
16
+ "sources": {
17
+ "worker": "test-worker"
18
+ },
19
+ "acts": [
20
+ {
21
+ "type": "test",
22
+ "which": "ibm",
23
+ "startTime": "26-01-01T00:00",
24
+ "endTime": "26-01-01T00:01",
25
+ "result": {
26
+ "standardResult": {
27
+ "instances": [
28
+ {
29
+ "ruleID": "r1",
30
+ "what": "Button has no accessible name",
31
+ "ordinalSeverity": 3,
32
+ "count": 1,
33
+ "catalogIndex": "0",
34
+ "checkpoint": 0,
35
+ "issueID": "linkNoText"
36
+ }
37
+ ],
38
+ "outcomeTotals": {
39
+ "failed": 0,
40
+ "cantTell": 0
41
+ }
42
+ }
43
+ }
44
+ }
45
+ ],
46
+ "jobData": {
47
+ "startTime": "26-01-01T00:00",
48
+ "endTime": "26-01-01T00:10",
49
+ "elapsedSeconds": 600,
50
+ "preventions": {},
51
+ "issuelessRules": []
52
+ },
53
+ "catalog": {
54
+ "0": {
55
+ "tagName": "BUTTON",
56
+ "id": "",
57
+ "startTag": "<button>",
58
+ "text": "Submit",
59
+ "textLinkable": false,
60
+ "boxID": "15:25:70:30",
61
+ "pathID": "/html/body/button[1]",
62
+ "headingIndex": "",
63
+ "checkpoint": 0
64
+ }
65
+ },
66
+ "images": {},
67
+ "checkpoints": []
68
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "id": "260101T0005-emp",
3
+ "what": "Empty Results Page",
4
+ "strict": false,
5
+ "standard": "only",
6
+ "device": {
7
+ "id": "default"
8
+ },
9
+ "browserID": "chromium",
10
+ "creationTimeStamp": "260101T0005",
11
+ "executionTimeStamp": "260101T0005",
12
+ "target": {
13
+ "what": "Empty Results Page",
14
+ "url": "https://example.com/empty"
15
+ },
16
+ "sources": {
17
+ "worker": "test-worker"
18
+ },
19
+ "acts": [
20
+ {
21
+ "type": "test",
22
+ "which": "axe",
23
+ "startTime": "26-01-01T00:00",
24
+ "endTime": "26-01-01T00:01",
25
+ "result": {
26
+ "standardResult": {
27
+ "instances": [],
28
+ "outcomeTotals": {
29
+ "failed": 0,
30
+ "cantTell": 0
31
+ }
32
+ }
33
+ }
34
+ }
35
+ ],
36
+ "jobData": {
37
+ "startTime": "26-01-01T00:00",
38
+ "endTime": "26-01-01T00:10",
39
+ "elapsedSeconds": 600,
40
+ "preventions": {},
41
+ "issuelessRules": []
42
+ },
43
+ "catalog": {},
44
+ "images": {},
45
+ "checkpoints": []
46
+ }
@@ -0,0 +1,71 @@
1
+ {
2
+ "id": "260101T0006-prv",
3
+ "what": "Prevented Page",
4
+ "strict": false,
5
+ "standard": "only",
6
+ "device": {
7
+ "id": "default"
8
+ },
9
+ "browserID": "chromium",
10
+ "creationTimeStamp": "260101T0006",
11
+ "executionTimeStamp": "260101T0006",
12
+ "target": {
13
+ "what": "Prevented Page",
14
+ "url": "https://example.com/prevented"
15
+ },
16
+ "sources": {
17
+ "worker": "test-worker"
18
+ },
19
+ "acts": [
20
+ {
21
+ "type": "test",
22
+ "which": "axe",
23
+ "startTime": "26-01-01T00:00",
24
+ "endTime": "26-01-01T00:01",
25
+ "result": {
26
+ "standardResult": {
27
+ "instances": [
28
+ {
29
+ "ruleID": "r11",
30
+ "what": "The image has no alt text",
31
+ "ordinalSeverity": 2,
32
+ "outcome": "failed",
33
+ "count": 1,
34
+ "catalogIndex": "0",
35
+ "checkpoint": 0,
36
+ "issueID": "linkNoText"
37
+ }
38
+ ],
39
+ "outcomeTotals": {
40
+ "failed": 1,
41
+ "cantTell": 0
42
+ }
43
+ }
44
+ }
45
+ }
46
+ ],
47
+ "jobData": {
48
+ "startTime": "26-01-01T00:00",
49
+ "endTime": "26-01-01T00:10",
50
+ "elapsedSeconds": 600,
51
+ "preventions": {
52
+ "alfa": "page timed out"
53
+ },
54
+ "issuelessRules": []
55
+ },
56
+ "catalog": {
57
+ "0": {
58
+ "tagName": "IMG",
59
+ "id": "",
60
+ "startTag": "<img>",
61
+ "text": "An image",
62
+ "textLinkable": false,
63
+ "boxID": "0:0:200:100",
64
+ "pathID": "/html/body/img[1]",
65
+ "headingIndex": "",
66
+ "checkpoint": 0
67
+ }
68
+ },
69
+ "images": {},
70
+ "checkpoints": []
71
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "id": "260202T0000-new",
3
+ "what": "Mixed Outcomes Page",
4
+ "strict": false,
5
+ "standard": "only",
6
+ "device": {
7
+ "id": "default"
8
+ },
9
+ "browserID": "chromium",
10
+ "creationTimeStamp": "260202T0000",
11
+ "executionTimeStamp": "260202T0000",
12
+ "target": {
13
+ "what": "Mixed Outcomes Page",
14
+ "url": "https://example.com/mixed"
15
+ },
16
+ "sources": {
17
+ "worker": "test-worker"
18
+ },
19
+ "acts": [
20
+ {
21
+ "type": "test",
22
+ "which": "axe",
23
+ "startTime": "26-01-01T00:00",
24
+ "endTime": "26-01-01T00:01",
25
+ "result": {
26
+ "standardResult": {
27
+ "instances": [
28
+ {
29
+ "ruleID": "r11",
30
+ "what": "The link does not have an accessible name",
31
+ "ordinalSeverity": 2,
32
+ "outcome": "failed",
33
+ "count": 1,
34
+ "catalogIndex": "0",
35
+ "checkpoint": 0,
36
+ "issueID": "linkNoText"
37
+ }
38
+ ],
39
+ "outcomeTotals": {
40
+ "failed": 1,
41
+ "cantTell": 0
42
+ }
43
+ }
44
+ }
45
+ }
46
+ ],
47
+ "jobData": {
48
+ "startTime": "26-01-01T00:00",
49
+ "endTime": "26-02-02T00:10",
50
+ "elapsedSeconds": 600,
51
+ "preventions": {},
52
+ "issuelessRules": []
53
+ },
54
+ "catalog": {
55
+ "0": {
56
+ "tagName": "A",
57
+ "id": "",
58
+ "startTag": "<a>",
59
+ "text": "About Us",
60
+ "textLinkable": false,
61
+ "boxID": "10:20:80:30",
62
+ "pathID": "/html/body/a[1]",
63
+ "headingIndex": "",
64
+ "checkpoint": 0
65
+ },
66
+ "1": {
67
+ "tagName": "P",
68
+ "id": "",
69
+ "startTag": "<p>",
70
+ "text": "ALL ABOUT US",
71
+ "textLinkable": false,
72
+ "boxID": "10:60:80:20",
73
+ "pathID": "/html/body/p[1]",
74
+ "headingIndex": "",
75
+ "checkpoint": 0
76
+ }
77
+ },
78
+ "images": {},
79
+ "checkpoints": []
80
+ }
package/util.js CHANGED
@@ -14,8 +14,7 @@ const wcagMap = require('./wcagMap.json');
14
14
 
15
15
  // CONSTANTS
16
16
 
17
- // Path of the data directory. Read afresh on every call (rather than cached at module load) so
18
- // that tests can point Kilotest at a fixture directory via the DB_DIR environment variable.
17
+ // Path of the data directory. Read afresh on every call (rather than cached at module load) so that tests can point Kilotest at a fixture directory via the DB_DIR environment variable.
19
18
  const dbPath = exports.dbPath = () => process.env.DB_DIR || path.join(__dirname, 'db');
20
19
  // Path of the jobs directory.
21
20
  const jobsPath = exports.jobsPath = () => path.join(dbPath(), 'jobs');