@jrpool/kilotest 59.1.4 → 60.0.1
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/README.md +2 -5
- package/api/awaitTest.test.ts +9 -9
- package/api/awaitTest.ts +12 -12
- package/api/getReport.test.ts +4 -4
- package/api/getReport.ts +9 -9
- package/api/listDiagnoses.test.ts +14 -14
- package/api/listDiagnoses.ts +8 -8
- package/api/listIssues.test.ts +15 -15
- package/api/listIssues.ts +18 -20
- package/api/listPages.test.ts +2 -2
- package/api/listPages.ts +4 -4
- package/api/listViolators.test.ts +10 -10
- package/api/listViolators.ts +10 -10
- package/api/orderNewTest.test.ts +1 -2
- package/api/orderNewTest.ts +3 -4
- package/api/orderRetest.test.ts +10 -10
- package/api/orderRetest.ts +13 -14
- package/api/requestRetest.test.ts +11 -11
- package/api/requestRetest.ts +11 -11
- package/api/routes.ts +9 -11
- package/api/schemas.ts +18 -28
- package/api/util.test.ts +2 -2
- package/api/util.ts +7 -7
- package/capability.md +4 -4
- package/docs/AI-TOOLS.md +43 -1
- package/docs/decisions/009-report-id.md +16 -0
- package/index.test.ts +91 -41
- package/index.ts +66 -15
- package/lhm.plugin.json +33 -119
- package/llms-full.txt +18 -24
- package/llms.txt +12 -12
- package/mcp.test.ts +11 -20
- package/mcp.ts +18 -18
- package/openapi-3.0.yaml +1847 -0
- package/openapi.yaml +38 -97
- package/package.json +1 -1
- package/routing.test.ts +1 -1
- package/scripts/generate-openapi.ts +83 -1
- package/server.json +1 -1
- package/util.test.ts +32 -33
- package/util.ts +47 -43
- package/web/hideReportForm/index.ts +5 -6
- package/web/listDiagnoses/index.ts +4 -5
- package/web/listDiagnoses/listDiagnoses.test.ts +13 -13
- package/web/listIssues/index.ts +11 -12
- package/web/listIssues/listIssues.test.ts +24 -24
- package/web/listPages/index.ts +2 -2
- package/web/listPages/listPages.test.ts +2 -2
- package/web/listTopIssues/index.ts +2 -2
- package/web/listViolators/index.ts +5 -6
- package/web/listViolators/listViolators.test.ts +12 -12
- package/web/reannotate/index.ts +3 -3
- package/web/reannotateForm/index.ts +1 -2
- package/web/reportDeletion.ts +9 -12
- package/web/requestRetest/index.ts +2 -2
- package/web/requestRetest/requestRetest.test.ts +7 -7
- package/web/requestRetestForm/index.html +2 -2
- package/web/requestRetestForm/index.ts +3 -4
- package/web/requestRetestForm/requestRetestForm.test.ts +7 -8
- package/web/unhideReportForm/index.ts +4 -6
- package/web/util.test.ts +29 -29
- package/web/util.ts +1 -1
|
@@ -10,9 +10,9 @@ import {populateTemplate, processTestRequest} from '../../util.ts';
|
|
|
10
10
|
// FUNCTIONS
|
|
11
11
|
|
|
12
12
|
export const answer = async (pageArgs: string, reason: string) => {
|
|
13
|
-
const
|
|
13
|
+
const reportID = pageArgs;
|
|
14
14
|
// Process the request. This resolves the cited report's description and URL itself.
|
|
15
|
-
const processResult = await processTestRequest(reason, {
|
|
15
|
+
const processResult = await processTestRequest(reason, {reportID});
|
|
16
16
|
// If the cited report does not exist:
|
|
17
17
|
if (processResult.result === 'nonreport') {
|
|
18
18
|
// Report this.
|
|
@@ -65,7 +65,7 @@ test('answer returns ok with a populated answer page for a valid retest request'
|
|
|
65
65
|
// Require the module after DB_DIR is set.
|
|
66
66
|
const {answer} = await import('./index.ts');
|
|
67
67
|
// Use the 260101T0001-ct report (All CantTell Page, https://example.com/canttell).
|
|
68
|
-
const result: any = await answer('260101T0001
|
|
68
|
+
const result: any = await answer('260101T0001-ct', 'Because changes were made');
|
|
69
69
|
assert.equal(result.status, 'ok');
|
|
70
70
|
assert.ok(result.answerPage, 'answerPage should be present');
|
|
71
71
|
// Verify the description and reason placeholders were replaced with the report target.
|
|
@@ -86,7 +86,7 @@ test('answer returns ok with a populated answer page for a valid retest request'
|
|
|
86
86
|
test('answer returns an error when the report does not exist', async () => {
|
|
87
87
|
const {answer} = await import('./index.ts');
|
|
88
88
|
// Use a nonexistent report timestamp and jobID.
|
|
89
|
-
const result: any = await answer('990101T0000
|
|
89
|
+
const result: any = await answer('990101T0000-xxx', 'Because changes were made');
|
|
90
90
|
assert.equal(result.status, 'error');
|
|
91
91
|
assert.equal(result.message, 'Invalid request');
|
|
92
92
|
});
|
|
@@ -94,8 +94,8 @@ test('answer returns an error when the report does not exist', async () => {
|
|
|
94
94
|
test('answer returns an error for a duplicate retest request', async () => {
|
|
95
95
|
const {answer} = await import('./index.ts');
|
|
96
96
|
// Submit the same retest request twice; the second is a duplicate.
|
|
97
|
-
await answer('260101T0001
|
|
98
|
-
const result: any = await answer('260101T0001
|
|
97
|
+
await answer('260101T0001-ct', 'Because changes were made');
|
|
98
|
+
const result: any = await answer('260101T0001-ct', 'Because changes were made');
|
|
99
99
|
assert.equal(result.status, 'error');
|
|
100
100
|
assert.equal(result.message, 'Test request duplicates an already submitted request');
|
|
101
101
|
});
|
|
@@ -103,7 +103,7 @@ test('answer returns an error for a duplicate retest request', async () => {
|
|
|
103
103
|
test('answer returns an error when the cited report has been superseded', async () => {
|
|
104
104
|
const {answer} = await import('./index.ts');
|
|
105
105
|
// 260101T0000-mix (Mixed Outcomes) is superseded by 260202T0000-new.
|
|
106
|
-
const result: any = await answer('260101T0000
|
|
106
|
+
const result: any = await answer('260101T0000-mix', 'Because changes were made');
|
|
107
107
|
assert.equal(result.status, 'error');
|
|
108
108
|
assert.equal(result.message, 'A later report about the page is already available');
|
|
109
109
|
});
|
|
@@ -119,7 +119,7 @@ test('answer returns an error when a matching job is already claimed or queued',
|
|
|
119
119
|
target: {what: 'All CantTell Page', url: 'https://example.com/unrelated'}
|
|
120
120
|
}));
|
|
121
121
|
try {
|
|
122
|
-
const result: any = await answer('260101T0001
|
|
122
|
+
const result: any = await answer('260101T0001-ct', 'Because changes were made');
|
|
123
123
|
assert.equal(result.status, 'error');
|
|
124
124
|
assert.equal(result.message, 'A request to test a page with the same description or URL is already approved');
|
|
125
125
|
}
|
|
@@ -135,7 +135,7 @@ test('answer returns an error with a fallback channel when the request queue is
|
|
|
135
135
|
timeStamp: '260101T0000', description: `Filler Page ${i}`, reason: 'Because filler'
|
|
136
136
|
}));
|
|
137
137
|
await fs.writeFile(testRequestsPath, JSON.stringify({'https://example.com/filler': filler}));
|
|
138
|
-
const result: any = await answer('260101T0001
|
|
138
|
+
const result: any = await answer('260101T0001-ct', 'Because changes were made');
|
|
139
139
|
assert.equal(result.status, 'error');
|
|
140
140
|
assert.ok(result.message.startsWith('Too many requests are awaiting approval right now.'));
|
|
141
141
|
assert.ok(result.message.includes('https://github.com/jrpool/kilotest/issues'));
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
<body>
|
|
14
14
|
<main>
|
|
15
15
|
<h1><a href="/">Kilotest</a>: Retest recommendation for __target__</h1>
|
|
16
|
-
<p>The __target__ page was <a href="/listIssues.html/
|
|
16
|
+
<p>The __target__ page was <a href="/listIssues.html/__reportID__">last tested</a> __ago__ ago by job <code>__reportID__</code> on __dateTime__.</p>
|
|
17
17
|
<p>To recommend a retest, submit the following form.</p>
|
|
18
|
-
<form action="/requestRetest.html/
|
|
18
|
+
<form action="/requestRetest.html/__reportID__" method="post">
|
|
19
19
|
<p><label>
|
|
20
20
|
Why retest the page (answer required)?<br>
|
|
21
21
|
<input size="70" minlength="5" maxlength="100" name="why" required>
|
|
@@ -12,12 +12,12 @@ import {getAgoString, getDateTimeString} from '../util.ts';
|
|
|
12
12
|
|
|
13
13
|
// Returns a retest recommendation form.
|
|
14
14
|
export const answer = async (pageArgs: string) => {
|
|
15
|
-
const
|
|
15
|
+
const reportID = pageArgs;
|
|
16
16
|
// Get data on the latest available reports.
|
|
17
17
|
const reportExtracts = await getReportExtracts(true);
|
|
18
18
|
// Get data on the report whose page is to be retested.
|
|
19
19
|
const reportExtract = reportExtracts.find(
|
|
20
|
-
(reportExtract: any) => reportExtract.
|
|
20
|
+
(reportExtract: any) => reportExtract.id === reportID
|
|
21
21
|
);
|
|
22
22
|
// Initialize the page description.
|
|
23
23
|
let target: string;
|
|
@@ -35,8 +35,7 @@ export const answer = async (pageArgs: string) => {
|
|
|
35
35
|
const reportTime = new Date(reportExtract?.reportTime ?? NaN);
|
|
36
36
|
const query: Record<string, string> = {
|
|
37
37
|
target,
|
|
38
|
-
|
|
39
|
-
jobID,
|
|
38
|
+
reportID,
|
|
40
39
|
ago: getAgoString(reportTime),
|
|
41
40
|
dateTime: getDateTimeString(reportTime)
|
|
42
41
|
};
|
|
@@ -30,7 +30,7 @@ after(() => {
|
|
|
30
30
|
// TESTS
|
|
31
31
|
|
|
32
32
|
test('requestRetestForm returns ok with the page name for a valid report', async () => {
|
|
33
|
-
const result = await answer('260202T0000
|
|
33
|
+
const result = await answer('260202T0000-new');
|
|
34
34
|
assert.equal(result.status, 'ok');
|
|
35
35
|
assert.ok(result.answerPage);
|
|
36
36
|
const html = parse(result.answerPage);
|
|
@@ -38,11 +38,11 @@ test('requestRetestForm returns ok with the page name for a valid report', async
|
|
|
38
38
|
assert.ok(title?.includes('Mixed Outcomes'));
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
test('requestRetestForm populates the form action with the
|
|
42
|
-
const result = await answer('260202T0000
|
|
41
|
+
test('requestRetestForm populates the form action with the reportID', async () => {
|
|
42
|
+
const result = await answer('260202T0000-new');
|
|
43
43
|
const html = parse(result.answerPage);
|
|
44
44
|
const form = html.querySelector('form');
|
|
45
|
-
assert.equal(form?.getAttribute('action'), '/requestRetest.html/260202T0000
|
|
45
|
+
assert.equal(form?.getAttribute('action'), '/requestRetest.html/260202T0000-new');
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
test('requestRetestForm shows the fallback message for a nonexistent report', async () => {
|
|
@@ -52,7 +52,7 @@ test('requestRetestForm shows the fallback message for a nonexistent report', as
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
test('requestRetestForm dates the report by its completion time', async () => {
|
|
55
|
-
const result = await answer('260202T0000
|
|
55
|
+
const result = await answer('260202T0000-new');
|
|
56
56
|
assert.ok(result.answerPage.includes('on 2026-02-02 at 00:10'));
|
|
57
57
|
});
|
|
58
58
|
|
|
@@ -63,10 +63,9 @@ test('requestRetestForm describes the time of a nonexistent report as unknown',
|
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
test('requestRetestForm includes the ago and dateTime placeholders replaced', async () => {
|
|
66
|
-
const result = await answer('260202T0000
|
|
66
|
+
const result = await answer('260202T0000-new');
|
|
67
67
|
assert.ok(!result.answerPage.includes('__ago__'));
|
|
68
68
|
assert.ok(!result.answerPage.includes('__dateTime__'));
|
|
69
69
|
assert.ok(!result.answerPage.includes('__target__'));
|
|
70
|
-
assert.ok(!result.answerPage.includes('
|
|
71
|
-
assert.ok(!result.answerPage.includes('__jobID__'));
|
|
70
|
+
assert.ok(!result.answerPage.includes('__reportID__'));
|
|
72
71
|
});
|
|
@@ -59,13 +59,11 @@ export const answer = async (_: any, search: string, method: string) => {
|
|
|
59
59
|
// Get the report.
|
|
60
60
|
const report = JSON.parse(reportJSON);
|
|
61
61
|
const {id, target} = report;
|
|
62
|
-
const [timeStamp, jobID] = id.split('-');
|
|
63
62
|
const {what: description} = target;
|
|
64
63
|
// Add its data to the array.
|
|
65
64
|
reportsData.push({
|
|
66
65
|
description,
|
|
67
|
-
|
|
68
|
-
jobID,
|
|
66
|
+
id,
|
|
69
67
|
reportTime: getReportEndTime(report)
|
|
70
68
|
});
|
|
71
69
|
}
|
|
@@ -80,12 +78,12 @@ export const answer = async (_: any, search: string, method: string) => {
|
|
|
80
78
|
const margin = ' '.repeat(12);
|
|
81
79
|
// For each report:
|
|
82
80
|
reportsData.forEach(data => {
|
|
83
|
-
const {
|
|
81
|
+
const {id, description, reportTime} = data;
|
|
84
82
|
const when = getDateTimeString(reportTime);
|
|
85
|
-
const specString = `${description} (job <code>${
|
|
83
|
+
const specString = `${description} (job <code>${id}</code> completed ${when})`;
|
|
86
84
|
// Add a line with a radio button to unhide it.
|
|
87
85
|
lines.push(
|
|
88
|
-
`${margin}<p><input type="radio" name="report" value="${
|
|
86
|
+
`${margin}<p><input type="radio" name="report" value="${id}"> ${specString}</p>`
|
|
89
87
|
);
|
|
90
88
|
});
|
|
91
89
|
const query: Record<string, string> = {
|
package/web/util.test.ts
CHANGED
|
@@ -119,8 +119,8 @@ test('makeBreakable inserts wbr before non-initial slashes', () => {
|
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
// Returns a fixture report, failing the test if it is not usable.
|
|
122
|
-
const getFixtureReport = async (
|
|
123
|
-
const report = await getReport(
|
|
122
|
+
const getFixtureReport = async (reportID: string) => {
|
|
123
|
+
const report = await getReport(reportID);
|
|
124
124
|
if (isReportError(report)) {
|
|
125
125
|
assert.fail(report.error);
|
|
126
126
|
}
|
|
@@ -128,19 +128,19 @@ const getFixtureReport = async (timeStamp: string, jobID: string) => {
|
|
|
128
128
|
};
|
|
129
129
|
|
|
130
130
|
test('getPageData returns page data for a valid report', async () => {
|
|
131
|
-
const data = getPageData(await getFixtureReport('260101T0000
|
|
131
|
+
const data = getPageData(await getFixtureReport('260101T0000-mix'));
|
|
132
132
|
assert.equal(data.description, 'Mixed Outcomes');
|
|
133
133
|
assert.equal(data.url, 'https://example.com/mixed');
|
|
134
134
|
assert.equal(typeof data.daysAgo, 'number');
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
test('getReport returns an error for a nonexistent report', async () => {
|
|
138
|
-
const report = await getReport('999999T9999
|
|
138
|
+
const report = await getReport('999999T9999-xxx');
|
|
139
139
|
assert.ok(isReportError(report));
|
|
140
140
|
});
|
|
141
141
|
|
|
142
142
|
test('getPageDataStrings returns HTML strings for a valid report', async () => {
|
|
143
|
-
const strings = getPageDataStrings(await getFixtureReport('260101T0000
|
|
143
|
+
const strings = getPageDataStrings(await getFixtureReport('260101T0000-mix'));
|
|
144
144
|
assert.equal(strings.description, 'Mixed Outcomes');
|
|
145
145
|
assert.equal(strings.url, 'https://example.com/mixed');
|
|
146
146
|
assert.equal(strings.urlLink, '<a href="https://example.com/mixed">https://example.com/mixed</a>');
|
|
@@ -149,7 +149,7 @@ test('getPageDataStrings returns HTML strings for a valid report', async () => {
|
|
|
149
149
|
});
|
|
150
150
|
|
|
151
151
|
test('getPageDataStrings dates a report by its completion time, not by its job time stamp', async () => {
|
|
152
|
-
const report = await getFixtureReport('260101T0001
|
|
152
|
+
const report = await getFixtureReport('260101T0001-ct');
|
|
153
153
|
report.jobData.endTime = '26-03-04T05:06';
|
|
154
154
|
const strings = getPageDataStrings(report);
|
|
155
155
|
assert.equal(strings.description, 'All CantTell Page');
|
|
@@ -167,7 +167,7 @@ test('getDateTimeString describes an invalid date as unknown', () => {
|
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
test('getPageDataStrings derives the strings from the report object', async () => {
|
|
170
|
-
const report = await getFixtureReport('260101T0000
|
|
170
|
+
const report = await getFixtureReport('260101T0000-mix');
|
|
171
171
|
report.target.what = 'Custom Page';
|
|
172
172
|
const strings = getPageDataStrings(report);
|
|
173
173
|
assert.equal(strings.description, 'Custom Page');
|
|
@@ -188,7 +188,7 @@ test('getPageDataStrings reports a 1-day-old report as tested 1 day ago', () =>
|
|
|
188
188
|
|
|
189
189
|
test('getReportData returns data for a valid report', async () => {
|
|
190
190
|
const {getReportData} = await import('./util.ts');
|
|
191
|
-
const result = getReportData(await getFixtureReport('260101T0000
|
|
191
|
+
const result = getReportData(await getFixtureReport('260101T0000-mix'));
|
|
192
192
|
assert.equal(result.url, 'https://example.com/mixed');
|
|
193
193
|
assert.equal(result.jobName, '260101T0000-mix');
|
|
194
194
|
});
|
|
@@ -201,7 +201,7 @@ test('getReportData falls back to the engine ID for an unknown prevented engine'
|
|
|
201
201
|
const reportPath = path.join(reportsPath(), '260103T0000-unk.json');
|
|
202
202
|
await fs.writeFile(reportPath, JSON.stringify(reportJSON));
|
|
203
203
|
try {
|
|
204
|
-
const result = getReportData(await getFixtureReport('260103T0000
|
|
204
|
+
const result = getReportData(await getFixtureReport('260103T0000-unk'));
|
|
205
205
|
assert.ok(result.preventedEngineNames.includes('unknownEngine'));
|
|
206
206
|
}
|
|
207
207
|
finally {
|
|
@@ -211,7 +211,7 @@ test('getReportData falls back to the engine ID for an unknown prevented engine'
|
|
|
211
211
|
|
|
212
212
|
test('getPageFactsLines returns the about-page list lines for a report', async () => {
|
|
213
213
|
const {getReportData} = await import('./util.ts');
|
|
214
|
-
const report = await getFixtureReport('260101T0000
|
|
214
|
+
const report = await getFixtureReport('260101T0000-mix');
|
|
215
215
|
const lines = getPageFactsLines(getPageDataStrings(report), getReportData(report), ' ');
|
|
216
216
|
const html = lines.join('\n');
|
|
217
217
|
assert.ok(html.includes('<li>URL: <a href="https://example.com/mixed">'));
|
|
@@ -223,19 +223,19 @@ test('getPageFactsLines returns the about-page list lines for a report', async (
|
|
|
223
223
|
|
|
224
224
|
test('getPageFactsLines ends with a link to download the full report', async () => {
|
|
225
225
|
const {getReportData} = await import('./util.ts');
|
|
226
|
-
const report = await getFixtureReport('260101T0000
|
|
226
|
+
const report = await getFixtureReport('260101T0000-mix');
|
|
227
227
|
const lines = getPageFactsLines(getPageDataStrings(report), getReportData(report), '');
|
|
228
228
|
const topItems = parse(lines.join('\n')).querySelectorAll('ul:not(ul ul) > li');
|
|
229
229
|
const lastItem = topItems[topItems.length - 1]!;
|
|
230
230
|
assert.ok(topItems[topItems.length - 2]!.text.trim().startsWith('Summary of results:'));
|
|
231
|
-
assert.equal(lastItem.querySelector('a')?.getAttribute('href'), '/fullReport.json/260101T0000
|
|
231
|
+
assert.equal(lastItem.querySelector('a')?.getAttribute('href'), '/fullReport.json/260101T0000-mix');
|
|
232
232
|
assert.equal(lastItem.text.trim(), 'Download the full technical report (JSON)');
|
|
233
233
|
});
|
|
234
234
|
|
|
235
235
|
// Returns the 3 rule-engine amounts and the 3 summary amounts of the page facts of a report.
|
|
236
|
-
const getResultFacts = async (
|
|
236
|
+
const getResultFacts = async (reportID: string) => {
|
|
237
237
|
const {getReportData} = await import('./util.ts');
|
|
238
|
-
const report = await getFixtureReport(
|
|
238
|
+
const report = await getFixtureReport(reportID);
|
|
239
239
|
const lines = getPageFactsLines(getPageDataStrings(report), getReportData(report), '');
|
|
240
240
|
const items = parse(lines.join('\n')).querySelectorAll('li');
|
|
241
241
|
const itemTexts: string[] = items.map(li => li.text.trim());
|
|
@@ -263,21 +263,21 @@ const getResultFacts = async (timeStamp: string, jobID: string) => {
|
|
|
263
263
|
};
|
|
264
264
|
|
|
265
265
|
// Expected facts, hand-computed from the fixtures.
|
|
266
|
-
const expectedFacts: [string,
|
|
267
|
-
//
|
|
268
|
-
['260101T0000
|
|
269
|
-
['260202T0000
|
|
270
|
-
['260101T0001
|
|
271
|
-
['260101T0002
|
|
272
|
-
['260101T0005
|
|
273
|
-
['260101T0006
|
|
274
|
-
['260101T0008
|
|
275
|
-
['260101T0009
|
|
266
|
+
const expectedFacts: [string, number, number, number, number, number, number][] = [
|
|
267
|
+
// Report ID, engines called, engines able to test, reporting engines, violations, violators, issues.
|
|
268
|
+
['260101T0000-mix', 2, 2, 2, 3, 2, 2],
|
|
269
|
+
['260202T0000-new', 1, 1, 1, 1, 1, 1],
|
|
270
|
+
['260101T0001-ct', 1, 1, 0, 0, 0, 0],
|
|
271
|
+
['260101T0002-no', 1, 1, 1, 1, 1, 1],
|
|
272
|
+
['260101T0005-emp', 1, 1, 0, 0, 0, 0],
|
|
273
|
+
['260101T0006-prv', 2, 1, 1, 1, 1, 1],
|
|
274
|
+
['260101T0008-mul', 2, 2, 2, 4, 3, 1],
|
|
275
|
+
['260101T0009-brd', 3, 3, 1, 4, 4, 1]
|
|
276
276
|
];
|
|
277
277
|
|
|
278
|
-
for (const [
|
|
279
|
-
test(`getPageFactsLines gives correct rule-engine and summary amounts for ${
|
|
280
|
-
const facts = await getResultFacts(
|
|
278
|
+
for (const [reportID, called, tested, reporters, violations, violators, issues] of expectedFacts) {
|
|
279
|
+
test(`getPageFactsLines gives correct rule-engine and summary amounts for ${reportID}`, async () => {
|
|
280
|
+
const facts = await getResultFacts(reportID);
|
|
281
281
|
assert.equal(facts.called, called);
|
|
282
282
|
assert.equal(facts.tested, tested);
|
|
283
283
|
assert.equal(facts.reporters, reporters);
|
|
@@ -290,7 +290,7 @@ for (const [timeStamp, jobID, called, tested, reporters, violations, violators,
|
|
|
290
290
|
|
|
291
291
|
test('getIssueFactsLines returns the about-issue list lines for a report', async () => {
|
|
292
292
|
const {getIssueFactsLines} = await import('./util.ts');
|
|
293
|
-
const report = await getFixtureReport('260101T0000
|
|
293
|
+
const report = await getFixtureReport('260101T0000-mix');
|
|
294
294
|
const lines = getIssueFactsLines(report, 'linkNoText', ' ');
|
|
295
295
|
const html = lines.join('\n');
|
|
296
296
|
assert.ok(html.includes('<li>Why it matters:'));
|
|
@@ -303,7 +303,7 @@ test('getIssueFactsLines returns the about-issue list lines for a report', async
|
|
|
303
303
|
|
|
304
304
|
test('getViolatorFactsLines returns the about-violator list lines for a report', async () => {
|
|
305
305
|
const {getViolatorFactsLines} = await import('./util.ts');
|
|
306
|
-
const report = await getFixtureReport('260101T0000
|
|
306
|
+
const report = await getFixtureReport('260101T0000-mix');
|
|
307
307
|
const lines = getViolatorFactsLines(report, 'linkNoText', '0', null, ' ');
|
|
308
308
|
const html = lines.join('\n');
|
|
309
309
|
assert.ok(html.includes('<li>Tag name: <code>'));
|
package/web/util.ts
CHANGED
|
@@ -271,7 +271,7 @@ export const getPageDataStrings = (report: UsableReport): PageDataStrings => {
|
|
|
271
271
|
url,
|
|
272
272
|
urlLink: `<a href="${url}">${url}</a>`,
|
|
273
273
|
testInfo: `Tested ${daysAgo === 1 ? '1 day' : `${daysAgo} days`} ago on ${when} by job <code>${report.id}</code>`,
|
|
274
|
-
fullReportLink: `<a href="/fullReport.json/${report.id
|
|
274
|
+
fullReportLink: `<a href="/fullReport.json/${report.id}">Download the full technical report</a> (JSON)`
|
|
275
275
|
};
|
|
276
276
|
};
|
|
277
277
|
// Returns the lines of a list of facts about the page of an available report.
|