@oalacea/daemon 0.5.0 → 0.5.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +46 -38
  2. package/LICENSE +23 -23
  3. package/README.md +147 -141
  4. package/agents/deps-analyzer.js +366 -366
  5. package/agents/detector.js +570 -570
  6. package/agents/fix-engine.js +305 -305
  7. package/agents/lighthouse-scanner.js +405 -405
  8. package/agents/perf-analyzer.js +294 -294
  9. package/agents/perf-front-analyzer.js +229 -229
  10. package/agents/test-generator.js +387 -387
  11. package/agents/test-runner.js +318 -318
  12. package/bin/Dockerfile +75 -74
  13. package/bin/cli.js +449 -449
  14. package/lib/config.js +250 -250
  15. package/lib/docker.js +207 -207
  16. package/lib/reporter.js +297 -297
  17. package/package.json +34 -34
  18. package/prompts/DEPS_EFFICIENCY.md +558 -558
  19. package/prompts/E2E.md +491 -491
  20. package/prompts/EXECUTE.md +1060 -1060
  21. package/prompts/INTEGRATION_API.md +484 -484
  22. package/prompts/INTEGRATION_DB.md +425 -425
  23. package/prompts/PERF_API.md +433 -433
  24. package/prompts/PERF_DB.md +430 -430
  25. package/prompts/PERF_FRONT.md +357 -357
  26. package/prompts/REMEDIATION.md +482 -482
  27. package/prompts/UNIT.md +260 -260
  28. package/scripts/dev.js +106 -106
  29. package/templates/README.md +38 -38
  30. package/templates/k6/load-test.js +54 -54
  31. package/templates/playwright/e2e.spec.ts +61 -61
  32. package/templates/vitest/angular-component.test.ts +38 -38
  33. package/templates/vitest/api.test.ts +51 -51
  34. package/templates/vitest/component.test.ts +27 -27
  35. package/templates/vitest/hook.test.ts +36 -36
  36. package/templates/vitest/solid-component.test.ts +34 -34
  37. package/templates/vitest/svelte-component.test.ts +33 -33
  38. package/templates/vitest/vue-component.test.ts +39 -39
