@jrpool/kilotest 26.0.0 → 27.0.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/index.js CHANGED
@@ -194,8 +194,16 @@ const requestHandler = async (request, response) => {
194
194
  response.setHeader('Access-Control-Allow-Origin', '*');
195
195
  response.end(homePage);
196
196
  }
197
+ // Otherwise, if it is for the the OpenAPI specification:
198
+ else if (pageName === 'openapi.yaml') {
199
+ const openapi = await fs.readFile('openapi.yaml', 'utf8');
200
+ response.setHeader('content-type', 'application/yaml; charset=utf-8');
201
+ response.setHeader('content-location', '/openapi.yaml');
202
+ response.setHeader('Access-Control-Allow-Origin', '*');
203
+ response.end(openapi);
204
+ }
197
205
  // Otherwise, if it is for a full report download:
198
- else if (pageName === 'fullReport.html') {
206
+ else if (pageName === 'fullReport.json') {
199
207
  const [timeStamp, jobID] = pageArgs.split('/');
200
208
  // If the request is syntactically valid:
201
209
  if (isTimeStamp(timeStamp) && isJobID(jobID)) {
package/openapi.yaml ADDED
@@ -0,0 +1,400 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: Kilotest Agent API
4
+ description: >-
5
+ Kilotest tests web pages for accessibility, usability, and standard
6
+ conformity using an ensemble of ten independent tools that employ
7
+ rule-based and machine-learning-based methods. This API enables AI
8
+ agents to recommend web pages for testing, discover available test
9
+ reports, and retrieve data from reports at multiple levels of detail.
10
+ For background on Kilotest and the advantages of ensemble testing,
11
+ visit https://kilotest.com.
12
+ version: 1.0.0
13
+ contact:
14
+ url: https://kilotest.com
15
+ email: info@kilotest.com
16
+ repository: https://github.com/jrpool/kilotest
17
+
18
+ servers:
19
+ - url: https://kilotest.com/api/{agentId}
20
+ description: Kilotest production server
21
+ variables:
22
+ agentId:
23
+ description: >-
24
+ Identifier assigned to the requesting agent by the Kilotest
25
+ operator. Contact the operator via info@kilotest.com to
26
+ obtain an identifier and a password.
27
+ default: research-agent
28
+
29
+ paths:
30
+ /targets:
31
+ post:
32
+ operationId: getReportSummaries
33
+ summary: Summarize all available reports
34
+ description: >-
35
+ Returns summary data about every non-hidden report available from
36
+ Kilotest, including the name and URL of the tested web page, when
37
+ the testing was performed, how many issues were reported, and URLs
38
+ for retrieving more detailed data from the report.
39
+ responses:
40
+ '200':
41
+ description: Summaries of available reports
42
+ content:
43
+ application/json:
44
+ schema:
45
+ $ref: '#/components/schemas/TargetsResponse'
46
+
47
+ /reportIssues/{timeStamp}/{jobID}:
48
+ post:
49
+ operationId: getReportIssues
50
+ summary: Get data on issues from a specific report
51
+ description: >-
52
+ Returns data about the issues reported in a specific Kilotest
53
+ report, grouped by priority. The data on each issue include the
54
+ tools that reported it, the number of HTML elements exhibiting
55
+ it, and URLs for retrieving element-level detail. The timeStamp
56
+ and jobID components identify the report and are available in
57
+ the getReportSummaries response.
58
+ parameters:
59
+ - name: timeStamp
60
+ in: path
61
+ required: true
62
+ description: >-
63
+ timeStamp component of the report identifier, in the format
64
+ YYMMDDTHHMM (e.g., 260503T0432).
65
+ schema:
66
+ type: string
67
+ pattern: '^\d{6}T\d{4}$'
68
+ example: '260503T0432'
69
+ - name: jobID
70
+ in: path
71
+ required: true
72
+ description: >-
73
+ Job identifier component of the report identifier (e.g., xx0).
74
+ schema:
75
+ type: string
76
+ example: 'xx0'
77
+ responses:
78
+ '200':
79
+ description: Data on issues from the specified report
80
+ content:
81
+ application/json:
82
+ schema:
83
+ $ref: '#/components/schemas/ReportIssuesResponse'
84
+ '404':
85
+ description: >-
86
+ No report with the specified identifier is available
87
+
88
+ /reportIssue/{issueID}/{timeStamp}/{jobID}:
89
+ post:
90
+ operationId: getReportIssue
91
+ summary: >-
92
+ Get element-level detail for a specific issue in a specific report
93
+ description: >-
94
+ Returns element-level detail for a single issue within a specific
95
+ report, including which HTML elements exhibit the issue and
96
+ diagnostic information from each tool that reported it. This is
97
+ the level at which tool-provided remediation guidance becomes
98
+ available. The issueID is available in the getReportIssues response.
99
+ parameters:
100
+ - name: issueID
101
+ in: path
102
+ required: true
103
+ description: >-
104
+ Issue identifier (e.g., imageNoText). Available under
105
+ "issues reported" > priority level > "identifier" in the
106
+ getReportIssues response.
107
+ schema:
108
+ type: string
109
+ example: 'imageNoText'
110
+ - name: timeStamp
111
+ in: path
112
+ required: true
113
+ schema:
114
+ type: string
115
+ - name: jobID
116
+ in: path
117
+ required: true
118
+ schema:
119
+ type: string
120
+ responses:
121
+ '200':
122
+ description: Element-level detail for the specified issue
123
+ content:
124
+ application/json:
125
+ schema:
126
+ $ref: '#/components/schemas/ReportIssueResponse'
127
+ '404':
128
+ description: No report or issue found with the specified identifiers
129
+
130
+ components:
131
+ schemas:
132
+
133
+ CommonResponseFields:
134
+ type: object
135
+ properties:
136
+ summary:
137
+ type: string
138
+ description: >-
139
+ Natural-language description of this response and of Kilotest.
140
+ Provides context for an agent encountering Kilotest for the
141
+ first time.
142
+ tool name:
143
+ type: string
144
+ example: Kilotest
145
+ request:
146
+ type: object
147
+ properties:
148
+ requesting agent:
149
+ type: object
150
+ properties:
151
+ identifier:
152
+ type: string
153
+ example: research-agent
154
+ name:
155
+ type: string
156
+ example: Internal Research Agent
157
+ type of request:
158
+ type: object
159
+ properties:
160
+ identifier:
161
+ type: string
162
+ description:
163
+ type: string
164
+ response metadata:
165
+ type: object
166
+ properties:
167
+ identifier:
168
+ type: string
169
+ description: Unique identifier for this response instance.
170
+ date and time:
171
+ type: string
172
+ format: date-time
173
+
174
+ ToolInfo:
175
+ type: object
176
+ description: An accessibility testing tool in the Kilotest ensemble.
177
+ properties:
178
+ identifier:
179
+ type: string
180
+ description: Short programmatic identifier for the tool.
181
+ example: alfa
182
+ name:
183
+ type: string
184
+ description: Display name of the tool.
185
+ example: Alfa
186
+ sponsor:
187
+ type: string
188
+ description: Organization that created or sponsors the tool.
189
+ example: Siteimprove
190
+
191
+ ToolFailure:
192
+ type: object
193
+ description: A tool that was unable to complete testing of the page.
194
+ properties:
195
+ name:
196
+ type: string
197
+ example: WAVE
198
+ reason for failure:
199
+ type: string
200
+ example: Not enough credits.
201
+
202
+ ToolsSummary:
203
+ type: object
204
+ description: Count and names of a set of tools.
205
+ properties:
206
+ number:
207
+ type: integer
208
+ names:
209
+ type: array
210
+ items:
211
+ type: string
212
+
213
+ NextTierURLs:
214
+ type: object
215
+ description: URLs for retrieving the next level of detail.
216
+ properties:
217
+ for you:
218
+ type: string
219
+ format: uri
220
+ description: URL for an agent to request the next tier of detail.
221
+ for humans:
222
+ type: string
223
+ format: uri
224
+ description: URL for a human to view the next tier of detail.
225
+
226
+ ReportSummaryItem:
227
+ type: object
228
+ description: Summary data about a single available report.
229
+ properties:
230
+ identifier:
231
+ type: string
232
+ example: 260504T1659-029
233
+ creation date:
234
+ type: string
235
+ format: date-time
236
+ days since the creation date:
237
+ type: integer
238
+ tested web page:
239
+ type: object
240
+ properties:
241
+ description:
242
+ type: string
243
+ URL:
244
+ type: string
245
+ format: uri
246
+ whether a later report about the same page exists:
247
+ type: boolean
248
+ description: >-
249
+ If true, a more recent report about this page is available.
250
+ If you want the latest results, use that report instead.
251
+ number of issues reported:
252
+ type: integer
253
+ number of HTML elements reported as exhibiting issues:
254
+ type: integer
255
+ tools that tried to test the page:
256
+ $ref: '#/components/schemas/ToolsSummary'
257
+ tools that were unable to test the page:
258
+ $ref: '#/components/schemas/ToolsSummary'
259
+ tools that reported issues:
260
+ $ref: '#/components/schemas/ToolsSummary'
261
+ URLs for getting data on the reported issues:
262
+ $ref: '#/components/schemas/NextTierURLs'
263
+ URL for getting the full technical report as JSON:
264
+ type: string
265
+ format: uri
266
+
267
+ TargetsResponse:
268
+ allOf:
269
+ - $ref: '#/components/schemas/CommonResponseFields'
270
+ - type: object
271
+ properties:
272
+ available reports:
273
+ type: array
274
+ description: >-
275
+ One entry per available Kilotest report, in alphabetical
276
+ order by page description and, in case of multiple reports
277
+ per page, in order of creation date and time. Reports are
278
+ matched by page description, not page URL, so, if only the
279
+ URL of a page has changed between reports, the reports are
280
+ treated as reports about the same page.
281
+ items:
282
+ $ref: '#/components/schemas/ReportSummaryItem'
283
+
284
+ IssueEntry:
285
+ type: object
286
+ description: >-
287
+ Details about a specific accessibility issue found on a page.
288
+ properties:
289
+ identifier:
290
+ type: string
291
+ example: imageNoText
292
+ summary:
293
+ type: string
294
+ description: Brief natural-language label for the issue.
295
+ example: image not named
296
+ related WCAG 2.2 standard:
297
+ type: object
298
+ description: >-
299
+ The WCAG 2.2 success criterion or guideline most closely
300
+ related to this issue.
301
+ properties:
302
+ layer:
303
+ type: string
304
+ enum: [guideline, success criterion]
305
+ 'numeric identifier':
306
+ type: string
307
+ pattern: '^\d\.\d(\.\d+)?$'
308
+ example: '1.1.1'
309
+ impact on a user:
310
+ type: string
311
+ description: >-
312
+ How this issue is likely to affect users.
313
+ tools reporting the issue:
314
+ $ref: '#/components/schemas/ToolsSummary'
315
+ number of HTML elements reported as exhibiting the issue:
316
+ type: integer
317
+ URLs for details about the issue on the page:
318
+ $ref: '#/components/schemas/NextTierURLs'
319
+
320
+ IssuesByPriority:
321
+ type: object
322
+ properties:
323
+ highest priority:
324
+ type: array
325
+ items:
326
+ $ref: '#/components/schemas/IssueEntry'
327
+ high priority:
328
+ type: array
329
+ items:
330
+ $ref: '#/components/schemas/IssueEntry'
331
+ low priority:
332
+ type: array
333
+ items:
334
+ $ref: '#/components/schemas/IssueEntry'
335
+ lowest priority:
336
+ type: array
337
+ items:
338
+ $ref: '#/components/schemas/IssueEntry'
339
+
340
+ ReportIssuesResponse:
341
+ allOf:
342
+ - $ref: '#/components/schemas/CommonResponseFields'
343
+ - type: object
344
+ properties:
345
+ report:
346
+ type: object
347
+ properties:
348
+ identifier:
349
+ type: string
350
+ creation date:
351
+ type: string
352
+ format: date-time
353
+ days since the creation date:
354
+ type: integer
355
+ tested web page:
356
+ type: object
357
+ properties:
358
+ description:
359
+ type: string
360
+ URL:
361
+ type: string
362
+ format: uri
363
+ tools that tried to test the page:
364
+ type: array
365
+ items:
366
+ $ref: '#/components/schemas/ToolInfo'
367
+ tools that were unable to test the page:
368
+ type: array
369
+ items:
370
+ $ref: '#/components/schemas/ToolFailure'
371
+ tools that reported issues:
372
+ $ref: '#/components/schemas/ToolsSummary'
373
+ number of issues reported:
374
+ type: object
375
+ properties:
376
+ total:
377
+ type: integer
378
+ by priority:
379
+ type: object
380
+ properties:
381
+ highest priority:
382
+ type: integer
383
+ high priority:
384
+ type: integer
385
+ low priority:
386
+ type: integer
387
+ lowest priority:
388
+ type: integer
389
+ number of HTML elements reported as exhibiting issues:
390
+ type: integer
391
+ issues reported:
392
+ $ref: '#/components/schemas/IssuesByPriority'
393
+
394
+ ReportIssueResponse:
395
+ allOf:
396
+ - $ref: '#/components/schemas/CommonResponseFields'
397
+ - type: object
398
+ description: >-
399
+ Element-level detail for a specific issue. Schema to be
400
+ completed once the tier-3 service is implemented.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jrpool/kilotest",
3
- "version": "26.0.0",
3
+ "version": "27.0.0",
4
4
  "description": "An ensemble testing service with a focus on accessibility",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -21,11 +21,14 @@ const {
21
21
  // Gets facts about an issue.
22
22
  const getIssueFacts = (thisHost, agentID, timeStamp, jobID, issue) => {
23
23
  const {issueID, reporterCount, reporters, summary, violatorCount, wcag, why} = issue;
24
- const wcagType = wcag.length === 3 ? 'principle' : 'success criterion';
24
+ const wcagType = wcag.length === 3 ? 'guideline' : 'success criterion';
25
25
  return {
26
26
  identifier: issueID,
27
27
  summary,
28
- [`related WCAG ${wcagType}`]: wcag,
28
+ 'related WCAG 2.2 standard': {
29
+ layer: wcagType,
30
+ 'numeric identifier': wcag
31
+ },
29
32
  'impact on a user': why,
30
33
  'tools reporting the issue': {
31
34
  'number': reporterCount,
@@ -33,8 +36,8 @@ const getIssueFacts = (thisHost, agentID, timeStamp, jobID, issue) => {
33
36
  },
34
37
  'number of HTML elements reported as exhibiting the issue': violatorCount,
35
38
  'URLs for details about the issue on the page': {
36
- 'for you': `${thisHost}/api/${agentID}/reportIssue/${timeStamp}/${jobID}/${issueID}`,
37
- 'for humans': `${thisHost}/reportIssue/${timeStamp}/${jobID}/${issueID}`
39
+ 'for you': `${thisHost}/api/${agentID}/reportIssue/${issueID}/${timeStamp}/${jobID}`,
40
+ 'for humans': `${thisHost}/reportIssue.html/${issueID}/${timeStamp}/${jobID}`
38
41
  }
39
42
  };
40
43
  };
@@ -72,16 +75,21 @@ exports.response = async args => {
72
75
  identifier: 'reportIssues',
73
76
  description: 'What issues does the specified report describe?'
74
77
  },
78
+ URLs: {
79
+ 'URL of your request': `${thisHost}/api/${agentID}/reportIssues/${timeStamp}/${jobID}`,
80
+ 'equivalent URL for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
81
+ },
75
82
  'closest ancestor request': {
76
83
  description: 'Which web pages are reports available about, and what are the statistics about the issues reported for each page?',
77
- 'URL for you': `${thisHost}/api/${agentID}/targets.html`,
78
- 'URL for humans': `${thisHost}/targets.html`
84
+ URLs: {
85
+ 'for you': `${thisHost}/api/${agentID}/targets.html`,
86
+ 'for humans': `${thisHost}/targets.html`
87
+ }
79
88
  }
80
89
  },
81
90
  'response metadata': {
82
91
  identifier: `${getNowStamp()}-${getRandomString(3)}`,
83
- 'date and time': new Date().toISOString(),
84
- 'URL of the human-oriented equivalent of this response': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
92
+ 'date and time': new Date().toISOString()
85
93
  },
86
94
  report: {
87
95
  identifier: `${timeStamp}-${jobID}`,
@@ -25,7 +25,7 @@
25
25
  <p>__reporterCount__ reported issues (__reporters__)</p>
26
26
  <p>__issueCount__ reported (__highestCount__ highest, __highCount__ high, __lowCount__ low, __lowestCount__ lowest priority)</p>
27
27
  <p>__violatorCount__ reported</p>
28
- <p>Download the <a href="/fullReport.html/__timeStamp__/__jobID__">full technical report</a></p>
28
+ <p>Download the <a href="/fullReport.json/__timeStamp__/__jobID__">full technical report</a></p>
29
29
  <h3>Details</h3>
30
30
  <details>
31
31
  <summary>Highest priority: __highestCount__</summary>
package/targets/api.js CHANGED
@@ -20,7 +20,8 @@ const thisHost = process.env.THIS_KILOTEST_HOST;
20
20
  // FUNCTIONS
21
21
 
22
22
  // Returns a response to a targets request.
23
- exports.response = async agentID => {
23
+ exports.response = async args => {
24
+ const [agentID] = args;
24
25
  const availableReports = [];
25
26
  // Get the non-hidden logs.
26
27
  const targetLogs = await getLogs();
@@ -70,7 +71,7 @@ exports.response = async agentID => {
70
71
  'for you': `${thisHost}/api/${agentID}/reportIssues/${timeStamp}/${jobID}`,
71
72
  'for humans': `${thisHost}/reportIssues/${timeStamp}/${jobID}`
72
73
  },
73
- 'URL for getting the full technical report as JSON': `${thisHost}/fullReport.html/${timeStamp}/${jobID}`
74
+ 'URL for getting the full technical report as JSON': `${thisHost}/fullReport.json/${timeStamp}/${jobID}`
74
75
  });
75
76
  }
76
77
  // Get a response.
@@ -87,7 +88,7 @@ exports.response = async agentID => {
87
88
  description: 'Give me summary data about each available report.'
88
89
  },
89
90
  URLs: {
90
- 'URL of this request': `${thisHost}/api/${agentID}/targets`,
91
+ 'URL of your request': `${thisHost}/api/${agentID}/targets`,
91
92
  'equivalent URL for humans': `${thisHost}/targets.html`
92
93
  }
93
94
  },
package/util.js CHANGED
@@ -35,11 +35,7 @@ const tools = exports.tools = {
35
35
  qualWeb: ['QualWeb', 'University of Lisbon'],
36
36
  testaro: ['Testaro', 'CVS Health'],
37
37
  wave: ['WAVE', 'Utah State University'],
38
- <<<<<<< HEAD
39
38
  wax: ['WallyAX', 'Wally']
40
- =======
41
- wax: ['WAX', 'Wally']
42
- >>>>>>> api3
43
39
  };
44
40
  exports.researchAgents = {
45
41
  'research-agent': 'Internal Research Agent'
@@ -371,7 +367,7 @@ exports.getReportData = async (timeStamp, jobID) => {
371
367
  if (act.type === 'test') {
372
368
  const {result, which} = act;
373
369
  // Ensure that the tool is in the temporary data.
374
- toolNameSet.add(which);
370
+ toolNameSet.add(tools[which][0]);
375
371
  const instances = result?.standardResult?.instances ?? [];
376
372
  // For each standard instance of the act:
377
373
  instances.forEach(instance => {