@jrpool/kilotest 37.1.0 → 38.1.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/mcp.js CHANGED
@@ -6,12 +6,14 @@
6
6
  // IMPORTS
7
7
 
8
8
  const {McpServer} = require('@modelcontextprotocol/sdk/server/mcp.js');
9
- const {StreamableHTTPServerTransport} = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
9
+ const {StreamableHTTPServerTransport} = require(
10
+ '@modelcontextprotocol/sdk/server/streamableHttp.js'
11
+ );
10
12
  const {z} = require('zod');
11
13
  const {isReportAvailable, isURL} = require('./util');
12
14
  const targetAPI = require('./target/api');
13
- const reportListAPI = require('./reportList/api');
14
- const reportIssuesAPI = require('./reportIssues/api');
15
+ const reportListAPI = require('./api/reportList');
16
+ const reportSummaryAPI = require('./api/reportSummary');
15
17
  const reportIssueAPI = require('./reportIssue/api');
16
18
  const testRecFormAPI = require('./testRecForm/api');
17
19
 
@@ -29,7 +31,7 @@ const createMCPServer = () => {
29
31
  {
30
32
  description: 'Returns summary data from every available Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of web pages that match the description or hostname fragment of a web page that you have provided. Matching is case-insensitive and succeeds if the page property either is included by or includes the specified fragment.',
31
33
  inputSchema: {
32
- what: z.string().describe('All or part of a description of the web page.'),
34
+ description: z.string().describe('All or part of a description of the web page.'),
33
35
  hostname: z.string().describe('All or part of the hostname of the URL of the web page.')
34
36
  },
35
37
  annotations: {
@@ -40,18 +42,18 @@ const createMCPServer = () => {
40
42
  openWorldHint: false
41
43
  }
42
44
  },
43
- async ({what, hostname}) => {
44
- const result = await targetAPI.response([what, hostname]);
45
+ async ({description, hostname}) => {
46
+ const result = await targetAPI.response([description, hostname]);
45
47
  return {content: [{type: 'text', text: JSON.stringify(result)}]};
46
48
  }
47
49
  );
48
50
  server.registerTool(
49
- 'getListOfAllAvailableReports',
51
+ 'listAllAvailableReports',
50
52
  {
51
53
  description: 'Returns a list of all available Kilotest reports; each report describes the results of a job that tested one web page for front-end quality (i.e. accessibility, usability, and standards conformity).',
52
54
  inputSchema: {},
53
55
  annotations: {
54
- title: 'Get a list of all available reports',
56
+ title: 'List all available reports',
55
57
  readOnlyHint: true,
56
58
  idempotentHint: true,
57
59
  destructiveHint: false,
@@ -64,15 +66,15 @@ const createMCPServer = () => {
64
66
  }
65
67
  );
66
68
  server.registerTool(
67
- 'describeQualityOfOneWebPage',
69
+ 'summarizeOneReport',
68
70
  {
69
- description: 'Returns data from a specified Kilotest report about issues for the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. The required timeStamp and jobID parameters identify the report and are obtained from a getListOfAllAvailableReports response.',
71
+ description: 'Returns a summary of a specified Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. The required timeStamp and jobID parameters identify the report and are obtained from a listAllAvailableReports response.',
70
72
  inputSchema: {
71
- timeStamp: z.string().describe('Report timestamp in YYMMDDTHHMM format, e.g. 260503T0432'),
73
+ timeStamp: z.string().describe('Timestamp of the report in YYMMDDTHHMM format, e.g. 260503T0432'),
72
74
  jobID: z.string().describe('Job identifier, e.g. x9z')
73
75
  },
74
76
  annotations: {
75
- title: 'Describe the quality of one web page',
77
+ title: 'Summarize one report',
76
78
  readOnlyHint: true,
77
79
  idempotentHint: true,
78
80
  destructiveHint: false,
@@ -80,14 +82,14 @@ const createMCPServer = () => {
80
82
  }
81
83
  },
82
84
  async ({timeStamp, jobID}) => {
83
- const result = await reportIssuesAPI.response([timeStamp, jobID]);
85
+ const result = await reportSummaryAPI.response([timeStamp, jobID]);
84
86
  return {content: [{type: 'text', text: JSON.stringify(result)}]};
85
87
  }
86
88
  );
87
89
  server.registerTool(
88
90
  'describeOneIssueFromOneReport',
89
91
  {
90
- description: 'Returns data from a specified Kilotest report about one of the issues for the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. The required issueID, timeStamp, and jobID parameters identify the issue and the report and are obtained from a describeQualityOfOneWebPage response.',
92
+ description: 'Returns data from a specified Kilotest report about one of the issues for the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. The required issueID, timeStamp, and jobID parameters identify the issue and the report and are obtained from a summarizeOneReport response.',
91
93
  inputSchema: {
92
94
  issueID: z.string().describe('Issue identifier, e.g. contrastPoor'),
93
95
  timeStamp: z.string().describe('Report timestamp in YYMMDDTHHMM format, e.g. 260503T0432'),
@@ -109,11 +111,11 @@ const createMCPServer = () => {
109
111
  server.registerTool(
110
112
  'recommendQualityTestingOfOneWebPage',
111
113
  {
112
- description: 'Recommends a web page for Kilotest to test for front-end quality (i.e. accessibility, usability, and standards conformity). Do not call this tool until after you call getListOfAllAvailableReports to check whether a report about the page, or a related page that satisfies your requirements, is available and to understand the naming conventions for pages.',
114
+ description: 'Recommends a web page for Kilotest to test for front-end quality (i.e. accessibility, usability, and standards conformity). Do not call this tool until after you call listAllAvailableReports to check whether a report about the page, or a related page that satisfies your requirements, is available and to understand the naming conventions for pages.',
113
115
  inputSchema: {
114
- what: z.string().describe('Short description of the page, following the naming conventions visible in the getListOfAllAvailableReports response'),
115
- url: z.string().describe('Full HTTPS URL of the page to test'),
116
- why: z.string().describe('Reason for recommending this page for testing')
116
+ 'description of the web page': z.string().describe('Short description of the page, following the naming conventions visible in the listAllAvailableReports response'),
117
+ 'URL of the web page': z.string().describe('Full HTTPS URL of the page to test'),
118
+ 'reason for testing the web page': z.string().describe('Reason for recommending this page for testing')
117
119
  },
118
120
  annotations: {
119
121
  title: 'Recommend quality testing of one web page',
@@ -123,7 +125,11 @@ const createMCPServer = () => {
123
125
  openWorldHint: false
124
126
  }
125
127
  },
126
- async ({what, url, why}) => {
128
+ async ({
129
+ 'description of the web page': what,
130
+ 'URL of the web page': url,
131
+ 'reason for testing the web page': why
132
+ }) => {
127
133
  if (!isURL(url)) {
128
134
  return {content: [{type: 'text', text: JSON.stringify({error: 'Invalid URL'})}], isError: true};
129
135
  }
package/openapi.yaml CHANGED
@@ -35,9 +35,9 @@ paths:
35
35
 
36
36
  /api/reportList:
37
37
  get:
38
- operationId: getListOfAllAvailableReports
39
- summary: Get a list of all available reports
40
- description: Get a list of all available reports. Each report describes the results of a job that tested a web page for front-end quality (i.e. accessibility, usability, and standards conformity). For each report, the list identifies which page was tested and when and provides URLs to begin incremental retrieval of the test results.
38
+ operationId: listAllAvailableReports
39
+ summary: List all available reports
40
+ description: List all available reports. Each report describes the results of a job that tested a web page for front-end quality (i.e. accessibility, usability, and standards conformity). For each report, the list identifies which page was tested and when and provides URLs to begin incremental retrieval of the test results.
41
41
  responses:
42
42
  '200':
43
43
  description: List of all available reports
@@ -50,7 +50,7 @@ paths:
50
50
  post:
51
51
  operationId: recommendQualityTestingOfOneWebPage
52
52
  summary: Recommend quality testing of one web page
53
- description: Submit a recommendation for Kilotest to test, for the first time, a particular web page for front-end quality (i.e. accessibility, usability, and standards conformity). Recommendations are typically approved and the testing completed within a day, whereupon the results can be found with the getListOfAllAvailableReports operation. Before submitting a recommendation, use the getListOfAllAvailableReports operation to ensure that no report about the page is available, and also to see the stylistic rules for the naming of pages. An attempt to recommend a page for testing will fail if a report about the page is already available.
53
+ description: Submit a recommendation for Kilotest to test, for the first time, a particular web page for front-end quality (i.e. accessibility, usability, and standards conformity). Recommendations are typically approved and the testing completed within a day, whereupon the results can be found with the listAllAvailableReports operation. Before submitting a recommendation, use the listAllAvailableReports operation to ensure that no report about the page is available, and also to see the stylistic rules for the naming of pages. An attempt to recommend a page for testing will fail if a report about the page is already available.
54
54
  requestBody:
55
55
  description: Test recommendation specifications
56
56
  required: true
@@ -66,11 +66,11 @@ paths:
66
66
  schema:
67
67
  $ref: '#/components/schemas/TestRecFormResponse'
68
68
 
69
- /api/reportIssues/{timeStamp}/{jobID}:
69
+ /api/reportSummary/{timeStamp}/{jobID}:
70
70
  get:
71
- operationId: describeQualityOfOneWebPage
72
- summary: Describe quality of one web page
73
- description: Get data about the quality of a specified Kilotest report. The data about each issue include its priority, the rule engines that reported it, the number of HTML elements exhibiting it, and URLs for retrieving element-level detail. The timeStamp and jobID parameters identify the report and are available in the response from the getListOfAllAvailableReports operation.
71
+ operationId: summarizeOneReport
72
+ summary: Summarize one report
73
+ description: Summarize one report. The summary should briefly describe the testing job and the results, including the rule engines that tested the web page and the issues that were revealed by the reported rule violations, and provide URLs for getting details about issues. The timeStamp and jobID parameters identify the report and were obtained from the response to a listAllAvailableReports operation.
74
74
  parameters:
75
75
  - name: timeStamp
76
76
  in: path
@@ -91,11 +91,11 @@ paths:
91
91
  - xx0
92
92
  responses:
93
93
  '200':
94
- description: Data on issues from the specified report
94
+ description: Summary of the specified report
95
95
  content:
96
96
  application/json:
97
97
  schema:
98
- $ref: '#/components/schemas/ReportIssuesResponse'
98
+ $ref: '#/components/schemas/ReportSummaryResponse'
99
99
  '404':
100
100
  description: No report with the specified identifier is available
101
101
 
@@ -108,7 +108,7 @@ paths:
108
108
  - name: issueID
109
109
  in: path
110
110
  required: true
111
- description: Issue identifier (e.g., imageNoText). Available under "issues reported" > priority level > "identifier" in the describeQualityOfOneWebPage response.
111
+ description: Issue identifier (e.g., imageNoText). Available under "response content" > "issues revealed" > [item] > "identifier" in the summarizeOneReport response.
112
112
  schema:
113
113
  type: string
114
114
  examples:
@@ -153,7 +153,7 @@ components:
153
153
  tool name:
154
154
  type: string
155
155
  examples:
156
- - getListOfAllAvailableReports
156
+ - listAllAvailableReports
157
157
  request:
158
158
  type: object
159
159
  properties:
@@ -177,15 +177,78 @@ components:
177
177
  URLs:
178
178
  type: object
179
179
  properties:
180
- 'URL of your request':
180
+ 'for you':
181
181
  type: string
182
- 'equivalent URL for humans':
182
+ 'for humans':
183
183
  type: string
184
184
  closest ancestor request:
185
185
  oneOf:
186
186
  - type: 'null'
187
187
  - type: object
188
188
  properties:
189
+ identifier:
190
+ type: string
191
+ description:
192
+ type: string
193
+ URLs:
194
+ type: object
195
+ properties:
196
+ 'for you':
197
+ type: string
198
+ 'for humans':
199
+ type: string
200
+ response metadata:
201
+ type: object
202
+ properties:
203
+ identifier:
204
+ type: string
205
+ description: Unique identifier for this response instance.
206
+ date and time:
207
+ type: string
208
+ description: UTC date and time when the response was generated, in ISO 8601 format.
209
+ format: date-time
210
+
211
+ SharedFacts:
212
+ type: object
213
+ properties:
214
+ summary:
215
+ type: string
216
+ description: Natural-language facts about the request, the response, and Kilotest.
217
+ tool collection name:
218
+ type: string
219
+ examples:
220
+ - Kilotest
221
+ tool name:
222
+ type: string
223
+ examples:
224
+ - listAllAvailableReports
225
+ request:
226
+ type: object
227
+ properties:
228
+ description:
229
+ type: string
230
+ method:
231
+ type: string
232
+ enum:
233
+ - GET
234
+ - POST
235
+ payload:
236
+ type: object
237
+ description: The request payload, if method is POST, or otherwise omitted.
238
+ URLs:
239
+ type: object
240
+ properties:
241
+ 'for you':
242
+ type: string
243
+ 'for humans':
244
+ type: string
245
+ closest ancestor request:
246
+ oneOf:
247
+ - type: 'null'
248
+ - type: object
249
+ properties:
250
+ 'tool name':
251
+ type: string
189
252
  description:
190
253
  type: string
191
254
  URLs:
@@ -209,13 +272,13 @@ components:
209
272
  TestRecForm:
210
273
  type: object
211
274
  properties:
212
- what:
275
+ description of the web page:
213
276
  type: string
214
277
  description: Description of the web page to be tested.
215
- url:
278
+ URL of the web page:
216
279
  type: string
217
280
  description: URL of the web page to be tested.
218
- why:
281
+ reason for testing the web page:
219
282
  type: string
220
283
  description: Reason for testing the page.
221
284
 
@@ -273,7 +336,7 @@ components:
273
336
  for you:
274
337
  type: string
275
338
  format: uri
276
- description: URL for an agent to request the next tier of detail.
339
+ description: URL for an LLM to request the next tier of detail.
277
340
  for humans:
278
341
  type: string
279
342
  format: uri
@@ -343,7 +406,7 @@ components:
343
406
  whether a later report about the same page exists:
344
407
  type: boolean
345
408
  description: If true, a more recent report about this page is available. If you want the latest results, use that report instead.
346
- URLs for incrementally getting facts from the report:
409
+ URLs for more details:
347
410
  $ref: '#/components/schemas/NextTierURLs'
348
411
  size of the report in bytes:
349
412
  type: integer
@@ -354,7 +417,7 @@ components:
354
417
  Target:
355
418
  type: object
356
419
  properties:
357
- what:
420
+ description:
358
421
  type: string
359
422
  description: All or part of a description of the web page. If the page is the home page of an organization, the description is the name of the organization (e.g., “Earthjustice”). Otherwise, the description appends minimal differentiating words to the name of the organization (e.g., “Earthjustice Donate”), without the word “page”.
360
423
  hostname:
@@ -363,12 +426,12 @@ components:
363
426
 
364
427
  ReportListResponse:
365
428
  allOf:
366
- - $ref: '#/components/schemas/CommonResponseFields'
429
+ - $ref: '#/components/schemas/SharedFacts'
367
430
  - type: object
368
431
  properties:
369
- available reports:
432
+ response content:
370
433
  type: array
371
- description: One entry per available Kilotest report, in alphabetical order by page description and, in case of multiple reports per page, in order of creation date and time. Reports are matched by page description, not page URL, so, if only the URL of a page has changed between reports, the reports are treated as reports about the same page.
434
+ description: One entry per available Kilotest report, in alphabetical order by page description and, in case of multiple reports per page, in order of creation date and time. Whether two reports are about the same page is determined by the page descriptions, not page URLs.
372
435
  items:
373
436
  $ref: '#/components/schemas/ReportListItem'
374
437
 
@@ -440,59 +503,51 @@ components:
440
503
  items:
441
504
  $ref: '#/components/schemas/IssueEntry'
442
505
 
443
- ReportIssuesResponse:
506
+ IssueSummary:
507
+ type: object
508
+ properties:
509
+ identifier:
510
+ type: string
511
+ summary:
512
+ type: string
513
+ impact on a user:
514
+ type: string
515
+ priority:
516
+ type: string
517
+ enum:
518
+ - lowest
519
+ - low
520
+ - high
521
+ - highest
522
+ URLs for more details:
523
+ $ref: '#/components/schemas/NextTierURLs'
524
+
525
+ ReportSummaryResponse:
444
526
  allOf:
445
- - $ref: '#/components/schemas/CommonResponseFields'
527
+ - $ref: '#/components/schemas/SharedFacts'
446
528
  - type: object
447
529
  properties:
448
- report:
449
- type: object
450
- properties:
451
- identifier:
452
- type: string
453
- creation date:
454
- type: string
455
- format: date-time
456
- days since the creation date:
457
- type: integer
458
- tested web page:
530
+ response content:
459
531
  type: object
460
532
  properties:
461
- description:
462
- type: string
463
- URL:
464
- type: string
465
- format: uri
466
- rule engines that tried to test the page:
467
- type: array
468
- items:
469
- $ref: '#/components/schemas/RuleEngineInfo'
470
- rule engines that were unable to test the page:
471
- type: array
472
- items:
473
- $ref: '#/components/schemas/RuleEngineFailure'
474
- rule engines that reported issues:
475
- $ref: '#/components/schemas/RuleEnginesSummary'
476
- number of issues reported:
477
- type: object
478
- properties:
479
- total:
533
+ rule engines that tried to test the page:
534
+ type: array
535
+ items:
536
+ $ref: '#/components/schemas/RuleEngineInfo'
537
+ rule engines that could not test the page:
538
+ type: array
539
+ items:
540
+ $ref: '#/components/schemas/RuleEngineFailure'
541
+ names of rule engines that reported rule violations:
542
+ type: array
543
+ items:
544
+ type: string
545
+ number of elements reported as violators:
480
546
  type: integer
481
- by priority:
482
- type: object
483
- properties:
484
- highest priority:
485
- type: integer
486
- high priority:
487
- type: integer
488
- low priority:
489
- type: integer
490
- lowest priority:
491
- type: integer
492
- number of HTML elements reported as exhibiting issues:
493
- type: integer
494
- issues reported:
495
- $ref: '#/components/schemas/IssuesByPriority'
547
+ issues revealed:
548
+ type: array
549
+ items:
550
+ $ref: '#/components/schemas/IssueSummary'
496
551
 
497
552
  HTMLElementDetail:
498
553
  type: object
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jrpool/kilotest",
3
- "version": "37.1.0",
3
+ "version": "38.1.0",
4
4
  "description": "An ensemble testing service with a focus on accessibility",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -21,9 +21,17 @@ exports.answer = async authCode => {
21
21
  for (const targetData of targetsData) {
22
22
  const [timeStamp, jobID] = targetData.jobName.split('-');
23
23
  // Reannotate it.
24
- await annotateReport(ruleIDs, timeStamp, jobID);
24
+ const annotationError = await annotateReport(ruleIDs, timeStamp, jobID);
25
+ // If this failed:
26
+ if (annotationError) {
27
+ // Return an error page.
28
+ return {
29
+ status: 'error',
30
+ message: annotationError
31
+ };
32
+ }
25
33
  }
26
- // Get the answer page.
34
+ // If every annotation succeeded, get the answer page.
27
35
  let answerPage = await fs.readFile(path.join(__dirname, 'index.html'), 'utf8');
28
36
  // Return it.
29
37
  return {
@@ -18,11 +18,18 @@ const populateQuery = async query => {
18
18
  const reClassified = {};
19
19
  // For each target:
20
20
  for (const targetLog of targetLogs) {
21
- const {jobName} = targetLog;
21
+ const {jobName = '-'} = targetLog;
22
22
  // Get the latest report on it.
23
23
  const report = await getReport(... jobName.split('-'));
24
- const {acts} = report;
25
- // For each act in the report:
24
+ const {acts = [], error} = report;
25
+ // If this failed:
26
+ if (error) {
27
+ // Populate the query with the reason.
28
+ query.error = error;
29
+ // Stop populating the query.
30
+ return;
31
+ }
32
+ // Otherwise, i.e. if it succeeded, for each act in the report:
26
33
  acts.forEach(act => {
27
34
  const {result, type, which} = act;
28
35
  // If it is a test act with standard instances:
@@ -100,7 +107,15 @@ exports.answer = async () => {
100
107
  const query = {};
101
108
  // Create a query to replace placeholders.
102
109
  await populateQuery(query);
103
- // Get the template.
110
+ // If the query reports an error:
111
+ if (query.error) {
112
+ // Return the error.
113
+ return {
114
+ status: 'error',
115
+ message: query.error
116
+ };
117
+ }
118
+ // Otherwise, i.e. if the query does not report an error, get the template.
104
119
  let answerPage = await fs.readFile(path.join(__dirname, 'index.html'), 'utf8');
105
120
  // Replace its placeholders.
106
121
  Object.keys(query).forEach(param => {
@@ -22,7 +22,15 @@ exports.answer = async (_, search) => {
22
22
  if (authCode === process.env.AUTH_CODE) {
23
23
  // Get the log of the report.
24
24
  const log = await getLog(... jobName.split('-'));
25
- // Add a hiddenness property to the log.
25
+ // If this failed:
26
+ if (log.error) {
27
+ // Return why.
28
+ return {
29
+ status: 'error',
30
+ message: log.error
31
+ }
32
+ }
33
+ // Otherwise, i.e. if it succeeded, add a hiddenness property to the log.
26
34
  log.hidden = true;
27
35
  // Save the updated log.
28
36
  await fs.writeFile(path.join(logsPath, `${jobName}.json`), getJSON(log));
@@ -37,13 +45,24 @@ exports.answer = async (_, search) => {
37
45
  }
38
46
  }
39
47
  const reportFileNames = await fs.readdir(reportsPath);
48
+ // Initialize an array of report specifications.
40
49
  const reportSpecs = [];
41
50
  // For each report:
42
51
  for (const reportFileName of reportFileNames) {
43
52
  const [timeStamp, jobID] = reportFileName.slice(0, -5).split('-');
44
53
  // Get its log.
45
54
  const log = await getLog(timeStamp, jobID);
55
+ // If this failed:
56
+ if (log.error) {
57
+ // Return why.
58
+ return {
59
+ status: 'error',
60
+ message: log.error
61
+ }
62
+ }
63
+ // Otherwise, i.e. if it succeeded:
46
64
  const {what, hidden} = log;
65
+ // Add the report to the array.
47
66
  reportSpecs.push({
48
67
  what,
49
68
  timeStamp,
@@ -24,8 +24,16 @@ const getIssueFacts = async (timeStamp, jobID, issue) => {
24
24
  const wcagType = wcag.length === 3 ? 'guideline' : 'success criterion';
25
25
  // Get the report.
26
26
  const report = await getReport(timeStamp, jobID);
27
+ const {acts, catalog, error} = report;
28
+ // If this failed:
29
+ if (error) {
30
+ // Return why.
31
+ return {
32
+ status: 'error',
33
+ message: error
34
+ };
35
+ }
27
36
  const violatorIndexSet = new Set();
28
- const {acts, catalog} = report;
29
37
  // For each act of the report:
30
38
  acts.forEach(act => {
31
39
  // If it is a test act:
@@ -56,7 +64,10 @@ const getIssueFacts = async (timeStamp, jobID, issue) => {
56
64
  'names': reporters.map(tool => tool.toolName)
57
65
  },
58
66
  'number of HTML elements reported as exhibiting the issue': violatorCount,
59
- 'HTML elements reported as exhibiting the issue': Array.from(violatorIndexSet).map(index => ({
67
+ 'HTML elements reported as exhibiting the issue': Array
68
+ .from(violatorIndexSet)
69
+ .filter(index => catalog[index])
70
+ .map(index => ({
60
71
  identifier: String(index),
61
72
  'tag name': catalog[index].tagName,
62
73
  'id attribute': catalog[index].id,
@@ -82,11 +93,19 @@ exports.response = async args => {
82
93
  }
83
94
  // Otherwise, i.e. if the report is available, get data on the report and its issues.
84
95
  const data = await getData(timeStamp, jobID);
85
- const {pageData, issuesData} = data;
96
+ const {error, issuesData, pageData} = data;
97
+ // If this failed:
98
+ if (error) {
99
+ // Return why.
100
+ return {
101
+ status: 'error',
102
+ message: error
103
+ };
104
+ }
86
105
  const {what, url, daysAgo} = pageData;
87
106
  const {issueCount, issues, preventions, reporterCount, reporters, violatorCount} = issuesData;
88
107
  let issue;
89
- // Get the level of and the data on the issue.
108
+ // Otherwise, i.e. if it succeeded, get the level of and the data on the issue.
90
109
  const issueLevel = [4, 3, 2, 1].find(level => {
91
110
  issue = issues[level].find(issue => issue.issueID === issueID);
92
111
  return issue;
@@ -116,14 +135,14 @@ exports.response = async args => {
116
135
  },
117
136
  method: 'GET',
118
137
  URLs: {
119
- 'URL of your request': `${thisHost}/api/reportIssue/${issueID}/${timeStamp}/${jobID}`,
120
- 'equivalent URL for humans': `${thisHost}/reportIssue.html/${issueID}/${timeStamp}/${jobID}`
138
+ 'for you': `${thisHost}/api/reportIssue/${issueID}/${timeStamp}/${jobID}`,
139
+ 'for humans': `${thisHost}/reportIssue.html/${issueID}/${timeStamp}/${jobID}`
121
140
  },
122
141
  'closest ancestor request': {
123
- identifier: 'describeQualityOfOneWebPage',
124
- description: 'Describe the quality of one web page.',
142
+ identifier: 'summarizeOneReport',
143
+ description: 'Summarize one report.',
125
144
  URLs: {
126
- 'for you': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
145
+ 'for you': `${thisHost}/api/reportSummary/${timeStamp}/${jobID}`,
127
146
  'for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
128
147
  }
129
148
  }