@jrpool/kilotest 43.0.2 → 44.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/aceconfig.js +1 -1
- package/api/getReport.js +1 -1
- package/api/listDiagnoses.js +2 -2
- package/api/listIssues.js +4 -4
- package/api/listReports.js +3 -3
- package/api/listViolators.js +3 -3
- package/api/requestRetest.js +3 -3
- package/api/requestTest.js +3 -3
- package/docs/AI-TOOLS.md +2 -2
- package/docs/SERVICE.md +5 -5
- package/index.html +2 -2
- package/index.js +31 -30
- package/llms-full.txt +8 -8
- package/llms.txt +7 -7
- package/package.json +1 -1
- package/robots.txt +8 -8
- package/sitemap.xml +3 -3
- package/util.js +25 -25
- package/web/{testOrder → enqueue}/index.js +6 -4
- package/web/{recActionForm → enqueueForm}/index.html +1 -1
- package/web/{recActionForm → enqueueForm}/index.js +1 -1
- package/web/{reportsExpungeForm → expungeReportsForm}/index.html +1 -1
- package/web/{reportsExpungeForm → expungeReportsForm}/index.js +4 -4
- package/web/{reportHideForm → hideReportForm}/index.html +1 -1
- package/web/{diagnoses → listDiagnoses}/index.js +7 -5
- package/web/{reportIssues → listIssues}/index.html +1 -1
- package/web/{reportIssues → listIssues}/index.js +12 -12
- package/web/{targets → listReports}/index.html +1 -1
- package/web/{targets → listReports}/index.js +11 -11
- package/web/{rules → listRules}/index.js +1 -1
- package/web/{issues → listTopIssues}/index.js +4 -4
- package/web/{reportIssue → listViolators}/index.js +6 -6
- package/web/manage/index.html +7 -7
- package/web/manage/index.js +1 -1
- package/web/{reportsPruneForm → pruneReportsForm}/index.html +1 -1
- package/web/{reportsPruneForm → pruneReportsForm}/index.js +4 -4
- package/web/reannotate/index.js +1 -1
- package/web/reannotateForm/index.js +11 -11
- package/web/{wcagRenew → renewWCAG}/index.js +1 -1
- package/web/{wcagRenewForm → renewWCAGForm}/index.html +1 -1
- package/web/{retestRec → requestRetest}/index.html +1 -1
- package/web/{retestRec → requestRetest}/index.js +4 -5
- package/web/{retestRecForm → requestRetestForm}/index.html +2 -2
- package/web/{retestRecForm → requestRetestForm}/index.js +1 -1
- package/web/{testRec → requestTest}/index.html +1 -1
- package/web/{testRec → requestTest}/index.js +5 -6
- package/web/{testRecForm → requestTestForm}/index.html +1 -1
- package/web/{testRecForm → requestTestForm}/index.js +2 -3
- package/web/{reportsRewindForm → rewindReportsForm}/index.html +1 -1
- package/web/{reportsRewindForm → rewindReportsForm}/index.js +4 -4
- package/web/tutorial/index.html +1 -1
- package/web/tutorial/index.js +1 -1
- package/web/{reportUnhideForm → unhideReportForm}/index.html +1 -1
- /package/web/{testOrder → enqueue}/index.html +0 -0
- /package/web/{reportHideForm → hideReportForm}/index.js +0 -0
- /package/web/{diagnoses → listDiagnoses}/index.html +0 -0
- /package/web/{rules → listRules}/index.html +0 -0
- /package/web/{issues → listTopIssues}/index.html +0 -0
- /package/web/{reportIssue → listViolators}/index.html +0 -0
- /package/web/{wcagRenew → renewWCAG}/index.html +0 -0
- /package/web/{wcagRenewForm → renewWCAGForm}/index.js +0 -0
- /package/web/{reportUnhideForm → unhideReportForm}/index.js +0 -0
package/aceconfig.js
CHANGED
package/api/getReport.js
CHANGED
|
@@ -56,7 +56,7 @@ exports.response = async args => {
|
|
|
56
56
|
},
|
|
57
57
|
'URLs of similar requests for web users': {
|
|
58
58
|
'this request': `${thisHost}/fullReport.json/${timeStamp}/${jobID}`,
|
|
59
|
-
'closest ancestor request': `${thisHost}/
|
|
59
|
+
'closest ancestor request': `${thisHost}/listIssues.html/${timeStamp}/${jobID}`
|
|
60
60
|
},
|
|
61
61
|
'response metadata': getResponseMetadata(),
|
|
62
62
|
'response content': responseContent
|
package/api/listDiagnoses.js
CHANGED
|
@@ -146,8 +146,8 @@ exports.response = async args => {
|
|
|
146
146
|
}
|
|
147
147
|
},
|
|
148
148
|
'URLs of similar requests for web users': {
|
|
149
|
-
'this request': `${thisHost}/
|
|
150
|
-
'closest ancestor request': `${thisHost}/
|
|
149
|
+
'this request': `${thisHost}/listDiagnoses.html/${issueID}/${timeStamp}/${jobID}/${catalogIndex}`,
|
|
150
|
+
'closest ancestor request': `${thisHost}/listViolators.html/${issueID}/${timeStamp}/${jobID}`
|
|
151
151
|
},
|
|
152
152
|
'response metadata': getResponseMetadata(),
|
|
153
153
|
'response content': responseContent
|
package/api/listIssues.js
CHANGED
|
@@ -172,7 +172,7 @@ exports.response = async args => {
|
|
|
172
172
|
};
|
|
173
173
|
// Add instructions for a web user to request a retest.
|
|
174
174
|
responseContent['how a web user can request that the page be retested'] = {
|
|
175
|
-
URL: `${thisHost}/
|
|
175
|
+
URL: `${thisHost}/requestRetestForm.html/${timeStamp}/${jobID}`
|
|
176
176
|
};
|
|
177
177
|
}
|
|
178
178
|
// Sort the data about issues by summary.
|
|
@@ -191,7 +191,7 @@ exports.response = async args => {
|
|
|
191
191
|
method: 'GET',
|
|
192
192
|
URL: `${thisHost}/api/listViolators/${id}/${timeStamp}/${jobID}`
|
|
193
193
|
},
|
|
194
|
-
'web users can get details about the issue at': `${thisHost}/
|
|
194
|
+
'web users can get details about the issue at': `${thisHost}/listViolators.html/${id}/${timeStamp}/${jobID}`
|
|
195
195
|
};
|
|
196
196
|
});
|
|
197
197
|
// Add the basics about the issues to the response content.
|
|
@@ -214,8 +214,8 @@ exports.response = async args => {
|
|
|
214
214
|
}
|
|
215
215
|
},
|
|
216
216
|
'URLs of similar requests for web users': {
|
|
217
|
-
'this request': `${thisHost}/
|
|
218
|
-
'closest ancestor request': `${thisHost}/
|
|
217
|
+
'this request': `${thisHost}/listIssues.html/${timeStamp}/${jobID}`,
|
|
218
|
+
'closest ancestor request': `${thisHost}/listReports.html`
|
|
219
219
|
},
|
|
220
220
|
'response metadata': getResponseMetadata(),
|
|
221
221
|
'response content': responseContent
|
package/api/listReports.js
CHANGED
|
@@ -34,7 +34,7 @@ exports.response = async () => {
|
|
|
34
34
|
method: 'GET',
|
|
35
35
|
URL: `${thisHost}/api/listIssues/${timeStamp}/${jobID}`
|
|
36
36
|
};
|
|
37
|
-
reportBasics['web users can get details about the report at'] = `${thisHost}/
|
|
37
|
+
reportBasics['web users can get details about the report at'] = `${thisHost}/listIssues.html/${timeStamp}/${jobID}`;
|
|
38
38
|
// Add the basics to the array.
|
|
39
39
|
reportsBasics.push(reportBasics);
|
|
40
40
|
}
|
|
@@ -63,7 +63,7 @@ exports.response = async () => {
|
|
|
63
63
|
};
|
|
64
64
|
// Add instructions for a web user to request a test to the response content.
|
|
65
65
|
responseContent['how a web user can request that the page be tested'] = {
|
|
66
|
-
URL: `${thisHost}/
|
|
66
|
+
URL: `${thisHost}/requestTestForm.html`
|
|
67
67
|
};
|
|
68
68
|
// Create a response body.
|
|
69
69
|
const body = {
|
|
@@ -76,7 +76,7 @@ exports.response = async () => {
|
|
|
76
76
|
'closest ancestor request': null
|
|
77
77
|
},
|
|
78
78
|
'URLs of similar requests for web users': {
|
|
79
|
-
'this request': `${thisHost}/
|
|
79
|
+
'this request': `${thisHost}/listReports.html`,
|
|
80
80
|
'closest ancestor request': null
|
|
81
81
|
},
|
|
82
82
|
'response metadata': getResponseMetadata(),
|
package/api/listViolators.js
CHANGED
|
@@ -130,7 +130,7 @@ exports.response = async args => {
|
|
|
130
130
|
URL: `${thisHost}/api/listDiagnoses/${catalogIndex}/${issueID}/${timeStamp}/${jobID}`,
|
|
131
131
|
'request method': 'GET'
|
|
132
132
|
},
|
|
133
|
-
'web users can get details about the element at': `${thisHost}/
|
|
133
|
+
'web users can get details about the element at': `${thisHost}/listDiagnoses.html/${issueID}/${timeStamp}/${jobID}/${catalogIndex}`
|
|
134
134
|
};
|
|
135
135
|
});
|
|
136
136
|
// Add basics about the violators to the response content.
|
|
@@ -153,8 +153,8 @@ exports.response = async args => {
|
|
|
153
153
|
}
|
|
154
154
|
},
|
|
155
155
|
'URLs of similar requests for web users': {
|
|
156
|
-
'this request': `${thisHost}/
|
|
157
|
-
'closest ancestor request': `${thisHost}/
|
|
156
|
+
'this request': `${thisHost}/listViolators.html/${issueID}/${timeStamp}/${jobID}`,
|
|
157
|
+
'closest ancestor request': `${thisHost}/listIssues.html/${timeStamp}/${jobID}`
|
|
158
158
|
},
|
|
159
159
|
'response metadata': getResponseMetadata(),
|
|
160
160
|
'response content': responseContent
|
package/api/requestRetest.js
CHANGED
|
@@ -69,7 +69,7 @@ exports.response = async args => {
|
|
|
69
69
|
responseContent['disposition of your request'] = {
|
|
70
70
|
'what happens next': 'Your request is likely to be approved and processed within 1 hour to 1 day.',
|
|
71
71
|
'how you can check for completion': 'You can call the listReports tool to learn whether the page has been retested and a new report is available.',
|
|
72
|
-
'how a web user can check for completion': `A web user can visit ${thisHost}/
|
|
72
|
+
'how a web user can check for completion': `A web user can visit ${thisHost}/listReports.html to learn whether the page has been retested and a new report is available.`
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
75
|
// Create a response body.
|
|
@@ -91,8 +91,8 @@ exports.response = async args => {
|
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
93
|
'URLs of similar requests for web users': {
|
|
94
|
-
'this request': `${thisHost}/
|
|
95
|
-
'closest ancestor request': `${thisHost}/
|
|
94
|
+
'this request': `${thisHost}/requestRetestForm.html/${timeStamp}/${jobID}`,
|
|
95
|
+
'closest ancestor request': `${thisHost}/listIssues.html/${timeStamp}/${jobID}`
|
|
96
96
|
},
|
|
97
97
|
'response metadata': getResponseMetadata(),
|
|
98
98
|
'response content': responseContent
|
package/api/requestTest.js
CHANGED
|
@@ -70,7 +70,7 @@ exports.response = async args => {
|
|
|
70
70
|
responseContent['disposition of your request'] = {
|
|
71
71
|
'what happens next': 'Your request is likely to be approved and processed within 1 hour to 1 day.',
|
|
72
72
|
'how you can check for completion': 'You can call the listReports tool to learn whether the page has been tested and a report is available.',
|
|
73
|
-
'how a web user can check for completion': `A web user can visit ${thisHost}/
|
|
73
|
+
'how a web user can check for completion': `A web user can visit ${thisHost}/listReports.html to learn whether the page has been tested and a report is available.`
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -95,8 +95,8 @@ exports.response = async args => {
|
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
97
|
'URLs of similar requests for web users': {
|
|
98
|
-
'this request': `${thisHost}/
|
|
99
|
-
'closest ancestor request': `${thisHost}/
|
|
98
|
+
'this request': `${thisHost}/requestTestForm.html`,
|
|
99
|
+
'closest ancestor request': `${thisHost}/listReports.html`
|
|
100
100
|
},
|
|
101
101
|
'response metadata': getResponseMetadata(),
|
|
102
102
|
'response content': responseContent
|
package/docs/AI-TOOLS.md
CHANGED
|
@@ -188,13 +188,13 @@ The [Perplexity documentation](https://www.perplexity.ai/help-center/en/articles
|
|
|
188
188
|
|
|
189
189
|
Once the compatibility of Kilotest as a connector with AI platforms of two different vendors had been confirmed, the focus of work returned to completion of the missing endpoints of the API. The first was an endpoint that would let a model efficiently search for an available report about a particular web page.
|
|
190
190
|
|
|
191
|
-
|
|
191
|
+
A new `summarizeQualityOfMatchingWebPages` tool provided inputs for fragments of a description and of a URL hostname of a web page and responds with summary data about all and only the available reports of pages that match at least one of those fragments, where matching means either including or being included by the provided fragment, case-insensitively.
|
|
192
192
|
|
|
193
193
|
### Increment 7
|
|
194
194
|
|
|
195
195
|
Further experimentation made it clear that Increment 6 had been a detour. The problem with Increment 6 was that it does not improve efficiency by eliminating the need to get a list of all reports. Models must get a list of all reports in order to be confident that the answer to the question “Is a report available yet?” is correct. Any algorithm that matches a page description and a URL with those of existing reports is error-prone, organization names change, website designs change, URLs change, and organizations are related to one another. Typically, a desired report does not yet exist. In that case, the model needs the full list of reports in order to understand the naming convention for pages and to adhere to that convention when submitting a request to have the page of interest tested.
|
|
196
196
|
|
|
197
|
-
For this reason, the tool
|
|
197
|
+
For this reason, the tool developed in increment 6 was deleted.
|
|
198
198
|
|
|
199
199
|
### Increment 8
|
|
200
200
|
|
package/docs/SERVICE.md
CHANGED
|
@@ -203,7 +203,7 @@ kilotest.com {
|
|
|
203
203
|
}
|
|
204
204
|
@allowedPOST {
|
|
205
205
|
method POST
|
|
206
|
-
path /mcp /
|
|
206
|
+
path /mcp /requestRetest.html/* /requestTest.html /recAction.html /reannotate.html /renewWCAG.html /api/* /tutorialComment.html
|
|
207
207
|
}
|
|
208
208
|
# Respond to OPTIONS requests.
|
|
209
209
|
@allowedOPTIONS method OPTIONS
|
|
@@ -332,17 +332,17 @@ In case Testaro again becomes a dependency of Kilotest, the notes below on secur
|
|
|
332
332
|
|
|
333
333
|
### Browser privileges
|
|
334
334
|
|
|
335
|
-
Testaro uses Playwright to launch and control headless browsers, often `chromium`. Those browsers navigate to web pages that are tested by the rule engines that Testaro integrates.
|
|
335
|
+
Testaro uses Playwright to launch and control headless browsers, often `chromium`. Those browsers navigate to web pages that are tested by the rule engines that Testaro integrates.
|
|
336
336
|
|
|
337
|
-
When
|
|
337
|
+
When Playwright (or Puppeteer) launches a `chromium` browser, in most environments it is [sandboxed](https://www.geeksforgeeks.org/ethical-hacking/what-is-browser-sandboxing/). Sandboxing is a security feature that prevents the browser from accessing potentially unsafe system resources. But in the Ubuntu Linux operating system that was installed on the Vultr Cloud Compute host a sandboxed browser requires an [unprivileged user namespace](https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces), and when Ubuntu was installed its configuration disallowed such namespaces. The file `/etc/sysctl.d/99-kilotest-userns.conf` with the content `kernel.apparmor_restrict_unprivileged_userns = 1` prohibited unprivileged user namespaces and thereby made sandboxed browsers unlaunchable.
|
|
338
338
|
|
|
339
339
|
#### Potential modification
|
|
340
340
|
|
|
341
341
|
One modification to cope with this prohibition on the Vultr Cloud Compute host would be to configure Playwright and Puppeteer to launch `chromium` non-sandboxed. In both cases, launch arguments `'--no-sandbox'` and `'--disable-setuid-sandbox'` are available to specify this.
|
|
342
342
|
|
|
343
343
|
- For Playwright, `'--no-sandbox'` and `'--disable-setuid-sandbox'` would be added to the arguments of `browserOptionArgs.push` in the Testaro `run.js` file.
|
|
344
|
-
- For the `qualWeb`
|
|
345
|
-
- The `ibm`
|
|
344
|
+
- For the `qualWeb` rule engine, this would be done in the Testaro `tests/qualweb.js` file, where the `qualWeb.start` method is called with an options argument. Its `args` array property would include `'--no-sandbox'` and `'--disable-setuid-sandbox'`.
|
|
345
|
+
- The `ibm` rule engine, too, could launch a Puppeteer `chromium` browser, if page content instead of a Playwright page were passed to the `accessibilityChecker.getCompliance` method, or if the implementation of the rule engine were changed in the future. For anticipation of such a case, the Testaro `aceconfig.js` file, of which a copy has been created at the root of the Kilotest project, would be modified. That file defines a `module.exports` object with a `puppeteerArgs` property, and, `--no-sandbox` and `--disable-setuid-sandbox` would be added to its array value.
|
|
346
346
|
|
|
347
347
|
#### Current modification
|
|
348
348
|
|
package/index.html
CHANGED
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
</details>
|
|
87
87
|
<h2>What do you want to know?</h2>
|
|
88
88
|
<ul class="nav">
|
|
89
|
-
<li><a href="
|
|
90
|
-
<li><a href="
|
|
89
|
+
<li><a href="listReports.html">Which web pages have been tested?</a></li>
|
|
90
|
+
<li><a href="listTopIssues.html">Which issues have been reported?</a></li>
|
|
91
91
|
<li><a href="manage.html">What can Kilotest managers do?</a></li>
|
|
92
92
|
</ul>
|
|
93
93
|
</main>
|
package/index.js
CHANGED
|
@@ -37,29 +37,29 @@ const path = require('path');
|
|
|
37
37
|
const {sendAlert} = require('./alerts');
|
|
38
38
|
const answer = {
|
|
39
39
|
ai0BalanceForm: require('./web/ai0BalanceForm/index').answer,
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
enqueue: require('./web/enqueue/index').answer,
|
|
41
|
+
enqueueForm: require('./web/enqueueForm/index').answer,
|
|
42
|
+
expungeReportsForm: require('./web/expungeReportsForm/index').answer,
|
|
43
|
+
hideReportForm: require('./web/hideReportForm/index').answer,
|
|
44
|
+
listDiagnoses: require('./web/listDiagnoses/index').answer,
|
|
45
|
+
listIssues: require('./web/listIssues/index').answer,
|
|
46
|
+
listReports: require('./web/listReports/index').answer,
|
|
47
|
+
listRules: require('./web/listRules/index').answer,
|
|
48
|
+
listTopIssues: require('./web/listTopIssues/index').answer,
|
|
49
|
+
listViolators: require('./web/listViolators/index').answer,
|
|
42
50
|
manage: require('./web/manage/index').answer,
|
|
51
|
+
pruneReportsForm: require('./web/pruneReportsForm/index').answer,
|
|
43
52
|
reannotate: require('./web/reannotate/index').answer,
|
|
44
53
|
reannotateForm: require('./web/reannotateForm/index').answer,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
retestRecForm: require('./web/retestRecForm/index').answer,
|
|
55
|
-
rules: require('./web/rules/index').answer,
|
|
56
|
-
targets: require('./web/targets/index').answer,
|
|
57
|
-
testOrder: require('./web/testOrder/index').answer,
|
|
58
|
-
testRec: require('./web/testRec/index').answer,
|
|
59
|
-
testRecForm: require('./web/testRecForm/index').answer,
|
|
60
|
-
tutorial: require('./web/tutorial/index').answer,
|
|
61
|
-
wcagRenew: require('./web/wcagRenew/index').answer,
|
|
62
|
-
wcagRenewForm: require('./web/wcagRenewForm/index').answer
|
|
54
|
+
renewWCAG: require('./web/renewWCAG/index').answer,
|
|
55
|
+
renewWCAGForm: require('./web/renewWCAGForm/index').answer,
|
|
56
|
+
requestRetest: require('./web/requestRetest/index').answer,
|
|
57
|
+
requestRetestForm: require('./web/requestRetestForm/index').answer,
|
|
58
|
+
requestTest: require('./web/requestTest/index').answer,
|
|
59
|
+
requestTestForm: require('./web/requestTestForm/index').answer,
|
|
60
|
+
rewindReportsForm: require('./web/rewindReportsForm/index').answer,
|
|
61
|
+
unhideReportForm: require('./web/unhideReportForm/index').answer,
|
|
62
|
+
tutorial: require('./web/tutorial/index').answer
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
// CONSTANTS
|
|
@@ -564,7 +564,7 @@ const requestHandler = async (request, response) => {
|
|
|
564
564
|
// Get the data from the request body.
|
|
565
565
|
const postData = await getPOSTData(request);
|
|
566
566
|
// If the request is a test recommendation:
|
|
567
|
-
if (pageName === '
|
|
567
|
+
if (pageName === 'requestTest.html') {
|
|
568
568
|
const {what, url, why} = postData;
|
|
569
569
|
// If the request is valid:
|
|
570
570
|
if (what && url.startsWith('https://') && why) {
|
|
@@ -578,7 +578,7 @@ const requestHandler = async (request, response) => {
|
|
|
578
578
|
// Serve headers for a response.
|
|
579
579
|
setHeaders('text/html', pathname, 'ultra');
|
|
580
580
|
// Get the answer data.
|
|
581
|
-
const answerData = await require(path.join(__dirname, 'web', '
|
|
581
|
+
const answerData = await require(path.join(__dirname, 'web', 'requestTest', 'index'))
|
|
582
582
|
.answer(what, url, why);
|
|
583
583
|
// If they are valid:
|
|
584
584
|
if (answerData.status === 'ok') {
|
|
@@ -599,7 +599,7 @@ const requestHandler = async (request, response) => {
|
|
|
599
599
|
}
|
|
600
600
|
}
|
|
601
601
|
// Otherwise, if it is a retest recommendation:
|
|
602
|
-
else if (pageName === '
|
|
602
|
+
else if (pageName === 'requestRetest.html') {
|
|
603
603
|
const {why} = postData;
|
|
604
604
|
const [timeStamp, jobID] = pathTail.split('/');
|
|
605
605
|
// If the request is valid:
|
|
@@ -607,7 +607,7 @@ const requestHandler = async (request, response) => {
|
|
|
607
607
|
// Serve response headers.
|
|
608
608
|
setHeaders('text/html', pathname, 'ultra');
|
|
609
609
|
// Get the answer data.
|
|
610
|
-
const answerData = await require(path.join(__dirname, 'web', '
|
|
610
|
+
const answerData = await require(path.join(__dirname, 'web', 'requestRetest', 'index'))
|
|
611
611
|
.answer(pathTail, why);
|
|
612
612
|
// If they are valid:
|
|
613
613
|
if (answerData.status === 'ok') {
|
|
@@ -626,7 +626,7 @@ const requestHandler = async (request, response) => {
|
|
|
626
626
|
await serveError({message: 'ERROR: Invalid retest recommendation'}, response, true);
|
|
627
627
|
}
|
|
628
628
|
}
|
|
629
|
-
// Otherwise, if it is an
|
|
629
|
+
// Otherwise, if it is an approval or rejection of a test request:
|
|
630
630
|
else if (pageName === 'recAction.html') {
|
|
631
631
|
const {target, authCode} = postData;
|
|
632
632
|
const [url, what] = target.split('\t');
|
|
@@ -639,7 +639,7 @@ const requestHandler = async (request, response) => {
|
|
|
639
639
|
// Set a location header for a response.
|
|
640
640
|
response.setHeader('content-location', pathname);
|
|
641
641
|
// Process the approval and get the answer data about the remaining recommendations.
|
|
642
|
-
const answerData = await require(path.join(__dirname, 'web', '
|
|
642
|
+
const answerData = await require(path.join(__dirname, 'web', 'enqueue', 'index'))
|
|
643
643
|
.answer(url, what, authCode);
|
|
644
644
|
// If the answer data are valid:
|
|
645
645
|
if (answerData.status === 'ok') {
|
|
@@ -664,9 +664,10 @@ const requestHandler = async (request, response) => {
|
|
|
664
664
|
await fs.writeFile(path.join(jobsPath, 'recs.json'), getJSON(recs));
|
|
665
665
|
});
|
|
666
666
|
// Set a location header for a response.
|
|
667
|
-
response.setHeader('content-location', '/
|
|
667
|
+
response.setHeader('content-location', '/enqueueForm.html');
|
|
668
668
|
// Get the answer data.
|
|
669
|
-
const answerData = await require(path.join(__dirname, 'web', '
|
|
669
|
+
const answerData = await require(path.join(__dirname, 'web', 'enqueueForm', 'index'))
|
|
670
|
+
.answer();
|
|
670
671
|
// Serve the test-order form with the remaining recommendations.
|
|
671
672
|
response.end(answerData.answerPage);
|
|
672
673
|
}
|
|
@@ -697,12 +698,12 @@ const requestHandler = async (request, response) => {
|
|
|
697
698
|
}
|
|
698
699
|
}
|
|
699
700
|
// Otherwise, if it is a WCAG map renewal:
|
|
700
|
-
else if (pageName === '
|
|
701
|
+
else if (pageName === 'renewWCAG.html') {
|
|
701
702
|
const {authCode} = postData;
|
|
702
703
|
// Set headers for a response.
|
|
703
704
|
setHeaders('text/html', pathname, 'low');
|
|
704
705
|
// Get the answer data.
|
|
705
|
-
const answerData = await require(path.join(__dirname, 'web', '
|
|
706
|
+
const answerData = await require(path.join(__dirname, 'web', 'renewWCAG', 'index'))
|
|
706
707
|
.answer(authCode);
|
|
707
708
|
// If the answer data are valid:
|
|
708
709
|
if (answerData.status === 'ok') {
|
package/llms-full.txt
CHANGED
|
@@ -59,13 +59,13 @@ In the marketplace for MCP servers that test for front-end quality, all servers
|
|
|
59
59
|
Kilotest offers a comprehensive suite of capabilities to users via its web UI:
|
|
60
60
|
|
|
61
61
|
- [Home page](https://kilotest.com/)
|
|
62
|
-
- [Get summary test results for all tested pages](https://kilotest.com/
|
|
63
|
-
- Get statistics about issues reported in one report: `https://kilotest.com/
|
|
64
|
-
- Get details about one issue reported in one report: `https://kilotest.com/
|
|
65
|
-
- Get diagnoses by rule engines of rule violations for one HTML element exhibiting one issue in one report: `https://kilotest.com/
|
|
66
|
-
- [Recommend the testing of a not-yet-tested page](https://kilotest.com/
|
|
67
|
-
- Recommend the retesting of a previously tested page: `https://kilotest.com/
|
|
68
|
-
- [Get statistics about frequently reported issues across all pages](https://kilotest.com/
|
|
62
|
+
- [Get summary test results for all tested pages](https://kilotest.com/listReports.html)
|
|
63
|
+
- Get statistics about issues reported in one report: `https://kilotest.com/listIssues.html/{timeStamp}/{jobID}`
|
|
64
|
+
- Get details about one issue reported in one report: `https://kilotest.com/listViolators.html/{issueID}/{timeStamp}/{jobID}`
|
|
65
|
+
- Get diagnoses by rule engines of rule violations for one HTML element exhibiting one issue in one report: `https://kilotest.com/listDiagnoses.html/{issueID}/{timeStamp}/{jobID}/{catalogIndex}`
|
|
66
|
+
- [Recommend the testing of a not-yet-tested page](https://kilotest.com/requestTestForm.html)
|
|
67
|
+
- Recommend the retesting of a previously tested page: `https://kilotest.com/requestRetestForm.html/{timeStamp}/{jobID}`
|
|
68
|
+
- [Get statistics about frequently reported issues across all pages](https://kilotest.com/listTopIssues.html)
|
|
69
69
|
- [Get a list of the operations that Kilotest managers are authorized to request](https://kilotest.com/manage.html)
|
|
70
70
|
- [Tutorial, “Accessibility testing strategies”](https://kilotest.com/tutorial.html)
|
|
71
71
|
- [Tutorial, “QAI tutorial”](https://kilotest.com/qai/)
|
|
@@ -145,7 +145,7 @@ When you request a test or a retest:
|
|
|
145
145
|
- rejection
|
|
146
146
|
- how to confirm approval
|
|
147
147
|
- check test completion by calling `listReports` and looking for the page and completion date in the list
|
|
148
|
-
- you advise the user to check in approximately 1 day for the test results on the Kilotest website, starting at `https://kilotest.com/
|
|
148
|
+
- you advise the user to check in approximately 1 day for the test results on the Kilotest website, starting at `https://kilotest.com/listReports.html`
|
|
149
149
|
|
|
150
150
|
An [OpenAPI specification for Kilotest](https://kilotest.com/openapi.yaml) is available.
|
|
151
151
|
|
package/llms.txt
CHANGED
|
@@ -19,15 +19,15 @@ Kilotest helps language models and AI platforms to give thorough, accurate and t
|
|
|
19
19
|
|
|
20
20
|
## Web UI
|
|
21
21
|
|
|
22
|
-
- [List all available reports](https://kilotest.com/
|
|
23
|
-
- List all issues in one report: `https://kilotest.com/
|
|
24
|
-
- List all elements exhibiting one issue in one report: `https://kilotest.com/
|
|
25
|
-
- List all diagnoses of one element exhibiting one issue in one report: `https://kilotest.com/
|
|
22
|
+
- [List all available reports](https://kilotest.com/listReports.html)
|
|
23
|
+
- List all issues in one report: `https://kilotest.com/listIssues.html/{timeStamp}/{jobID}`
|
|
24
|
+
- List all elements exhibiting one issue in one report: `https://kilotest.com/listViolators.html/{issueID}/{timeStamp}/{jobID}`
|
|
25
|
+
- List all diagnoses of one element exhibiting one issue in one report: `https://kilotest.com/listDiagnoses.html/{issueID}/{timeStamp}/{jobID}/{catalogIndex}`
|
|
26
26
|
- Get one full report in JSON: `https://kilotest.com/fullReport.json/{timeStamp}/{jobID}`
|
|
27
|
-
- [Request testing of a web page](https://kilotest.com/
|
|
28
|
-
- Request retesting of a web page: `https://kilotest.com/
|
|
27
|
+
- [Request testing of a web page](https://kilotest.com/requestTestForm.html)
|
|
28
|
+
- Request retesting of a web page: `https://kilotest.com/requestRetestForm.html/{timeStamp}/{jobID}`
|
|
29
29
|
- [List the operations that Kilotest managers are authorized to request](https://kilotest.com/manage.html)
|
|
30
|
-
- [Provide statistics about frequently reported issues across all pages](https://kilotest.com/
|
|
30
|
+
- [Provide statistics about frequently reported issues across all pages](https://kilotest.com/listTopIssues.html)
|
|
31
31
|
- [Tutorial, “Accessibility testing strategies”](https://kilotest.com/tutorial.html)
|
|
32
32
|
|
|
33
33
|
## More documents
|
package/package.json
CHANGED
package/robots.txt
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
User-agent: *
|
|
3
3
|
Allow: /
|
|
4
4
|
Disallow: /ai0BalanceForm.html
|
|
5
|
-
Disallow: /
|
|
5
|
+
Disallow: /enqueueForm.html
|
|
6
6
|
Disallow: /recAction.html
|
|
7
7
|
Disallow: /reannotateForm.html
|
|
8
8
|
Disallow: /reannotate.html
|
|
9
|
-
Disallow: /
|
|
10
|
-
Disallow: /
|
|
11
|
-
Disallow: /
|
|
12
|
-
Disallow: /
|
|
13
|
-
Disallow: /
|
|
14
|
-
Disallow: /
|
|
15
|
-
Disallow: /
|
|
9
|
+
Disallow: /hideReportForm.html
|
|
10
|
+
Disallow: /unhideReportForm.html
|
|
11
|
+
Disallow: /pruneReportsForm.html
|
|
12
|
+
Disallow: /rewindReportsForm.html
|
|
13
|
+
Disallow: /expungeReportsForm.html
|
|
14
|
+
Disallow: /renewWCAGForm.html
|
|
15
|
+
Disallow: /renewWCAG.html
|
|
16
16
|
Sitemap: https://kilotest.com/sitemap.xml
|
package/sitemap.xml
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<!-- sitemap.xml -->
|
|
2
2
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
3
3
|
<url><loc>https://kilotest.com/</loc></url>
|
|
4
|
-
<url><loc>https://kilotest.com/
|
|
5
|
-
<url><loc>https://kilotest.com/
|
|
6
|
-
<url><loc>https://kilotest.com/
|
|
4
|
+
<url><loc>https://kilotest.com/listReports.html</loc></url>
|
|
5
|
+
<url><loc>https://kilotest.com/listTopIssues.html</loc></url>
|
|
6
|
+
<url><loc>https://kilotest.com/requestTestForm.html</loc></url>
|
|
7
7
|
<url><loc>https://kilotest.com/manage.html</loc></url>
|
|
8
8
|
<url><loc>https://kilotest.com/tutorial.html</loc></url>
|
|
9
9
|
<url><loc>https://kilotest.com/openapi.yaml</loc></url>
|
package/util.js
CHANGED
|
@@ -27,7 +27,7 @@ const hiddenReportsPath = exports.hiddenReportsPath = path.join(dbPath, 'hiddenR
|
|
|
27
27
|
// Path of the reports data file.
|
|
28
28
|
const reportsExtractPath = exports.reportsExtractPath = path.join(dbPath, 'reportsExtract.json');
|
|
29
29
|
// IDs, names, and sponsors of Testaro rule engines.
|
|
30
|
-
const
|
|
30
|
+
const ruleEngines = exports.ruleEngines = {
|
|
31
31
|
alfa: ['Alfa', 'Siteimprove'],
|
|
32
32
|
aslint: ['ASLint', 'eSSENTIAL Accessibility'],
|
|
33
33
|
axe: ['Axe', 'Deque'],
|
|
@@ -41,7 +41,6 @@ const tools = exports.tools = {
|
|
|
41
41
|
wave: ['WAVE', 'Utah State University'],
|
|
42
42
|
wax: ['WallyAX', 'Wally']
|
|
43
43
|
};
|
|
44
|
-
exports.ruleEngines = tools;
|
|
45
44
|
exports.researchAgents = {
|
|
46
45
|
'research-agent': 'Internal Research Agent'
|
|
47
46
|
}
|
|
@@ -252,13 +251,14 @@ exports.getTextFragmentHref = (text, url) => {
|
|
|
252
251
|
return `${url}#:~:text=${fragmentList}`;
|
|
253
252
|
};
|
|
254
253
|
// Returns a +-delimited list of sorted names of rule engines.
|
|
255
|
-
exports.
|
|
256
|
-
.map(
|
|
254
|
+
exports.getEngineList = engineIDs => Array.from(engineIDs)
|
|
255
|
+
.map(engineID => ruleEngines[engineID][0])
|
|
257
256
|
.sort((a, b) => a.localeCompare(b, 'en', {sensitivity: 'base'}))
|
|
258
257
|
.join(' + ');
|
|
259
258
|
// Returns a string of names of rule engines.
|
|
260
|
-
exports.
|
|
261
|
-
|
|
259
|
+
exports.getEngineNamesString = engineIDSet => alphaSort(
|
|
260
|
+
Array.from(engineIDSet).map(engineID => ruleEngines[engineID]?.[0] || engineID)
|
|
261
|
+
).join(' + ');
|
|
262
262
|
// Gets the WCAG Understanding link for a numeric WCAG standard identifier.
|
|
263
263
|
exports.getWCAGLink = numericID => {
|
|
264
264
|
// Return the link.
|
|
@@ -339,12 +339,12 @@ const objectSort = exports.objectSort = (objects, property, sortType) => objects
|
|
|
339
339
|
// Otherwise, do not sort.
|
|
340
340
|
return 0;
|
|
341
341
|
});
|
|
342
|
-
// Processes a test or retest
|
|
343
|
-
exports.
|
|
342
|
+
// Processes a test or retest request in the UI.
|
|
343
|
+
exports.processTestRequest = async (testType, dirName, what, url, why) => {
|
|
344
344
|
// If the recommendation is valid:
|
|
345
345
|
if (
|
|
346
346
|
['test', 'retest'].includes(testType)
|
|
347
|
-
&& ['
|
|
347
|
+
&& ['Test', 'Retest'].some(end => dirName.endsWith(end))
|
|
348
348
|
&& what
|
|
349
349
|
&& isURL(url)
|
|
350
350
|
&& why.length > 4
|
|
@@ -444,7 +444,7 @@ const isValidReport = exports.isValidReport = report => {
|
|
|
444
444
|
&& report.acts.every(act =>
|
|
445
445
|
typeof act === 'object'
|
|
446
446
|
&& typeof act.type === 'string'
|
|
447
|
-
&& act.type === 'test' ? Object.keys(
|
|
447
|
+
&& act.type === 'test' ? Object.keys(ruleEngines).includes(act.which) : true
|
|
448
448
|
)
|
|
449
449
|
&& typeof report.jobData === 'object'
|
|
450
450
|
&& report.jobData.endTime
|
|
@@ -536,16 +536,16 @@ exports.getReportData = async (timeStamp, jobID) => {
|
|
|
536
536
|
creationDate: getDateTime(timeStamp),
|
|
537
537
|
daysAgo: getAgoDays(timeStamp),
|
|
538
538
|
issueCount: 0,
|
|
539
|
-
|
|
540
|
-
|
|
539
|
+
engineNames: [],
|
|
540
|
+
engineCount: 0,
|
|
541
541
|
reporterNames: [],
|
|
542
542
|
reporterCount: 0,
|
|
543
543
|
violatorCount: 0,
|
|
544
|
-
|
|
545
|
-
|
|
544
|
+
preventedEngineNames: [],
|
|
545
|
+
preventedEngineCount: 0
|
|
546
546
|
};
|
|
547
547
|
const issueIDSet = new Set();
|
|
548
|
-
const
|
|
548
|
+
const engineNameSet = new Set();
|
|
549
549
|
const reporterIDSet = new Set();
|
|
550
550
|
const violatorIndexSet = new Set();
|
|
551
551
|
// For each act of the report:
|
|
@@ -553,15 +553,15 @@ exports.getReportData = async (timeStamp, jobID) => {
|
|
|
553
553
|
// If it is a test act:
|
|
554
554
|
if (act.type === 'test') {
|
|
555
555
|
const {result, which} = act;
|
|
556
|
-
// Ensure that the
|
|
557
|
-
|
|
556
|
+
// Ensure that the rule engine is in the temporary data.
|
|
557
|
+
engineNameSet.add(ruleEngines[which][0]);
|
|
558
558
|
const instances = result?.standardResult?.instances ?? [];
|
|
559
559
|
// For each standard instance of the act:
|
|
560
560
|
instances.forEach(instance => {
|
|
561
561
|
const {catalogIndex, issueID} = instance;
|
|
562
562
|
// If it has a non-ignorable classified issue ID:
|
|
563
563
|
if (issueID && issueSpecs[issueID] && issueID !== 'ignorable') {
|
|
564
|
-
// Ensure that the
|
|
564
|
+
// Ensure that the rule engine is in the temporary data.
|
|
565
565
|
reporterIDSet.add(which);
|
|
566
566
|
// Ensure that the issue is in the temporary data.
|
|
567
567
|
issueIDSet.add(issueID);
|
|
@@ -576,21 +576,21 @@ exports.getReportData = async (timeStamp, jobID) => {
|
|
|
576
576
|
});
|
|
577
577
|
// Populate the data with the act data.
|
|
578
578
|
data.issueCount = issueIDSet.size;
|
|
579
|
-
data.
|
|
580
|
-
.from(
|
|
579
|
+
data.engineNames = Array
|
|
580
|
+
.from(engineNameSet)
|
|
581
581
|
.sort((a, b) => a.localeCompare(b, 'en', {sensitivity: 'base'}));
|
|
582
|
-
data.
|
|
582
|
+
data.engineCount = engineNameSet.size;
|
|
583
583
|
data.reporterNames = Array
|
|
584
584
|
.from(reporterIDSet)
|
|
585
|
-
.map(id =>
|
|
585
|
+
.map(id => ruleEngines[id][0])
|
|
586
586
|
.sort((a, b) => a.localeCompare(b, 'en', {sensitivity: 'base'}));
|
|
587
587
|
data.reporterCount = data.reporterNames.length;
|
|
588
588
|
data.violatorCount = violatorIndexSet.size;
|
|
589
589
|
// Add the names of any prevented rule engines to the data.
|
|
590
|
-
data.
|
|
591
|
-
.map(
|
|
590
|
+
data.preventedEngineNames = Object.keys(report.jobData?.preventions || {})
|
|
591
|
+
.map(engineID => ruleEngines[engineID][0])
|
|
592
592
|
.sort((a, b) => a.localeCompare(b, 'en', {sensitivity: 'base'}));
|
|
593
|
-
data.
|
|
593
|
+
data.preventedEngineCount = data.preventedEngineNames.length;
|
|
594
594
|
// Return the data.
|
|
595
595
|
return data;
|
|
596
596
|
}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
/*
|
|
2
2
|
index.js
|
|
3
|
-
Implements a
|
|
3
|
+
Implements a test request approval.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// IMPORTS
|
|
7
7
|
|
|
8
|
-
const {
|
|
8
|
+
const {
|
|
9
|
+
getJSON, getNowStamp, getRandomString, getRecs, isURL, jobsPath, recsLock
|
|
10
|
+
} = require('../../util');
|
|
9
11
|
const fs = require('fs/promises');
|
|
10
12
|
const path = require('path');
|
|
11
13
|
|
|
12
14
|
// FUNCTIONS
|
|
13
15
|
|
|
14
|
-
// Implements a test
|
|
16
|
+
// Implements a test request approval and returns a revised request page.
|
|
15
17
|
exports.answer = async (url, what, authCode) => {
|
|
16
18
|
// If the arguments are valid:
|
|
17
19
|
if (isURL(url) && what && authCode === process.env.AUTH_CODE) {
|
|
@@ -40,7 +42,7 @@ exports.answer = async (url, what, authCode) => {
|
|
|
40
42
|
await recsLock(async () => {
|
|
41
43
|
// Get the recommendations.
|
|
42
44
|
const recs = await getRecs();
|
|
43
|
-
// Delete the recommendations to
|
|
45
|
+
// Delete the recommendations to test the target.
|
|
44
46
|
delete recs[url];
|
|
45
47
|
// Save the revised recommendations.
|
|
46
48
|
await fs.writeFile(path.join(jobsPath, 'recs.json'), getJSON(recs));
|