playwright-ai-reporter 0.0.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/LICENSE +21 -0
- package/README.md +1183 -0
- package/dist/colors.d.ts +54 -0
- package/dist/colors.js +57 -0
- package/dist/examples/ReporterWorkflow.d.ts +54 -0
- package/dist/examples/ReporterWorkflow.js +307 -0
- package/dist/providers/ProviderRegistry.d.ts +79 -0
- package/dist/providers/ProviderRegistry.js +195 -0
- package/dist/providers/ai/AIProviderFactory.d.ts +33 -0
- package/dist/providers/ai/AIProviderFactory.js +82 -0
- package/dist/providers/ai/AnthropicProvider.d.ts +15 -0
- package/dist/providers/ai/AnthropicProvider.js +128 -0
- package/dist/providers/ai/AzureOpenAIProvider.d.ts +20 -0
- package/dist/providers/ai/AzureOpenAIProvider.js +158 -0
- package/dist/providers/ai/GoogleAIProvider.d.ts +17 -0
- package/dist/providers/ai/GoogleAIProvider.js +154 -0
- package/dist/providers/ai/MistralProvider.d.ts +16 -0
- package/dist/providers/ai/MistralProvider.js +137 -0
- package/dist/providers/ai/OpenAIProvider.d.ts +16 -0
- package/dist/providers/ai/OpenAIProvider.js +141 -0
- package/dist/providers/bugTrackers/AzureDevOpsBugTracker.d.ts +32 -0
- package/dist/providers/bugTrackers/AzureDevOpsBugTracker.js +295 -0
- package/dist/providers/bugTrackers/GitHubBugTracker.d.ts +28 -0
- package/dist/providers/bugTrackers/GitHubBugTracker.js +241 -0
- package/dist/providers/bugTrackers/JiraBugTracker.d.ts +29 -0
- package/dist/providers/bugTrackers/JiraBugTracker.js +279 -0
- package/dist/providers/databases/MySQLProvider.d.ts +32 -0
- package/dist/providers/databases/MySQLProvider.js +274 -0
- package/dist/providers/databases/SQLiteProvider.d.ts +28 -0
- package/dist/providers/databases/SQLiteProvider.js +272 -0
- package/dist/providers/factories/BugTrackerFactory.d.ts +20 -0
- package/dist/providers/factories/BugTrackerFactory.js +50 -0
- package/dist/providers/factories/DatabaseFactory.d.ts +28 -0
- package/dist/providers/factories/DatabaseFactory.js +71 -0
- package/dist/providers/factories/NotificationFactory.d.ts +24 -0
- package/dist/providers/factories/NotificationFactory.js +64 -0
- package/dist/providers/factories/PRProviderFactory.d.ts +20 -0
- package/dist/providers/factories/PRProviderFactory.js +45 -0
- package/dist/providers/index.d.ts +28 -0
- package/dist/providers/index.js +55 -0
- package/dist/providers/interfaces/IAIProvider.d.ts +59 -0
- package/dist/providers/interfaces/IAIProvider.js +5 -0
- package/dist/providers/interfaces/IBugTrackerProvider.d.ts +70 -0
- package/dist/providers/interfaces/IBugTrackerProvider.js +20 -0
- package/dist/providers/interfaces/IDatabaseProvider.d.ts +90 -0
- package/dist/providers/interfaces/IDatabaseProvider.js +5 -0
- package/dist/providers/interfaces/INotificationProvider.d.ts +59 -0
- package/dist/providers/interfaces/INotificationProvider.js +13 -0
- package/dist/providers/interfaces/IPRProvider.d.ts +82 -0
- package/dist/providers/interfaces/IPRProvider.js +5 -0
- package/dist/providers/notifications/EmailNotificationProvider.d.ts +29 -0
- package/dist/providers/notifications/EmailNotificationProvider.js +290 -0
- package/dist/providers/pr/AzureDevOpsPRProvider.d.ts +30 -0
- package/dist/providers/pr/AzureDevOpsPRProvider.js +263 -0
- package/dist/providers/pr/GitHubPRProvider.d.ts +29 -0
- package/dist/providers/pr/GitHubPRProvider.js +320 -0
- package/dist/reporter.d.ts +138 -0
- package/dist/reporter.js +787 -0
- package/dist/types/index.d.ts +168 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/buildInfoUtils.d.ts +26 -0
- package/dist/utils/buildInfoUtils.js +125 -0
- package/dist/utils/configValidator.d.ts +67 -0
- package/dist/utils/configValidator.js +454 -0
- package/dist/utils/fileHandlerUtils.d.ts +42 -0
- package/dist/utils/fileHandlerUtils.js +136 -0
- package/dist/utils/genaiUtils.d.ts +38 -0
- package/dist/utils/genaiUtils.js +178 -0
- package/dist/utils/historyUtils.d.ts +49 -0
- package/dist/utils/historyUtils.js +118 -0
- package/dist/utils/utils.d.ts +104 -0
- package/dist/utils/utils.js +371 -0
- package/docs/API.md +591 -0
- package/docs/ENV_CONFIG_GUIDE.md +444 -0
- package/docs/IMPLEMENTATION_SUMMARY.md +285 -0
- package/docs/PROVIDERS.md +261 -0
- package/docs/QUICKSTART.md +350 -0
- package/docs/README.md +253 -0
- package/docs/TROUBLESHOOTING.md +577 -0
- package/docs/design.md +384 -0
- package/docs/logo.png +0 -0
- package/examples/README.md +326 -0
- package/examples/VALIDATION.md +68 -0
- package/examples/env-configs/.env.anthropic-minimal +40 -0
- package/examples/env-configs/.env.azure-stack +71 -0
- package/examples/env-configs/.env.example +32 -0
- package/examples/env-configs/.env.github-stack +57 -0
- package/examples/env-configs/.env.google-mysql +61 -0
- package/examples/env-configs/.env.ms-auth-examples +56 -0
- package/examples/env-configs/.env.openai-jira +64 -0
- package/examples/package.json +22 -0
- package/package.json +70 -0
- package/playwright-ai-reporter-0.0.4.tgz +0 -0
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration validator and diagnostic tool
|
|
4
|
+
*
|
|
5
|
+
* This utility helps validate provider configurations and diagnose issues
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.ConfigValidator = void 0;
|
|
42
|
+
const dotenv = __importStar(require("dotenv"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const AIProviderFactory_1 = require("../providers/ai/AIProviderFactory");
|
|
45
|
+
const BugTrackerFactory_1 = require("../providers/factories/BugTrackerFactory");
|
|
46
|
+
const DatabaseFactory_1 = require("../providers/factories/DatabaseFactory");
|
|
47
|
+
dotenv.config({ path: path.resolve(process.cwd(), '.env') });
|
|
48
|
+
class ConfigValidator {
|
|
49
|
+
/**
|
|
50
|
+
* Validate all configured providers
|
|
51
|
+
*/
|
|
52
|
+
static async validateAll() {
|
|
53
|
+
const results = [];
|
|
54
|
+
console.log('\n=== Provider Configuration Validation ===\n');
|
|
55
|
+
// Validate AI Provider
|
|
56
|
+
results.push(await this.validateAIProvider());
|
|
57
|
+
// Validate Bug Tracker (if configured)
|
|
58
|
+
if (process.env.BUG_TRACKER_PROVIDER) {
|
|
59
|
+
results.push(await this.validateBugTracker());
|
|
60
|
+
}
|
|
61
|
+
// Validate Database (if configured)
|
|
62
|
+
if (process.env.DATABASE_PROVIDER) {
|
|
63
|
+
results.push(await this.validateDatabase());
|
|
64
|
+
}
|
|
65
|
+
// Validate Notification Provider (if configured)
|
|
66
|
+
if (process.env.NOTIFICATION_PROVIDER) {
|
|
67
|
+
results.push(await this.validateNotificationProvider());
|
|
68
|
+
}
|
|
69
|
+
// Validate PR Provider (if configured)
|
|
70
|
+
if (process.env.PR_PROVIDER) {
|
|
71
|
+
results.push(await this.validatePRProvider());
|
|
72
|
+
}
|
|
73
|
+
this.printResults(results);
|
|
74
|
+
return results;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Validate AI provider configuration
|
|
78
|
+
*/
|
|
79
|
+
static async validateAIProvider() {
|
|
80
|
+
const providerType = process.env.AI_PROVIDER || 'azure-openai';
|
|
81
|
+
try {
|
|
82
|
+
// Check if provider type is supported
|
|
83
|
+
if (!AIProviderFactory_1.AIProviderFactory.isProviderSupported(providerType)) {
|
|
84
|
+
return {
|
|
85
|
+
provider: 'AI Provider',
|
|
86
|
+
valid: false,
|
|
87
|
+
configured: false,
|
|
88
|
+
message: `Unsupported AI provider: ${providerType}`,
|
|
89
|
+
details: { supportedProviders: AIProviderFactory_1.AIProviderFactory.getSupportedProviders() },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Check provider-specific configuration
|
|
93
|
+
const configCheck = this.checkAIProviderConfig(providerType);
|
|
94
|
+
if (!configCheck.valid) {
|
|
95
|
+
return {
|
|
96
|
+
provider: 'AI Provider',
|
|
97
|
+
valid: false,
|
|
98
|
+
configured: false,
|
|
99
|
+
message: configCheck.message,
|
|
100
|
+
details: configCheck.details,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// Try to initialize and test connection
|
|
104
|
+
const provider = await AIProviderFactory_1.AIProviderFactory.createProvider(providerType);
|
|
105
|
+
const connected = await provider.testConnection();
|
|
106
|
+
return {
|
|
107
|
+
provider: `AI Provider (${provider.getName()})`,
|
|
108
|
+
valid: true,
|
|
109
|
+
configured: true,
|
|
110
|
+
connected,
|
|
111
|
+
message: connected ? 'Successfully connected' : 'Configuration valid but connection failed',
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
return {
|
|
116
|
+
provider: 'AI Provider',
|
|
117
|
+
valid: false,
|
|
118
|
+
configured: false,
|
|
119
|
+
message: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Check AI provider specific configuration
|
|
125
|
+
*/
|
|
126
|
+
static checkAIProviderConfig(providerType) {
|
|
127
|
+
const checks = {
|
|
128
|
+
'azure-openai': ['AZURE_OPENAI_ENDPOINT', 'AZURE_OPENAI_DEPLOYMENT_NAME'],
|
|
129
|
+
openai: ['OPENAI_API_KEY'],
|
|
130
|
+
anthropic: ['ANTHROPIC_API_KEY'],
|
|
131
|
+
'google-ai': ['GOOGLE_AI_API_KEY'],
|
|
132
|
+
mistral: ['MISTRAL_API_KEY'],
|
|
133
|
+
};
|
|
134
|
+
const requiredVars = checks[providerType] || [];
|
|
135
|
+
const missing = requiredVars.filter((v) => !process.env[v]);
|
|
136
|
+
if (missing.length > 0) {
|
|
137
|
+
return {
|
|
138
|
+
valid: false,
|
|
139
|
+
message: `Missing required environment variables: ${missing.join(', ')}`,
|
|
140
|
+
details: { required: requiredVars, missing },
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return { valid: true, message: 'Configuration complete' };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Validate bug tracker configuration
|
|
147
|
+
*/
|
|
148
|
+
static async validateBugTracker() {
|
|
149
|
+
const providerType = process.env.BUG_TRACKER_PROVIDER;
|
|
150
|
+
try {
|
|
151
|
+
if (!providerType) {
|
|
152
|
+
return {
|
|
153
|
+
provider: 'Bug Tracker',
|
|
154
|
+
valid: false,
|
|
155
|
+
configured: false,
|
|
156
|
+
message: 'BUG_TRACKER_PROVIDER not set',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const configCheck = this.checkBugTrackerConfig(providerType);
|
|
160
|
+
if (!configCheck.valid) {
|
|
161
|
+
return {
|
|
162
|
+
provider: 'Bug Tracker',
|
|
163
|
+
valid: false,
|
|
164
|
+
configured: false,
|
|
165
|
+
message: configCheck.message,
|
|
166
|
+
details: configCheck.details,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
// Try to initialize
|
|
170
|
+
const provider = await BugTrackerFactory_1.BugTrackerFactory.createProvider(providerType);
|
|
171
|
+
return {
|
|
172
|
+
provider: `Bug Tracker (${providerType})`,
|
|
173
|
+
valid: true,
|
|
174
|
+
configured: true,
|
|
175
|
+
message: 'Configuration valid',
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
return {
|
|
180
|
+
provider: 'Bug Tracker',
|
|
181
|
+
valid: false,
|
|
182
|
+
configured: false,
|
|
183
|
+
message: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Check bug tracker specific configuration
|
|
189
|
+
*/
|
|
190
|
+
static checkBugTrackerConfig(providerType) {
|
|
191
|
+
const checks = {
|
|
192
|
+
'azure-devops': ['AZURE_DEVOPS_ORG_URL', 'AZURE_DEVOPS_PROJECT', 'AZURE_DEVOPS_PAT'],
|
|
193
|
+
github: ['GITHUB_TOKEN', 'GITHUB_OWNER', 'GITHUB_REPO'],
|
|
194
|
+
jira: ['JIRA_HOST', 'JIRA_EMAIL', 'JIRA_API_TOKEN', 'JIRA_PROJECT_KEY'],
|
|
195
|
+
};
|
|
196
|
+
const requiredVars = checks[providerType] || [];
|
|
197
|
+
const missing = requiredVars.filter((v) => !process.env[v]);
|
|
198
|
+
if (missing.length > 0) {
|
|
199
|
+
return {
|
|
200
|
+
valid: false,
|
|
201
|
+
message: `Missing required environment variables: ${missing.join(', ')}`,
|
|
202
|
+
details: { required: requiredVars, missing },
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return { valid: true, message: 'Configuration complete' };
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Validate database configuration
|
|
209
|
+
*/
|
|
210
|
+
static async validateDatabase() {
|
|
211
|
+
const providerType = process.env.DATABASE_PROVIDER;
|
|
212
|
+
try {
|
|
213
|
+
if (!providerType) {
|
|
214
|
+
return {
|
|
215
|
+
provider: 'Database',
|
|
216
|
+
valid: false,
|
|
217
|
+
configured: false,
|
|
218
|
+
message: 'DATABASE_PROVIDER not set',
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
const configCheck = this.checkDatabaseConfig(providerType);
|
|
222
|
+
if (!configCheck.valid) {
|
|
223
|
+
return {
|
|
224
|
+
provider: 'Database',
|
|
225
|
+
valid: false,
|
|
226
|
+
configured: false,
|
|
227
|
+
message: configCheck.message,
|
|
228
|
+
details: configCheck.details,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
// Try to initialize
|
|
232
|
+
const provider = await DatabaseFactory_1.DatabaseFactory.createProvider(providerType);
|
|
233
|
+
await provider.close();
|
|
234
|
+
return {
|
|
235
|
+
provider: `Database (${providerType})`,
|
|
236
|
+
valid: true,
|
|
237
|
+
configured: true,
|
|
238
|
+
connected: true,
|
|
239
|
+
message: 'Successfully connected',
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
return {
|
|
244
|
+
provider: 'Database',
|
|
245
|
+
valid: false,
|
|
246
|
+
configured: false,
|
|
247
|
+
message: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Check database specific configuration
|
|
253
|
+
*/
|
|
254
|
+
static checkDatabaseConfig(providerType) {
|
|
255
|
+
const checks = {
|
|
256
|
+
sqlite: [], // No required config for SQLite
|
|
257
|
+
mysql: ['MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DATABASE'],
|
|
258
|
+
postgresql: ['POSTGRES_HOST', 'POSTGRES_USER', 'POSTGRES_PASSWORD', 'POSTGRES_DATABASE'],
|
|
259
|
+
};
|
|
260
|
+
const requiredVars = checks[providerType] || [];
|
|
261
|
+
const missing = requiredVars.filter((v) => !process.env[v]);
|
|
262
|
+
if (missing.length > 0) {
|
|
263
|
+
return {
|
|
264
|
+
valid: false,
|
|
265
|
+
message: `Missing required environment variables: ${missing.join(', ')}`,
|
|
266
|
+
details: { required: requiredVars, missing },
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return { valid: true, message: 'Configuration complete' };
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Validate notification provider configuration
|
|
273
|
+
*/
|
|
274
|
+
static async validateNotificationProvider() {
|
|
275
|
+
const providerType = process.env.NOTIFICATION_PROVIDER;
|
|
276
|
+
try {
|
|
277
|
+
if (!providerType) {
|
|
278
|
+
return {
|
|
279
|
+
provider: 'Notification',
|
|
280
|
+
valid: false,
|
|
281
|
+
configured: false,
|
|
282
|
+
message: 'NOTIFICATION_PROVIDER not set',
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const configCheck = this.checkNotificationConfig(providerType);
|
|
286
|
+
if (!configCheck.valid) {
|
|
287
|
+
return {
|
|
288
|
+
provider: 'Notification',
|
|
289
|
+
valid: false,
|
|
290
|
+
configured: false,
|
|
291
|
+
message: configCheck.message,
|
|
292
|
+
details: configCheck.details,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
provider: `Notification (${providerType})`,
|
|
297
|
+
valid: true,
|
|
298
|
+
configured: true,
|
|
299
|
+
message: 'Configuration valid',
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
return {
|
|
304
|
+
provider: 'Notification',
|
|
305
|
+
valid: false,
|
|
306
|
+
configured: false,
|
|
307
|
+
message: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Check notification provider specific configuration
|
|
313
|
+
*/
|
|
314
|
+
static checkNotificationConfig(providerType) {
|
|
315
|
+
const checks = {
|
|
316
|
+
email: ['EMAIL_HOST', 'EMAIL_USER', 'EMAIL_PASSWORD', 'EMAIL_FROM'],
|
|
317
|
+
slack: ['SLACK_WEBHOOK_URL'],
|
|
318
|
+
teams: ['TEAMS_WEBHOOK_URL'],
|
|
319
|
+
};
|
|
320
|
+
const requiredVars = checks[providerType] || [];
|
|
321
|
+
const missing = requiredVars.filter((v) => !process.env[v]);
|
|
322
|
+
if (missing.length > 0) {
|
|
323
|
+
return {
|
|
324
|
+
valid: false,
|
|
325
|
+
message: `Missing required environment variables: ${missing.join(', ')}`,
|
|
326
|
+
details: { required: requiredVars, missing },
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
return { valid: true, message: 'Configuration complete' };
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Validate PR provider configuration
|
|
333
|
+
*/
|
|
334
|
+
static async validatePRProvider() {
|
|
335
|
+
const providerType = process.env.PR_PROVIDER;
|
|
336
|
+
try {
|
|
337
|
+
if (!providerType) {
|
|
338
|
+
return {
|
|
339
|
+
provider: 'PR Provider',
|
|
340
|
+
valid: false,
|
|
341
|
+
configured: false,
|
|
342
|
+
message: 'PR_PROVIDER not set',
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const configCheck = this.checkPRProviderConfig(providerType);
|
|
346
|
+
if (!configCheck.valid) {
|
|
347
|
+
return {
|
|
348
|
+
provider: 'PR Provider',
|
|
349
|
+
valid: false,
|
|
350
|
+
configured: false,
|
|
351
|
+
message: configCheck.message,
|
|
352
|
+
details: configCheck.details,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
provider: `PR Provider (${providerType})`,
|
|
357
|
+
valid: true,
|
|
358
|
+
configured: true,
|
|
359
|
+
message: 'Configuration valid',
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
return {
|
|
364
|
+
provider: 'PR Provider',
|
|
365
|
+
valid: false,
|
|
366
|
+
configured: false,
|
|
367
|
+
message: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Check PR provider specific configuration
|
|
373
|
+
*/
|
|
374
|
+
static checkPRProviderConfig(providerType) {
|
|
375
|
+
const checks = {
|
|
376
|
+
github: ['GITHUB_TOKEN', 'GITHUB_OWNER', 'GITHUB_REPO'],
|
|
377
|
+
'azure-devops': ['AZURE_DEVOPS_ORG_URL', 'AZURE_DEVOPS_PROJECT', 'AZURE_DEVOPS_PAT'],
|
|
378
|
+
};
|
|
379
|
+
const requiredVars = checks[providerType] || [];
|
|
380
|
+
const missing = requiredVars.filter((v) => !process.env[v]);
|
|
381
|
+
if (missing.length > 0) {
|
|
382
|
+
return {
|
|
383
|
+
valid: false,
|
|
384
|
+
message: `Missing required environment variables: ${missing.join(', ')}`,
|
|
385
|
+
details: { required: requiredVars, missing },
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
return { valid: true, message: 'Configuration complete' };
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Print validation results
|
|
392
|
+
*/
|
|
393
|
+
static printResults(results) {
|
|
394
|
+
console.log('\n=== Validation Results ===\n');
|
|
395
|
+
let allValid = true;
|
|
396
|
+
results.forEach((result) => {
|
|
397
|
+
const status = result.valid ? '✓' : '✗';
|
|
398
|
+
const color = result.valid ? '\x1b[32m' : '\x1b[31m';
|
|
399
|
+
const reset = '\x1b[0m';
|
|
400
|
+
console.log(`${color}${status} ${result.provider}${reset}`);
|
|
401
|
+
console.log(` ${result.message}`);
|
|
402
|
+
if (result.connected !== undefined) {
|
|
403
|
+
const connStatus = result.connected ? '✓ Connected' : '✗ Connection failed';
|
|
404
|
+
console.log(` ${connStatus}`);
|
|
405
|
+
}
|
|
406
|
+
if (result.details) {
|
|
407
|
+
console.log(` Details:`, result.details);
|
|
408
|
+
}
|
|
409
|
+
console.log('');
|
|
410
|
+
if (!result.valid) {
|
|
411
|
+
allValid = false;
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
if (allValid) {
|
|
415
|
+
console.log('\x1b[32m✓ All configured providers are valid!\x1b[0m\n');
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
console.log('\x1b[31m✗ Some providers have configuration issues\x1b[0m\n');
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Generate a configuration report
|
|
423
|
+
*/
|
|
424
|
+
static async generateReport() {
|
|
425
|
+
const results = await this.validateAll();
|
|
426
|
+
let report = '# Provider Configuration Report\n\n';
|
|
427
|
+
report += `Generated: ${new Date().toISOString()}\n\n`;
|
|
428
|
+
report += '## Configured Providers\n\n';
|
|
429
|
+
results.forEach((result) => {
|
|
430
|
+
report += `### ${result.provider}\n\n`;
|
|
431
|
+
report += `- Status: ${result.valid ? 'Valid' : 'Invalid'}\n`;
|
|
432
|
+
report += `- Configured: ${result.configured ? 'Yes' : 'No'}\n`;
|
|
433
|
+
if (result.connected !== undefined) {
|
|
434
|
+
report += `- Connected: ${result.connected ? 'Yes' : 'No'}\n`;
|
|
435
|
+
}
|
|
436
|
+
report += `- Message: ${result.message}\n`;
|
|
437
|
+
if (result.details) {
|
|
438
|
+
report += `- Details: \`${JSON.stringify(result.details)}\`\n`;
|
|
439
|
+
}
|
|
440
|
+
report += '\n';
|
|
441
|
+
});
|
|
442
|
+
return report;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
exports.ConfigValidator = ConfigValidator;
|
|
446
|
+
// CLI usage
|
|
447
|
+
if (require.main === module) {
|
|
448
|
+
ConfigValidator.validateAll()
|
|
449
|
+
.then(() => process.exit(0))
|
|
450
|
+
.catch((error) => {
|
|
451
|
+
console.error('Validation failed:', error);
|
|
452
|
+
process.exit(1);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { TestFailure, TestCaseDetails, TestSummary } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Handles writing test results to JSON files
|
|
4
|
+
*/
|
|
5
|
+
export declare class FileHandler {
|
|
6
|
+
private readonly failuresFilePath;
|
|
7
|
+
private readonly summaryFilePath;
|
|
8
|
+
private failuresBuffer;
|
|
9
|
+
private writeInterval;
|
|
10
|
+
private isBufferDirty;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new FileHandler instance
|
|
13
|
+
* @param outputDir - Directory where JSON files will be saved
|
|
14
|
+
*/
|
|
15
|
+
constructor(outputDir?: string);
|
|
16
|
+
/**
|
|
17
|
+
* Adds a test failure to the failures file
|
|
18
|
+
* @param failure - The test failure to add
|
|
19
|
+
*/
|
|
20
|
+
addFailure(failure: TestFailure): void;
|
|
21
|
+
/**
|
|
22
|
+
* Writes test summary and all test cases to files
|
|
23
|
+
* @param summary - Test run summary
|
|
24
|
+
* @param allTestCases - All test cases from the run
|
|
25
|
+
*/
|
|
26
|
+
writeSummary(summary: TestSummary, allTestCases: TestCaseDetails[]): void;
|
|
27
|
+
/**
|
|
28
|
+
* Starts the periodic buffer flush
|
|
29
|
+
* @private
|
|
30
|
+
*/
|
|
31
|
+
private startPeriodicFlush;
|
|
32
|
+
/**
|
|
33
|
+
* Stops the periodic buffer flush
|
|
34
|
+
* @private
|
|
35
|
+
*/
|
|
36
|
+
private stopPeriodicFlush;
|
|
37
|
+
/**
|
|
38
|
+
* Flushes the failures buffer to disk
|
|
39
|
+
* @private
|
|
40
|
+
*/
|
|
41
|
+
private flushFailuresBuffer;
|
|
42
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FileHandler = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
/**
|
|
40
|
+
* Handles writing test results to JSON files
|
|
41
|
+
*/
|
|
42
|
+
class FileHandler {
|
|
43
|
+
/**
|
|
44
|
+
* Creates a new FileHandler instance
|
|
45
|
+
* @param outputDir - Directory where JSON files will be saved
|
|
46
|
+
*/
|
|
47
|
+
constructor(outputDir = './test-results') {
|
|
48
|
+
this.failuresBuffer = [];
|
|
49
|
+
this.writeInterval = null;
|
|
50
|
+
this.isBufferDirty = false;
|
|
51
|
+
// Ensure the output directory exists
|
|
52
|
+
if (!fs.existsSync(outputDir)) {
|
|
53
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
this.failuresFilePath = path.join(outputDir, 'testFailures.json');
|
|
56
|
+
this.summaryFilePath = path.join(outputDir, 'testSummary.json');
|
|
57
|
+
// Initialize failures file with empty array if it doesn't exist
|
|
58
|
+
if (!fs.existsSync(this.failuresFilePath)) {
|
|
59
|
+
fs.writeFileSync(this.failuresFilePath, JSON.stringify([], null, 2));
|
|
60
|
+
}
|
|
61
|
+
// Setup periodic flushing of the buffer (every 5 seconds)
|
|
62
|
+
this.startPeriodicFlush();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Adds a test failure to the failures file
|
|
66
|
+
* @param failure - The test failure to add
|
|
67
|
+
*/
|
|
68
|
+
addFailure(failure) {
|
|
69
|
+
this.failuresBuffer.push(failure);
|
|
70
|
+
this.isBufferDirty = true;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Writes test summary and all test cases to files
|
|
74
|
+
* @param summary - Test run summary
|
|
75
|
+
* @param allTestCases - All test cases from the run
|
|
76
|
+
*/
|
|
77
|
+
writeSummary(summary, allTestCases) {
|
|
78
|
+
const summaryWithTests = {
|
|
79
|
+
...summary,
|
|
80
|
+
allTestCases,
|
|
81
|
+
timestamp: new Date().toISOString(),
|
|
82
|
+
runEnvironment: summary.buildInfo?.isPipeline ? 'Pipeline' : 'Local',
|
|
83
|
+
};
|
|
84
|
+
fs.writeFileSync(this.summaryFilePath, JSON.stringify(summaryWithTests, null, 2));
|
|
85
|
+
// Final flush of failures buffer
|
|
86
|
+
this.flushFailuresBuffer();
|
|
87
|
+
// Stop the periodic flush
|
|
88
|
+
this.stopPeriodicFlush();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Starts the periodic buffer flush
|
|
92
|
+
* @private
|
|
93
|
+
*/
|
|
94
|
+
startPeriodicFlush() {
|
|
95
|
+
this.writeInterval = setInterval(() => {
|
|
96
|
+
this.flushFailuresBuffer();
|
|
97
|
+
}, 5000); // Flush every 5 seconds
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Stops the periodic buffer flush
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
stopPeriodicFlush() {
|
|
104
|
+
if (this.writeInterval) {
|
|
105
|
+
clearInterval(this.writeInterval);
|
|
106
|
+
this.writeInterval = null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Flushes the failures buffer to disk
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
113
|
+
flushFailuresBuffer() {
|
|
114
|
+
if (!this.isBufferDirty)
|
|
115
|
+
return;
|
|
116
|
+
try {
|
|
117
|
+
// Read existing failures
|
|
118
|
+
let existingFailures = [];
|
|
119
|
+
if (fs.existsSync(this.failuresFilePath)) {
|
|
120
|
+
const content = fs.readFileSync(this.failuresFilePath, 'utf8');
|
|
121
|
+
existingFailures = JSON.parse(content);
|
|
122
|
+
}
|
|
123
|
+
// Append new failures
|
|
124
|
+
const allFailures = [...existingFailures, ...this.failuresBuffer];
|
|
125
|
+
// Write back to file
|
|
126
|
+
fs.writeFileSync(this.failuresFilePath, JSON.stringify(allFailures, null, 2));
|
|
127
|
+
// Clear buffer
|
|
128
|
+
this.failuresBuffer = [];
|
|
129
|
+
this.isBufferDirty = false;
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
console.error('Error writing failures to file:', error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.FileHandler = FileHandler;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { TestFailure } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Utility for generating AI-powered suggestions for test failures
|
|
4
|
+
*/
|
|
5
|
+
export declare class GenAIUtils {
|
|
6
|
+
/**
|
|
7
|
+
* Calls the configured AI provider to get a suggestion for fixing a failed test
|
|
8
|
+
*
|
|
9
|
+
* @param prompt - The prompt to send to the AI
|
|
10
|
+
* @returns AI's suggested fix
|
|
11
|
+
*/
|
|
12
|
+
static callGenAISuggestion(prompt: string): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Generates a fix suggestion for a failed test
|
|
15
|
+
*
|
|
16
|
+
* @param failure - The test failure information
|
|
17
|
+
* @param sourceCode - Map of source code files for context
|
|
18
|
+
* @returns The path to the saved suggestion file
|
|
19
|
+
*/
|
|
20
|
+
static generateFixSuggestion(failure: TestFailure, sourceCode: Map<string, string>): Promise<{
|
|
21
|
+
promptPath: string;
|
|
22
|
+
fixPath: string;
|
|
23
|
+
} | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Truncates a stack trace to a reasonable length
|
|
26
|
+
*
|
|
27
|
+
* @param stack - The full stack trace
|
|
28
|
+
* @returns Truncated stack trace
|
|
29
|
+
*/
|
|
30
|
+
private static truncateStackTrace;
|
|
31
|
+
/**
|
|
32
|
+
* Sanitizes a filename to be used in a file path
|
|
33
|
+
*
|
|
34
|
+
* @param filename - The filename to sanitize
|
|
35
|
+
* @returns Sanitized filename
|
|
36
|
+
*/
|
|
37
|
+
private static sanitizeFilename;
|
|
38
|
+
}
|