@jrpool/kilotest 46.0.3 → 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/package.json
CHANGED
|
@@ -2,14 +2,9 @@
|
|
|
2
2
|
buildFixtures.js
|
|
3
3
|
Builds the fixture corpus for Kilotest tests.
|
|
4
4
|
|
|
5
|
-
Each fixture is a minimal Testaro report in the current format, crafted so
|
|
6
|
-
that the expected API response can be hand-computed and hard-coded into
|
|
7
|
-
tests. The fixtures collectively cover the `outcome` property values
|
|
8
|
-
(`failed`, `cantTell`, and missing/undefined), superseded reports, empty
|
|
9
|
-
reports, and prevented rule engines.
|
|
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.
|
|
10
6
|
|
|
11
7
|
Run with: node test/fixtures/buildFixtures.js [targetDir]
|
|
12
|
-
Defaults to test/fixtures/db under the project root.
|
|
13
8
|
*/
|
|
14
9
|
|
|
15
10
|
// IMPORTS
|
|
@@ -20,14 +15,17 @@ const path = require('path');
|
|
|
20
15
|
// CONSTANTS
|
|
21
16
|
|
|
22
17
|
// Issue IDs with known specs in testaro-issues, chosen for different weights.
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
18
|
+
// weight 4 (highest)
|
|
19
|
+
const issueLinkNoText = 'linkNoText';
|
|
20
|
+
// weight 4
|
|
21
|
+
const issueFocusIndication = 'focusIndicationBad';
|
|
22
|
+
// weight 1 (lowest)
|
|
23
|
+
const issueAllCaps = 'allCaps';
|
|
26
24
|
|
|
27
25
|
// Rule engine IDs that exist in util.js ruleEngines.
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
26
|
+
const engineAxe = 'axe';
|
|
27
|
+
const engineAlfa = 'alfa';
|
|
28
|
+
const engineIbm = 'ibm';
|
|
31
29
|
|
|
32
30
|
// FUNCTIONS
|
|
33
31
|
|
|
@@ -116,27 +114,23 @@ const main = async () => {
|
|
|
116
114
|
await fs.mkdir(path.join(targetDir, 'jobs', 'failed'), {recursive: true});
|
|
117
115
|
await fs.mkdir(path.join(targetDir, 'hiddenReports'), {recursive: true});
|
|
118
116
|
|
|
119
|
-
// Fixture 1: mixedOutcomes
|
|
120
|
-
// Two rule engines, three instances: one failed, one cantTell, one failed.
|
|
121
|
-
// The cantTell instance must be excluded from issue/violator counts.
|
|
122
|
-
// Two distinct issues (linkNoText weight 4, allCaps weight 1) and two
|
|
123
|
-
// distinct violator catalog indexes (0 and 1).
|
|
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).
|
|
124
118
|
const mixedCatalog = {
|
|
125
119
|
'0': catalogItem('A', 'About Us', '/html/body/a[1]', '10:20:80:30'),
|
|
126
120
|
'1': catalogItem('P', 'ALL ABOUT US', '/html/body/p[1]', '10:60:80:20')
|
|
127
121
|
};
|
|
128
122
|
const mixedActs = [
|
|
129
|
-
testAct(
|
|
123
|
+
testAct(engineAxe, [
|
|
130
124
|
instance('r11', 'The link does not have an accessible name', 'failed',
|
|
131
|
-
|
|
125
|
+
issueLinkNoText, 0, 2, 1),
|
|
132
126
|
instance('r65', 'Focus Visible', 'cantTell',
|
|
133
|
-
|
|
127
|
+
issueFocusIndication, 0, 0, 1)
|
|
134
128
|
]),
|
|
135
|
-
testAct(
|
|
129
|
+
testAct(engineAlfa, [
|
|
136
130
|
instance('r11', 'The link does not have an accessible name', 'failed',
|
|
137
|
-
|
|
131
|
+
issueLinkNoText, 0, 2, 1),
|
|
138
132
|
instance('r3', 'Text is all-capital', 'failed',
|
|
139
|
-
|
|
133
|
+
issueAllCaps, 1, 1, 1)
|
|
140
134
|
])
|
|
141
135
|
];
|
|
142
136
|
await writeJSON(
|
|
@@ -145,16 +139,14 @@ const main = async () => {
|
|
|
145
139
|
'https://example.com/mixed', mixedActs, mixedCatalog)
|
|
146
140
|
);
|
|
147
141
|
|
|
148
|
-
// Fixture 2: allCantTell
|
|
149
|
-
// All instances have outcome cantTell, so no issues or violators should be
|
|
150
|
-
// reported by listIssues, listViolators, or listDiagnoses.
|
|
142
|
+
// Fixture 2: allCantTell. All instances have outcome cantTell, so no issues or violators should be reported by listIssues, listViolators, or listDiagnoses.
|
|
151
143
|
const cantTellCatalog = {
|
|
152
144
|
'0': catalogItem('A', 'Click here', '/html/body/a[1]', '5:10:60:20')
|
|
153
145
|
};
|
|
154
146
|
const cantTellActs = [
|
|
155
|
-
testAct(
|
|
147
|
+
testAct(engineAxe, [
|
|
156
148
|
instance('r65', 'Focus Visible', 'cantTell',
|
|
157
|
-
|
|
149
|
+
issueFocusIndication, 0, 0, 1)
|
|
158
150
|
])
|
|
159
151
|
];
|
|
160
152
|
await writeJSON(
|
|
@@ -163,15 +155,12 @@ const main = async () => {
|
|
|
163
155
|
'https://example.com/canttell', cantTellActs, cantTellCatalog)
|
|
164
156
|
);
|
|
165
157
|
|
|
166
|
-
// Fixture 3: noOutcomes
|
|
167
|
-
// Instances with no outcome property. Testaro defaults to 'failed', but
|
|
168
|
-
// Kilotest code checks `outcome !== 'cantTell'`, so missing outcome (undefined)
|
|
169
|
-
// is treated as a violation. This verifies that behavior.
|
|
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.
|
|
170
159
|
const noOutcomeCatalog = {
|
|
171
160
|
'0': catalogItem('BUTTON', 'Submit', '/html/body/button[1]', '15:25:70:30')
|
|
172
161
|
};
|
|
173
162
|
const noOutcomeActs = [
|
|
174
|
-
testAct(
|
|
163
|
+
testAct(engineIbm, [
|
|
175
164
|
{
|
|
176
165
|
ruleID: 'r1',
|
|
177
166
|
what: 'Button has no accessible name',
|
|
@@ -179,7 +168,7 @@ const main = async () => {
|
|
|
179
168
|
count: 1,
|
|
180
169
|
catalogIndex: '0',
|
|
181
170
|
checkpoint: 0,
|
|
182
|
-
issueID:
|
|
171
|
+
issueID: issueLinkNoText
|
|
183
172
|
}
|
|
184
173
|
])
|
|
185
174
|
];
|
|
@@ -189,13 +178,11 @@ const main = async () => {
|
|
|
189
178
|
'https://example.com/nooutcomes', noOutcomeActs, noOutcomeCatalog)
|
|
190
179
|
);
|
|
191
180
|
|
|
192
|
-
// Fixture 4: superseded
|
|
193
|
-
// A report about the same page as mixedOutcomes but with a later timestamp,
|
|
194
|
-
// so mixedOutcomes is superseded by this one.
|
|
181
|
+
// Fixture 4: superseded. A report about the same page as mixedOutcomes but with a later timestamp, so mixedOutcomes is superseded by this one.
|
|
195
182
|
const newerActs = [
|
|
196
|
-
testAct(
|
|
183
|
+
testAct(engineAxe, [
|
|
197
184
|
instance('r11', 'The link does not have an accessible name', 'failed',
|
|
198
|
-
|
|
185
|
+
issueLinkNoText, 0, 2, 1)
|
|
199
186
|
])
|
|
200
187
|
];
|
|
201
188
|
await writeJSON(
|
|
@@ -204,24 +191,21 @@ const main = async () => {
|
|
|
204
191
|
'https://example.com/mixed', newerActs, mixedCatalog, '26-02-02T00:10')
|
|
205
192
|
);
|
|
206
193
|
|
|
207
|
-
// Fixture 5: empty
|
|
208
|
-
// A valid report with no test acts that have instances, so listIssues
|
|
209
|
-
// returns zero issues.
|
|
194
|
+
// Fixture 5: empty. A valid report with no test acts that have instances, so listIssues returns zero issues.
|
|
210
195
|
await writeJSON(
|
|
211
196
|
path.join(reportsDir, '260101T0005-emp.json'),
|
|
212
197
|
report('260101T0005-emp', 'Empty Results Page',
|
|
213
|
-
'https://example.com/empty', [testAct(
|
|
198
|
+
'https://example.com/empty', [testAct(engineAxe, [])], {})
|
|
214
199
|
);
|
|
215
200
|
|
|
216
|
-
// Fixture 6: prevented
|
|
217
|
-
// A report where one rule engine was prevented from testing.
|
|
201
|
+
// Fixture 6: prevented. A report where one rule engine was prevented from testing.
|
|
218
202
|
const preventedCatalog = {
|
|
219
203
|
'0': catalogItem('IMG', 'An image', '/html/body/img[1]', '0:0:200:100')
|
|
220
204
|
};
|
|
221
205
|
const preventedActs = [
|
|
222
|
-
testAct(
|
|
206
|
+
testAct(engineAxe, [
|
|
223
207
|
instance('r11', 'The image has no alt text', 'failed',
|
|
224
|
-
|
|
208
|
+
issueLinkNoText, 0, 2, 1)
|
|
225
209
|
])
|
|
226
210
|
];
|
|
227
211
|
const preventedReport = report('260101T0006-prv', 'Prevented Page',
|
|
@@ -232,6 +216,23 @@ const main = async () => {
|
|
|
232
216
|
preventedReport
|
|
233
217
|
);
|
|
234
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
|
+
|
|
235
236
|
// Write an empty recs.json so getRecs does not try to create one.
|
|
236
237
|
await writeJSON(path.join(targetDir, 'jobs', 'recs.json'), {});
|
|
237
238
|
|
|
@@ -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
|
+
}
|
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');
|