@jrpool/kilotest 46.0.8 → 46.0.14

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.
Files changed (60) hide show
  1. package/.devin/config.local.json +4 -1
  2. package/.github/workflows/{smoke-test.yml → ci.yml} +8 -2
  3. package/README.md +14 -8
  4. package/alerts.test.js +137 -0
  5. package/api/listDiagnoses.test.js +44 -0
  6. package/api/listIssues.js +1 -1
  7. package/api/listIssues.test.js +10 -0
  8. package/api/listReports.test.js +6 -2
  9. package/api/listViolators.test.js +35 -0
  10. package/api/requestTest.test.js +7 -0
  11. package/api/routes.test.js +63 -0
  12. package/api/util.js +9 -11
  13. package/api/util.test.js +68 -2
  14. package/apiIntegration.test.js +13 -3
  15. package/docs/AI-TOOLS.md +41 -158
  16. package/docs/{Smoke Test.json → CI.json} +4 -3
  17. package/index.html +3 -3
  18. package/index.js +64 -77
  19. package/index.test.js +1152 -0
  20. package/indexBalances.test.js +188 -0
  21. package/indexFallback.test.js +33 -0
  22. package/indexServe.test.js +59 -0
  23. package/indexWorkers.test.js +79 -0
  24. package/lhm.plugin.json +3218 -0
  25. package/llms-full.txt +6 -7
  26. package/llms.txt +1 -1
  27. package/mcp.js +2 -2
  28. package/mcp.test.js +281 -0
  29. package/openapi.yaml +1 -1
  30. package/package.json +10 -5
  31. package/routing.test.js +13 -3
  32. package/scripts/generate-openapi.js +1 -1
  33. package/test/fixtures/buildFixtures.js +83 -0
  34. package/test/fixtures/db/reports/260101T0008-mul.json +137 -0
  35. package/test/fixtures/db/reports/260101T0009-brd.json +147 -0
  36. package/test/setup.cjs +14 -0
  37. package/util.js +16 -6
  38. package/util.test.js +886 -3
  39. package/web/ai0BalanceForm/ai0BalanceForm.test.js +88 -0
  40. package/web/expungeReportsForm/expungeReportsForm.test.js +114 -0
  41. package/web/hideReportForm/hideReportForm.test.js +82 -0
  42. package/web/listDiagnoses/listDiagnoses.test.js +160 -0
  43. package/web/listIssues/listIssues.test.js +109 -0
  44. package/web/listReports/listReports.test.js +139 -3
  45. package/web/listRules/listRules.test.js +103 -0
  46. package/web/listTopIssues/listTopIssues.test.js +126 -0
  47. package/web/listViolators/index.js +1 -2
  48. package/web/listViolators/listViolators.test.js +256 -0
  49. package/web/pruneReportsForm/pruneReportsForm.test.js +86 -0
  50. package/web/reannotate/reannotate.test.js +144 -0
  51. package/web/reannotateForm/reannotateForm.test.js +134 -0
  52. package/web/renewWCAG/renewWCAG.test.js +124 -0
  53. package/web/requestRetest/requestRetest.test.js +119 -0
  54. package/web/requestRetestForm/requestRetestForm.test.js +62 -0
  55. package/web/requestTest/requestTest.test.js +115 -0
  56. package/web/requestTestForm/requestTestForm.test.js +40 -0
  57. package/web/rewindReportsForm/rewindReportsForm.test.js +86 -0
  58. package/web/tutorial/index.html +3 -3
  59. package/web/tutorial/tutorial.test.js +97 -0
  60. package/web/unhideReportForm/unhideReportForm.test.js +135 -0