@@ -1,318 +1,318 @@
1
- /**
2
- * Daemon - Test Runner Agent
3
- *
4
- * Executes tests and parses results.
5
- * Supports Vitest, Jest, and Playwright.
6
- */
7
-
8
- const { execSync } = require('child_process');
9
- const fs = require('fs');
10
- const path = require('path');
11
-
12
- // Configuration
13
- const CONFIG = {
14
- container: 'daemon-tools',
15
- docker: 'docker exec',
16
- };
17
-
18
- /**
19
- * Run tests inside the Docker container
20
- */
21
- function runTests(command, options = {}) {
22
- const dockerCmd = `${CONFIG.docker} ${CONFIG.container} ${command}`;
23
-
24
- try {
25
- const output = execSync(dockerCmd, {
26
- encoding: 'utf-8',
27
- stdio: options.silent ? 'pipe' : 'inherit',
28
- timeout: options.timeout || 120000,
29
- cwd: options.cwd || process.cwd(),
30
- });
31
-
32
- return {
33
- success: true,
34
- output,
35
- exitCode: 0,
36
- };
37
- } catch (error) {
38
- return {
39
- success: false,
40
- output: error.stdout || '',
41
- error: error.stderr || error.message,
42
- exitCode: error.status || 1,
43
- };
44
- }
45
- }
46
-
47
- /**
48
- * Run unit tests
49
- */
50
- function runUnitTests(testFile = null) {
51
- const cmd = testFile
52
- ? `npm test -- ${testFile}`
53
- : `npm test`;
54
-
55
- return runTests(cmd);
56
- }
57
-
58
- /**
59
- * Run integration tests
60
- */
61
- function runIntegrationTests(testFile = null) {
62
- const cmd = testFile
63
- ? `npm test -- ${testFile}`
64
- : `npm test -- tests/integration`;
65
-
66
- return runTests(cmd);
67
- }
68
-
69
- /**
70
- * Run E2E tests
71
- */
72
- function runE2ETests(testFile = null) {
73
- const cmd = testFile
74
- ? `npx playwright test ${testFile}`
75
- : `npx playwright test`;
76
-
77
- return runTests(cmd);
78
- }
79
-
80
- /**
81
- * Run performance tests
82
- */
83
- function runPerformanceTests(testFile = null) {
84
- const cmd = testFile
85
- ? `k6 run ${testFile}`
86
- : `k6 run tests/performance`;
87
-
88
- return runTests(cmd);
89
- }
90
-
91
- /**
92
- * Parse Vitest/Jest output
93
- */
94
- function parseTestOutput(output) {
95
- const results = {
96
- total: 0,
97
- passed: 0,
98
- failed: 0,
99
- skipped: 0,
100
- failures: [],
101
- };
102
-
103
- // Parse Vitest output
104
- const testFiles = output.match(/Test Files\s+\d+ passed/g);
105
- if (testFiles) {
106
- results.total += parseInt(testFiles[0].match(/\d+/)[0]);
107
- }
108
-
109
- const passed = output.match(/(\d+) passed/);
110
- if (passed) {
111
- results.passed += parseInt(passed[1]);
112
- }
113
-
114
- const failed = output.match(/(\d+) failed/);
115
- if (failed) {
116
- results.failed += parseInt(failed[1]);
117
- // Parse failure details
118
- const failOutput = output.match(/FAIL\s+(.+)/g);
119
- if (failOutput) {
120
- results.failures = failOutput.map((f) => {
121
- const match = f.match(/FAIL\s+(.+?)\s+/);
122
- return match ? match[1] : f;
123
- });
124
- }
125
- }
126
-
127
- const skipped = output.match(/(\d+) skipped/);
128
- if (skipped) {
129
- results.skipped += parseInt(skipped[1]);
130
- }
131
-
132
- return results;
133
- }
134
-
135
- /**
136
- * Parse Playwright output
137
- */
138
- function parseE2EOutput(output) {
139
- const results = {
140
- total: 0,
141
- passed: 0,
142
- failed: 0,
143
- skipped: 0,
144
- failures: [],
145
- };
146
-
147
- const passed = output.match(/passed\s+(\d+)/);
148
- if (passed) results.passed += parseInt(passed[1]);
149
-
150
- const failed = output.match(/failed\s+(\d+)/);
151
- if (failed) {
152
- results.failed += parseInt(failed[1]);
153
- // Parse failure details
154
- const failLines = output.match(/^.*?\[ERROR\].*$/gm);
155
- if (failLines) {
156
- results.failures = failLines;
157
- }
158
- }
159
-
160
- const skipped = output.match(/skipped\s+(\d+)/);
161
- if (skipped) results.skipped += parseInt(skipped[1]);
162
-
163
- results.total = results.passed + results.failed + results.skipped;
164
-
165
- return results;
166
- }
167
-
168
- /**
169
- * Parse k6 output
170
- */
171
- function parsePerfOutput(output) {
172
- const results = {
173
- requests: 0,
174
- duration: 0,
175
- avgResponseTime: 0,
176
- p95: 0,
177
- p99: 0,
178
- rps: 0,
179
- failureRate: 0,
180
- };
181
-
182
- // Parse k6 summary output
183
- const checks = output.match(/checks.*?:\s+([\d.]+)%/);
184
- if (checks) results.failureRate = 100 - parseFloat(checks[1]);
185
-
186
- const dataReceived = output.match(/data_received\s+([\d.]+\s+\w+)/);
187
- if (dataReceived) results.dataReceived = dataReceived[1];
188
-
189
- const httpReqDuration = output.match(/http_req_duration.*?avg=\s*([\d.]+)ms.*?p\(95\)=\s*([\d.]+)ms/);
190
- if (httpReqDuration) {
191
- results.avgResponseTime = parseFloat(httpReqDuration[1]);
192
- results.p95 = parseFloat(httpReqDuration[2]);
193
- }
194
-
195
- const httpReqs = output.match(/http_reqs\s+([\d.]+)/);
196
- if (httpReqs) results.requests = parseInt(httpReqs[1]);
197
-
198
- const iterationDuration = output.match(/iteration_duration.*?avg=\s*([\d.]+)/);
199
- if (iterationDuration) results.duration = parseFloat(iterationDuration[1]);
200
-
201
- return results;
202
- }
203
-
204
- /**
205
- * Get test coverage
206
- */
207
- function getCoverage() {
208
- const result = runTests('npm test -- --coverage');
209
-
210
- if (!result.success) {
211
- return null;
212
- }
213
-
214
- const coverage = {
215
- lines: 0,
216
- functions: 0,
217
- branches: 0,
218
- statements: 0,
219
- };
220
-
221
- // Parse coverage output
222
- const lines = result.output.match(/All files[^]*?(\d+)%/);
223
- if (lines) coverage.lines = parseInt(lines[1]);
224
-
225
- const functions = result.output.match(/functions[^]*?(\d+)%/);
226
- if (functions) coverage.functions = parseInt(functions[1]);
227
-
228
- const branches = result.output.match(/branches[^]*?(\d+)%/);
229
- if (branches) coverage.branches = parseInt(branches[1]);
230
-
231
- const statements = result.output.match(/statements[^]*?(\d+)%/);
232
- if (statements) coverage.statements = parseInt(statements[1]);
233
-
234
- return coverage;
235
- }
236
-
237
- /**
238
- * Run all tests and return summary
239
- */
240
- async function runAllTests() {
241
- const summary = {
242
- unit: null,
243
- integration: null,
244
- e2e: null,
245
- performance: null,
246
- coverage: null,
247
- };
248
-
249
- // Unit tests
250
- const unitResult = runUnitTests();
251
- summary.unit = {
252
- ...parseTestOutput(unitResult.output),
253
- success: unitResult.success,
254
- };
255
-
256
- // Integration tests
257
- const integrationResult = runIntegrationTests();
258
- summary.integration = {
259
- ...parseTestOutput(integrationResult.output),
260
- success: integrationResult.success,
261
- };
262
-
263
- // E2E tests
264
- const e2eResult = runE2ETests();
265
- summary.e2e = {
266
- ...parseE2EOutput(e2eResult.output),
267
- success: e2eResult.success,
268
- };
269
-
270
- // Performance tests
271
- const perfResult = runPerformanceTests();
272
- summary.performance = {
273
- ...parsePerfOutput(perfResult.output),
274
- success: perfResult.success,
275
- };
276
-
277
- // Coverage
278
- summary.coverage = getCoverage();
279
-
280
- return summary;
281
- }
282
-
283
- /**
284
- * Run a single test file
285
- */
286
- function runSingleTest(testPath) {
287
- return runTests(`npm test -- ${testPath}`);
288
- }
289
-
290
- /**
291
- * Watch tests
292
- */
293
- function watchTests() {
294
- return runTests('npm test -- --watch');
295
- }
296
-
297
- /**
298
- * Debug a failing test
299
- */
300
- function debugTest(testPath) {
301
- return runTests(`npm test -- ${testPath} --reporter=verbose --no-coverage`);
302
- }
303
-
304
- module.exports = {
305
- runTests,
306
- runUnitTests,
307
- runIntegrationTests,
308
- runE2ETests,
309
- runPerformanceTests,
310
- parseTestOutput,
311
- parseE2EOutput,
312
- parsePerfOutput,
313
- getCoverage,
314
- runAllTests,
315
- runSingleTest,
316
- watchTests,
317
- debugTest,
318
- };
1
+ /**
2
+ * Daemon - Test Runner Agent
3
+ *
4
+ * Executes tests and parses results.
5
+ * Supports Vitest, Jest, and Playwright.
6
+ */
7
+
8
+ const { execSync } = require('child_process');
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ // Configuration
13
+ const CONFIG = {
14
+ container: 'daemon-tools',
15
+ docker: 'docker exec',
16
+ };
17
+
18
+ /**
19
+ * Run tests inside the Docker container
20
+ */
21
+ function runTests(command, options = {}) {
22
+ const dockerCmd = `${CONFIG.docker} ${CONFIG.container} ${command}`;
23
+
24
+ try {
25
+ const output = execSync(dockerCmd, {
26
+ encoding: 'utf-8',
27
+ stdio: options.silent ? 'pipe' : 'inherit',
28
+ timeout: options.timeout || 120000,
29
+ cwd: options.cwd || process.cwd(),
30
+ });
31
+
32
+ return {
33
+ success: true,
34
+ output,
35
+ exitCode: 0,
36
+ };
37
+ } catch (error) {
38
+ return {
39
+ success: false,
40
+ output: error.stdout || '',
41
+ error: error.stderr || error.message,
42
+ exitCode: error.status || 1,
43
+ };
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Run unit tests
49
+ */
50
+ function runUnitTests(testFile = null) {
51
+ const cmd = testFile
52
+ ? `npm test -- ${testFile}`
53
+ : `npm test`;
54
+
55
+ return runTests(cmd);
56
+ }
57
+
58
+ /**
59
+ * Run integration tests
60
+ */
61
+ function runIntegrationTests(testFile = null) {
62
+ const cmd = testFile
63
+ ? `npm test -- ${testFile}`
64
+ : `npm test -- tests/integration`;
65
+
66
+ return runTests(cmd);
67
+ }
68
+
69
+ /**
70
+ * Run E2E tests
71
+ */
72
+ function runE2ETests(testFile = null) {
73
+ const cmd = testFile
74
+ ? `npx playwright test ${testFile}`
75
+ : `npx playwright test`;
76
+
77
+ return runTests(cmd);
78
+ }
79
+
80
+ /**
81
+ * Run performance tests
82
+ */
83
+ function runPerformanceTests(testFile = null) {
84
+ const cmd = testFile
85
+ ? `k6 run ${testFile}`
86
+ : `k6 run tests/performance`;
87
+
88
+ return runTests(cmd);
89
+ }
90
+
91
+ /**
92
+ * Parse Vitest/Jest output
93
+ */
94
+ function parseTestOutput(output) {
95
+ const results = {
96
+ total: 0,
97
+ passed: 0,
98
+ failed: 0,
99
+ skipped: 0,
100
+ failures: [],
101
+ };
102
+
103
+ // Parse Vitest output
104
+ const testFiles = output.match(/Test Files\s+\d+ passed/g);
105
+ if (testFiles) {
106
+ results.total += parseInt(testFiles[0].match(/\d+/)[0]);
107
+ }
108
+
109
+ const passed = output.match(/(\d+) passed/);
110
+ if (passed) {
111
+ results.passed += parseInt(passed[1]);
112
+ }
113
+
114
+ const failed = output.match(/(\d+) failed/);
115
+ if (failed) {
116
+ results.failed += parseInt(failed[1]);
117
+ // Parse failure details
118
+ const failOutput = output.match(/FAIL\s+(.+)/g);
119
+ if (failOutput) {
120
+ results.failures = failOutput.map((f) => {
121
+ const match = f.match(/FAIL\s+(.+?)\s+/);
122
+ return match ? match[1] : f;
123
+ });
124
+ }
125
+ }
126
+
127
+ const skipped = output.match(/(\d+) skipped/);
128
+ if (skipped) {
129
+ results.skipped += parseInt(skipped[1]);
130
+ }
131
+
132
+ return results;
133
+ }
134
+
135
+ /**
136
+ * Parse Playwright output
137
+ */
138
+ function parseE2EOutput(output) {
139
+ const results = {
140
+ total: 0,
141
+ passed: 0,
142
+ failed: 0,
143
+ skipped: 0,
144
+ failures: [],
145
+ };
146
+
147
+ const passed = output.match(/passed\s+(\d+)/);
148
+ if (passed) results.passed += parseInt(passed[1]);
149
+
150
+ const failed = output.match(/failed\s+(\d+)/);
151
+ if (failed) {
152
+ results.failed += parseInt(failed[1]);
153
+ // Parse failure details
154
+ const failLines = output.match(/^.*?\[ERROR\].*$/gm);
155
+ if (failLines) {
156
+ results.failures = failLines;
157
+ }
158
+ }
159
+
160
+ const skipped = output.match(/skipped\s+(\d+)/);
161
+ if (skipped) results.skipped += parseInt(skipped[1]);
162
+
163
+ results.total = results.passed + results.failed + results.skipped;
164
+
165
+ return results;
166
+ }
167
+
168
+ /**
169
+ * Parse k6 output
170
+ */
171
+ function parsePerfOutput(output) {
172
+ const results = {
173
+ requests: 0,
174
+ duration: 0,
175
+ avgResponseTime: 0,
176
+ p95: 0,
177
+ p99: 0,
178
+ rps: 0,
179
+ failureRate: 0,
180
+ };
181
+
182
+ // Parse k6 summary output
183
+ const checks = output.match(/checks.*?:\s+([\d.]+)%/);
184
+ if (checks) results.failureRate = 100 - parseFloat(checks[1]);
185
+
186
+ const dataReceived = output.match(/data_received\s+([\d.]+\s+\w+)/);
187
+ if (dataReceived) results.dataReceived = dataReceived[1];
188
+
189
+ const httpReqDuration = output.match(/http_req_duration.*?avg=\s*([\d.]+)ms.*?p\(95\)=\s*([\d.]+)ms/);
190
+ if (httpReqDuration) {
191
+ results.avgResponseTime = parseFloat(httpReqDuration[1]);
192
+ results.p95 = parseFloat(httpReqDuration[2]);
193
+ }
194
+
195
+ const httpReqs = output.match(/http_reqs\s+([\d.]+)/);
196
+ if (httpReqs) results.requests = parseInt(httpReqs[1]);
197
+
198
+ const iterationDuration = output.match(/iteration_duration.*?avg=\s*([\d.]+)/);
199
+ if (iterationDuration) results.duration = parseFloat(iterationDuration[1]);
200
+
201
+ return results;
202
+ }
203
+
204
+ /**
205
+ * Get test coverage
206
+ */
207
+ function getCoverage() {
208
+ const result = runTests('npm test -- --coverage');
209
+
210
+ if (!result.success) {
211
+ return null;
212
+ }
213
+
214
+ const coverage = {
215
+ lines: 0,
216
+ functions: 0,
217
+ branches: 0,
218
+ statements: 0,
219
+ };
220
+
221
+ // Parse coverage output
222
+ const lines = result.output.match(/All files[^]*?(\d+)%/);
223
+ if (lines) coverage.lines = parseInt(lines[1]);
224
+
225
+ const functions = result.output.match(/functions[^]*?(\d+)%/);
226
+ if (functions) coverage.functions = parseInt(functions[1]);
227
+
228
+ const branches = result.output.match(/branches[^]*?(\d+)%/);
229
+ if (branches) coverage.branches = parseInt(branches[1]);
230
+
231
+ const statements = result.output.match(/statements[^]*?(\d+)%/);
232
+ if (statements) coverage.statements = parseInt(statements[1]);
233
+
234
+ return coverage;
235
+ }
236
+
237
+ /**
238
+ * Run all tests and return summary
239
+ */
240
+ async function runAllTests() {
241
+ const summary = {
242
+ unit: null,
243
+ integration: null,
244
+ e2e: null,
245
+ performance: null,
246
+ coverage: null,
247
+ };
248
+
249
+ // Unit tests
250
+ const unitResult = runUnitTests();
251
+ summary.unit = {
252
+ ...parseTestOutput(unitResult.output),
253
+ success: unitResult.success,
254
+ };
255
+
256
+ // Integration tests
257
+ const integrationResult = runIntegrationTests();
258
+ summary.integration = {
259
+ ...parseTestOutput(integrationResult.output),
260
+ success: integrationResult.success,
261
+ };
262
+
263
+ // E2E tests
264
+ const e2eResult = runE2ETests();
265
+ summary.e2e = {
266
+ ...parseE2EOutput(e2eResult.output),
267
+ success: e2eResult.success,
268
+ };
269
+
270
+ // Performance tests
271
+ const perfResult = runPerformanceTests();
272
+ summary.performance = {
273
+ ...parsePerfOutput(perfResult.output),
274
+ success: perfResult.success,
275
+ };
276
+
277
+ // Coverage
278
+ summary.coverage = getCoverage();
279
+
280
+ return summary;
281
+ }
282
+
283
+ /**
284
+ * Run a single test file
285
+ */
286
+ function runSingleTest(testPath) {
287
+ return runTests(`npm test -- ${testPath}`);
288
+ }
289
+
290
+ /**
291
+ * Watch tests
292
+ */
293
+ function watchTests() {
294
+ return runTests('npm test -- --watch');
295
+ }
296
+
297
+ /**
298
+ * Debug a failing test
299
+ */
300
+ function debugTest(testPath) {
301
+ return runTests(`npm test -- ${testPath} --reporter=verbose --no-coverage`);
302
+ }
303
+
304
+ module.exports = {
305
+ runTests,
306
+ runUnitTests,
307
+ runIntegrationTests,
308
+ runE2ETests,
309
+ runPerformanceTests,
310
+ parseTestOutput,
311
+ parseE2EOutput,
312
+ parsePerfOutput,
313
+ getCoverage,
314
+ runAllTests,
315
+ runSingleTest,
316
+ watchTests,
317
+ debugTest,
318
+ };