@jrpool/kilotest 30.0.3 → 31.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +41 -4
- package/llms-full.txt +31 -14
- package/llms.txt +4 -1
- package/openapi.yaml +85 -21
- package/package.json +1 -1
- package/reportIssues/api.js +3 -2
- package/researchAgent.js +45 -5
- package/sitemap.xml +2 -0
- package/targets/api.js +3 -1
- package/testRecForm/api.js +48 -0
- package/util.js +16 -11
package/index.js
CHANGED
|
@@ -14,6 +14,7 @@ const {
|
|
|
14
14
|
getJobNames,
|
|
15
15
|
getJSON,
|
|
16
16
|
getLogPath,
|
|
17
|
+
getLogs,
|
|
17
18
|
getObject,
|
|
18
19
|
getPOSTData,
|
|
19
20
|
getReport,
|
|
@@ -22,6 +23,7 @@ const {
|
|
|
22
23
|
isHidden,
|
|
23
24
|
isTimeStamp,
|
|
24
25
|
isJobID,
|
|
26
|
+
isURL,
|
|
25
27
|
jobsPath,
|
|
26
28
|
logsPath,
|
|
27
29
|
reportsPath,
|
|
@@ -198,7 +200,7 @@ const requestHandler = async (request, response) => {
|
|
|
198
200
|
// Serve response headers, including one allowing requests from other applications.
|
|
199
201
|
response.setHeader('Access-Control-Allow-Origin', '*');
|
|
200
202
|
response.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
201
|
-
response.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
203
|
+
response.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
202
204
|
response.statusCode = 204;
|
|
203
205
|
response.end();
|
|
204
206
|
}
|
|
@@ -568,10 +570,10 @@ const requestHandler = async (request, response) => {
|
|
|
568
570
|
// Get the segments of the path after api.
|
|
569
571
|
const segments = pathTail.split('/');
|
|
570
572
|
// If the first segment is the ID of the Testaro agent and the agent is authenticated:
|
|
571
|
-
if (
|
|
572
|
-
const agentID =
|
|
573
|
+
if (segments[0] === testaroAgent && postData.agentPW === testaroAgentPW) {
|
|
574
|
+
const agentID = segments[0];
|
|
573
575
|
// Get the requested service from the path.
|
|
574
|
-
const service =
|
|
576
|
+
const service = segments[1];
|
|
575
577
|
// If the service is job assignment:
|
|
576
578
|
if (service === 'job') {
|
|
577
579
|
let clean = true;
|
|
@@ -678,6 +680,41 @@ const requestHandler = async (request, response) => {
|
|
|
678
680
|
);
|
|
679
681
|
}
|
|
680
682
|
}
|
|
683
|
+
// Otherwise, if the first segment is the test recommendation service:
|
|
684
|
+
else if (segments[0] === 'testRecForm') {
|
|
685
|
+
const {what, url, why} = postData;
|
|
686
|
+
const logs = await getLogs();
|
|
687
|
+
const whats = logs.map(log => log.what);
|
|
688
|
+
const urls = logs.map(log => log.url);
|
|
689
|
+
// If the payload is a valid test recommendation:
|
|
690
|
+
if (what && isURL(url) && why) {
|
|
691
|
+
// If an available report has the same URL or the same page description:
|
|
692
|
+
if (whats.includes(what) || urls.includes(url)) {
|
|
693
|
+
// Report this.
|
|
694
|
+
await serveError(
|
|
695
|
+
'ERROR: A report with the same page description or URL is already available',
|
|
696
|
+
response,
|
|
697
|
+
false
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
// Otherwise, i.e. if no report on the page is available:
|
|
701
|
+
else {
|
|
702
|
+
// Process the recommendation and get the response data.
|
|
703
|
+
const responseData = await require(path.join(__dirname, 'testRecForm', 'api'))
|
|
704
|
+
.response(what, url, why);
|
|
705
|
+
// Send them.
|
|
706
|
+
setHeaders('application/json', null, 'high');
|
|
707
|
+
response.end(JSON.stringify(responseData));
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
// Otherwise, i.e. if the request is invalid:
|
|
712
|
+
else {
|
|
713
|
+
// Report this.
|
|
714
|
+
await serveError(
|
|
715
|
+
{message: 'ERROR: Invalid API request'}, response, false
|
|
716
|
+
);
|
|
717
|
+
}
|
|
681
718
|
}
|
|
682
719
|
// Otherwise, if it is a tutorial comment:
|
|
683
720
|
else if (pageName === 'tutorialComment.html') {
|
package/llms-full.txt
CHANGED
|
@@ -13,6 +13,7 @@ An LLM cannot produce for an AI agent thorough, accurate, and inexpensive inform
|
|
|
13
13
|
- selects, as tools, an ensemble of 10 rule engines that implement tests for, in total, more than a thousand rules for front-end quality
|
|
14
14
|
- runs the tests of the rule engines
|
|
15
15
|
- combines the reports of the rule engines into a single integrated report
|
|
16
|
+
- consolidates the 1000+ rules having 10 different naming systems into 300+ “issues” with a uniform naming system
|
|
16
17
|
- extracts from the report statistics and details at the level of granularity required by an agent to fulfill any particular request
|
|
17
18
|
|
|
18
19
|
## How Kilotest integrates methods
|
|
@@ -30,11 +31,11 @@ LLMs that attempt to evaluate front-end quality with no delegation are likely to
|
|
|
30
31
|
|
|
31
32
|
## Kilotest versus other tools
|
|
32
33
|
|
|
33
|
-
In the marketplace for
|
|
34
|
+
In the marketplace for MCP servers that test for front-end quality, all tools other than Kilotest leverage at most 1 rule engine, most often `axe-core`. Kilotest leverages `axe-core` plus 9 other rule engines. This has these main effects:
|
|
34
35
|
|
|
35
36
|
- For pages that have not yet been tested, a single-tool MCP can provide faster results than Kilotest. A tool running only the `axe-core` tests can complete its work in about 5 seconds or less. Kilotest usually completes its work in 2 to 3 minutes, because some of the tests involve navigation and interaction with the page and LLM inference. Moreover, the Kilotest API feature suite is currently in an alpha phase, allowing agents, like human users, to **recommend** new pages for testing but allowing only managers to act on such recommendations. The wait for manager action can take up to a day. A feature permitting immediate testing ordered by AI agents is planned, but, until it is implemented, Kilotest will be useful for not-yet-tested pages only in long-running workflows.
|
|
36
|
-
- For pages that have already been tested by Kilotest, Kilotest can provide faster results than a single-tool MCP, because Kilotest stores test results for subsequent retrieval. A retrieval from Kilotest can be completed in less than 2 seconds.
|
|
37
|
-
- Kilotest results are more comprehensive than single-tool MCP results. Every rule engine provides limited coverage of front-end quality, so false negatives (missed defects) are more common with single-tool
|
|
37
|
+
- For pages that have already been tested by Kilotest, Kilotest can provide faster results than a single-tool MCP server, because Kilotest stores test results for subsequent retrieval. A retrieval from Kilotest can be completed in less than 2 seconds.
|
|
38
|
+
- Kilotest results are more comprehensive than single-tool MCP server results. Every rule engine provides limited coverage of front-end quality, so false negatives (missed defects) are more common with single-tool MCP servers. This difference [has been documented in research](https://arxiv.org/pdf/2304.07591).
|
|
38
39
|
|
|
39
40
|
## How to use Kilotest
|
|
40
41
|
|
|
@@ -47,26 +48,42 @@ Kilotest offers a comprehensive suite of capabilities to users via its web UI:
|
|
|
47
48
|
- Provide statistics about issues reported in one job: `https://kilotest.com/reportIssues.html/{timeStamp}/{jobID}`
|
|
48
49
|
- Provide details about one issue reported in one job: `https://kilotest.com/reportIssue.html/{issueID}/{timeStamp}/{jobID}`
|
|
49
50
|
- Provide diagnoses by tools of rule violations for one HTML element exhibiting one issue in one job: `https://kilotest.com/diagnoses.html/{issueID}/{timeStamp}/{jobID}/{catalogIndex}`
|
|
51
|
+
- [Receive a recommendation to test a not-yet-tested page](`https://kilotest.com/testRecForm.html`)
|
|
52
|
+
- Receive a recommendation to retest a previously tested page: `https://kilotest.com/retestRecForm.html/{timeStamp}/{jobID}`
|
|
50
53
|
- [Provide statistics about frequently reported issues across all pages](https://kilotest.com/issues.html)
|
|
54
|
+
- [List the operations that Kilotest managers are authorized to request](https://kilotest.com/manage.html)
|
|
51
55
|
- [Tutorial, “Accessibility testing strategies”](https://kilotest.com/tutorial.html)
|
|
52
56
|
- [Provide a list of features available for use of Kilotest managers](https://kilotest.com/manage.html)
|
|
53
57
|
|
|
54
58
|
### Agent API
|
|
55
59
|
|
|
56
|
-
Kilotest is implementing a richer suite of capabilities optimized for AI agents, including direct immediate testing. The implementation is currently in an alpha phase and offers
|
|
57
|
-
|
|
58
|
-
- `targets
|
|
59
|
-
-
|
|
60
|
+
Kilotest is implementing a richer suite of capabilities optimized for AI agents, including direct immediate testing. The implementation is currently in an alpha phase and offers 3 API endpoints:
|
|
61
|
+
|
|
62
|
+
- `targets`
|
|
63
|
+
- method: `GET`
|
|
64
|
+
- purpose: summarize test results from all jobs (a job is a session in which a web page is tested and a report is produced)
|
|
65
|
+
- path: `/api/targets`
|
|
66
|
+
- `reportIssues`
|
|
67
|
+
- method: `GET`
|
|
68
|
+
- purpose: provide statistics about issues reported in one job report
|
|
69
|
+
- path: `/api/reportIssues/{timeStamp}/{jobID}`
|
|
70
|
+
- parameters
|
|
71
|
+
- `timeStamp`: initial segment of job identifier
|
|
72
|
+
- `jobID`: final segment of job identifier
|
|
73
|
+
- source of parameters: response to a `targets` request
|
|
74
|
+
- `testRecForm`
|
|
75
|
+
- method: `POST`
|
|
76
|
+
- purpose: receive a recommendation to test a not-yet-tested page
|
|
77
|
+
- path: `/api/testRecForm`
|
|
78
|
+
- payload properties
|
|
79
|
+
- `what`: description of the page to be tested
|
|
80
|
+
- `url`: URL of the page to be tested
|
|
81
|
+
- `why`: reason for testing the page
|
|
82
|
+
- how to verify disposition of the recommendation: submit a `targets` request and inspect the response to determine whether a report on the page is now available
|
|
60
83
|
|
|
61
84
|
An [OpenAPI specification for Kilotest](https://kilotest.com/openapi.yaml) is available.
|
|
62
85
|
|
|
63
|
-
Until direct immediate testing is available, an agent can recommend testing of a web page
|
|
64
|
-
|
|
65
|
-
- web UI: First verify that the page has not yet been tested, using the `targets` API endpoint. After that, complete and submit the [web UI recommendation form](https://kilotest.com/testRecForm.html).
|
|
66
|
-
- email: Send a message to `info@kilotest.com`, identifying:
|
|
67
|
-
- the URL of the page to be tested
|
|
68
|
-
- a proper name for the page to be tested (e.g., “ABC Corporation contact page”)
|
|
69
|
-
- a reason for your recommendation (e.g., “Page users have reported accessibility problems”)
|
|
86
|
+
Until direct immediate testing is available, an agent can recommend testing of a web page with a `testRecForm` request.
|
|
70
87
|
|
|
71
88
|
### More information
|
|
72
89
|
|
package/llms.txt
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Kilotest helps AI agents give thorough, accurate and truthful answers when users ask how accessible, usable, or standard conformant web pages are. Kilotest integrates ten independent rule engines to test web pages and report results with multipage, single-page, and element-level statistics and details.
|
|
4
4
|
|
|
5
|
-
In the API section below, all endpoints require `GET` requests.
|
|
5
|
+
In the API section below, all endpoints require `GET` requests except as noted.
|
|
6
6
|
|
|
7
7
|
There is a [detailed explanation of Kilotest and its capabilities for AI agents](https://kilotest.com/llms-full.txt).
|
|
8
8
|
|
|
@@ -10,6 +10,7 @@ There is a [detailed explanation of Kilotest and its capabilities for AI agents]
|
|
|
10
10
|
|
|
11
11
|
- [Summarize test results for all tested pages](/api/targets)
|
|
12
12
|
- Provide statistics about issues reported in one job: `/api/reportIssues/{timeStamp}/{jobID}`
|
|
13
|
+
- Recommend testing of a web page: `/api/testRecForm` (requires `POST` request)
|
|
13
14
|
- [OpenAPI specification for Kilotest](https://kilotest.com/openapi.yaml)
|
|
14
15
|
|
|
15
16
|
## Web UI
|
|
@@ -19,4 +20,6 @@ There is a [detailed explanation of Kilotest and its capabilities for AI agents]
|
|
|
19
20
|
- Provide details about one issue reported in one job: `https://kilotest.com/reportIssue.html/{issueID}/{timeStamp}/{jobID}`
|
|
20
21
|
- Provide diagnoses about one issue exhibited by one HTML element in one job: `https://kilotest.com/diagnoses.html/{issueID}/{timeStamp}/{jobID}/{catalogIndex}`
|
|
21
22
|
- [Provide statistics about frequently reported issues across all pages](https://kilotest.com/issues.html)
|
|
23
|
+
- [Recommend testing of a web page](https://kilotest.com/testRecForm.html)
|
|
24
|
+
- [List the operations that Kilotest managers are authorized to request](https://kilotest.com/manage.html)
|
|
22
25
|
- [Tutorial, “Accessibility testing strategies”](https://kilotest.com/tutorial.html)
|
package/openapi.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
openapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: Kilotest Agent API
|
|
4
|
-
description: Kilotest tests web pages for accessibility, usability, and standard conformity using an ensemble of ten independent tools that employ rule-based and machine-learning-based methods. This API enables AI agents to recommend web pages for testing
|
|
4
|
+
description: Kilotest tests web pages for accessibility, usability, and standard conformity using an ensemble of ten independent tools that employ rule-based and machine-learning-based methods. This API enables AI agents to recommend web pages for testing, discover available test reports, and retrieve data from reports. For background on Kilotest and the advantages of ensemble testing, visit https://kilotest.com.
|
|
5
5
|
version: 1.0.0
|
|
6
6
|
contact:
|
|
7
7
|
url: https://kilotest.com
|
|
@@ -13,10 +13,30 @@ servers:
|
|
|
13
13
|
description: Kilotest production server
|
|
14
14
|
|
|
15
15
|
paths:
|
|
16
|
-
/api/
|
|
16
|
+
/api/testRecForm:
|
|
17
17
|
post:
|
|
18
|
-
operationId:
|
|
19
|
-
summary:
|
|
18
|
+
operationId: testRecForm
|
|
19
|
+
summary: Receives a testing recommendation
|
|
20
|
+
description: Receives a recommendation for Kilotest to test a particular web page.
|
|
21
|
+
requestBody:
|
|
22
|
+
description: Test recommendation specifications
|
|
23
|
+
required: true
|
|
24
|
+
content:
|
|
25
|
+
application/json:
|
|
26
|
+
schema:
|
|
27
|
+
$ref: '#/components/schemas/TestRecForm'
|
|
28
|
+
responses:
|
|
29
|
+
'200':
|
|
30
|
+
description: Acknowledgement of test recommendation
|
|
31
|
+
content:
|
|
32
|
+
application/json:
|
|
33
|
+
schema:
|
|
34
|
+
$ref: '#/components/schemas/TestRecFormResponse'
|
|
35
|
+
|
|
36
|
+
/api/targets:
|
|
37
|
+
get:
|
|
38
|
+
operationId: targets
|
|
39
|
+
summary: Summarizes all available reports
|
|
20
40
|
description: Returns summary data about every non-hidden report available from Kilotest, including the name and URL of the tested web page, when the testing was performed, how many issues were reported, and URLs for retrieving more detailed data from the report.
|
|
21
41
|
responses:
|
|
22
42
|
'200':
|
|
@@ -24,13 +44,13 @@ paths:
|
|
|
24
44
|
content:
|
|
25
45
|
application/json:
|
|
26
46
|
schema:
|
|
27
|
-
$ref: '#/components/schemas/
|
|
47
|
+
$ref: '#/components/schemas/TargetsResponse'
|
|
28
48
|
|
|
29
49
|
/api/reportIssues/{timeStamp}/{jobID}:
|
|
30
|
-
|
|
50
|
+
get:
|
|
31
51
|
operationId: getReportIssues
|
|
32
|
-
summary:
|
|
33
|
-
description: Returns data about the issues reported in a specific Kilotest report, grouped by priority. The data on each issue include the tools that reported it, the number of HTML elements exhibiting it, and URLs for retrieving element-level detail. The timeStamp and jobID components identify the report and are available in the
|
|
52
|
+
summary: Gets data on issues from a specific report
|
|
53
|
+
description: Returns data about the issues reported in a specific Kilotest report, grouped by priority. The data on each issue include the tools that reported it, the number of HTML elements exhibiting it, and URLs for retrieving element-level detail. The timeStamp and jobID components identify the report and are available in the targets response.
|
|
34
54
|
parameters:
|
|
35
55
|
- name: timeStamp
|
|
36
56
|
in: path
|
|
@@ -58,9 +78,9 @@ paths:
|
|
|
58
78
|
description: No report with the specified identifier is available
|
|
59
79
|
|
|
60
80
|
/api/reportIssue/{issueID}/{timeStamp}/{jobID}:
|
|
61
|
-
|
|
81
|
+
get:
|
|
62
82
|
operationId: getReportIssue
|
|
63
|
-
summary:
|
|
83
|
+
summary: Gets details about a specific issue in a specific report (NOT YET IMPLEMENTED)
|
|
64
84
|
description: Returns details about a single issue within a specific report, including which HTML elements exhibit the issue and, for each such element, URLs for retrieving tool-by-tool diagnoses of the issue on the element. NOT YET IMPLEMENTED.
|
|
65
85
|
parameters:
|
|
66
86
|
- name: issueID
|
|
@@ -105,22 +125,40 @@ components:
|
|
|
105
125
|
request:
|
|
106
126
|
type: object
|
|
107
127
|
properties:
|
|
108
|
-
|
|
128
|
+
type of request:
|
|
109
129
|
type: object
|
|
110
130
|
properties:
|
|
111
131
|
identifier:
|
|
112
132
|
type: string
|
|
113
|
-
|
|
114
|
-
name:
|
|
133
|
+
description:
|
|
115
134
|
type: string
|
|
116
|
-
|
|
117
|
-
|
|
135
|
+
method:
|
|
136
|
+
type: string
|
|
137
|
+
enum:
|
|
138
|
+
- GET
|
|
139
|
+
- POST
|
|
140
|
+
payload:
|
|
141
|
+
type: object
|
|
142
|
+
description: Present only for POST requests. The request payload.
|
|
143
|
+
URLs:
|
|
118
144
|
type: object
|
|
119
145
|
properties:
|
|
120
|
-
|
|
146
|
+
'URL of your request':
|
|
121
147
|
type: string
|
|
148
|
+
'equivalent URL for humans':
|
|
149
|
+
type: string
|
|
150
|
+
closest ancestor request:
|
|
151
|
+
type: [object, 'null']
|
|
152
|
+
properties:
|
|
122
153
|
description:
|
|
123
154
|
type: string
|
|
155
|
+
URLs:
|
|
156
|
+
type: object
|
|
157
|
+
properties:
|
|
158
|
+
'for you':
|
|
159
|
+
type: string
|
|
160
|
+
'for humans':
|
|
161
|
+
type: string
|
|
124
162
|
response metadata:
|
|
125
163
|
type: object
|
|
126
164
|
properties:
|
|
@@ -131,6 +169,30 @@ components:
|
|
|
131
169
|
type: string
|
|
132
170
|
format: date-time
|
|
133
171
|
|
|
172
|
+
TestRecForm:
|
|
173
|
+
type: object
|
|
174
|
+
properties:
|
|
175
|
+
what:
|
|
176
|
+
type: string
|
|
177
|
+
description: Description of the web page to be tested.
|
|
178
|
+
url:
|
|
179
|
+
type: string
|
|
180
|
+
description: URL of the web page to be tested.
|
|
181
|
+
why:
|
|
182
|
+
type: string
|
|
183
|
+
description: Reason for testing the page.
|
|
184
|
+
|
|
185
|
+
TestRecFormResponse:
|
|
186
|
+
allOf:
|
|
187
|
+
- $ref: '#/components/schemas/CommonResponseFields'
|
|
188
|
+
- type: object
|
|
189
|
+
properties:
|
|
190
|
+
available reports:
|
|
191
|
+
type: array
|
|
192
|
+
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.
|
|
193
|
+
items:
|
|
194
|
+
$ref: '#/components/schemas/TargetsItem'
|
|
195
|
+
|
|
134
196
|
ToolInfo:
|
|
135
197
|
type: object
|
|
136
198
|
description: An accessibility testing tool in the Kilotest ensemble.
|
|
@@ -145,7 +207,7 @@ components:
|
|
|
145
207
|
example: Alfa
|
|
146
208
|
sponsor:
|
|
147
209
|
type: string
|
|
148
|
-
description: Organization that created or sponsors the tool.
|
|
210
|
+
description: Organization that created, initially sponsored, or now sponsors the tool.
|
|
149
211
|
example: Siteimprove
|
|
150
212
|
|
|
151
213
|
ToolFailure:
|
|
@@ -183,7 +245,7 @@ components:
|
|
|
183
245
|
format: uri
|
|
184
246
|
description: URL for a human to view the next tier of detail.
|
|
185
247
|
|
|
186
|
-
|
|
248
|
+
targetsItem:
|
|
187
249
|
type: object
|
|
188
250
|
description: Summary data about a single available report.
|
|
189
251
|
properties:
|
|
@@ -222,7 +284,7 @@ components:
|
|
|
222
284
|
type: string
|
|
223
285
|
format: uri
|
|
224
286
|
|
|
225
|
-
|
|
287
|
+
TargetsResponse:
|
|
226
288
|
allOf:
|
|
227
289
|
- $ref: '#/components/schemas/CommonResponseFields'
|
|
228
290
|
- type: object
|
|
@@ -231,7 +293,7 @@ components:
|
|
|
231
293
|
type: array
|
|
232
294
|
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.
|
|
233
295
|
items:
|
|
234
|
-
$ref: '#/components/schemas/
|
|
296
|
+
$ref: '#/components/schemas/TargetsItem'
|
|
235
297
|
|
|
236
298
|
IssueEntry:
|
|
237
299
|
type: object
|
|
@@ -250,7 +312,9 @@ components:
|
|
|
250
312
|
properties:
|
|
251
313
|
layer:
|
|
252
314
|
type: string
|
|
253
|
-
enum:
|
|
315
|
+
enum:
|
|
316
|
+
- guideline
|
|
317
|
+
- success criterion
|
|
254
318
|
'numeric identifier':
|
|
255
319
|
type: string
|
|
256
320
|
pattern: '^\d\.\d(\.\d+)?$'
|
package/package.json
CHANGED
package/reportIssues/api.js
CHANGED
|
@@ -62,7 +62,7 @@ exports.response = async args => {
|
|
|
62
62
|
}));
|
|
63
63
|
const thisHost = process.env.THIS_KILOTEST_HOST;
|
|
64
64
|
// Get a response.
|
|
65
|
-
const
|
|
65
|
+
const content = {
|
|
66
66
|
summary: `This document fulfills a request made by an agent to the Kilotest service. The agent requested data from a Kilotest report about the accessibility, usability, and standard-conformity of a web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten testing tools, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes several API endpoints for agents and several web UI URLs for humans to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of tools, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
|
|
67
67
|
'tool name': 'Kilotest',
|
|
68
68
|
request: {
|
|
@@ -70,6 +70,7 @@ exports.response = async args => {
|
|
|
70
70
|
identifier: 'reportIssues',
|
|
71
71
|
description: 'What issues does the specified report describe?'
|
|
72
72
|
},
|
|
73
|
+
method: 'GET',
|
|
73
74
|
URLs: {
|
|
74
75
|
'URL of your request': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
|
|
75
76
|
'equivalent URL for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
|
|
@@ -122,5 +123,5 @@ exports.response = async args => {
|
|
|
122
123
|
.map(issue => getIssueFacts(thisHost, timeStamp, jobID, issue))
|
|
123
124
|
}
|
|
124
125
|
};
|
|
125
|
-
return
|
|
126
|
+
return content;
|
|
126
127
|
};
|
package/researchAgent.js
CHANGED
|
@@ -30,11 +30,11 @@ const port = hostParts[2] || (scheme === 'https' ? 443 : 80);
|
|
|
30
30
|
|
|
31
31
|
// FUNCTIONS
|
|
32
32
|
|
|
33
|
-
// Submits
|
|
33
|
+
// Submits three request to a random Kilotest host.
|
|
34
34
|
const requestService = async () => {
|
|
35
35
|
const client = scheme === 'https' ? httpsClient : httpClient;
|
|
36
|
-
const getRequestOptions = path => ({
|
|
37
|
-
method
|
|
36
|
+
const getRequestOptions = (path, method = 'GET') => ({
|
|
37
|
+
method,
|
|
38
38
|
host,
|
|
39
39
|
port,
|
|
40
40
|
path,
|
|
@@ -43,6 +43,7 @@ const requestService = async () => {
|
|
|
43
43
|
}
|
|
44
44
|
});
|
|
45
45
|
const path = `/api/targets`;
|
|
46
|
+
console.log('======================');
|
|
46
47
|
console.log(`About to submit ${scheme} request as JSON on port ${port} to ${host}${path}`);
|
|
47
48
|
// Submit a targets request.
|
|
48
49
|
client.request(getRequestOptions(path), response => {
|
|
@@ -65,15 +66,14 @@ const requestService = async () => {
|
|
|
65
66
|
try {
|
|
66
67
|
// Output it.
|
|
67
68
|
const contentObj = JSON.parse(content);
|
|
68
|
-
console.log('======================');
|
|
69
69
|
console.log(JSON.stringify(contentObj, null, 2));
|
|
70
70
|
// Get the IDs of the available reports.
|
|
71
71
|
const reportIDs = contentObj['available reports'].map(report => report.identifier);
|
|
72
72
|
// Choose one at random.
|
|
73
73
|
const [timeStamp, jobID] = reportIDs[Math.floor(Math.random() * reportIDs.length)]
|
|
74
74
|
.split('-');
|
|
75
|
-
console.log('======================');
|
|
76
75
|
const path = `/api/reportIssues/${timeStamp}/${jobID}`;
|
|
76
|
+
console.log('======================');
|
|
77
77
|
console.log(`About to submit ${scheme} request as JSON on port ${port} to ${host}${path}`);
|
|
78
78
|
const requestOptions = getRequestOptions(path);
|
|
79
79
|
// Submit an issues request for it.
|
|
@@ -98,7 +98,47 @@ const requestService = async () => {
|
|
|
98
98
|
// Output it.
|
|
99
99
|
const contentObj = JSON.parse(content);
|
|
100
100
|
console.log(JSON.stringify(contentObj, null, 2));
|
|
101
|
+
const testRecPath = `/api/testRecForm`;
|
|
101
102
|
console.log('======================');
|
|
103
|
+
console.log(
|
|
104
|
+
`About to submit ${scheme} POST request as JSON on port ${port} to ${host}${testRecPath}`
|
|
105
|
+
);
|
|
106
|
+
const testRecOptions = getRequestOptions(testRecPath, 'POST');
|
|
107
|
+
// Submit a test recommendation.
|
|
108
|
+
client.request(testRecOptions, response => {
|
|
109
|
+
// Initialize a collection of data from the response.
|
|
110
|
+
const chunks = [];
|
|
111
|
+
response
|
|
112
|
+
// If the response throws an error:
|
|
113
|
+
.on('error', async error => {
|
|
114
|
+
// Report it.
|
|
115
|
+
console.log(error.message);
|
|
116
|
+
})
|
|
117
|
+
// If the response delivers data:
|
|
118
|
+
.on('data', chunk => {
|
|
119
|
+
// Add them to the collection.
|
|
120
|
+
chunks.push(chunk);
|
|
121
|
+
})
|
|
122
|
+
// When the response is completed:
|
|
123
|
+
.on('end', async () => {
|
|
124
|
+
const content = chunks.join('');
|
|
125
|
+
try {
|
|
126
|
+
// Output it.
|
|
127
|
+
const contentObj = JSON.parse(content);
|
|
128
|
+
console.log(JSON.stringify(contentObj, null, 2));
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.log(error.message);
|
|
132
|
+
console.log(`Test recommendation response content: ${content || 'No content'}`);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
})
|
|
136
|
+
// Finish sending the test recommendation request.
|
|
137
|
+
.end(JSON.stringify({
|
|
138
|
+
what: 'Page Not Already Tested',
|
|
139
|
+
url: 'https://pagenotalreadytested.info',
|
|
140
|
+
why: 'This is only a test'
|
|
141
|
+
}));
|
|
102
142
|
}
|
|
103
143
|
catch (error) {
|
|
104
144
|
console.log(error.message);
|
package/sitemap.xml
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
<url><loc>https://kilotest.com/</loc></url>
|
|
4
4
|
<url><loc>https://kilotest.com/targets.html</loc></url>
|
|
5
5
|
<url><loc>https://kilotest.com/issues.html</loc></url>
|
|
6
|
+
<url><loc>https://kilotest.com/testRecForm.html</loc></url>
|
|
7
|
+
<url><loc>https://kilotest.com/manage.html</loc></url>
|
|
6
8
|
<url><loc>https://kilotest.com/tutorial.html</loc></url>
|
|
7
9
|
<url><loc>https://kilotest.com/openapi.yaml</loc></url>
|
|
8
10
|
<url><loc>https://kilotest.com/llms.txt</loc></url>
|
package/targets/api.js
CHANGED
|
@@ -82,10 +82,12 @@ exports.response = async () => {
|
|
|
82
82
|
identifier: 'targets',
|
|
83
83
|
description: 'Give me summary data about each available report.'
|
|
84
84
|
},
|
|
85
|
+
method: 'GET',
|
|
85
86
|
URLs: {
|
|
86
87
|
'URL of your request': `${thisHost}/api/targets`,
|
|
87
88
|
'equivalent URL for humans': `${thisHost}/targets.html`
|
|
88
|
-
}
|
|
89
|
+
},
|
|
90
|
+
'closest ancestor request': null
|
|
89
91
|
},
|
|
90
92
|
'response metadata': {
|
|
91
93
|
identifier: `${getNowStamp()}-${getRandomString(3)}`,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*
|
|
2
|
+
api.js
|
|
3
|
+
Responds to the test-recommendation request.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// IMPORTS
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
getNowStamp,
|
|
10
|
+
getRandomString,
|
|
11
|
+
updateRecs
|
|
12
|
+
} = require('../util');
|
|
13
|
+
|
|
14
|
+
// FUNCTIONS
|
|
15
|
+
|
|
16
|
+
// Returns a response to a test-recommendation request.
|
|
17
|
+
exports.response = async (what, url, why) => {
|
|
18
|
+
const thisHost = process.env.THIS_KILOTEST_HOST;
|
|
19
|
+
// Record the recommendation.
|
|
20
|
+
await updateRecs(what, url, why);
|
|
21
|
+
// Get a response.
|
|
22
|
+
const content = {
|
|
23
|
+
summary: `This response acknowledges a request made by an agent to the Kilotest service. The agent recommended that Kilotest test the ${what} web page at ${url} for accessibility, usability, and standard-conformity. A Kilotest manager usually approves a recommendation within a day. When the recommendation is approved, the testing will be performed and results will become available. You can check for the availability of the results at ${thisHost}/api/targets. Kilotest performs its testing with the help of Testaro, Testilo, and an ensemble of ten testing tools, using a combination of rule- and machine-learning-based methods. Kilotest exposes several API endpoints for agents and several web UI URLs for humans to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of tools, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
|
|
24
|
+
'tool name': 'Kilotest',
|
|
25
|
+
request: {
|
|
26
|
+
'type of request': {
|
|
27
|
+
identifier: 'testRecForm',
|
|
28
|
+
description: 'I recommend that Kilotest test a particular web page.'
|
|
29
|
+
},
|
|
30
|
+
method: 'POST',
|
|
31
|
+
payload: {
|
|
32
|
+
'description of the web page': what,
|
|
33
|
+
'URL of the web page': url,
|
|
34
|
+
'reason for testing the web page': why
|
|
35
|
+
},
|
|
36
|
+
URLs: {
|
|
37
|
+
'URL of your request': `${thisHost}/api/testRecForm`,
|
|
38
|
+
'equivalent URL for humans': `${thisHost}/testRecForm.html`
|
|
39
|
+
},
|
|
40
|
+
'closest ancestor request': null
|
|
41
|
+
},
|
|
42
|
+
'response metadata': {
|
|
43
|
+
identifier: `${getNowStamp()}-${getRandomString(3)}`,
|
|
44
|
+
'date and time': new Date().toISOString()
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return content;
|
|
48
|
+
};
|
package/util.js
CHANGED
|
@@ -626,6 +626,20 @@ const getPlainText = string => string.replace(/&/g, '+').replace(/[<>"'&]/g, ' '
|
|
|
626
626
|
const getNowStamp = exports.getNowStamp = () => {
|
|
627
627
|
return getTimeStamp(new Date());
|
|
628
628
|
};
|
|
629
|
+
// Updates the test recommendations.
|
|
630
|
+
const updateRecs = exports.updateRecs = async (what, url, why) => {
|
|
631
|
+
// Get the data on waiting recommendations.
|
|
632
|
+
const recs = await getRecs();
|
|
633
|
+
recs[url] ??= [];
|
|
634
|
+
// Add the recommendation to those for the target.
|
|
635
|
+
recs[url].push({
|
|
636
|
+
timeStamp: getNowStamp(),
|
|
637
|
+
what,
|
|
638
|
+
why
|
|
639
|
+
});
|
|
640
|
+
// Save the revised recommendations.
|
|
641
|
+
await fs.writeFile(recsPath, getJSON(recs));
|
|
642
|
+
};
|
|
629
643
|
// Processes a test or retest recommendation.
|
|
630
644
|
exports.processRec = async (testType, dirName, what, url, why) => {
|
|
631
645
|
// If the recommendation is valid:
|
|
@@ -638,17 +652,8 @@ exports.processRec = async (testType, dirName, what, url, why) => {
|
|
|
638
652
|
) {
|
|
639
653
|
// Make the reason display-safe.
|
|
640
654
|
const plainWhy = getPlainText(why);
|
|
641
|
-
//
|
|
642
|
-
|
|
643
|
-
recs[url] ??= [];
|
|
644
|
-
// Add the recommendation to those for the target.
|
|
645
|
-
recs[url].push({
|
|
646
|
-
timeStamp: getNowStamp(),
|
|
647
|
-
what,
|
|
648
|
-
why: plainWhy
|
|
649
|
-
});
|
|
650
|
-
// Save the revised recommendations.
|
|
651
|
-
await fs.writeFile(recsPath, getJSON(recs));
|
|
655
|
+
// Update the waiting recommendations.
|
|
656
|
+
await updateRecs(what, url, plainWhy);
|
|
652
657
|
// Log the recommendation.
|
|
653
658
|
console.log(`Test recommendation received for ${what}: ${plainWhy}`);
|
|
654
659
|
// Alert a manager about it.
|