@@ -0,0 +1,147 @@
1
+ {
2
+ "id": "260101T0009-brd",
3
+ "what": "Branch Coverage Page",
4
+ "strict": false,
5
+ "standard": "only",
6
+ "device": {
7
+ "id": "default"
8
+ },
9
+ "browserID": "chromium",
10
+ "creationTimeStamp": "260101T0009",
11
+ "executionTimeStamp": "260101T0009",
12
+ "target": {
13
+ "what": "Branch Coverage Page",
14
+ "url": "https://example.com/branch"
15
+ },
16
+ "sources": {
17
+ "worker": "test-worker"
18
+ },
19
+ "acts": [
20
+ {
21
+ "type": "test",
22
+ "which": "axe",
23
+ "startTime": "26-01-01T00:00",
24
+ "endTime": "26-01-01T00:01",
25
+ "result": {
26
+ "standardResult": {
27
+ "instances": [
28
+ {
29
+ "ruleID": "r99",
30
+ "what": "r99",
31
+ "ordinalSeverity": 2,
32
+ "outcome": "failed",
33
+ "count": 1,
34
+ "catalogIndex": "0",
35
+ "checkpoint": 0,
36
+ "issueID": "duplicateID"
37
+ },
38
+ {
39
+ "ruleID": "r100",
40
+ "what": "Element has no role",
41
+ "ordinalSeverity": 1,
42
+ "outcome": "failed",
43
+ "catalogIndex": "1",
44
+ "checkpoint": 0,
45
+ "issueID": "duplicateID"
46
+ },
47
+ {
48
+ "ruleID": "r101",
49
+ "what": "Duplicate ID found",
50
+ "ordinalSeverity": 2,
51
+ "outcome": "failed",
52
+ "count": 1,
53
+ "catalogIndex": "2",
54
+ "checkpoint": 0,
55
+ "issueID": "duplicateID"
56
+ },
57
+ {
58
+ "ruleID": "r102",
59
+ "what": "Duplicate ID in orphan",
60
+ "ordinalSeverity": 2,
61
+ "outcome": "failed",
62
+ "count": 1,
63
+ "catalogIndex": "3",
64
+ "checkpoint": 0,
65
+ "issueID": "duplicateID"
66
+ }
67
+ ],
68
+ "outcomeTotals": {
69
+ "failed": 4,
70
+ "cantTell": 0
71
+ }
72
+ }
73
+ }
74
+ },
75
+ {
76
+ "type": "test",
77
+ "which": "alfa",
78
+ "startTime": "26-01-01T00:00",
79
+ "endTime": "26-01-01T00:01",
80
+ "result": {
81
+ "standardResult": {}
82
+ }
83
+ },
84
+ {
85
+ "type": "test",
86
+ "which": "ibm",
87
+ "startTime": "26-01-01T00:00",
88
+ "endTime": "26-01-01T00:01",
89
+ "result": {
90
+ "standardResult": {
91
+ "instances": [
92
+ {
93
+ "ruleID": "r50",
94
+ "what": "Link has no text",
95
+ "ordinalSeverity": 2,
96
+ "outcome": "failed",
97
+ "catalogIndex": "0",
98
+ "checkpoint": 0
99
+ }
100
+ ],
101
+ "outcomeTotals": {
102
+ "failed": 1,
103
+ "cantTell": 0
104
+ }
105
+ }
106
+ }
107
+ }
108
+ ],
109
+ "jobData": {
110
+ "startTime": "26-01-01T00:00",
111
+ "endTime": "26-01-01T00:10",
112
+ "elapsedSeconds": 600,
113
+ "issuelessRules": []
114
+ },
115
+ "catalog": {
116
+ "0": {
117
+ "tagName": "DIV",
118
+ "id": "",
119
+ "startTag": "<div>",
120
+ "text": "",
121
+ "textLinkable": false,
122
+ "boxID": "0:0:100:50",
123
+ "pathID": "/html/body/div[1]",
124
+ "headingIndex": "",
125
+ "checkpoint": 0
126
+ },
127
+ "1": {
128
+ "id": "",
129
+ "startTag": "<div>",
130
+ "text": null,
131
+ "textLinkable": false,
132
+ "boxID": "5:5:90:40",
133
+ "pathID": "/html/body/div[2]",
134
+ "headingIndex": "",
135
+ "checkpoint": 0
136
+ },
137
+ "2": {
138
+ "id": "",
139
+ "text": "No tags",
140
+ "textLinkable": false,
141
+ "headingIndex": "",
142
+ "checkpoint": 0
143
+ }
144
+ },
145
+ "images": {},
146
+ "checkpoints": []
147
+ }
package/test/setup.cjs ADDED
@@ -0,0 +1,14 @@
1
+ /*
2
+ test/setup.cjs
3
+ Clears alert configuration env vars before any modules are required,
4
+ so that tests calling sendAlert indirectly never trigger real email alerts.
5
+ This file is loaded via --require before any test file runs.
6
+
7
+ The env vars are set to empty strings rather than deleted, because
8
+ dotenv does not override existing env vars. This prevents the .env
9
+ file loaded by index.js from re-arming the alert configuration.
10
+ */
11
+
12
+ for (const key of ['MANAGER_EMAIL', 'ALERT_API_HOST', 'ALERT_API_PATH', 'ALERT_API_KEY', 'ALERT_FROM']) {
13
+ process.env[key] = '';
14
+ }
package/util.js CHANGED
@@ -142,11 +142,18 @@ const getJobNames = exports.getJobNames = async () => {
142
142
  const jobNames = {};
143
143
  let fileNames;
144
144
  for (const category of ['queue', 'claimed', 'failed']) {
145
+ const categoryPath = path.join(jobsPath(), category);
145
146
  try {
146
- fileNames = await fs.readdir(path.join(jobsPath(), category));
147
+ fileNames = await fs.readdir(categoryPath);
147
148
  }
148
149
  catch(error) {
149
- return `ERROR: Job directory ${category} not readable (${error.message})`;
150
+ if (error.code === 'ENOENT') {
151
+ await fs.mkdir(categoryPath, {recursive: true});
152
+ fileNames = [];
153
+ }
154
+ else {
155
+ return `ERROR: Job directory ${category} not readable (${error.message})`;
156
+ }
150
157
  }
151
158
  jobNames[category] = fileNames;
152
159
  }
@@ -220,6 +227,9 @@ exports.getPOSTData = request => new Promise(resolve => {
220
227
  const query = querystring.parse(body);
221
228
  resolve(query);
222
229
  }
230
+ else {
231
+ resolve(null);
232
+ }
223
233
  });
224
234
  });
225
235
  // Returns the waiting test and retest recommendations.
@@ -604,9 +614,9 @@ const getPageData = exports.getPageData = async (timeStamp, jobID) => {
604
614
  return report;
605
615
  }
606
616
  const {url, what} = report.target;
607
- const reportStats = await getReportStats(timeStamp, jobID)
608
- // Otherwise, i.e. if it succeeded, get the elapsed time in days since the report was created.
609
- const daysAgo = getAgoDays(reportStats.reportTime);
617
+ // Get the elapsed time in days since the report was completed, using the
618
+ // report content rather than the file system birth time.
619
+ const daysAgo = getAgoDays(new Date(`20${report.jobData.endTime}Z`));
610
620
  // Return the data.
611
621
  return {
612
622
  what,
@@ -640,7 +650,7 @@ exports.getPageDataStrings = async (timeStamp, jobID, pageData) => {
640
650
  };
641
651
  };
642
652
  // Returns the creation time and size of a report.
643
- const getReportStats = exports.getReportStats = async (timeStamp, jobID) => {
653
+ exports.getReportStats = async (timeStamp, jobID) => {
644
654
  let reportStat;
645
655
  try {
646
656
  reportStat = await fs.stat(path.join(reportsPath(), `${timeStamp}-${jobID}.json`));