vibecodingmachine-core 2026.2.26-1739 → 2026.3.9-850
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/package.json +1 -1
- package/src/agents/AgentCheckDiscoveryService.js +180 -0
- package/src/agents/AgentCheckService.js +18 -261
- package/src/agents/AgentCheckStatisticsService.js +195 -0
- package/src/agents/EnvironmentConfigurationManager.js +31 -380
- package/src/agents/InstallationType.js +19 -6
- package/src/agents/SimpleAgentCheckService.js +472 -0
- package/src/agents/config-managers/ConfigUtils.js +72 -0
- package/src/agents/config-managers/DefaultConfig.js +58 -0
- package/src/agents/config-managers/EnvVarLoader.js +66 -0
- package/src/agents/config-managers/FileConfigLoader.js +124 -0
- package/src/agents/config-managers/TypeConverters.js +61 -0
- package/src/agents/config-managers/VariableMappings.js +92 -0
- package/src/agents/discovery/AgentDiscoveryService-refactored.js +272 -0
- package/src/agents/discovery/AgentDiscoveryService.js +29 -403
- package/src/agents/discovery/agent-validator.js +262 -0
- package/src/agents/discovery/discovery-results.js +176 -0
- package/src/agents/discovery/discovery-scanner.js +268 -0
- package/src/agents/discovery/discovery-utils.js +161 -0
- package/src/agents/discovery/executable-analyzer.js +290 -0
- package/src/agents/discovery/history-manager.js +310 -0
- package/src/agents/verification/ResultAnalyzer-refactored.js +341 -0
- package/src/agents/verification/ResultAnalyzer.js +30 -431
- package/src/agents/verification/analysis-utils.js +310 -0
- package/src/agents/verification/batch-analyzer.js +440 -0
- package/src/agents/verification/pattern-recognizer.js +369 -0
- package/src/agents/verification/report-generator.js +320 -0
- package/src/agents/verification/test-analyzer.js +290 -0
- package/src/agents/windows/InstallerFactory.js +4 -0
- package/src/agents/windows/VSCodeExtensionInstaller.js +404 -0
- package/src/analysis/analysis-engine.js +314 -0
- package/src/analysis/ast-analyzer.js +342 -0
- package/src/analysis/boundary-detector-refactored.js +378 -0
- package/src/analysis/boundary-detector.js +200 -603
- package/src/analysis/boundary-scanner.js +609 -0
- package/src/analysis/boundary-types.js +118 -0
- package/src/analysis/boundary-utils.js +293 -0
- package/src/analysis/deadline-priority-calculator.js +18 -0
- package/src/analysis/detection-methods.js +347 -0
- package/src/analysis/importance-priority-calculator.js +18 -0
- package/src/analysis/priority/factor-calculators.js +204 -0
- package/src/analysis/priority/factor-helpers.js +71 -0
- package/src/analysis/priority/priority-constants.js +73 -0
- package/src/analysis/priority/priority-factor-calculators.js +301 -0
- package/src/analysis/priority/reasons-generator.js +44 -0
- package/src/analysis/priority-calculator.js +15 -580
- package/src/analysis/strategy-generator.js +16 -66
- package/src/analysis/type-priority-calculator.js +18 -0
- package/src/analysis/urgency-priority-calculator.js +18 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +2 -40
- package/src/commands/disable-requirement.js +60 -0
- package/src/commands/disable-spec.js +60 -0
- package/src/commands/enable-requirement.js +60 -0
- package/src/commands/enable-spec.js +60 -0
- package/src/commands/registry.js +1 -6
- package/src/commands/requirements.js +8 -2
- package/src/ide-integration/applescript-manager.cjs +9 -24
- package/src/ide-integration/cdp-handlers/chat-reader.js +44 -0
- package/src/ide-integration/cdp-handlers/connection-handler.js +88 -0
- package/src/ide-integration/cdp-handlers/continuation-handler.js +314 -0
- package/src/ide-integration/cdp-handlers/message-submitter.js +75 -0
- package/src/ide-integration/cdp-handlers/text-sender.js +138 -0
- package/src/ide-integration/cdp-manager.js +28 -573
- package/src/ide-integration/claude-code-cli-manager.cjs +48 -12
- package/src/ide-integration/ide-openers/claude-opener.js +171 -0
- package/src/ide-integration/ide-openers/cursor-opener.js +53 -0
- package/src/ide-integration/ide-openers/other-ides-opener.js +230 -0
- package/src/ide-integration/ide-openers/vscode-opener.js +147 -0
- package/src/ide-integration/macos-ide-manager.js +20 -582
- package/src/ide-integration/macos-quota-checker.js +164 -0
- package/src/ide-integration/macos-text-sender.js +19 -38
- package/src/ide-integration/provider-manager.cjs +52 -7
- package/src/index.cjs +6 -0
- package/src/index.js +10 -0
- package/src/llm/direct-llm-manager.cjs +501 -0
- package/src/localization/translations/en-part1.js +363 -0
- package/src/localization/translations/en-part2.js +320 -0
- package/src/localization/translations/en.js +4 -687
- package/src/localization/translations/es-part1.js +363 -0
- package/src/localization/translations/es-part2.js +320 -0
- package/src/localization/translations/es.js +4 -688
- package/src/models/file-analysis-collection.js +139 -0
- package/src/models/file-analysis-metrics.js +50 -0
- package/src/models/file-analysis.js +15 -262
- package/src/models/plan-manager.js +410 -0
- package/src/models/refactoring-models.js +380 -0
- package/src/models/refactoring-plan-refactored.js +81 -0
- package/src/models/refactoring-plan.js +2 -663
- package/src/monitoring/alert-system.js +4 -45
- package/src/monitoring/continuous-scan-notifications.js +37 -191
- package/src/monitoring/notification-handlers/base-handler.js +58 -0
- package/src/monitoring/notification-handlers/error-handler.js +36 -0
- package/src/monitoring/notification-handlers/index.js +21 -0
- package/src/monitoring/notification-handlers/new-violation-handler.js +91 -0
- package/src/monitoring/notification-handlers/progress-handler.js +48 -0
- package/src/monitoring/notification-handlers/resolved-violation-handler.js +54 -0
- package/src/monitoring/notification-handlers/threshold-handler.js +36 -0
- package/src/provider-registry.js +8 -0
- package/src/refactoring/boundary/boundary-detector-refactored.js +58 -0
- package/src/refactoring/boundary/boundary-detector.js +26 -596
- package/src/refactoring/boundary/detectors/boundary-analyzers.js +281 -0
- package/src/refactoring/boundary/detectors/boundary-core.js +167 -0
- package/src/refactoring/boundary/detectors/class-detector.js +247 -0
- package/src/refactoring/boundary/detectors/config-detector.js +270 -0
- package/src/refactoring/boundary/detectors/constant-detector.js +269 -0
- package/src/refactoring/boundary/detectors/function-detector.js +248 -0
- package/src/refactoring/boundary/detectors/module-detector.js +249 -0
- package/src/refactoring/boundary/detectors/object-detector.js +247 -0
- package/src/refactoring/boundary/detectors/type-detectors.js +338 -0
- package/src/refactoring/boundary/detectors/utility-detector.js +270 -0
- package/src/refactoring/circular-dependency-resolver-original.js +16 -76
- package/src/refactoring/code-mover-refactored.js +309 -0
- package/src/refactoring/code-mover.js +48 -355
- package/src/refactoring/execution-status.js +18 -0
- package/src/refactoring/execution-strategies.js +172 -0
- package/src/refactoring/file-splitter-core.js +568 -0
- package/src/refactoring/file-splitter-types.js +136 -0
- package/src/refactoring/file-splitter.js +2 -682
- package/src/refactoring/functionality-validator.js +11 -51
- package/src/refactoring/import-manager-refactored.js +385 -0
- package/src/refactoring/import-manager.js +112 -487
- package/src/refactoring/import-models.js +189 -0
- package/src/refactoring/import-parser.js +306 -0
- package/src/refactoring/move-executor.js +431 -0
- package/src/refactoring/move-utils.js +368 -0
- package/src/refactoring/operation-executor.js +76 -0
- package/src/refactoring/plan-creator.js +36 -0
- package/src/refactoring/plan-executor.js +143 -0
- package/src/refactoring/plan-validator.js +68 -0
- package/src/refactoring/refactoring-executor-result.js +70 -0
- package/src/refactoring/refactoring-executor.js +34 -569
- package/src/refactoring/refactoring-operation.js +94 -0
- package/src/refactoring/refactoring-plan.js +69 -0
- package/src/refactoring/refactoring-rollback.js +22 -527
- package/src/refactoring/rollback-handlers/RollbackExecutor.js +107 -0
- package/src/refactoring/rollback-handlers/RollbackManager.js +265 -0
- package/src/refactoring/rollback-handlers/RollbackOperation.js +105 -0
- package/src/refactoring/rollback-handlers/RollbackResult.js +109 -0
- package/src/refactoring/rollback-handlers/RollbackStatistics.js +77 -0
- package/src/refactoring/test-validator.js +32 -448
- package/src/refactoring/validation/baseline-runner.js +71 -0
- package/src/refactoring/validation/report-generator.js +136 -0
- package/src/refactoring/validation/result-comparator.js +92 -0
- package/src/refactoring/validation/test-suite.js +59 -0
- package/src/refactoring/validation/test-validation-result.js +83 -0
- package/src/refactoring/validation/validation-runner.js +95 -0
- package/src/refactoring/validation/validation-status.js +18 -0
- package/src/rui/commands/AgentCommandParser.js +60 -369
- package/src/rui/commands/AgentResponseFormatter.js +7 -47
- package/src/rui/commands/parsers/CommandMapper.js +148 -0
- package/src/rui/commands/parsers/CommandValidator.js +228 -0
- package/src/rui/commands/parsers/ComponentExtractor.js +100 -0
- package/src/rui/commands/parsers/TokenParser.js +69 -0
- package/src/rui/commands/parsers/tokenizer.js +153 -0
- package/src/utils/current-requirement-operations.js +50 -1
- package/src/utils/report-generator.js +18 -514
- package/src/utils/report-generators/analysis-generator.js +115 -0
- package/src/utils/report-generators/base-generator.js +141 -0
- package/src/utils/report-generators/compliance-generator.js +41 -0
- package/src/utils/report-generators/format-handlers.js +185 -0
- package/src/utils/report-generators/refactoring-generator.js +46 -0
- package/src/utils/report-generators/validation-generator.js +63 -0
- package/src/utils/requirement-enable-disable.js +265 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +69 -1
- package/src/utils/requirement-helpers/requirement-mover.js +88 -1
- package/src/utils/requirement-helpers.js +5 -2
- package/src/utils/smoke-test-cli.js +45 -8
- package/src/utils/specification-enable-disable.js +122 -0
- package/src/utils/specification-helpers.js +30 -4
- package/src/utils/specification-migration.js +5 -5
- package/src/utils/test-comparator.js +118 -0
- package/src/utils/test-config.js +54 -0
- package/src/utils/test-executor.js +133 -0
- package/src/utils/test-parser.js +215 -0
- package/src/utils/test-runner-baseline.js +63 -0
- package/src/utils/test-runner-core.js +98 -0
- package/src/utils/test-runner-report.js +39 -0
- package/src/utils/test-runner-validation.js +71 -0
- package/src/utils/test-runner.js +11 -535
- package/src/validation/comparison-analyzer.js +333 -0
- package/src/validation/compliance-reporter-new.js +282 -0
- package/src/validation/compliance-reporter-refactored.js +344 -0
- package/src/validation/compliance-reporter.js +278 -591
- package/src/validation/compliance-utils.js +278 -0
- package/src/validation/html-generator.js +446 -0
- package/src/validation/metrics/category-calculator.js +137 -0
- package/src/validation/metrics/metrics-helpers.js +155 -0
- package/src/validation/metrics/overview-calculator.js +85 -0
- package/src/validation/metrics/overview-metrics.js +41 -0
- package/src/validation/metrics/quality-calculator.js +166 -0
- package/src/validation/metrics/size-calculator.js +69 -0
- package/src/validation/metrics-calculator.js +27 -551
package/src/utils/test-runner.js
CHANGED
|
@@ -5,571 +5,47 @@
|
|
|
5
5
|
* Provides test execution, result analysis, and regression detection.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const {
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Test result types
|
|
14
|
-
*/
|
|
15
|
-
const TEST_RESULT_TYPES = {
|
|
16
|
-
PASS: 'pass',
|
|
17
|
-
FAIL: 'fail',
|
|
18
|
-
SKIP: 'skip',
|
|
19
|
-
ERROR: 'error'
|
|
20
|
-
};
|
|
8
|
+
const { TestRunnerCore, TEST_RESULT_TYPES } = require('./test-runner-core');
|
|
9
|
+
const { runBaseline } = require('./test-runner-baseline');
|
|
10
|
+
const { runValidation, runSpecific } = require('./test-runner-validation');
|
|
11
|
+
const { generateReport } = require('./test-runner-report');
|
|
21
12
|
|
|
22
13
|
/**
|
|
23
14
|
* Test runner class
|
|
24
15
|
*/
|
|
25
|
-
class TestRunner {
|
|
16
|
+
class TestRunner extends TestRunnerCore {
|
|
26
17
|
constructor(options = {}) {
|
|
27
|
-
|
|
28
|
-
testCommand: 'npm test',
|
|
29
|
-
testDir: 'tests',
|
|
30
|
-
timeout: 300000, // 5 minutes
|
|
31
|
-
retries: 0,
|
|
32
|
-
verbose: false,
|
|
33
|
-
...options
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
this.baselineResults = null;
|
|
37
|
-
this.currentResults = null;
|
|
38
|
-
this.regressionDetected = false;
|
|
18
|
+
super(options);
|
|
39
19
|
}
|
|
40
20
|
|
|
41
21
|
/**
|
|
42
22
|
* Run baseline tests before refactoring
|
|
43
23
|
*/
|
|
44
24
|
async runBaseline() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
const results = await this.executeTests();
|
|
49
|
-
this.baselineResults = results;
|
|
50
|
-
|
|
51
|
-
console.log(`Baseline completed: ${results.passed}/${results.total} passed`);
|
|
52
|
-
return results;
|
|
53
|
-
} catch (error) {
|
|
54
|
-
throw new Error(`Baseline test execution failed: ${error.message}`);
|
|
55
|
-
}
|
|
25
|
+
return runBaseline(this);
|
|
56
26
|
}
|
|
57
27
|
|
|
58
28
|
/**
|
|
59
29
|
* Run tests after refactoring
|
|
60
30
|
*/
|
|
61
31
|
async runValidation() {
|
|
62
|
-
|
|
63
|
-
throw new Error('Baseline results not available. Run baseline first.');
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
console.log('Running validation tests...');
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const results = await this.executeTests();
|
|
70
|
-
this.currentResults = results;
|
|
71
|
-
|
|
72
|
-
// Compare with baseline
|
|
73
|
-
const comparison = this.compareResults(this.baselineResults, results);
|
|
74
|
-
this.regressionDetected = comparison.hasRegressions;
|
|
75
|
-
|
|
76
|
-
console.log(`Validation completed: ${results.passed}/${results.total} passed`);
|
|
77
|
-
|
|
78
|
-
if (this.regressionDetected) {
|
|
79
|
-
console.log(`⚠️ Regressions detected: ${comparison.regressions.length}`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
results,
|
|
84
|
-
comparison,
|
|
85
|
-
hasRegressions: this.regressionDetected
|
|
86
|
-
};
|
|
87
|
-
} catch (error) {
|
|
88
|
-
throw new Error(`Validation test execution failed: ${error.message}`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Execute tests and collect results
|
|
94
|
-
*/
|
|
95
|
-
async executeTests() {
|
|
96
|
-
return new Promise((resolve, reject) => {
|
|
97
|
-
const startTime = Date.now();
|
|
98
|
-
let output = '';
|
|
99
|
-
let errorOutput = '';
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
// Use npm test with JSON reporter if available
|
|
103
|
-
const testProcess = spawn('npm', ['test', '--', '--json', '--verbose'], {
|
|
104
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
105
|
-
cwd: process.cwd()
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
testProcess.stdout.on('data', (data) => {
|
|
109
|
-
output += data.toString();
|
|
110
|
-
if (this.options.verbose) {
|
|
111
|
-
process.stdout.write(data);
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
testProcess.stderr.on('data', (data) => {
|
|
116
|
-
errorOutput += data.toString();
|
|
117
|
-
if (this.options.verbose) {
|
|
118
|
-
process.stderr.write(data);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
testProcess.on('close', (code) => {
|
|
123
|
-
const duration = Date.now() - startTime;
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const results = this.parseTestOutput(output, errorOutput, code, duration);
|
|
127
|
-
resolve(results);
|
|
128
|
-
} catch (parseError) {
|
|
129
|
-
// Fallback to basic parsing
|
|
130
|
-
const fallbackResults = this.parseBasicOutput(output, errorOutput, code, duration);
|
|
131
|
-
resolve(fallbackResults);
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
testProcess.on('error', (error) => {
|
|
136
|
-
reject(new Error(`Test process failed: ${error.message}`));
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// Set timeout
|
|
140
|
-
if (this.options.timeout) {
|
|
141
|
-
setTimeout(() => {
|
|
142
|
-
testProcess.kill('SIGKILL');
|
|
143
|
-
reject(new Error(`Test execution timed out after ${this.options.timeout}ms`));
|
|
144
|
-
}, this.options.timeout);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
} catch (error) {
|
|
148
|
-
reject(new Error(`Failed to start test process: ${error.message}`));
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Parse test output (Jest JSON format)
|
|
155
|
-
*/
|
|
156
|
-
parseTestOutput(stdout, stderr, exitCode, duration) {
|
|
157
|
-
try {
|
|
158
|
-
// Try to parse JSON output
|
|
159
|
-
const jsonMatch = stdout.match(/\{[\s\S]*\}/);
|
|
160
|
-
if (jsonMatch) {
|
|
161
|
-
const jsonData = JSON.parse(jsonMatch[0]);
|
|
162
|
-
return this.parseJestResults(jsonData, duration);
|
|
163
|
-
}
|
|
164
|
-
} catch (error) {
|
|
165
|
-
// JSON parsing failed, fall back to basic parsing
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return this.parseBasicOutput(stdout, stderr, exitCode, duration);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Parse Jest results
|
|
173
|
-
*/
|
|
174
|
-
parseJestResults(jsonData, duration) {
|
|
175
|
-
const results = {
|
|
176
|
-
total: 0,
|
|
177
|
-
passed: 0,
|
|
178
|
-
failed: 0,
|
|
179
|
-
skipped: 0,
|
|
180
|
-
errors: 0,
|
|
181
|
-
duration,
|
|
182
|
-
suites: [],
|
|
183
|
-
tests: [],
|
|
184
|
-
coverage: null
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
if (jsonData.numTotalTests) {
|
|
188
|
-
results.total = jsonData.numTotalTests;
|
|
189
|
-
results.passed = jsonData.numPassedTests || 0;
|
|
190
|
-
results.failed = jsonData.numFailedTests || 0;
|
|
191
|
-
results.skipped = jsonData.numPendingTests || 0;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (jsonData.testResults) {
|
|
195
|
-
for (const testSuite of jsonData.testResults) {
|
|
196
|
-
const suite = {
|
|
197
|
-
name: testSuite.name,
|
|
198
|
-
file: testSuite.testFilePath,
|
|
199
|
-
passed: 0,
|
|
200
|
-
failed: 0,
|
|
201
|
-
skipped: 0,
|
|
202
|
-
duration: testSuite.perfStats?.end || 0,
|
|
203
|
-
tests: []
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
if (testSuite.assertionResults) {
|
|
207
|
-
for (const test of testSuite.assertionResults) {
|
|
208
|
-
const testResult = {
|
|
209
|
-
title: test.title,
|
|
210
|
-
fullName: test.fullName,
|
|
211
|
-
status: test.status,
|
|
212
|
-
duration: test.duration || 0,
|
|
213
|
-
failureMessages: test.failureMessages || []
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
suite.tests.push(testResult);
|
|
217
|
-
results.tests.push(testResult);
|
|
218
|
-
|
|
219
|
-
switch (test.status) {
|
|
220
|
-
case 'passed':
|
|
221
|
-
suite.passed++;
|
|
222
|
-
break;
|
|
223
|
-
case 'failed':
|
|
224
|
-
suite.failed++;
|
|
225
|
-
break;
|
|
226
|
-
case 'pending':
|
|
227
|
-
suite.skipped++;
|
|
228
|
-
break;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
results.suites.push(suite);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (jsonData.coverageMap) {
|
|
238
|
-
results.coverage = this.parseCoverageData(jsonData.coverageMap);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return results;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Parse basic test output
|
|
246
|
-
*/
|
|
247
|
-
parseBasicOutput(stdout, stderr, exitCode, duration) {
|
|
248
|
-
const results = {
|
|
249
|
-
total: 0,
|
|
250
|
-
passed: 0,
|
|
251
|
-
failed: 0,
|
|
252
|
-
skipped: 0,
|
|
253
|
-
errors: 0,
|
|
254
|
-
duration,
|
|
255
|
-
suites: [],
|
|
256
|
-
tests: [],
|
|
257
|
-
coverage: null
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
// Parse Jest-style output
|
|
261
|
-
const testMatch = stdout.match(/(\d+)\s+tests?\s+(\d+)\s+failed/);
|
|
262
|
-
if (testMatch) {
|
|
263
|
-
results.total = parseInt(testMatch[1]);
|
|
264
|
-
results.failed = parseInt(testMatch[2]);
|
|
265
|
-
results.passed = results.total - results.failed;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Parse pass/fail summary
|
|
269
|
-
const passMatch = stdout.match(/(\d+)\s+passing/);
|
|
270
|
-
if (passMatch) {
|
|
271
|
-
results.passed = parseInt(passMatch[1]);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
const failMatch = stdout.match(/(\d+)\s+failing/);
|
|
275
|
-
if (failMatch) {
|
|
276
|
-
results.failed = parseInt(failMatch[1]);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const skipMatch = stdout.match(/(\d+)\s+skipping/);
|
|
280
|
-
if (skipMatch) {
|
|
281
|
-
results.skipped = parseInt(skipMatch[1]);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Extract individual test results
|
|
285
|
-
const testLines = stdout.split('\n');
|
|
286
|
-
for (const line of testLines) {
|
|
287
|
-
const testMatch = line.match(/^(✓|✗|○)\s+(.+)$/);
|
|
288
|
-
if (testMatch) {
|
|
289
|
-
const status = testMatch[1] === '✓' ? 'passed' :
|
|
290
|
-
testMatch[1] === '✗' ? 'failed' : 'skipped';
|
|
291
|
-
const title = testMatch[2];
|
|
292
|
-
|
|
293
|
-
results.tests.push({
|
|
294
|
-
title,
|
|
295
|
-
status,
|
|
296
|
-
duration: 0,
|
|
297
|
-
failureMessages: status === 'failed' ? [line] : []
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
return results;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Parse coverage data
|
|
307
|
-
*/
|
|
308
|
-
parseCoverageData(coverageMap) {
|
|
309
|
-
const coverage = {
|
|
310
|
-
lines: { total: 0, covered: 0, percentage: 0 },
|
|
311
|
-
functions: { total: 0, covered: 0, percentage: 0 },
|
|
312
|
-
branches: { total: 0, covered: 0, percentage: 0 },
|
|
313
|
-
statements: { total: 0, covered: 0, percentage: 0 }
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
for (const [filePath, fileCoverage] of Object.entries(coverageMap)) {
|
|
317
|
-
// Parse line coverage
|
|
318
|
-
if (fileCoverage.l) {
|
|
319
|
-
const lines = Object.values(fileCoverage.l);
|
|
320
|
-
coverage.lines.total += lines.length;
|
|
321
|
-
coverage.lines.covered += lines.filter(count => count > 0).length;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Parse function coverage
|
|
325
|
-
if (fileCoverage.f) {
|
|
326
|
-
const functions = Object.values(fileCoverage.f);
|
|
327
|
-
coverage.functions.total += functions.length;
|
|
328
|
-
coverage.functions.covered += functions.filter(count => count > 0).length;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Parse branch coverage
|
|
332
|
-
if (fileCoverage.b) {
|
|
333
|
-
for (const branches of Object.values(fileCoverage.b)) {
|
|
334
|
-
coverage.branches.total += branches.length;
|
|
335
|
-
coverage.branches.covered += branches.filter(count => count > 0).length;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// Parse statement coverage
|
|
340
|
-
if (fileCoverage.s) {
|
|
341
|
-
const statements = Object.values(fileCoverage.s);
|
|
342
|
-
coverage.statements.total += statements.length;
|
|
343
|
-
coverage.statements.covered += statements.filter(count => count > 0).length;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Calculate percentages
|
|
348
|
-
for (const metric of Object.values(coverage)) {
|
|
349
|
-
metric.percentage = metric.total > 0 ?
|
|
350
|
-
Math.round((metric.covered / metric.total) * 100) : 0;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return coverage;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Compare baseline and current results
|
|
358
|
-
*/
|
|
359
|
-
compareResults(baseline, current) {
|
|
360
|
-
const comparison = {
|
|
361
|
-
hasRegressions: false,
|
|
362
|
-
regressions: [],
|
|
363
|
-
improvements: [],
|
|
364
|
-
unchanged: [],
|
|
365
|
-
summary: {
|
|
366
|
-
baseline: {
|
|
367
|
-
total: baseline.total,
|
|
368
|
-
passed: baseline.passed,
|
|
369
|
-
failed: baseline.failed,
|
|
370
|
-
duration: baseline.duration
|
|
371
|
-
},
|
|
372
|
-
current: {
|
|
373
|
-
total: current.total,
|
|
374
|
-
passed: current.passed,
|
|
375
|
-
failed: current.failed,
|
|
376
|
-
duration: current.duration
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
// Check for test count changes
|
|
382
|
-
if (current.total < baseline.total) {
|
|
383
|
-
comparison.regressions.push({
|
|
384
|
-
type: 'missing_tests',
|
|
385
|
-
message: `${baseline.total - current.total} tests are missing`,
|
|
386
|
-
severity: 'high'
|
|
387
|
-
});
|
|
388
|
-
comparison.hasRegressions = true;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (current.total > baseline.total) {
|
|
392
|
-
comparison.improvements.push({
|
|
393
|
-
type: 'new_tests',
|
|
394
|
-
message: `${current.total - baseline.total} new tests added`,
|
|
395
|
-
severity: 'info'
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// Check for test failures
|
|
400
|
-
if (current.failed > baseline.failed) {
|
|
401
|
-
comparison.regressions.push({
|
|
402
|
-
type: 'new_failures',
|
|
403
|
-
message: `${current.failed - baseline.failed} new test failures`,
|
|
404
|
-
severity: 'high'
|
|
405
|
-
});
|
|
406
|
-
comparison.hasRegressions = true;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
if (current.failed < baseline.failed) {
|
|
410
|
-
comparison.improvements.push({
|
|
411
|
-
type: 'fixed_failures',
|
|
412
|
-
message: `${baseline.failed - current.failed} test failures fixed`,
|
|
413
|
-
severity: 'good'
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// Check for performance regression
|
|
418
|
-
const performanceIncrease = current.duration - baseline.duration;
|
|
419
|
-
const performancePercent = (performanceIncrease / baseline.duration) * 100;
|
|
420
|
-
|
|
421
|
-
if (performanceIncrease > 5000 && performancePercent > 10) { // 5s and 10%
|
|
422
|
-
comparison.regressions.push({
|
|
423
|
-
type: 'performance',
|
|
424
|
-
message: `Test execution increased by ${Math.round(performancePercent)}% (${Math.round(performanceIncrease/1000)}s)`,
|
|
425
|
-
severity: 'medium'
|
|
426
|
-
});
|
|
427
|
-
comparison.hasRegressions = true;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// Compare individual test results
|
|
431
|
-
const baselineTests = new Map();
|
|
432
|
-
for (const test of baseline.tests) {
|
|
433
|
-
baselineTests.set(test.fullName, test);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
for (const test of current.tests) {
|
|
437
|
-
const baselineTest = baselineTests.get(test.fullName);
|
|
438
|
-
|
|
439
|
-
if (!baselineTest) {
|
|
440
|
-
comparison.improvements.push({
|
|
441
|
-
type: 'new_test',
|
|
442
|
-
message: `New test: ${test.title}`,
|
|
443
|
-
severity: 'info'
|
|
444
|
-
});
|
|
445
|
-
} else if (baselineTest.status === 'passed' && test.status === 'failed') {
|
|
446
|
-
comparison.regressions.push({
|
|
447
|
-
type: 'test_regression',
|
|
448
|
-
message: `Test now failing: ${test.title}`,
|
|
449
|
-
severity: 'high',
|
|
450
|
-
test: test
|
|
451
|
-
});
|
|
452
|
-
comparison.hasRegressions = true;
|
|
453
|
-
} else if (baselineTest.status === 'failed' && test.status === 'passed') {
|
|
454
|
-
comparison.improvements.push({
|
|
455
|
-
type: 'test_fixed',
|
|
456
|
-
message: `Test now passing: ${test.title}`,
|
|
457
|
-
severity: 'good'
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
return comparison;
|
|
32
|
+
return runValidation(this);
|
|
463
33
|
}
|
|
464
34
|
|
|
465
35
|
/**
|
|
466
36
|
* Run specific test files
|
|
467
37
|
*/
|
|
468
38
|
async runSpecificTests(testFiles) {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
const testArgs = ['test', '--', ...testFiles];
|
|
472
|
-
|
|
473
|
-
return new Promise((resolve, reject) => {
|
|
474
|
-
const startTime = Date.now();
|
|
475
|
-
let output = '';
|
|
476
|
-
let errorOutput = '';
|
|
477
|
-
|
|
478
|
-
const testProcess = spawn('npm', testArgs, {
|
|
479
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
480
|
-
cwd: process.cwd()
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
testProcess.stdout.on('data', (data) => {
|
|
484
|
-
output += data.toString();
|
|
485
|
-
if (this.options.verbose) {
|
|
486
|
-
process.stdout.write(data);
|
|
487
|
-
}
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
testProcess.stderr.on('data', (data) => {
|
|
491
|
-
errorOutput += data.toString();
|
|
492
|
-
if (this.options.verbose) {
|
|
493
|
-
process.stderr.write(data);
|
|
494
|
-
}
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
testProcess.on('close', (code) => {
|
|
498
|
-
const duration = Date.now() - startTime;
|
|
499
|
-
const results = this.parseBasicOutput(output, errorOutput, code, duration);
|
|
500
|
-
resolve(results);
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
testProcess.on('error', (error) => {
|
|
504
|
-
reject(new Error(`Test process failed: ${error.message}`));
|
|
505
|
-
});
|
|
39
|
+
return runSpecific(testFiles, {
|
|
40
|
+
verbose: this.options.verbose
|
|
506
41
|
});
|
|
507
42
|
}
|
|
508
43
|
|
|
509
|
-
/**
|
|
510
|
-
* Check if tests are available
|
|
511
|
-
*/
|
|
512
|
-
checkTestAvailability() {
|
|
513
|
-
const testPaths = [
|
|
514
|
-
'package.json',
|
|
515
|
-
'tests',
|
|
516
|
-
'__tests__',
|
|
517
|
-
'test',
|
|
518
|
-
'spec'
|
|
519
|
-
];
|
|
520
|
-
|
|
521
|
-
for (const testPath of testPaths) {
|
|
522
|
-
if (fs.existsSync(testPath)) {
|
|
523
|
-
return true;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
return false;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
/**
|
|
531
|
-
* Get test configuration
|
|
532
|
-
*/
|
|
533
|
-
getTestConfig() {
|
|
534
|
-
try {
|
|
535
|
-
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
|
536
|
-
return {
|
|
537
|
-
hasTestScript: !!packageJson.scripts?.test,
|
|
538
|
-
testScript: packageJson.scripts?.test,
|
|
539
|
-
jestConfig: packageJson.jest,
|
|
540
|
-
dependencies: {
|
|
541
|
-
jest: packageJson.dependencies?.jest || packageJson.devDependencies?.jest,
|
|
542
|
-
mocha: packageJson.dependencies?.mocha || packageJson.devDependencies?.mocha,
|
|
543
|
-
jasmine: packageJson.dependencies?.jasmine || packageJson.devDependencies?.jasmine
|
|
544
|
-
}
|
|
545
|
-
};
|
|
546
|
-
} catch (error) {
|
|
547
|
-
return { hasTestScript: false };
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
44
|
/**
|
|
552
45
|
* Generate test report
|
|
553
46
|
*/
|
|
554
47
|
generateReport() {
|
|
555
|
-
|
|
556
|
-
throw new Error('No test results available. Run tests first.');
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
const report = {
|
|
560
|
-
timestamp: new Date().toISOString(),
|
|
561
|
-
baseline: this.baselineResults,
|
|
562
|
-
current: this.currentResults,
|
|
563
|
-
comparison: this.compareResults(this.baselineResults, this.currentResults),
|
|
564
|
-
config: this.getTestConfig(),
|
|
565
|
-
summary: {
|
|
566
|
-
hasRegressions: this.regressionDetected,
|
|
567
|
-
testCountChanged: this.baselineResults.total !== this.currentResults.total,
|
|
568
|
-
performanceChanged: Math.abs(this.currentResults.duration - this.baselineResults.duration) > 1000
|
|
569
|
-
}
|
|
570
|
-
};
|
|
571
|
-
|
|
572
|
-
return report;
|
|
48
|
+
return generateReport(this);
|
|
573
49
|
}
|
|
574
50
|
}
|
|
575
51
|
|