claudecode-omc 4.7.4 → 4.8.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-plugin/plugin.json +1 -1
- package/README.md +50 -0
- package/agents/test-engineer.md +74 -0
- package/bridge/cli.cjs +9335 -117
- package/dist/cli/index.js +201 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/testing/analyzers/complexity.d.ts +18 -0
- package/dist/testing/analyzers/complexity.d.ts.map +1 -0
- package/dist/testing/analyzers/complexity.js +121 -0
- package/dist/testing/analyzers/complexity.js.map +1 -0
- package/dist/testing/analyzers/coverage.d.ts +13 -0
- package/dist/testing/analyzers/coverage.d.ts.map +1 -0
- package/dist/testing/analyzers/coverage.js +99 -0
- package/dist/testing/analyzers/coverage.js.map +1 -0
- package/dist/testing/analyzers/quality-scorer.d.ts +8 -0
- package/dist/testing/analyzers/quality-scorer.d.ts.map +1 -0
- package/dist/testing/analyzers/quality-scorer.js +128 -0
- package/dist/testing/analyzers/quality-scorer.js.map +1 -0
- package/dist/testing/analyzers/types.d.ts +56 -0
- package/dist/testing/analyzers/types.d.ts.map +1 -0
- package/dist/testing/analyzers/types.js +2 -0
- package/dist/testing/analyzers/types.js.map +1 -0
- package/dist/testing/cli/agent-integration.d.ts +20 -0
- package/dist/testing/cli/agent-integration.d.ts.map +1 -0
- package/dist/testing/cli/agent-integration.js +60 -0
- package/dist/testing/cli/agent-integration.js.map +1 -0
- package/dist/testing/cli/commands.d.ts +100 -0
- package/dist/testing/cli/commands.d.ts.map +1 -0
- package/dist/testing/cli/commands.js +250 -0
- package/dist/testing/cli/commands.js.map +1 -0
- package/dist/testing/cli/ultraqa-integration.d.ts +13 -0
- package/dist/testing/cli/ultraqa-integration.d.ts.map +1 -0
- package/dist/testing/cli/ultraqa-integration.js +68 -0
- package/dist/testing/cli/ultraqa-integration.js.map +1 -0
- package/dist/testing/detectors/go.d.ts +3 -0
- package/dist/testing/detectors/go.d.ts.map +1 -0
- package/dist/testing/detectors/go.js +38 -0
- package/dist/testing/detectors/go.js.map +1 -0
- package/dist/testing/detectors/index.d.ts +8 -0
- package/dist/testing/detectors/index.d.ts.map +1 -0
- package/dist/testing/detectors/index.js +46 -0
- package/dist/testing/detectors/index.js.map +1 -0
- package/dist/testing/detectors/package-json.d.ts +3 -0
- package/dist/testing/detectors/package-json.d.ts.map +1 -0
- package/dist/testing/detectors/package-json.js +52 -0
- package/dist/testing/detectors/package-json.js.map +1 -0
- package/dist/testing/detectors/python.d.ts +3 -0
- package/dist/testing/detectors/python.d.ts.map +1 -0
- package/dist/testing/detectors/python.js +37 -0
- package/dist/testing/detectors/python.js.map +1 -0
- package/dist/testing/detectors/rust.d.ts +3 -0
- package/dist/testing/detectors/rust.d.ts.map +1 -0
- package/dist/testing/detectors/rust.js +39 -0
- package/dist/testing/detectors/rust.js.map +1 -0
- package/dist/testing/generators/contract.d.ts +14 -0
- package/dist/testing/generators/contract.d.ts.map +1 -0
- package/dist/testing/generators/contract.js +163 -0
- package/dist/testing/generators/contract.js.map +1 -0
- package/dist/testing/generators/e2e.d.ts +34 -0
- package/dist/testing/generators/e2e.d.ts.map +1 -0
- package/dist/testing/generators/e2e.js +74 -0
- package/dist/testing/generators/e2e.js.map +1 -0
- package/dist/testing/generators/go.d.ts +12 -0
- package/dist/testing/generators/go.d.ts.map +1 -0
- package/dist/testing/generators/go.js +144 -0
- package/dist/testing/generators/go.js.map +1 -0
- package/dist/testing/generators/nodejs.d.ts +12 -0
- package/dist/testing/generators/nodejs.d.ts.map +1 -0
- package/dist/testing/generators/nodejs.js +37 -0
- package/dist/testing/generators/nodejs.js.map +1 -0
- package/dist/testing/generators/python.d.ts +12 -0
- package/dist/testing/generators/python.d.ts.map +1 -0
- package/dist/testing/generators/python.js +163 -0
- package/dist/testing/generators/python.js.map +1 -0
- package/dist/testing/generators/react.d.ts +12 -0
- package/dist/testing/generators/react.d.ts.map +1 -0
- package/dist/testing/generators/react.js +31 -0
- package/dist/testing/generators/react.js.map +1 -0
- package/dist/testing/generators/rust.d.ts +11 -0
- package/dist/testing/generators/rust.d.ts.map +1 -0
- package/dist/testing/generators/rust.js +138 -0
- package/dist/testing/generators/rust.js.map +1 -0
- package/dist/testing/index.d.ts +6 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +11 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/integrations/autopilot.d.ts +42 -0
- package/dist/testing/integrations/autopilot.d.ts.map +1 -0
- package/dist/testing/integrations/autopilot.js +55 -0
- package/dist/testing/integrations/autopilot.js.map +1 -0
- package/dist/testing/integrations/cicd.d.ts +26 -0
- package/dist/testing/integrations/cicd.d.ts.map +1 -0
- package/dist/testing/integrations/cicd.js +162 -0
- package/dist/testing/integrations/cicd.js.map +1 -0
- package/dist/testing/integrations/giskard/behavioral-tests.d.ts +4 -0
- package/dist/testing/integrations/giskard/behavioral-tests.d.ts.map +1 -0
- package/dist/testing/integrations/giskard/behavioral-tests.js +66 -0
- package/dist/testing/integrations/giskard/behavioral-tests.js.map +1 -0
- package/dist/testing/integrations/giskard/types.d.ts +35 -0
- package/dist/testing/integrations/giskard/types.d.ts.map +1 -0
- package/dist/testing/integrations/giskard/types.js +2 -0
- package/dist/testing/integrations/giskard/types.js.map +1 -0
- package/dist/testing/integrations/promptfoo/config-generator.d.ts +5 -0
- package/dist/testing/integrations/promptfoo/config-generator.d.ts.map +1 -0
- package/dist/testing/integrations/promptfoo/config-generator.js +44 -0
- package/dist/testing/integrations/promptfoo/config-generator.js.map +1 -0
- package/dist/testing/integrations/promptfoo/types.d.ts +36 -0
- package/dist/testing/integrations/promptfoo/types.d.ts.map +1 -0
- package/dist/testing/integrations/promptfoo/types.js +2 -0
- package/dist/testing/integrations/promptfoo/types.js.map +1 -0
- package/dist/testing/integrations/ralph.d.ts +65 -0
- package/dist/testing/integrations/ralph.d.ts.map +1 -0
- package/dist/testing/integrations/ralph.js +69 -0
- package/dist/testing/integrations/ralph.js.map +1 -0
- package/dist/testing/performance/cache-manager.d.ts +16 -0
- package/dist/testing/performance/cache-manager.d.ts.map +1 -0
- package/dist/testing/performance/cache-manager.js +39 -0
- package/dist/testing/performance/cache-manager.js.map +1 -0
- package/dist/testing/performance/parallel-generator.d.ts +23 -0
- package/dist/testing/performance/parallel-generator.d.ts.map +1 -0
- package/dist/testing/performance/parallel-generator.js +31 -0
- package/dist/testing/performance/parallel-generator.js.map +1 -0
- package/dist/testing/types.d.ts +23 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +2 -0
- package/dist/testing/types.js.map +1 -0
- package/docs/2026-03-06-llm-testing-system-phase1.md +0 -0
- package/docs/plans/2026-03-06-llm-testing-system-design.md +311 -0
- package/docs/plans/2026-03-06-llm-testing-system-phase1.md +1268 -0
- package/docs/plans/2026-03-06-llm-testing-system-phase2.md +3053 -0
- package/docs/plans/2026-03-06-llm-testing-system-phase3.md +1830 -0
- package/docs/testing/PHASE2.md +266 -0
- package/docs/testing/PHASE3.md +601 -0
- package/docs/testing/README.md +634 -0
- package/package.json +1 -1
- package/skills/test-gen/skill.md +531 -0
- package/skills/ultraqa.md +58 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
export async function analyzeCoverage(options) {
|
|
5
|
+
const { projectRoot, coverageData } = options;
|
|
6
|
+
let coverage = coverageData;
|
|
7
|
+
// If no coverage data provided, run coverage tool
|
|
8
|
+
if (!coverage) {
|
|
9
|
+
try {
|
|
10
|
+
// Run c8 to generate coverage
|
|
11
|
+
execSync('pnpm test --coverage --reporter=json', {
|
|
12
|
+
cwd: projectRoot,
|
|
13
|
+
stdio: 'pipe',
|
|
14
|
+
});
|
|
15
|
+
// Read coverage report
|
|
16
|
+
const coveragePath = path.join(projectRoot, 'coverage', 'coverage-summary.json');
|
|
17
|
+
const coverageContent = await fs.readFile(coveragePath, 'utf-8');
|
|
18
|
+
coverage = JSON.parse(coverageContent);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw new Error(`Failed to generate coverage: ${error}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const total = coverage.total;
|
|
25
|
+
return {
|
|
26
|
+
totalCoverage: total.lines.pct,
|
|
27
|
+
lineCoverage: total.lines.pct,
|
|
28
|
+
functionCoverage: total.functions.pct,
|
|
29
|
+
branchCoverage: total.branches.pct,
|
|
30
|
+
statementCoverage: total.statements.pct,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export async function identifyGaps(options) {
|
|
34
|
+
const { projectRoot, uncoveredLines } = options;
|
|
35
|
+
const gaps = [];
|
|
36
|
+
for (const [file, lines] of Object.entries(uncoveredLines)) {
|
|
37
|
+
// Group consecutive lines into ranges
|
|
38
|
+
const ranges = groupConsecutiveLines(lines);
|
|
39
|
+
for (const range of ranges) {
|
|
40
|
+
// Read code snippet
|
|
41
|
+
const filePath = path.join(projectRoot, file);
|
|
42
|
+
let codeSnippet;
|
|
43
|
+
try {
|
|
44
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
45
|
+
const allLines = content.split('\n');
|
|
46
|
+
codeSnippet = allLines.slice(range.start - 1, range.end).join('\n');
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
// File might not exist in test environment
|
|
50
|
+
}
|
|
51
|
+
// Analyze reason for gap
|
|
52
|
+
const reason = analyzeGapReason(codeSnippet || '');
|
|
53
|
+
gaps.push({
|
|
54
|
+
file,
|
|
55
|
+
startLine: range.start,
|
|
56
|
+
endLine: range.end,
|
|
57
|
+
reason,
|
|
58
|
+
codeSnippet,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
gaps,
|
|
64
|
+
totalGaps: gaps.length,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function groupConsecutiveLines(lines) {
|
|
68
|
+
if (lines.length === 0)
|
|
69
|
+
return [];
|
|
70
|
+
const sorted = [...lines].sort((a, b) => a - b);
|
|
71
|
+
const ranges = [];
|
|
72
|
+
let start = sorted[0];
|
|
73
|
+
let end = sorted[0];
|
|
74
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
75
|
+
if (sorted[i] === end + 1) {
|
|
76
|
+
end = sorted[i];
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
ranges.push({ start, end });
|
|
80
|
+
start = sorted[i];
|
|
81
|
+
end = sorted[i];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
ranges.push({ start, end });
|
|
85
|
+
return ranges;
|
|
86
|
+
}
|
|
87
|
+
function analyzeGapReason(code) {
|
|
88
|
+
if (code.includes('catch') || code.includes('throw')) {
|
|
89
|
+
return 'Error handling not covered';
|
|
90
|
+
}
|
|
91
|
+
if (code.includes('if') || code.includes('else')) {
|
|
92
|
+
return 'Conditional branch not covered';
|
|
93
|
+
}
|
|
94
|
+
if (code.includes('null') || code.includes('undefined')) {
|
|
95
|
+
return 'Null/undefined check not covered';
|
|
96
|
+
}
|
|
97
|
+
return 'Code path not covered';
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../../src/testing/analyzers/coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TestQualityScore } from './types.js';
|
|
2
|
+
interface ScoreTestQualityOptions {
|
|
3
|
+
testCode: string;
|
|
4
|
+
testType: 'unit' | 'integration' | 'e2e';
|
|
5
|
+
}
|
|
6
|
+
export declare function scoreTestQuality(options: ScoreTestQualityOptions): Promise<TestQualityScore>;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=quality-scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-scorer.d.ts","sourceRoot":"","sources":["../../../src/testing/analyzers/quality-scorer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,YAAY,CAAC;AAEvE,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,KAAK,CAAC;CAC1C;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8IlG"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
export async function scoreTestQuality(options) {
|
|
2
|
+
const { testCode } = options;
|
|
3
|
+
// Count assertions
|
|
4
|
+
const assertionCount = (testCode.match(/expect\(/g) || []).length;
|
|
5
|
+
const hasAssertions = assertionCount > 0;
|
|
6
|
+
// Check for edge cases
|
|
7
|
+
const hasEdgeCases = testCode.includes('null') ||
|
|
8
|
+
testCode.includes('undefined') ||
|
|
9
|
+
testCode.includes('0') ||
|
|
10
|
+
testCode.includes('empty') ||
|
|
11
|
+
testCode.includes('-1') ||
|
|
12
|
+
testCode.includes('\'\'') ||
|
|
13
|
+
testCode.includes('""');
|
|
14
|
+
// Check for specific assertions (toBe, toEqual, etc. vs just truthy checks)
|
|
15
|
+
const specificAssertionPatterns = [
|
|
16
|
+
/\.toBe\(/g,
|
|
17
|
+
/\.toEqual\(/g,
|
|
18
|
+
/\.toStrictEqual\(/g,
|
|
19
|
+
/\.toMatch\(/g,
|
|
20
|
+
/\.toContain\(/g,
|
|
21
|
+
/\.toHaveLength\(/g,
|
|
22
|
+
];
|
|
23
|
+
const specificAssertionCount = specificAssertionPatterns.reduce((count, pattern) => count + (testCode.match(pattern) || []).length, 0);
|
|
24
|
+
const hasSpecificAssertions = specificAssertionCount > 0;
|
|
25
|
+
// Check for shared state (global variables, module-level state)
|
|
26
|
+
const hasSharedState = testCode.includes('let ') && !testCode.match(/test\([^)]*\)\s*=>\s*\{[^}]*let /s) ||
|
|
27
|
+
testCode.includes('var ') && !testCode.match(/test\([^)]*\)\s*=>\s*\{[^}]*var /s);
|
|
28
|
+
// Check for descriptive test names
|
|
29
|
+
const testNames = testCode.match(/test\(['"]([^'"]+)['"]/g) || [];
|
|
30
|
+
const hasDescriptiveNames = testNames.every(name => {
|
|
31
|
+
const testName = name.match(/test\(['"]([^'"]+)['"]/)?.[1] || '';
|
|
32
|
+
return testName.length > 15 && (testName.includes('should') || testName.includes('when'));
|
|
33
|
+
});
|
|
34
|
+
// Check for mocks
|
|
35
|
+
const hasMocks = testCode.includes('mock') || testCode.includes('spy') || testCode.includes('stub');
|
|
36
|
+
// Check for setup/teardown
|
|
37
|
+
const hasSetup = testCode.includes('beforeEach') || testCode.includes('beforeAll');
|
|
38
|
+
const hasTeardown = testCode.includes('afterEach') || testCode.includes('afterAll');
|
|
39
|
+
const metrics = {
|
|
40
|
+
assertionCount,
|
|
41
|
+
hasEdgeCases,
|
|
42
|
+
hasAssertions,
|
|
43
|
+
hasSpecificAssertions,
|
|
44
|
+
hasSharedState,
|
|
45
|
+
hasDescriptiveNames,
|
|
46
|
+
hasMocks,
|
|
47
|
+
hasSetup,
|
|
48
|
+
hasTeardown,
|
|
49
|
+
};
|
|
50
|
+
// Calculate completeness score (0-100)
|
|
51
|
+
let completenessScore = 0;
|
|
52
|
+
if (hasAssertions)
|
|
53
|
+
completenessScore += 40;
|
|
54
|
+
completenessScore += Math.min(assertionCount * 10, 30); // Up to 30 points for assertions
|
|
55
|
+
if (hasEdgeCases)
|
|
56
|
+
completenessScore += 15;
|
|
57
|
+
if (hasMocks)
|
|
58
|
+
completenessScore += 10;
|
|
59
|
+
if (hasSetup || hasTeardown)
|
|
60
|
+
completenessScore += 5;
|
|
61
|
+
// Calculate assertion quality score (0-100)
|
|
62
|
+
let assertionQuality = 0;
|
|
63
|
+
if (hasAssertions) {
|
|
64
|
+
assertionQuality += 50;
|
|
65
|
+
if (hasSpecificAssertions) {
|
|
66
|
+
const specificRatio = specificAssertionCount / assertionCount;
|
|
67
|
+
assertionQuality += specificRatio * 50;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Calculate independence score (0-100)
|
|
71
|
+
let independenceScore = 100;
|
|
72
|
+
if (hasSharedState)
|
|
73
|
+
independenceScore -= 40;
|
|
74
|
+
if (!hasSetup && testCode.includes('const ') && testCode.split('const ').length > 3) {
|
|
75
|
+
independenceScore -= 10; // Penalize if no setup but lots of constants (might be duplicated)
|
|
76
|
+
}
|
|
77
|
+
// Calculate naming score (0-100)
|
|
78
|
+
let namingScore = 0;
|
|
79
|
+
if (testNames.length > 0) {
|
|
80
|
+
namingScore = hasDescriptiveNames ? 90 : 50;
|
|
81
|
+
if (testNames.some(name => name.includes('should')))
|
|
82
|
+
namingScore += 10;
|
|
83
|
+
}
|
|
84
|
+
// Calculate overall score (weighted average)
|
|
85
|
+
const overallScore = Math.round(completenessScore * 0.35 +
|
|
86
|
+
assertionQuality * 0.25 +
|
|
87
|
+
independenceScore * 0.20 +
|
|
88
|
+
namingScore * 0.20);
|
|
89
|
+
// Generate recommendations
|
|
90
|
+
const recommendations = [];
|
|
91
|
+
if (!hasAssertions) {
|
|
92
|
+
recommendations.push('Add assertions to verify behavior');
|
|
93
|
+
}
|
|
94
|
+
if (assertionCount < 2) {
|
|
95
|
+
recommendations.push('Add more test cases to cover edge cases');
|
|
96
|
+
}
|
|
97
|
+
if (!hasEdgeCases) {
|
|
98
|
+
recommendations.push('Test edge cases like null, undefined, empty values, and boundary conditions');
|
|
99
|
+
}
|
|
100
|
+
if (!hasSpecificAssertions) {
|
|
101
|
+
recommendations.push('Use specific assertions (toBe, toEqual) instead of generic truthy checks');
|
|
102
|
+
}
|
|
103
|
+
if (hasSharedState) {
|
|
104
|
+
recommendations.push('Avoid shared state between tests - use beforeEach for setup');
|
|
105
|
+
}
|
|
106
|
+
if (!hasDescriptiveNames) {
|
|
107
|
+
recommendations.push('Use descriptive test names that explain what is being tested');
|
|
108
|
+
}
|
|
109
|
+
if (assertionQuality < 60) {
|
|
110
|
+
recommendations.push('Improve assertion quality with more specific matchers');
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
completenessScore: Math.min(completenessScore, 100),
|
|
114
|
+
assertionQuality: Math.min(assertionQuality, 100),
|
|
115
|
+
independenceScore: Math.min(independenceScore, 100),
|
|
116
|
+
namingScore: Math.min(namingScore, 100),
|
|
117
|
+
overallScore: Math.min(overallScore, 100),
|
|
118
|
+
assertionCount,
|
|
119
|
+
hasEdgeCases,
|
|
120
|
+
hasAssertions,
|
|
121
|
+
hasSpecificAssertions,
|
|
122
|
+
hasSharedState,
|
|
123
|
+
hasDescriptiveNames,
|
|
124
|
+
metrics,
|
|
125
|
+
recommendations,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=quality-scorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-scorer.js","sourceRoot":"","sources":["../../../src/testing/analyzers/quality-scorer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export interface CoverageMetrics {
|
|
2
|
+
total: number;
|
|
3
|
+
covered: number;
|
|
4
|
+
pct: number;
|
|
5
|
+
}
|
|
6
|
+
export interface CoverageReport {
|
|
7
|
+
lines: CoverageMetrics;
|
|
8
|
+
statements: CoverageMetrics;
|
|
9
|
+
functions: CoverageMetrics;
|
|
10
|
+
branches: CoverageMetrics;
|
|
11
|
+
}
|
|
12
|
+
export interface CoverageAnalysisResult {
|
|
13
|
+
totalCoverage: number;
|
|
14
|
+
lineCoverage: number;
|
|
15
|
+
functionCoverage: number;
|
|
16
|
+
branchCoverage: number;
|
|
17
|
+
statementCoverage: number;
|
|
18
|
+
}
|
|
19
|
+
export interface CoverageGap {
|
|
20
|
+
file: string;
|
|
21
|
+
startLine: number;
|
|
22
|
+
endLine: number;
|
|
23
|
+
reason: string;
|
|
24
|
+
codeSnippet?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface GapAnalysisResult {
|
|
27
|
+
gaps: CoverageGap[];
|
|
28
|
+
totalGaps: number;
|
|
29
|
+
}
|
|
30
|
+
export interface TestQualityMetrics {
|
|
31
|
+
assertionCount: number;
|
|
32
|
+
hasEdgeCases: boolean;
|
|
33
|
+
hasAssertions: boolean;
|
|
34
|
+
hasSpecificAssertions: boolean;
|
|
35
|
+
hasSharedState: boolean;
|
|
36
|
+
hasDescriptiveNames: boolean;
|
|
37
|
+
hasMocks: boolean;
|
|
38
|
+
hasSetup: boolean;
|
|
39
|
+
hasTeardown: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface TestQualityScore {
|
|
42
|
+
completenessScore: number;
|
|
43
|
+
assertionQuality: number;
|
|
44
|
+
independenceScore: number;
|
|
45
|
+
namingScore: number;
|
|
46
|
+
overallScore: number;
|
|
47
|
+
assertionCount: number;
|
|
48
|
+
hasEdgeCases: boolean;
|
|
49
|
+
hasAssertions: boolean;
|
|
50
|
+
hasSpecificAssertions: boolean;
|
|
51
|
+
hasSharedState: boolean;
|
|
52
|
+
hasDescriptiveNames: boolean;
|
|
53
|
+
metrics: TestQualityMetrics;
|
|
54
|
+
recommendations: string[];
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/testing/analyzers/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,eAAe,CAAC;IACvB,UAAU,EAAE,eAAe,CAAC;IAC5B,SAAS,EAAE,eAAe,CAAC;IAC3B,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/testing/analyzers/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { TechStack } from '../types.js';
|
|
2
|
+
import type { ComplexityAnalysisResult } from '../analyzers/complexity.js';
|
|
3
|
+
export interface TestEngineerContext {
|
|
4
|
+
filePath: string;
|
|
5
|
+
code: string;
|
|
6
|
+
techStack: TechStack;
|
|
7
|
+
complexity: 'simple' | 'complex';
|
|
8
|
+
complexityMetrics: ComplexityAnalysisResult;
|
|
9
|
+
suggestedApproach: 'auto-generate' | 'guided' | 'manual';
|
|
10
|
+
questionsForUser?: string[];
|
|
11
|
+
}
|
|
12
|
+
interface PrepareContextOptions {
|
|
13
|
+
filePath: string;
|
|
14
|
+
code: string;
|
|
15
|
+
projectRoot: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function prepareTestEngineerContext(options: PrepareContextOptions): Promise<TestEngineerContext>;
|
|
18
|
+
export declare function invokeTestEngineerAgent(context: TestEngineerContext): Promise<string>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=agent-integration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-integration.d.ts","sourceRoot":"","sources":["../../../src/testing/cli/agent-integration.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE3E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAC;IACjC,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,iBAAiB,EAAE,eAAe,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACzD,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAyB7G;AAwCD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAG3F"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { detectTechStack } from '../detectors/index.js';
|
|
2
|
+
import { analyzeComplexity } from '../analyzers/complexity.js';
|
|
3
|
+
export async function prepareTestEngineerContext(options) {
|
|
4
|
+
const { filePath, code, projectRoot } = options;
|
|
5
|
+
const techStack = await detectTechStack(projectRoot);
|
|
6
|
+
const complexityMetrics = await analyzeComplexity({ code, filePath });
|
|
7
|
+
let suggestedApproach;
|
|
8
|
+
let questionsForUser;
|
|
9
|
+
if (complexityMetrics.complexity === 'simple') {
|
|
10
|
+
suggestedApproach = 'auto-generate';
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
suggestedApproach = 'guided';
|
|
14
|
+
questionsForUser = generateQuestionsForComplexCode(complexityMetrics);
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
filePath,
|
|
18
|
+
code,
|
|
19
|
+
techStack,
|
|
20
|
+
complexity: complexityMetrics.complexity,
|
|
21
|
+
complexityMetrics,
|
|
22
|
+
suggestedApproach,
|
|
23
|
+
questionsForUser,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function generateQuestionsForComplexCode(metrics) {
|
|
27
|
+
const questions = [];
|
|
28
|
+
if (metrics.reasons.includes('Payment processing logic')) {
|
|
29
|
+
questions.push('What are the expected payment flows? (success, failure, retry)');
|
|
30
|
+
questions.push('Should I mock external payment provider API calls?');
|
|
31
|
+
questions.push('What error scenarios should be tested?');
|
|
32
|
+
}
|
|
33
|
+
if (metrics.reasons.includes('Authentication logic')) {
|
|
34
|
+
questions.push('What authentication methods should be tested?');
|
|
35
|
+
questions.push('Should I test token expiration and refresh?');
|
|
36
|
+
questions.push('What authorization scenarios should be covered?');
|
|
37
|
+
}
|
|
38
|
+
if (metrics.reasons.includes('Database transactions')) {
|
|
39
|
+
questions.push('What database states should I test?');
|
|
40
|
+
questions.push('Should I test transaction rollbacks?');
|
|
41
|
+
questions.push('Are there specific edge cases for data integrity?');
|
|
42
|
+
}
|
|
43
|
+
if (metrics.reasons.includes('External API calls')) {
|
|
44
|
+
questions.push('Should I mock external API calls?');
|
|
45
|
+
questions.push('What API failure scenarios should be tested?');
|
|
46
|
+
questions.push('Are there rate limiting or retry logic to test?');
|
|
47
|
+
}
|
|
48
|
+
if (metrics.reasons.includes('Multiple async operations')) {
|
|
49
|
+
questions.push('Should I test concurrent execution scenarios?');
|
|
50
|
+
questions.push('Are there race conditions to consider?');
|
|
51
|
+
questions.push('What timeout scenarios should be tested?');
|
|
52
|
+
}
|
|
53
|
+
questions.push('Are there specific edge cases or business rules I should know about?');
|
|
54
|
+
return questions;
|
|
55
|
+
}
|
|
56
|
+
export async function invokeTestEngineerAgent(context) {
|
|
57
|
+
const agentCommand = `test-engineer --file="${context.filePath}" --complexity="${context.complexity}" --approach="${context.suggestedApproach}"`;
|
|
58
|
+
return agentCommand;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=agent-integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-integration.js","sourceRoot":"","sources":["../../../src/testing/cli/agent-integration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAoB/D,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,OAA8B;IAC7E,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAEhD,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;IACrD,MAAM,iBAAiB,GAAG,MAAM,iBAAiB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEtE,IAAI,iBAAwD,CAAC;IAC7D,IAAI,gBAAsC,CAAC;IAE3C,IAAI,iBAAiB,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC9C,iBAAiB,GAAG,eAAe,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,iBAAiB,GAAG,QAAQ,CAAC;QAC7B,gBAAgB,GAAG,+BAA+B,CAAC,iBAAiB,CAAC,CAAC;IACxE,CAAC;IAED,OAAO;QACL,QAAQ;QACR,IAAI;QACJ,SAAS;QACT,UAAU,EAAE,iBAAiB,CAAC,UAAU;QACxC,iBAAiB;QACjB,iBAAiB;QACjB,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CAAC,OAAiC;IACxE,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC;QACzD,SAAS,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QACjF,SAAS,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;QACrE,SAAS,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC;QACrD,SAAS,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAChE,SAAS,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAC9D,SAAS,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;QACtD,SAAS,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QACtD,SAAS,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACvD,SAAS,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACnD,SAAS,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACpD,SAAS,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC/D,SAAS,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAC,EAAE,CAAC;QAC1D,SAAS,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAChE,SAAS,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;QACzD,SAAS,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAC7D,CAAC;IAED,SAAS,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;IAEvF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,OAA4B;IACxE,MAAM,YAAY,GAAG,yBAAyB,OAAO,CAAC,QAAQ,mBAAmB,OAAO,CAAC,UAAU,iBAAiB,OAAO,CAAC,iBAAiB,GAAG,CAAC;IACjJ,OAAO,YAAY,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { TechStack } from '../types.js';
|
|
2
|
+
import type { CoverageAnalysisResult } from '../analyzers/types.js';
|
|
3
|
+
import type { ComplexityAnalysisResult } from '../analyzers/complexity.js';
|
|
4
|
+
type Language = 'typescript' | 'react' | 'python' | 'go' | 'rust';
|
|
5
|
+
interface TestGenOptions {
|
|
6
|
+
filePath: string;
|
|
7
|
+
output?: string;
|
|
8
|
+
language?: Language;
|
|
9
|
+
}
|
|
10
|
+
interface TestGenResult {
|
|
11
|
+
success: boolean;
|
|
12
|
+
testFilePath?: string;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function testGenCommand(options: TestGenOptions): Promise<TestGenResult>;
|
|
16
|
+
interface DetectStackOptions {
|
|
17
|
+
projectRoot: string;
|
|
18
|
+
}
|
|
19
|
+
interface DetectStackResult {
|
|
20
|
+
stack: TechStack;
|
|
21
|
+
}
|
|
22
|
+
export declare function testDetectStackCommand(options: DetectStackOptions): Promise<DetectStackResult>;
|
|
23
|
+
interface AnalyzeCoverageCommandOptions {
|
|
24
|
+
projectRoot: string;
|
|
25
|
+
coverageData?: any;
|
|
26
|
+
}
|
|
27
|
+
export declare function testAnalyzeCoverageCommand(options: AnalyzeCoverageCommandOptions): Promise<CoverageAnalysisResult>;
|
|
28
|
+
interface ContractCommandOptions {
|
|
29
|
+
specPath: string;
|
|
30
|
+
spec?: any;
|
|
31
|
+
framework: 'pact' | 'supertest' | 'msw';
|
|
32
|
+
consumer?: string;
|
|
33
|
+
provider?: string;
|
|
34
|
+
}
|
|
35
|
+
interface ContractCommandResult {
|
|
36
|
+
success: boolean;
|
|
37
|
+
testCode: string;
|
|
38
|
+
testFilePath: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function testContractCommand(options: ContractCommandOptions): Promise<ContractCommandResult>;
|
|
41
|
+
interface ComplexityCommandOptions {
|
|
42
|
+
filePath: string;
|
|
43
|
+
}
|
|
44
|
+
export declare function testComplexityCommand(options: ComplexityCommandOptions): Promise<ComplexityAnalysisResult>;
|
|
45
|
+
interface PromptfooCommandOptions {
|
|
46
|
+
promptFile: string;
|
|
47
|
+
provider?: string;
|
|
48
|
+
output?: string;
|
|
49
|
+
}
|
|
50
|
+
interface PromptfooCommandResult {
|
|
51
|
+
success: boolean;
|
|
52
|
+
configPath?: string;
|
|
53
|
+
error?: string;
|
|
54
|
+
}
|
|
55
|
+
export declare function testPromptfooCommand(options: PromptfooCommandOptions): Promise<PromptfooCommandResult>;
|
|
56
|
+
interface E2ECommandOptions {
|
|
57
|
+
flowDescription: string;
|
|
58
|
+
baseUrl?: string;
|
|
59
|
+
testName?: string;
|
|
60
|
+
output?: string;
|
|
61
|
+
}
|
|
62
|
+
interface E2ECommandResult {
|
|
63
|
+
success: boolean;
|
|
64
|
+
testFilePath?: string;
|
|
65
|
+
error?: string;
|
|
66
|
+
}
|
|
67
|
+
export declare function testE2ECommand(options: E2ECommandOptions): Promise<E2ECommandResult>;
|
|
68
|
+
interface GiskardCommandOptions {
|
|
69
|
+
filePath: string;
|
|
70
|
+
testType?: 'perturbation' | 'robustness';
|
|
71
|
+
output?: string;
|
|
72
|
+
}
|
|
73
|
+
interface GiskardCommandResult {
|
|
74
|
+
success: boolean;
|
|
75
|
+
testFilePath?: string;
|
|
76
|
+
error?: string;
|
|
77
|
+
}
|
|
78
|
+
export declare function testGiskardCommand(options: GiskardCommandOptions): Promise<GiskardCommandResult>;
|
|
79
|
+
interface CICDCommandOptions {
|
|
80
|
+
language?: 'nodejs' | 'python' | 'go' | 'rust';
|
|
81
|
+
output?: string;
|
|
82
|
+
}
|
|
83
|
+
interface CICDCommandResult {
|
|
84
|
+
success: boolean;
|
|
85
|
+
workflowPath?: string;
|
|
86
|
+
error?: string;
|
|
87
|
+
}
|
|
88
|
+
export declare function testCICDCommand(options: CICDCommandOptions): Promise<CICDCommandResult>;
|
|
89
|
+
interface QualityCommandOptions {
|
|
90
|
+
testFilePath: string;
|
|
91
|
+
testType?: 'unit' | 'integration' | 'e2e';
|
|
92
|
+
}
|
|
93
|
+
interface QualityCommandResult {
|
|
94
|
+
success: boolean;
|
|
95
|
+
score?: any;
|
|
96
|
+
error?: string;
|
|
97
|
+
}
|
|
98
|
+
export declare function testQualityCommand(options: QualityCommandOptions): Promise<QualityCommandResult>;
|
|
99
|
+
export {};
|
|
100
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/testing/cli/commands.ts"],"names":[],"mappings":"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"}
|