agentic-qe 1.3.2 → 1.3.4
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/agents/qe-api-contract-validator.md +20 -0
- package/.claude/agents/qe-chaos-engineer.md +20 -0
- package/.claude/agents/qe-coverage-analyzer.md +21 -0
- package/.claude/agents/qe-deployment-readiness.md +20 -0
- package/.claude/agents/qe-flaky-test-hunter.md +20 -0
- package/.claude/agents/qe-fleet-commander.md +20 -0
- package/.claude/agents/qe-performance-tester.md +21 -0
- package/.claude/agents/qe-production-intelligence.md +20 -0
- package/.claude/agents/qe-quality-analyzer.md +20 -0
- package/.claude/agents/qe-quality-gate.md +20 -0
- package/.claude/agents/qe-regression-risk-analyzer.md +20 -0
- package/.claude/agents/qe-requirements-validator.md +20 -0
- package/.claude/agents/qe-security-scanner.md +21 -0
- package/.claude/agents/qe-test-data-architect.md +19 -0
- package/.claude/agents/qe-test-executor.md +20 -0
- package/.claude/agents/qe-test-generator.md +22 -0
- package/.claude/agents/qe-visual-tester.md +22 -0
- package/CHANGELOG.md +114 -0
- package/README.md +322 -991
- package/README.md.backup-20251026 +1366 -0
- package/bin/aqe-mcp +65 -0
- package/dist/agents/BaseAgent.js +1 -1
- package/dist/agents/BaseAgent.js.map +1 -1
- package/dist/agents/CoverageAnalyzerAgent.js +16 -16
- package/dist/agents/CoverageAnalyzerAgent.js.map +1 -1
- package/dist/agents/FlakyTestHunterAgent.js +1 -1
- package/dist/agents/FlakyTestHunterAgent.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +71 -37
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/core/memory/EnhancedAgentDBService.d.ts +127 -0
- package/dist/core/memory/EnhancedAgentDBService.d.ts.map +1 -0
- package/dist/core/memory/EnhancedAgentDBService.js +298 -0
- package/dist/core/memory/EnhancedAgentDBService.js.map +1 -0
- package/dist/core/neural/NeuralTrainer.js +2 -2
- package/dist/core/neural/NeuralTrainer.js.map +1 -1
- package/dist/learning/FixRecommendationEngine.d.ts +68 -0
- package/dist/learning/FixRecommendationEngine.d.ts.map +1 -0
- package/dist/learning/FixRecommendationEngine.js +500 -0
- package/dist/learning/FixRecommendationEngine.js.map +1 -0
- package/dist/learning/FlakyTestDetector.d.ts +19 -0
- package/dist/learning/FlakyTestDetector.d.ts.map +1 -1
- package/dist/learning/FlakyTestDetector.js +121 -2
- package/dist/learning/FlakyTestDetector.js.map +1 -1
- package/dist/learning/index.d.ts +2 -0
- package/dist/learning/index.d.ts.map +1 -1
- package/dist/learning/index.js +5 -0
- package/dist/learning/index.js.map +1 -1
- package/dist/learning/types.d.ts +11 -0
- package/dist/learning/types.d.ts.map +1 -1
- package/dist/reasoning/PatternQualityScorer.d.ts +134 -0
- package/dist/reasoning/PatternQualityScorer.d.ts.map +1 -0
- package/dist/reasoning/PatternQualityScorer.js +340 -0
- package/dist/reasoning/PatternQualityScorer.js.map +1 -0
- package/dist/reasoning/QEReasoningBank.d.ts +51 -4
- package/dist/reasoning/QEReasoningBank.d.ts.map +1 -1
- package/dist/reasoning/QEReasoningBank.js +173 -11
- package/dist/reasoning/QEReasoningBank.js.map +1 -1
- package/dist/reasoning/VectorSimilarity.d.ts +131 -0
- package/dist/reasoning/VectorSimilarity.d.ts.map +1 -0
- package/dist/reasoning/VectorSimilarity.js +250 -0
- package/dist/reasoning/VectorSimilarity.js.map +1 -0
- package/dist/reasoning/index.d.ts +8 -1
- package/dist/reasoning/index.d.ts.map +1 -1
- package/dist/reasoning/index.js +13 -2
- package/dist/reasoning/index.js.map +1 -1
- package/dist/streaming/BaseStreamHandler.d.ts +89 -0
- package/dist/streaming/BaseStreamHandler.d.ts.map +1 -0
- package/dist/streaming/BaseStreamHandler.js +168 -0
- package/dist/streaming/BaseStreamHandler.js.map +1 -0
- package/dist/streaming/TestGenerateStreamHandler.d.ts +103 -0
- package/dist/streaming/TestGenerateStreamHandler.d.ts.map +1 -0
- package/dist/streaming/TestGenerateStreamHandler.js +321 -0
- package/dist/streaming/TestGenerateStreamHandler.js.map +1 -0
- package/dist/streaming/index.d.ts +16 -0
- package/dist/streaming/index.d.ts.map +1 -0
- package/dist/streaming/index.js +39 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/utils/Database.d.ts.map +1 -1
- package/dist/utils/Database.js +15 -1
- package/dist/utils/Database.js.map +1 -1
- package/dist/utils/__mocks__/Logger.d.ts +26 -0
- package/dist/utils/__mocks__/Logger.d.ts.map +1 -0
- package/dist/utils/__mocks__/Logger.js +42 -0
- package/dist/utils/__mocks__/Logger.js.map +1 -0
- package/package.json +19 -6
- package/dist/agents/mixins/NeuralCapableMixin.d.ts +0 -130
- package/dist/agents/mixins/NeuralCapableMixin.d.ts.map +0 -1
- package/dist/agents/mixins/NeuralCapableMixin.js +0 -358
- package/dist/agents/mixins/NeuralCapableMixin.js.map +0 -1
- package/dist/agents/mixins/QUICCapableMixin.d.ts +0 -34
- package/dist/agents/mixins/QUICCapableMixin.d.ts.map +0 -1
- package/dist/agents/mixins/QUICCapableMixin.js +0 -346
- package/dist/agents/mixins/QUICCapableMixin.js.map +0 -1
- package/dist/core/security/CertificateValidator.d.ts +0 -130
- package/dist/core/security/CertificateValidator.d.ts.map +0 -1
- package/dist/core/security/CertificateValidator.js +0 -376
- package/dist/core/security/CertificateValidator.js.map +0 -1
- package/dist/core/transport/QUICTransport.d.ts +0 -62
- package/dist/core/transport/QUICTransport.d.ts.map +0 -1
- package/dist/core/transport/QUICTransport.js +0 -381
- package/dist/core/transport/QUICTransport.js.map +0 -1
- package/dist/core/transport/SecureQUICTransport.d.ts +0 -71
- package/dist/core/transport/SecureQUICTransport.d.ts.map +0 -1
- package/dist/core/transport/SecureQUICTransport.js +0 -253
- package/dist/core/transport/SecureQUICTransport.js.map +0 -1
- package/dist/learning/AdvancedFeatureExtractor.d.ts +0 -123
- package/dist/learning/AdvancedFeatureExtractor.d.ts.map +0 -1
- package/dist/learning/AdvancedFeatureExtractor.js +0 -423
- package/dist/learning/AdvancedFeatureExtractor.js.map +0 -1
- package/dist/learning/NeuralPatternMatcher.d.ts +0 -184
- package/dist/learning/NeuralPatternMatcher.d.ts.map +0 -1
- package/dist/learning/NeuralPatternMatcher.js +0 -702
- package/dist/learning/NeuralPatternMatcher.js.map +0 -1
- package/dist/learning/NeuralTrainer.d.ts +0 -209
- package/dist/learning/NeuralTrainer.d.ts.map +0 -1
- package/dist/learning/NeuralTrainer.js +0 -478
- package/dist/learning/NeuralTrainer.js.map +0 -1
- package/dist/transport/QUICTransport.d.ts +0 -340
- package/dist/transport/QUICTransport.d.ts.map +0 -1
- package/dist/transport/QUICTransport.js +0 -814
- package/dist/transport/QUICTransport.js.map +0 -1
- package/dist/transport/UDPTransport.d.ts +0 -348
- package/dist/transport/UDPTransport.d.ts.map +0 -1
- package/dist/transport/UDPTransport.js +0 -820
- package/dist/transport/UDPTransport.js.map +0 -1
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* FixRecommendationEngine - Automated fix recommendations for flaky tests
|
|
4
|
+
*
|
|
5
|
+
* Generates actionable fix recommendations with code examples based on root cause analysis
|
|
6
|
+
*
|
|
7
|
+
* @module learning/FixRecommendationEngine
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.FixRecommendationEngine = void 0;
|
|
12
|
+
/**
|
|
13
|
+
* FixRecommendationEngine for generating automated fix recommendations
|
|
14
|
+
*/
|
|
15
|
+
class FixRecommendationEngine {
|
|
16
|
+
/**
|
|
17
|
+
* Generate fix recommendations based on root cause
|
|
18
|
+
*
|
|
19
|
+
* @param rootCause - Root cause analysis result
|
|
20
|
+
* @returns Array of fix recommendations with code examples
|
|
21
|
+
*/
|
|
22
|
+
generateRecommendations(rootCause) {
|
|
23
|
+
switch (rootCause.cause) {
|
|
24
|
+
case 'timing':
|
|
25
|
+
return this.timingFixes(rootCause);
|
|
26
|
+
case 'race_condition':
|
|
27
|
+
return this.raceFixes(rootCause);
|
|
28
|
+
case 'dependency':
|
|
29
|
+
return this.dependencyFixes(rootCause);
|
|
30
|
+
case 'isolation':
|
|
31
|
+
return this.isolationFixes(rootCause);
|
|
32
|
+
case 'environment':
|
|
33
|
+
return this.environmentFixes(rootCause);
|
|
34
|
+
default:
|
|
35
|
+
return this.genericFixes(rootCause);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Timing-related fixes
|
|
40
|
+
*/
|
|
41
|
+
timingFixes(rootCause) {
|
|
42
|
+
const fixes = [];
|
|
43
|
+
// Fix 1: Add explicit wait with retry logic
|
|
44
|
+
fixes.push({
|
|
45
|
+
priority: 'high',
|
|
46
|
+
category: 'timing',
|
|
47
|
+
recommendation: 'Add explicit wait with retry logic to handle asynchronous operations',
|
|
48
|
+
codeExample: `// Before
|
|
49
|
+
expect(element).toBeVisible();
|
|
50
|
+
|
|
51
|
+
// After - Using waitFor with retry
|
|
52
|
+
import { waitFor } from '@testing-library/react';
|
|
53
|
+
|
|
54
|
+
await waitFor(
|
|
55
|
+
() => expect(element).toBeVisible(),
|
|
56
|
+
{
|
|
57
|
+
timeout: 5000,
|
|
58
|
+
interval: 100
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Or with retry wrapper
|
|
63
|
+
async function withRetry(fn: () => void, retries = 3) {
|
|
64
|
+
for (let i = 0; i < retries; i++) {
|
|
65
|
+
try {
|
|
66
|
+
await fn();
|
|
67
|
+
return;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (i === retries - 1) throw error;
|
|
70
|
+
await new Promise(resolve => setTimeout(resolve, 100 * (i + 1)));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
await withRetry(() => expect(element).toBeVisible());`,
|
|
76
|
+
estimatedEffort: 'low'
|
|
77
|
+
});
|
|
78
|
+
// Fix 2: Use proper async/await patterns
|
|
79
|
+
fixes.push({
|
|
80
|
+
priority: 'high',
|
|
81
|
+
category: 'timing',
|
|
82
|
+
recommendation: 'Ensure proper async/await usage for asynchronous operations',
|
|
83
|
+
codeExample: `// Before - Missing await
|
|
84
|
+
it('should fetch data', () => {
|
|
85
|
+
const data = fetchData(); // Returns Promise
|
|
86
|
+
expect(data).toEqual({ id: 1 });
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// After - Proper async/await
|
|
90
|
+
it('should fetch data', async () => {
|
|
91
|
+
const data = await fetchData();
|
|
92
|
+
expect(data).toEqual({ id: 1 });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Or with .resolves
|
|
96
|
+
it('should fetch data', () => {
|
|
97
|
+
return expect(fetchData()).resolves.toEqual({ id: 1 });
|
|
98
|
+
});`,
|
|
99
|
+
estimatedEffort: 'low'
|
|
100
|
+
});
|
|
101
|
+
// Fix 3: Add timeout configuration
|
|
102
|
+
fixes.push({
|
|
103
|
+
priority: 'medium',
|
|
104
|
+
category: 'timing',
|
|
105
|
+
recommendation: 'Configure appropriate timeouts for slow operations',
|
|
106
|
+
codeExample: `// Test-specific timeout
|
|
107
|
+
it('should handle slow operation', async () => {
|
|
108
|
+
await slowOperation();
|
|
109
|
+
expect(result).toBeDefined();
|
|
110
|
+
}, 10000); // 10 second timeout
|
|
111
|
+
|
|
112
|
+
// Or using Jest setTimeout
|
|
113
|
+
beforeEach(() => {
|
|
114
|
+
jest.setTimeout(10000);
|
|
115
|
+
});`,
|
|
116
|
+
estimatedEffort: 'low'
|
|
117
|
+
});
|
|
118
|
+
return fixes;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Race condition fixes
|
|
122
|
+
*/
|
|
123
|
+
raceFixes(rootCause) {
|
|
124
|
+
const fixes = [];
|
|
125
|
+
// Fix 1: Add proper synchronization
|
|
126
|
+
fixes.push({
|
|
127
|
+
priority: 'critical',
|
|
128
|
+
category: 'concurrency',
|
|
129
|
+
recommendation: 'Add synchronization mechanisms to prevent race conditions',
|
|
130
|
+
codeExample: `// Before - Race condition
|
|
131
|
+
let sharedState = 0;
|
|
132
|
+
Promise.all([
|
|
133
|
+
updateState(),
|
|
134
|
+
checkState()
|
|
135
|
+
]);
|
|
136
|
+
|
|
137
|
+
// After - Using mutex/lock pattern
|
|
138
|
+
import { Mutex } from 'async-mutex';
|
|
139
|
+
|
|
140
|
+
const mutex = new Mutex();
|
|
141
|
+
let sharedState = 0;
|
|
142
|
+
|
|
143
|
+
async function updateState() {
|
|
144
|
+
const release = await mutex.acquire();
|
|
145
|
+
try {
|
|
146
|
+
sharedState++;
|
|
147
|
+
} finally {
|
|
148
|
+
release();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Or using atomic operations
|
|
153
|
+
import { Atomics } from 'atomics';
|
|
154
|
+
|
|
155
|
+
const sharedBuffer = new SharedArrayBuffer(4);
|
|
156
|
+
const sharedArray = new Int32Array(sharedBuffer);
|
|
157
|
+
Atomics.add(sharedArray, 0, 1); // Atomic increment`,
|
|
158
|
+
estimatedEffort: 'medium'
|
|
159
|
+
});
|
|
160
|
+
// Fix 2: Use test isolation
|
|
161
|
+
fixes.push({
|
|
162
|
+
priority: 'high',
|
|
163
|
+
category: 'concurrency',
|
|
164
|
+
recommendation: 'Isolate concurrent tests using proper setup/teardown',
|
|
165
|
+
codeExample: `// Before - Shared state across tests
|
|
166
|
+
let counter = 0;
|
|
167
|
+
|
|
168
|
+
it('test 1', () => {
|
|
169
|
+
counter++;
|
|
170
|
+
expect(counter).toBe(1);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('test 2', () => {
|
|
174
|
+
counter++;
|
|
175
|
+
expect(counter).toBe(1); // Fails due to shared state
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// After - Isolated state
|
|
179
|
+
describe('Counter tests', () => {
|
|
180
|
+
let counter: number;
|
|
181
|
+
|
|
182
|
+
beforeEach(() => {
|
|
183
|
+
counter = 0; // Reset for each test
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('test 1', () => {
|
|
187
|
+
counter++;
|
|
188
|
+
expect(counter).toBe(1);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('test 2', () => {
|
|
192
|
+
counter++;
|
|
193
|
+
expect(counter).toBe(1); // Now passes
|
|
194
|
+
});
|
|
195
|
+
});`,
|
|
196
|
+
estimatedEffort: 'low'
|
|
197
|
+
});
|
|
198
|
+
return fixes;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Dependency-related fixes
|
|
202
|
+
*/
|
|
203
|
+
dependencyFixes(rootCause) {
|
|
204
|
+
const fixes = [];
|
|
205
|
+
// Fix 1: Mock external dependencies
|
|
206
|
+
fixes.push({
|
|
207
|
+
priority: 'high',
|
|
208
|
+
category: 'external',
|
|
209
|
+
recommendation: 'Mock external dependencies to eliminate external variability',
|
|
210
|
+
codeExample: `// Before - Real API calls
|
|
211
|
+
it('should fetch user data', async () => {
|
|
212
|
+
const user = await api.getUser(123);
|
|
213
|
+
expect(user.name).toBe('John');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// After - Mocked dependencies
|
|
217
|
+
import { jest } from '@jest/globals';
|
|
218
|
+
|
|
219
|
+
jest.mock('./api', () => ({
|
|
220
|
+
getUser: jest.fn().mockResolvedValue({
|
|
221
|
+
id: 123,
|
|
222
|
+
name: 'John'
|
|
223
|
+
})
|
|
224
|
+
}));
|
|
225
|
+
|
|
226
|
+
it('should fetch user data', async () => {
|
|
227
|
+
const user = await api.getUser(123);
|
|
228
|
+
expect(user.name).toBe('John');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// With MSW for HTTP mocking
|
|
232
|
+
import { rest } from 'msw';
|
|
233
|
+
import { setupServer } from 'msw/node';
|
|
234
|
+
|
|
235
|
+
const server = setupServer(
|
|
236
|
+
rest.get('/api/user/:id', (req, res, ctx) => {
|
|
237
|
+
return res(ctx.json({ id: 123, name: 'John' }));
|
|
238
|
+
})
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
beforeAll(() => server.listen());
|
|
242
|
+
afterEach(() => server.resetHandlers());
|
|
243
|
+
afterAll(() => server.close());`,
|
|
244
|
+
estimatedEffort: 'medium'
|
|
245
|
+
});
|
|
246
|
+
// Fix 2: Stub time-dependent functions
|
|
247
|
+
fixes.push({
|
|
248
|
+
priority: 'medium',
|
|
249
|
+
category: 'external',
|
|
250
|
+
recommendation: 'Stub time-dependent functions for deterministic results',
|
|
251
|
+
codeExample: `// Before - Real date/time
|
|
252
|
+
it('should check expiry', () => {
|
|
253
|
+
const token = { expiresAt: Date.now() + 1000 };
|
|
254
|
+
expect(isExpired(token)).toBe(false);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// After - Mocked time
|
|
258
|
+
jest.useFakeTimers();
|
|
259
|
+
jest.setSystemTime(new Date('2024-01-01'));
|
|
260
|
+
|
|
261
|
+
it('should check expiry', () => {
|
|
262
|
+
const token = { expiresAt: new Date('2024-01-02').getTime() };
|
|
263
|
+
expect(isExpired(token)).toBe(false);
|
|
264
|
+
|
|
265
|
+
// Advance time
|
|
266
|
+
jest.advanceTimersByTime(24 * 60 * 60 * 1000);
|
|
267
|
+
expect(isExpired(token)).toBe(true);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
jest.useRealTimers(); // Cleanup`,
|
|
271
|
+
estimatedEffort: 'low'
|
|
272
|
+
});
|
|
273
|
+
return fixes;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Isolation-related fixes
|
|
277
|
+
*/
|
|
278
|
+
isolationFixes(rootCause) {
|
|
279
|
+
const fixes = [];
|
|
280
|
+
// Fix 1: Proper test cleanup
|
|
281
|
+
fixes.push({
|
|
282
|
+
priority: 'high',
|
|
283
|
+
category: 'data',
|
|
284
|
+
recommendation: 'Add proper cleanup in afterEach to ensure test isolation',
|
|
285
|
+
codeExample: `// Before - No cleanup
|
|
286
|
+
it('test 1', () => {
|
|
287
|
+
localStorage.setItem('key', 'value1');
|
|
288
|
+
// ... test logic
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('test 2', () => {
|
|
292
|
+
// Fails due to leftover state
|
|
293
|
+
expect(localStorage.getItem('key')).toBeNull();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// After - Proper cleanup
|
|
297
|
+
describe('LocalStorage tests', () => {
|
|
298
|
+
afterEach(() => {
|
|
299
|
+
localStorage.clear();
|
|
300
|
+
jest.clearAllMocks();
|
|
301
|
+
jest.clearAllTimers();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('test 1', () => {
|
|
305
|
+
localStorage.setItem('key', 'value1');
|
|
306
|
+
expect(localStorage.getItem('key')).toBe('value1');
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('test 2', () => {
|
|
310
|
+
expect(localStorage.getItem('key')).toBeNull();
|
|
311
|
+
});
|
|
312
|
+
});`,
|
|
313
|
+
estimatedEffort: 'low'
|
|
314
|
+
});
|
|
315
|
+
// Fix 2: Reset global state
|
|
316
|
+
fixes.push({
|
|
317
|
+
priority: 'high',
|
|
318
|
+
category: 'data',
|
|
319
|
+
recommendation: 'Reset global state and singletons between tests',
|
|
320
|
+
codeExample: `// Before - Singleton with state
|
|
321
|
+
class ConfigManager {
|
|
322
|
+
private static instance: ConfigManager;
|
|
323
|
+
private config: any = {};
|
|
324
|
+
|
|
325
|
+
static getInstance() {
|
|
326
|
+
if (!this.instance) {
|
|
327
|
+
this.instance = new ConfigManager();
|
|
328
|
+
}
|
|
329
|
+
return this.instance;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// After - Add reset method
|
|
334
|
+
class ConfigManager {
|
|
335
|
+
private static instance: ConfigManager;
|
|
336
|
+
private config: any = {};
|
|
337
|
+
|
|
338
|
+
static getInstance() {
|
|
339
|
+
if (!this.instance) {
|
|
340
|
+
this.instance = new ConfigManager();
|
|
341
|
+
}
|
|
342
|
+
return this.instance;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
static resetInstance() {
|
|
346
|
+
this.instance = null as any;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// In tests
|
|
351
|
+
afterEach(() => {
|
|
352
|
+
ConfigManager.resetInstance();
|
|
353
|
+
});`,
|
|
354
|
+
estimatedEffort: 'medium'
|
|
355
|
+
});
|
|
356
|
+
return fixes;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Environment-related fixes
|
|
360
|
+
*/
|
|
361
|
+
environmentFixes(rootCause) {
|
|
362
|
+
const fixes = [];
|
|
363
|
+
// Fix 1: Use test doubles for environment
|
|
364
|
+
fixes.push({
|
|
365
|
+
priority: 'medium',
|
|
366
|
+
category: 'environmental',
|
|
367
|
+
recommendation: 'Use test doubles to eliminate environment variability',
|
|
368
|
+
codeExample: `// Before - Relying on environment
|
|
369
|
+
it('should use correct API URL', () => {
|
|
370
|
+
const url = process.env.API_URL;
|
|
371
|
+
expect(url).toBeDefined();
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// After - Mock environment
|
|
375
|
+
const originalEnv = process.env;
|
|
376
|
+
|
|
377
|
+
beforeEach(() => {
|
|
378
|
+
jest.resetModules();
|
|
379
|
+
process.env = {
|
|
380
|
+
...originalEnv,
|
|
381
|
+
API_URL: 'https://test.api.com',
|
|
382
|
+
NODE_ENV: 'test'
|
|
383
|
+
};
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
afterEach(() => {
|
|
387
|
+
process.env = originalEnv;
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('should use correct API URL', () => {
|
|
391
|
+
const url = process.env.API_URL;
|
|
392
|
+
expect(url).toBe('https://test.api.com');
|
|
393
|
+
});`,
|
|
394
|
+
estimatedEffort: 'low'
|
|
395
|
+
});
|
|
396
|
+
// Fix 2: Use test containers
|
|
397
|
+
fixes.push({
|
|
398
|
+
priority: 'medium',
|
|
399
|
+
category: 'environmental',
|
|
400
|
+
recommendation: 'Use test containers for consistent database/service environments',
|
|
401
|
+
codeExample: `// Using Testcontainers
|
|
402
|
+
import { GenericContainer } from 'testcontainers';
|
|
403
|
+
|
|
404
|
+
describe('Database tests', () => {
|
|
405
|
+
let container: any;
|
|
406
|
+
let database: any;
|
|
407
|
+
|
|
408
|
+
beforeAll(async () => {
|
|
409
|
+
container = await new GenericContainer('postgres:14')
|
|
410
|
+
.withExposedPorts(5432)
|
|
411
|
+
.withEnv('POSTGRES_PASSWORD', 'test')
|
|
412
|
+
.start();
|
|
413
|
+
|
|
414
|
+
const port = container.getMappedPort(5432);
|
|
415
|
+
database = await connectToDatabase({
|
|
416
|
+
host: 'localhost',
|
|
417
|
+
port,
|
|
418
|
+
password: 'test'
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
afterAll(async () => {
|
|
423
|
+
await database.close();
|
|
424
|
+
await container.stop();
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it('should query database', async () => {
|
|
428
|
+
const result = await database.query('SELECT 1');
|
|
429
|
+
expect(result).toBeDefined();
|
|
430
|
+
});
|
|
431
|
+
});`,
|
|
432
|
+
estimatedEffort: 'high'
|
|
433
|
+
});
|
|
434
|
+
return fixes;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Generic fixes for unknown root causes
|
|
438
|
+
*/
|
|
439
|
+
genericFixes(rootCause) {
|
|
440
|
+
return [{
|
|
441
|
+
priority: 'medium',
|
|
442
|
+
category: 'data',
|
|
443
|
+
recommendation: 'Add retry logic and better error handling',
|
|
444
|
+
codeExample: `// Generic retry wrapper
|
|
445
|
+
async function retryTest(testFn: () => Promise<void>, maxRetries = 3) {
|
|
446
|
+
let lastError: Error;
|
|
447
|
+
|
|
448
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
449
|
+
try {
|
|
450
|
+
await testFn();
|
|
451
|
+
return; // Success
|
|
452
|
+
} catch (error) {
|
|
453
|
+
lastError = error as Error;
|
|
454
|
+
await new Promise(resolve => setTimeout(resolve, 100 * (i + 1)));
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
throw lastError!;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Usage
|
|
462
|
+
it('flaky test', async () => {
|
|
463
|
+
await retryTest(async () => {
|
|
464
|
+
// Test logic here
|
|
465
|
+
expect(await someAsyncOperation()).toBe(expected);
|
|
466
|
+
});
|
|
467
|
+
});`,
|
|
468
|
+
estimatedEffort: 'low'
|
|
469
|
+
}];
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Get priority order for recommendations
|
|
473
|
+
*/
|
|
474
|
+
getPriorityOrder(recommendations) {
|
|
475
|
+
const priorityMap = {
|
|
476
|
+
critical: 4,
|
|
477
|
+
high: 3,
|
|
478
|
+
medium: 2,
|
|
479
|
+
low: 1
|
|
480
|
+
};
|
|
481
|
+
return recommendations.sort((a, b) => {
|
|
482
|
+
return priorityMap[b.priority] - priorityMap[a.priority];
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Filter recommendations by effort
|
|
487
|
+
*/
|
|
488
|
+
filterByEffort(recommendations, maxEffort) {
|
|
489
|
+
const effortMap = {
|
|
490
|
+
low: 1,
|
|
491
|
+
medium: 2,
|
|
492
|
+
high: 3
|
|
493
|
+
};
|
|
494
|
+
const threshold = effortMap[maxEffort];
|
|
495
|
+
return recommendations.filter(rec => effortMap[rec.estimatedEffort] <= threshold);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
exports.FixRecommendationEngine = FixRecommendationEngine;
|
|
499
|
+
exports.default = FixRecommendationEngine;
|
|
500
|
+
//# sourceMappingURL=FixRecommendationEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FixRecommendationEngine.js","sourceRoot":"","sources":["../../src/learning/FixRecommendationEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Achieves 90% accuracy in identifying flaky tests
|
|
4
4
|
*/
|
|
5
5
|
import { TestResult, FlakyTest } from './types';
|
|
6
|
+
import { RootCauseAnalysis } from './FixRecommendationEngine';
|
|
6
7
|
export interface FlakyDetectionOptions {
|
|
7
8
|
minRuns?: number;
|
|
8
9
|
passRateThreshold?: number;
|
|
@@ -21,6 +22,7 @@ export interface ResolvedFlakyDetectionOptions {
|
|
|
21
22
|
}
|
|
22
23
|
export declare class FlakyTestDetector {
|
|
23
24
|
private model;
|
|
25
|
+
private fixEngine;
|
|
24
26
|
private options;
|
|
25
27
|
constructor(options?: FlakyDetectionOptions);
|
|
26
28
|
/**
|
|
@@ -51,5 +53,22 @@ export declare class FlakyTestDetector {
|
|
|
51
53
|
private identifyFailurePattern;
|
|
52
54
|
private calculateEnvironmentVariability;
|
|
53
55
|
private calculateSeverity;
|
|
56
|
+
/**
|
|
57
|
+
* Analyze root cause of flakiness using ML patterns
|
|
58
|
+
*
|
|
59
|
+
* @param testName - Name of the flaky test
|
|
60
|
+
* @param results - Test execution results
|
|
61
|
+
* @param failurePattern - Identified failure pattern
|
|
62
|
+
* @returns Root cause analysis with ML confidence
|
|
63
|
+
*/
|
|
64
|
+
analyzeRootCause(testName: string, results: TestResult[], failurePattern: 'intermittent' | 'environmental' | 'timing' | 'resource'): RootCauseAnalysis;
|
|
65
|
+
/**
|
|
66
|
+
* Check if failures occur sequentially (race condition indicator)
|
|
67
|
+
*/
|
|
68
|
+
private areFailuresSequential;
|
|
69
|
+
/**
|
|
70
|
+
* Map failure pattern to root cause
|
|
71
|
+
*/
|
|
72
|
+
private mapFailurePatternToRootCause;
|
|
54
73
|
}
|
|
55
74
|
//# sourceMappingURL=FlakyTestDetector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FlakyTestDetector.d.ts","sourceRoot":"","sources":["../../src/learning/FlakyTestDetector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"FlakyTestDetector.d.ts","sourceRoot":"","sources":["../../src/learning/FlakyTestDetector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAA0B,MAAM,SAAS,CAAC;AAIxE,OAAO,EAA2B,iBAAiB,EAAa,MAAM,2BAA2B,CAAC;AAElG,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,OAAO,CAAgC;gBAEnC,OAAO,GAAE,qBAA0B;IAa/C;;;OAGG;IACG,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IA4EnE;;OAEG;IACG,UAAU,CACd,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EACvC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC;IAmBhB;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAsDrF;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG;QACtC,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;KACvB;IAsBD,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,sBAAsB;IA4B9B,OAAO,CAAC,+BAA+B;IAgBvC,OAAO,CAAC,iBAAiB;IAUzB;;;;;;;OAOG;IACH,gBAAgB,CACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,UAAU,EAAE,EACrB,cAAc,EAAE,cAAc,GAAG,eAAe,GAAG,QAAQ,GAAG,UAAU,GACvE,iBAAiB;IA+EpB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAsB7B;;OAEG;IACH,OAAO,CAAC,4BAA4B;CAYrC"}
|