@jrpool/kilotest 46.1.2 → 48.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/.claude/settings.local.json +13 -1
- package/.devin/config.local.json +5 -1
- package/.github/workflows/ci.yml +0 -3
- package/.github/workflows/periodic-smoke-tests.yml +30 -0
- package/.github/workflows/publish-mcp.yml +4 -4
- package/{alerts.test.js → alerts.test.ts} +17 -29
- package/{alerts.js → alerts.ts} +10 -13
- package/api/{getReport.test.js → getReport.test.ts} +9 -10
- package/api/{getReport.js → getReport.ts} +23 -24
- package/api/{listDiagnoses.test.js → listDiagnoses.test.ts} +26 -27
- package/api/{listDiagnoses.js → listDiagnoses.ts} +46 -70
- package/api/{listIssues.test.js → listIssues.test.ts} +21 -14
- package/api/{listIssues.js → listIssues.ts} +75 -74
- package/api/{listReports.test.js → listReports.test.ts} +17 -16
- package/api/listReports.ts +87 -0
- package/api/{listViolators.test.js → listViolators.test.ts} +19 -20
- package/api/{listViolators.js → listViolators.ts} +45 -70
- package/api/requestFeature.test.ts +54 -0
- package/api/{requestFeature.js → requestFeature.ts} +18 -15
- package/api/requestRetest.test.ts +144 -0
- package/api/requestRetest.ts +119 -0
- package/api/requestTest.test.ts +153 -0
- package/api/requestTest.ts +123 -0
- package/api/{routes.test.js → routes.test.ts} +5 -5
- package/api/{routes.js → routes.ts} +6 -6
- package/api/{schemas.js → schemas.ts} +69 -50
- package/api/{util.test.js → util.test.ts} +35 -14
- package/api/{util.js → util.ts} +54 -51
- package/api/version.ts +8 -0
- package/{apiIntegration.test.js → apiIntegration.test.ts} +12 -13
- package/balances.ts +87 -0
- package/{checkinfo.js → checkinfo.ts} +24 -20
- package/docs/AI-TOOLS.md +4 -4
- package/docs/BACKLOG.md +360 -0
- package/docs/SERVICE.md +170 -17
- package/docs/decisions/002-coverage-tool.md +40 -0
- package/docs/decisions/003-adr-threshold.md +34 -0
- package/docs/decisions/004-docs-directory.md +23 -0
- package/docs/decisions/005-observability.md +28 -0
- package/docs/decisions/006-git-workflow.md +28 -0
- package/docs/decisions/007-internal-testing.md +34 -0
- package/docs/decisions/008-dependencies.md +28 -0
- package/docs/decisions/009-qai-integration.md +40 -0
- package/docs/decisions/QAI-HISTORICAL-CONTEXT.md +42 -0
- package/eslint.config.mjs +27 -0
- package/index.html +3 -3
- package/{index.test.js → index.test.ts} +397 -152
- package/{index.js → index.ts} +386 -285
- package/{indexBalances.test.js → indexBalances.test.ts} +21 -17
- package/{indexServe.test.js → indexServe.test.ts} +9 -9
- package/linkValidation.test.ts +190 -0
- package/{mcp.test.js → mcp.test.ts} +53 -26
- package/{mcp.js → mcp.ts} +29 -20
- package/memory/MEMORY.md +7 -0
- package/memory/user_maintainer_context.md +24 -0
- package/openapi.yaml +115 -68
- package/package.json +35 -15
- package/pm2.config.cjs +29 -0
- package/{routes.test.js → routes.test.ts} +8 -7
- package/{routing.test.js → routing.test.ts} +11 -12
- package/scripts/{generate-openapi.js → generate-openapi.ts} +13 -13
- package/serve.ts +15 -0
- package/smokeTest.ts +234 -0
- package/test/dbFixture.ts +21 -0
- package/test/fixtures/{buildFixtures.js → buildFixtures.ts} +14 -13
- package/test/{setup.cjs → setup.ts} +2 -2
- package/tsconfig.json +16 -0
- package/util.test.ts +1129 -0
- package/util.ts +1017 -0
- package/web/ai0BalanceForm/{ai0BalanceForm.test.js → ai0BalanceForm.test.ts} +15 -15
- package/web/ai0BalanceForm/{index.js → index.ts} +10 -18
- package/web/enqueue/index.ts +56 -0
- package/web/enqueueForm/index.html +9 -9
- package/web/enqueueForm/index.ts +43 -0
- package/web/expungeReportsForm/{expungeReportsForm.test.js → expungeReportsForm.test.ts} +18 -20
- package/web/expungeReportsForm/index.ts +18 -0
- package/web/hideReportForm/{hideReportForm.test.js → hideReportForm.test.ts} +14 -14
- package/web/hideReportForm/{index.js → index.ts} +17 -21
- package/web/listDiagnoses/{index.js → index.ts} +48 -58
- package/web/listDiagnoses/{listDiagnoses.test.js → listDiagnoses.test.ts} +39 -34
- package/web/listIssues/{index.js → index.ts} +67 -92
- package/web/listIssues/{listIssues.test.js → listIssues.test.ts} +45 -51
- package/web/listReports/index.html +3 -3
- package/web/listReports/{index.js → index.ts} +74 -58
- package/web/listReports/{listReports.test.js → listReports.test.ts} +41 -43
- package/web/listRules/{index.js → index.ts} +18 -23
- package/web/listRules/{listRules.test.js → listRules.test.ts} +26 -19
- package/web/listTopIssues/{index.js → index.ts} +36 -47
- package/web/listTopIssues/{listTopIssues.test.js → listTopIssues.test.ts} +26 -17
- package/web/listViolators/{index.js → index.ts} +51 -71
- package/web/listViolators/{listViolators.test.js → listViolators.test.ts} +43 -36
- package/web/manage/index.ts +22 -0
- package/web/pruneReportsForm/index.ts +18 -0
- package/web/pruneReportsForm/{pruneReportsForm.test.js → pruneReportsForm.test.ts} +11 -11
- package/web/reannotate/index.ts +71 -0
- package/web/reannotate/{reannotate.test.js → reannotate.test.ts} +19 -22
- package/web/reannotateForm/{index.js → index.ts} +41 -50
- package/web/reannotateForm/{reannotateForm.test.js → reannotateForm.test.ts} +13 -16
- package/web/renewWCAG/{index.js → index.ts} +9 -9
- package/web/renewWCAG/{renewWCAG.test.js → renewWCAG.test.ts} +17 -20
- package/web/renewWCAGForm/index.ts +22 -0
- package/web/{expungeReportsForm/index.js → reportDeletion.ts} +57 -39
- package/web/requestRetest/index.html +7 -7
- package/web/requestRetest/index.ts +62 -0
- package/web/requestRetest/requestRetest.test.ts +130 -0
- package/web/requestRetestForm/{index.js → index.ts} +10 -16
- package/web/requestRetestForm/{requestRetestForm.test.js → requestRetestForm.test.ts} +11 -12
- package/web/requestTest/index.html +7 -7
- package/web/requestTest/index.ts +52 -0
- package/web/requestTest/{requestTest.test.js → requestTest.test.ts} +39 -24
- package/web/requestTestForm/index.html +4 -4
- package/web/requestTestForm/index.ts +21 -0
- package/web/requestTestForm/{requestTestForm.test.js → requestTestForm.test.ts} +9 -9
- package/web/rewindReportsForm/index.ts +18 -0
- package/web/rewindReportsForm/{rewindReportsForm.test.js → rewindReportsForm.test.ts} +11 -11
- package/web/tutorialAI/index.html +184 -0
- package/web/tutorialAI/index.ts +80 -0
- package/web/tutorialAI/tutorialAI.test.ts +192 -0
- package/web/{tutorial → tutorialWeb}/index.html +9 -8
- package/web/tutorialWeb/index.ts +78 -0
- package/web/tutorialWeb/tutorialWeb.test.ts +195 -0
- package/web/unhideReportForm/{index.js → index.ts} +18 -22
- package/web/unhideReportForm/{unhideReportForm.test.js → unhideReportForm.test.ts} +16 -16
- package/aceconfig.js +0 -28
- package/api/listReports.js +0 -89
- package/api/requestFeature.test.js +0 -58
- package/api/requestRetest.js +0 -96
- package/api/requestRetest.test.js +0 -80
- package/api/requestTest.js +0 -106
- package/api/requestTest.test.js +0 -92
- package/api/version.js +0 -8
- package/indexFallback.test.js +0 -33
- package/indexWorkers.test.js +0 -79
- package/jsconfig.json +0 -8
- package/pm2.config.js +0 -18
- package/smokeTest.js +0 -128
- package/util.js +0 -744
- package/util.test.js +0 -968
- package/web/enqueue/index.js +0 -67
- package/web/enqueueForm/index.js +0 -49
- package/web/manage/index.js +0 -22
- package/web/pruneReportsForm/index.js +0 -123
- package/web/reannotate/index.js +0 -58
- package/web/renewWCAGForm/index.js +0 -22
- package/web/requestRetest/index.js +0 -31
- package/web/requestRetest/requestRetest.test.js +0 -119
- package/web/requestTest/index.js +0 -24
- package/web/requestTestForm/index.js +0 -21
- package/web/rewindReportsForm/index.js +0 -121
- package/web/tutorial/index.js +0 -63
- package/web/tutorial/tutorial.test.js +0 -97
- /package/test/fixtures/db/jobs/{recs.json → testRequests.json} +0 -0
- /package/web/{tutorial → tutorialWeb}/images/newsletter-form.png +0 -0
package/indexFallback.test.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
indexFallback.test.js
|
|
3
|
-
Tests that index.js loads successfully when PROTOCOL and TESTARO_WORKERS
|
|
4
|
-
are not set, exercising the || fallback branches at module load time.
|
|
5
|
-
This must be a separate file because index.js reads these env vars
|
|
6
|
-
at module load time, and each test file runs in its own process.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// ENVIRONMENT (must be set before requiring index.js)
|
|
10
|
-
|
|
11
|
-
const path = require('node:path');
|
|
12
|
-
const fixtureDBDir = path.join(__dirname, 'test', 'fixtures', 'db');
|
|
13
|
-
|
|
14
|
-
process.env.DB_DIR = fixtureDBDir;
|
|
15
|
-
process.env.AUTH_CODE = 'test-auth-code';
|
|
16
|
-
// Set PROTOCOL and TESTARO_WORKERS to empty strings (falsy) so that
|
|
17
|
-
// the || fallbacks in index.js are exercised. dotenv does not override
|
|
18
|
-
// existing env vars, so .env will not replace these.
|
|
19
|
-
process.env.PROTOCOL = '';
|
|
20
|
-
process.env.TESTARO_WORKERS = '';
|
|
21
|
-
|
|
22
|
-
// IMPORTS
|
|
23
|
-
|
|
24
|
-
const {test} = require('node:test');
|
|
25
|
-
const assert = require('node:assert/strict');
|
|
26
|
-
const {requestHandler} = require('./index');
|
|
27
|
-
|
|
28
|
-
// TESTS
|
|
29
|
-
|
|
30
|
-
test('index.js loads with empty PROTOCOL and TESTARO_WORKERS using fallbacks', () => {
|
|
31
|
-
// If index.js loaded successfully, requestHandler is a function.
|
|
32
|
-
assert.equal(typeof requestHandler, 'function');
|
|
33
|
-
});
|
package/indexWorkers.test.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
indexWorkers.test.js
|
|
3
|
-
Tests for index.js when TESTARO_WORKERS is invalid JSON.
|
|
4
|
-
This must be a separate file because index.js reads TESTARO_WORKERS
|
|
5
|
-
at module load time.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// ENVIRONMENT (must be set before requiring index.js)
|
|
9
|
-
|
|
10
|
-
const path = require('node:path');
|
|
11
|
-
const fixtureDBDir = path.join(__dirname, 'test', 'fixtures', 'db');
|
|
12
|
-
|
|
13
|
-
process.env.DB_DIR = fixtureDBDir;
|
|
14
|
-
process.env.AUTH_CODE = 'test-auth-code';
|
|
15
|
-
process.env.TESTARO_WORKERS = 'not valid json';
|
|
16
|
-
|
|
17
|
-
// IMPORTS
|
|
18
|
-
|
|
19
|
-
const {test} = require('node:test');
|
|
20
|
-
const assert = require('node:assert/strict');
|
|
21
|
-
const http = require('node:http');
|
|
22
|
-
const {requestHandler} = require('./index');
|
|
23
|
-
|
|
24
|
-
// CONSTANTS
|
|
25
|
-
|
|
26
|
-
const port = 3993;
|
|
27
|
-
|
|
28
|
-
// HELPERS
|
|
29
|
-
|
|
30
|
-
const request = (method, requestPath, body = null, headers = {}) => new Promise((resolve, reject) => {
|
|
31
|
-
const options = {method, host: 'localhost', port, path: requestPath, headers: {...headers}};
|
|
32
|
-
let bodyData = '';
|
|
33
|
-
if (body) {
|
|
34
|
-
bodyData = JSON.stringify(body);
|
|
35
|
-
options.headers['content-type'] = 'application/json';
|
|
36
|
-
options.headers['content-length'] = Buffer.byteLength(bodyData);
|
|
37
|
-
}
|
|
38
|
-
const req = http.request(options, response => {
|
|
39
|
-
const chunks = [];
|
|
40
|
-
response.on('data', chunk => chunks.push(chunk));
|
|
41
|
-
response.on('end', () => {
|
|
42
|
-
resolve({statusCode: response.statusCode, headers: response.headers, body: Buffer.concat(chunks).toString()});
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
req.on('error', reject);
|
|
46
|
-
req.end(bodyData || '');
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// TESTS
|
|
50
|
-
|
|
51
|
-
test('index.js loads with invalid TESTARO_WORKERS and treats workers as empty', () => {
|
|
52
|
-
// If index.js loaded successfully, requestHandler is a function.
|
|
53
|
-
assert.equal(typeof requestHandler, 'function');
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test('POST /worker/job with invalid TESTARO_WORKERS returns 401 for any credentials', async () => {
|
|
57
|
-
const server = http.createServer(requestHandler);
|
|
58
|
-
await new Promise(resolve => server.listen(port, () => resolve()));
|
|
59
|
-
try {
|
|
60
|
-
const auth = Buffer.from('worker1:secret1').toString('base64');
|
|
61
|
-
const res = await request('POST', '/worker/job', {}, {
|
|
62
|
-
authorization: `Basic ${auth}`
|
|
63
|
-
});
|
|
64
|
-
assert.equal(res.statusCode, 401);
|
|
65
|
-
}
|
|
66
|
-
finally {
|
|
67
|
-
server.closeAllConnections?.();
|
|
68
|
-
await new Promise(resolve => {
|
|
69
|
-
const timer = setTimeout(() => {
|
|
70
|
-
server.closeAllConnections?.();
|
|
71
|
-
resolve();
|
|
72
|
-
}, 1000);
|
|
73
|
-
server.close(() => {
|
|
74
|
-
clearTimeout(timer);
|
|
75
|
-
resolve();
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
});
|
package/jsconfig.json
DELETED
package/pm2.config.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
apps: [
|
|
3
|
-
{
|
|
4
|
-
name: 'kilotest',
|
|
5
|
-
script: 'index.js',
|
|
6
|
-
instances: 1,
|
|
7
|
-
autorestart: true,
|
|
8
|
-
watch: false,
|
|
9
|
-
max_memory_restart: '500M',
|
|
10
|
-
time: true,
|
|
11
|
-
env: {
|
|
12
|
-
NODE_ENV: 'production',
|
|
13
|
-
BASE_PATH: '/',
|
|
14
|
-
DEMO_SSE_DELAY_MS: '100'
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
]
|
|
18
|
-
};
|
package/smokeTest.js
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
smokeTest.js
|
|
3
|
-
Sends requests to all valid GET and POST paths on the deployed server and verifies that Caddy forwards them to Kilotest (i.e., the response is not a bare Caddy 404).
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// IMPORTS
|
|
7
|
-
|
|
8
|
-
const https = require('https');
|
|
9
|
-
const {routes} = require('./index');
|
|
10
|
-
|
|
11
|
-
// CONSTANTS
|
|
12
|
-
|
|
13
|
-
const host = process.env.SMOKE_HOST || 'kilotest.com';
|
|
14
|
-
// Concrete paths matching each wildcard pattern in the routes table, for smoke testing.
|
|
15
|
-
const concretePaths = {
|
|
16
|
-
GET: {
|
|
17
|
-
'*.html*': '/listReports.html',
|
|
18
|
-
'/': '/',
|
|
19
|
-
'/api-docs': '/api-docs',
|
|
20
|
-
'/api/*': '/api/listReports',
|
|
21
|
-
'/capability.md': '/capability.md',
|
|
22
|
-
'/favicon.*': '/favicon.ico',
|
|
23
|
-
'/fullReport.json/*': '/fullReport.json/260101T0000/mix',
|
|
24
|
-
'/index.html': '/index.html',
|
|
25
|
-
'/llms-full.txt': '/llms-full.txt',
|
|
26
|
-
'/llms.txt': '/llms.txt',
|
|
27
|
-
'/mcp': '/mcp',
|
|
28
|
-
'/openapi.json': '/openapi.json',
|
|
29
|
-
'/openapi.yaml': '/openapi.yaml',
|
|
30
|
-
'/robots.txt': '/robots.txt',
|
|
31
|
-
'/sitemap.xml': '/sitemap.xml',
|
|
32
|
-
'/style.css': '/style.css',
|
|
33
|
-
'/swagger.json': '/swagger.json',
|
|
34
|
-
'/swagger.yaml': '/swagger.yaml',
|
|
35
|
-
'/tutorial/images/*': '/tutorial/images/diagram.png'
|
|
36
|
-
},
|
|
37
|
-
POST: {
|
|
38
|
-
'/api/*': '/api/requestFeature',
|
|
39
|
-
'/mcp': '/mcp',
|
|
40
|
-
'/reannotate.html': '/reannotate.html',
|
|
41
|
-
'/recAction.html': '/recAction.html',
|
|
42
|
-
'/renewWCAG.html': '/renewWCAG.html',
|
|
43
|
-
'/requestRetest.html/*': '/requestRetest.html/260101T0001/ct',
|
|
44
|
-
'/requestTest.html': '/requestTest.html',
|
|
45
|
-
'/tutorialComment.html': '/tutorialComment.html',
|
|
46
|
-
'/worker/job': '/worker/job',
|
|
47
|
-
'/worker/report': '/worker/report'
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
// Minimal POST bodies for paths that require them.
|
|
51
|
-
const postBodies = {
|
|
52
|
-
'/api/requestFeature': {feature: 'smoke test'},
|
|
53
|
-
'/mcp': {},
|
|
54
|
-
'/reannotate.html': {authCode: 'invalid'},
|
|
55
|
-
'/recAction.html': {
|
|
56
|
-
target: 'https://smoketest.example.com\tSmoke Test Page', authCode: 'invalid'
|
|
57
|
-
},
|
|
58
|
-
'/renewWCAG.html': {authCode: 'invalid'},
|
|
59
|
-
'/requestRetest.html/260101T0001/ct': {why: 'smoke test'},
|
|
60
|
-
'/requestTest.html': {what: 'Smoke Test Page', url: 'https://smoketest.example.com', why: 'smoke test'},
|
|
61
|
-
'/tutorialComment.html': {content: 'smoke test'},
|
|
62
|
-
'/worker/job': {},
|
|
63
|
-
'/worker/report': {}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// FUNCTIONS
|
|
67
|
-
|
|
68
|
-
// Sends an HTTPS request and returns the status code and body length.
|
|
69
|
-
const sendRequest = (method, requestPath) => new Promise((resolve, reject) => {
|
|
70
|
-
const body = method === 'POST' ? JSON.stringify(postBodies[requestPath] || {}) : null;
|
|
71
|
-
const headers = {'x-kilotest-smoke': '1'};
|
|
72
|
-
if (body) {
|
|
73
|
-
headers['content-type'] = 'application/json; charset=utf-8';
|
|
74
|
-
headers['content-length'] = Buffer.byteLength(body);
|
|
75
|
-
}
|
|
76
|
-
const options = {
|
|
77
|
-
method,
|
|
78
|
-
host,
|
|
79
|
-
path: requestPath,
|
|
80
|
-
headers
|
|
81
|
-
};
|
|
82
|
-
const req = https.request(options, response => {
|
|
83
|
-
const chunks = [];
|
|
84
|
-
response.on('data', chunk => chunks.push(chunk));
|
|
85
|
-
response.on('end', () => {
|
|
86
|
-
const responseBody = chunks.join('');
|
|
87
|
-
resolve({statusCode: response.statusCode, bodyLength: responseBody.length});
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
req.on('error', reject);
|
|
91
|
-
req.end(body || '');
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Returns whether a response is a bare Caddy 404 (the failure this test detects).
|
|
95
|
-
const isCaddy404 = result => result.statusCode === 404 && result.bodyLength === 0;
|
|
96
|
-
|
|
97
|
-
// EXECUTION
|
|
98
|
-
|
|
99
|
-
(async () => {
|
|
100
|
-
let failures = 0;
|
|
101
|
-
for (const method of ['GET', 'POST']) {
|
|
102
|
-
console.log(`\n=== ${method} paths ===`);
|
|
103
|
-
for (const pattern of routes[method]) {
|
|
104
|
-
const requestPath = concretePaths[method][pattern];
|
|
105
|
-
if (!requestPath) {
|
|
106
|
-
console.log(`FAIL: no concrete path defined for pattern ${pattern}`);
|
|
107
|
-
failures++;
|
|
108
|
-
continue;
|
|
109
|
-
}
|
|
110
|
-
try {
|
|
111
|
-
const result = await sendRequest(method, requestPath);
|
|
112
|
-
if (isCaddy404(result)) {
|
|
113
|
-
console.log(`FAIL: ${method} ${requestPath} -> Caddy 404 (path not forwarded)`);
|
|
114
|
-
failures++;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
console.log(`PASS: ${method} ${requestPath} -> ${result.statusCode} (body ${result.bodyLength} bytes)`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
console.log(`FAIL: ${method} ${requestPath} -> error: ${error.message}`);
|
|
122
|
-
failures++;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
console.log(`\n=== ${failures === 0 ? 'All paths forwarded' : `${failures} failure(s)`} ===`);
|
|
127
|
-
process.exit(failures === 0 ? 0 : 1);
|
|
128
|
-
})();
|