@jrpool/kilotest 37.1.0 → 38.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/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.0.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
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  index.js
3
- Answers the diagnoses question.
3
+ Answers the reportIssue question.
4
4
  */
5
5
 
6
6
  // IMPORTS
@@ -25,10 +25,26 @@ const path = require('path');
25
25
 
26
26
  // Adds parameters to a query for the answer page.
27
27
  const populateQuery = async (issueID, timeStamp, jobID, query) => {
28
- // Add facts about the issue to the query.
29
- query.issue = issues[issueID].summary;
28
+ // Get descriptions of the page facts.
30
29
  const pageDataStrings = await getPageDataStrings(timeStamp, jobID);
31
- const {what, url, urlLink, testInfo} = pageDataStrings;
30
+ // If this failed:
31
+ if (pageDataStrings.error) {
32
+ // Populate the query with the reason.
33
+ query.error = pageDataStrings.error;
34
+ // Stop populating the query.
35
+ return;
36
+ }
37
+ // Otherwise, i.e. if it succeeded, add the issue summary to the query.
38
+ query.issue = issues[issueID]?.summary;
39
+ // If adding the issue summary failed:
40
+ if (! query.issue) {
41
+ // Populate the query with the reason.
42
+ query.error = 'Issue not found';
43
+ // Stop populating the query.
44
+ return;
45
+ }
46
+ const {testInfo, url, urlLink, what} = pageDataStrings;
47
+ // Add page facts to the query.
32
48
  query.target = what;
33
49
  query.urlLink = urlLink;
34
50
  query.testInfo = testInfo;
@@ -44,6 +60,14 @@ const populateQuery = async (issueID, timeStamp, jobID, query) => {
44
60
  // Get the report.
45
61
  const report = await getReport(timeStamp, jobID);
46
62
  const {acts, catalog} = report;
63
+ // If this failed:
64
+ if (report.error) {
65
+ // Populate the query with the reason.
66
+ query.error = report.error;
67
+ // Stop populating the query.
68
+ return;
69
+ }
70
+ // Otherwise, i.e. if it succeeded, get the test acts of the report.
47
71
  const testActs = acts.filter(act => act.type === 'test');
48
72
  // For each test act:
49
73
  testActs.forEach(act => {
@@ -159,7 +183,15 @@ exports.answer = async pageArgs => {
159
183
  const query = {};
160
184
  // Create a query to replace the placeholders.
161
185
  await populateQuery(issueID, timeStamp, jobID, query);
162
- // If the test specifications are valid:
186
+ // If this failed:
187
+ if (query.error) {
188
+ // Return the error.
189
+ return {
190
+ status: 'error',
191
+ message: query.error
192
+ };
193
+ }
194
+ // Otherwise, if it succeeded and the report facts were obtained:
163
195
  if (query.testInfo) {
164
196
  // Get the template.
165
197
  let answerPage = await fs.readFile(path.join(__dirname, 'index.html'), 'utf8');
@@ -173,9 +205,9 @@ exports.answer = async pageArgs => {
173
205
  answerPage
174
206
  };
175
207
  }
176
- // Otherwise, report this.
208
+ // Otherwise, i.e. if the report facts were not obtained, report this.
177
209
  return {
178
210
  status: 'error',
179
- message: 'Invalid report specification'
211
+ message: 'Report facts not obtained'
180
212
  };
181
213
  };
@@ -24,20 +24,24 @@ const populateQuery = async (timeStamp, jobID, query) => {
24
24
  // Get data on the target and its issues according to the report.
25
25
  const data = await getData(timeStamp, jobID);
26
26
  const {pageData, issuesData} = data;
27
- // If the page data are invalid:
28
- if (typeof pageData === 'string') {
29
- // Return this.
30
- return pageData;
27
+ // If this failed:
28
+ if (data.error) {
29
+ // Populate the query with the reason.
30
+ query.error = data.error;
31
+ // Stop populating the query.
32
+ return;
31
33
  }
32
- // Otherwise, if the issues data are invalid:
33
- if (typeof issuesData === 'string') {
34
- // Return this.
35
- return issuesData;
36
- }
37
- // Otherwise, get fact descriptions for the target.
34
+ // Otherwise, i.e. if it succeeded, get fact descriptions for the target.
38
35
  const pageInfo = await getPageDataStrings(timeStamp, jobID, pageData);
39
- const {what, urlLink, testInfo} = pageInfo;
40
- // Add target data to the query.
36
+ const {testInfo, urlLink, what} = pageInfo;
37
+ // If this failed:
38
+ if (pageInfo.error) {
39
+ // Populate the query with the reason.
40
+ query.error = pageInfo.error;
41
+ // Stop populating the query.
42
+ return;
43
+ }
44
+ // Otherwise, i.e. if it succeeded, add target data to the query.
41
45
  query.target = what;
42
46
  query.urlLink = urlLink;
43
47
  query.testInfo = testInfo;
@@ -154,7 +158,15 @@ exports.answer = async pageArgs => {
154
158
  const query = {};
155
159
  // Create a query to replace the placeholders.
156
160
  await populateQuery(timeStamp, jobID, query);
157
- // If the report facts were obtained:
161
+ // If this failed:
162
+ if (query.error) {
163
+ // Return the error.
164
+ return {
165
+ status: 'error',
166
+ message: query.error
167
+ };
168
+ }
169
+ // Otherwise, if it succeeded and the report facts were obtained:
158
170
  if (query.testInfo) {
159
171
  // Get the template.
160
172
  let answerPage = await fs.readFile(path.join(__dirname, 'index.html'), 'utf8');
@@ -171,6 +183,6 @@ exports.answer = async pageArgs => {
171
183
  // Otherwise, i.e. if they were not obtained, report this.
172
184
  return {
173
185
  status: 'error',
174
- message: 'Report processing failed'
186
+ message: 'Report facts not obtained'
175
187
  };
176
188
  };