testgenius-ai
Version:
🚀 TestGenius AI - The Ultimate E2E Testing Framework for Everyone | No Coding Required • AI-Powered Automation • Beautiful Reports • Zero Complexity
646 lines • 34 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AllureReporter = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const child_process_1 = require("child_process");
const chalk_1 = __importDefault(require("chalk"));
const CostTracker_1 = require("./CostTracker");
class AllureReporter {
constructor(config) {
this.config = config;
this.costTracker = new CostTracker_1.CostTracker(config);
}
async generateAllureReport(results) {
if (!this.config.reporting || !this.config.reporting.allure || !this.config.reporting.allure.enabled) {
console.log(chalk_1.default.yellow('⚠️ Allure reporting is disabled in configuration'));
return;
}
try {
console.log(chalk_1.default.blue('📊 Generating Allure report...'));
// Ensure Allure results directory exists with default fallback
const resultsDir = this.config.reporting.allure.resultsDir || 'allure-results';
await fs_extra_1.default.ensureDir(resultsDir);
// Generate Allure results for each test
for (const result of results) {
await this.generateAllureResult(result);
}
// Generate cost tracking widgets if enabled
if (this.config.costTracking?.enabled) {
await this.generateCostTrackingWidgets(resultsDir);
await this.generateCostSummaryFile(resultsDir);
}
// Generate Allure report
await this.generateAllureReportFromResults();
console.log(chalk_1.default.green('✅ Allure report generated successfully!'));
console.log(chalk_1.default.blue(`📁 Results: ${resultsDir}`));
console.log(chalk_1.default.blue(`📊 Report: ${this.config.reporting.allure.reportDir || 'allure-report'}`));
}
catch (error) {
console.error(chalk_1.default.red('❌ Failed to generate Allure report:'), error.message);
}
}
async generateAllureResult(result) {
if (!this.config.reporting || !this.config.reporting.allure)
return;
const resultsDir = this.config.reporting.allure.resultsDir || 'allure-results';
// Use Allure's expected file naming convention
const resultFile = path_1.default.join(resultsDir, `${result.id}-result.json`);
const allureResult = {
name: result.testId,
fullName: `${result.testId} - ${result.testId}`,
status: result.success ? 'passed' : 'failed',
statusDetails: {
message: result.errors?.join(', ') || '',
trace: result.errors?.join('\n') || ''
},
start: result.startTime.getTime(),
stop: result.endTime?.getTime() || Date.now(),
duration: result.duration || 0,
description: `Test execution for ${result.testId}`,
descriptionHtml: `<p>Test execution for ${result.testId}</p>`,
links: [],
labels: [
{ name: 'testId', value: result.testId },
{ name: 'sessionId', value: result.sessionId },
{ name: 'browser', value: result.browser || 'chrome' },
{ name: 'severity', value: this.config.reporting.allure.severity || 'normal' },
{ name: 'environment', value: this.config.reporting.allure.environment || 'default' },
{ name: 'framework', value: 'testgenius' },
{ name: 'language', value: 'javascript' }
],
parameters: [],
steps: result.steps?.map((step, index) => ({
name: step.description,
status: step.status === 'success' ? 'passed' : 'failed',
start: result.startTime.getTime() + (index * 1000),
stop: result.startTime.getTime() + ((index + 1) * 1000)
})) || []
};
// Add cost tracking data if enabled
if (this.config.costTracking?.enabled) {
await this.addCostTrackingData(allureResult, result);
}
// Add screenshots as separate steps if enabled
if (this.config.reporting.allure.attachments && result.screenshots.length > 0) {
for (const screenshot of result.screenshots) {
if (await fs_extra_1.default.pathExists(screenshot)) {
const attachmentName = path_1.default.basename(screenshot);
const attachmentPath = path_1.default.join(resultsDir, attachmentName);
await fs_extra_1.default.copy(screenshot, attachmentPath);
allureResult.steps.push({
name: `Screenshot captured: ${attachmentName}`,
status: 'passed',
start: result.startTime.getTime(),
stop: result.startTime.getTime() + 1000
});
}
}
}
await fs_extra_1.default.writeJson(resultFile, allureResult, { spaces: 2 });
}
/**
* Add cost tracking data to Allure result
*/
async addCostTrackingData(allureResult, result) {
try {
// Try to find cost data for this test
const costDataFile = path_1.default.join(process.cwd(), 'cost-data.json');
if (await fs_extra_1.default.pathExists(costDataFile)) {
const costData = await fs_extra_1.default.readJson(costDataFile);
const testCostData = costData.find(data => data.testId === result.testId && data.sessionId === result.sessionId);
if (testCostData) {
// Add cost information to labels
allureResult.labels.push({ name: 'cost', value: `$${testCostData.costMetrics.estimatedCost.toFixed(4)}` }, { name: 'model', value: testCostData.costMetrics.tokenUsage.model }, { name: 'tokens', value: testCostData.costMetrics.tokenUsage.totalTokens.toString() });
// Add cost details to description
const costDetails = `
<h4>Cost Analysis</h4>
<p><strong>Total Cost:</strong> $${testCostData.costMetrics.estimatedCost.toFixed(4)}</p>
<p><strong>Model:</strong> ${testCostData.costMetrics.tokenUsage.model}</p>
<p><strong>Tokens Used:</strong> ${testCostData.costMetrics.tokenUsage.totalTokens}</p>
<p><strong>Prompt Tokens:</strong> ${testCostData.costMetrics.tokenUsage.promptTokens}</p>
<p><strong>Completion Tokens:</strong> ${testCostData.costMetrics.tokenUsage.completionTokens}</p>
`;
allureResult.descriptionHtml += costDetails;
}
}
}
catch (error) {
console.warn(chalk_1.default.yellow('⚠️ Failed to add cost tracking data to Allure result:'), error.message);
}
}
/**
* Generate custom Allure widgets for cost tracking
*/
async generateCostTrackingWidgets(resultsDir) {
try {
const widgetsDir = path_1.default.join(resultsDir, 'widgets');
await fs_extra_1.default.ensureDir(widgetsDir);
// Generate cost summary widget
const costReport = await this.costTracker.generateCostReport();
// Enhanced cost summary widget with more details
const costSummaryWidget = {
name: 'cost-summary',
title: '💰 AI Testing Cost Summary',
type: 'text',
data: {
title: 'AI Testing Cost Analysis',
value: [
`📊 **Total Tests Executed:** ${costReport.totalTests}`,
`💵 **Total Cost:** $${costReport.totalCost.toFixed(4)}`,
`📈 **Average Cost per Test:** $${costReport.averageCostPerTest.toFixed(4)}`,
`🎯 **Potential Savings:** $${costReport.costSavings.toFixed(4)}`,
`📅 **Report Generated:** ${new Date().toLocaleString()}`,
`💡 **Cost Tracking Status:** ${costReport.totalCost > 0 ? 'Active' : 'No AI costs detected'}`
].join('\n\n')
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-summary.json'), costSummaryWidget, { spaces: 2 });
// Generate detailed cost breakdown widget
const costBreakdownWidget = {
name: 'cost-breakdown',
title: '📊 Cost Breakdown',
type: 'table',
data: {
title: 'Detailed Cost Analysis',
headers: ['Metric', 'Value', 'Details'],
rows: [
['Total Tests', costReport.totalTests.toString(), 'All executed tests'],
['Successful Tests', costReport.topExpensiveTests.filter(t => t.success).length.toString(), 'Tests that passed'],
['Failed Tests', costReport.topExpensiveTests.filter(t => !t.success).length.toString(), 'Tests that failed'],
['Total Cost', `$${costReport.totalCost.toFixed(4)}`, 'Sum of all test costs'],
['Average Cost', `$${costReport.averageCostPerTest.toFixed(4)}`, 'Cost per individual test'],
['Cost per Success', costReport.topExpensiveTests.filter(t => t.success).length > 0 ?
`$${(costReport.totalCost / costReport.topExpensiveTests.filter(t => t.success).length).toFixed(4)}` : '$0.0000', 'Cost per successful test'],
['Potential Savings', `$${costReport.costSavings.toFixed(4)}`, 'Estimated savings from optimization']
]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-breakdown.json'), costBreakdownWidget, { spaces: 2 });
// Generate cost trend widget
const costTrendWidget = {
name: 'cost-trend',
title: '📈 Cost Trend Analysis',
type: 'line-chart',
data: {
title: 'Daily Cost Trend',
series: [{
name: 'Daily Cost',
data: costReport.costTrend.map(item => ({
x: item.date,
y: item.cost
}))
}]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-trend.json'), costTrendWidget, { spaces: 2 });
// Generate cost trend bar chart
const costTrendBarWidget = {
name: 'cost-trend-bar',
title: '📊 Cost Trend (Bar Chart)',
type: 'bar-chart',
data: {
title: 'Daily Cost Distribution',
series: [{
name: 'Daily Cost',
data: costReport.costTrend.map(item => ({
x: item.date,
y: item.cost
}))
}]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-trend-bar.json'), costTrendBarWidget, { spaces: 2 });
// Generate cost vs tests line chart
const costVsTestsWidget = {
name: 'cost-vs-tests',
title: '📈 Cost vs Tests Correlation',
type: 'line-chart',
data: {
title: 'Cost vs Number of Tests',
series: [
{
name: 'Daily Cost',
data: costReport.costTrend.map(item => ({
x: item.date,
y: item.cost
}))
},
{
name: 'Number of Tests',
data: costReport.costTrend.map(item => ({
x: item.date,
y: item.tests
}))
}
]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-vs-tests.json'), costVsTestsWidget, { spaces: 2 });
// Generate cost by category pie chart
const costByCategoryWidget = {
name: 'cost-by-category',
title: '📋 Cost by Category',
type: 'pie-chart',
data: {
title: 'Cost Distribution by Model',
series: costReport.costByCategory.map(category => ({
name: category.category,
value: category.cost,
tests: category.tests
}))
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-by-category.json'), costByCategoryWidget, { spaces: 2 });
// Generate cost by category bar chart
const costByCategoryBarWidget = {
name: 'cost-by-category-bar',
title: '📊 Cost by Category (Bar Chart)',
type: 'bar-chart',
data: {
title: 'Cost Distribution by Model',
series: [{
name: 'Cost by Model',
data: costReport.costByCategory.map(category => ({
x: category.category,
y: category.cost
}))
}]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-by-category-bar.json'), costByCategoryBarWidget, { spaces: 2 });
// Generate tests by category bar chart
const testsByCategoryWidget = {
name: 'tests-by-category',
title: '📊 Tests by Category',
type: 'bar-chart',
data: {
title: 'Number of Tests by Model',
series: [{
name: 'Tests by Model',
data: costReport.costByCategory.map(category => ({
x: category.category,
y: category.tests
}))
}]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'tests-by-category.json'), testsByCategoryWidget, { spaces: 2 });
// Generate expensive tests bar chart
const expensiveTestsBarWidget = {
name: 'expensive-tests-bar',
title: '🏆 Most Expensive Tests (Bar Chart)',
type: 'bar-chart',
data: {
title: 'Top 10 Most Expensive Tests',
series: [{
name: 'Test Cost',
data: costReport.topExpensiveTests.slice(0, 10).map(test => ({
x: test.testId,
y: test.costMetrics.estimatedCost
}))
}]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'expensive-tests-bar.json'), expensiveTestsBarWidget, { spaces: 2 });
// Generate success vs failure cost pie chart
const successFailureCostWidget = {
name: 'success-failure-cost',
title: '✅❌ Success vs Failure Cost',
type: 'pie-chart',
data: {
title: 'Cost Distribution by Test Status',
series: [
{
name: 'Successful Tests',
value: costReport.topExpensiveTests.filter(t => t.success).reduce((sum, test) => sum + test.costMetrics.estimatedCost, 0)
},
{
name: 'Failed Tests',
value: costReport.topExpensiveTests.filter(t => !t.success).reduce((sum, test) => sum + test.costMetrics.estimatedCost, 0)
}
]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'success-failure-cost.json'), successFailureCostWidget, { spaces: 2 });
// Generate cost efficiency area chart
const costEfficiencyAreaWidget = {
name: 'cost-efficiency-area',
title: '⚡ Cost Efficiency Over Time',
type: 'area-chart',
data: {
title: 'Cost Efficiency Trend',
series: [
{
name: 'Cost per Test',
data: costReport.costTrend.map(item => ({
x: item.date,
y: item.tests > 0 ? item.cost / item.tests : 0
}))
}
]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-efficiency-area.json'), costEfficiencyAreaWidget, { spaces: 2 });
// Generate token usage distribution pie chart
const tokenUsageWidget = {
name: 'token-usage-distribution',
title: '🔤 Token Usage Distribution',
type: 'pie-chart',
data: {
title: 'Token Usage by Type',
series: [
{
name: 'Prompt Tokens',
value: costReport.topExpensiveTests.reduce((sum, test) => sum + test.costMetrics.tokenUsage.promptTokens, 0)
},
{
name: 'Completion Tokens',
value: costReport.topExpensiveTests.reduce((sum, test) => sum + test.costMetrics.tokenUsage.completionTokens, 0)
}
]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'token-usage-distribution.json'), tokenUsageWidget, { spaces: 2 });
// Generate cost savings potential bar chart
const costSavingsWidget = {
name: 'cost-savings-potential',
title: '💰 Cost Savings Potential',
type: 'bar-chart',
data: {
title: 'Potential Cost Savings by Optimization',
series: [
{
name: 'Current Cost',
data: [{
x: 'Current',
y: costReport.totalCost
}]
},
{
name: 'Potential Savings',
data: [{
x: 'Savings',
y: costReport.costSavings
}]
}
]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-savings-potential.json'), costSavingsWidget, { spaces: 2 });
// Generate monthly cost projection line chart
const monthlyProjectionWidget = {
name: 'monthly-cost-projection',
title: '📅 Monthly Cost Projection',
type: 'line-chart',
data: {
title: 'Projected Monthly Costs',
series: [
{
name: 'Current Month',
data: costReport.costTrend.slice(-30).map(item => ({
x: item.date,
y: item.cost
}))
},
{
name: 'Projected (30 days)',
data: costReport.costTrend.slice(-30).map((item, index) => ({
x: new Date(new Date(item.date).getTime() + (index + 1) * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
y: item.cost * 1.1 // 10% growth projection
}))
}
]
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'monthly-cost-projection.json'), monthlyProjectionWidget, { spaces: 2 });
// Generate optimization recommendations widget
const optimizationWidget = {
name: 'optimization-recommendations',
title: '🚀 Cost Optimization',
type: 'text',
data: {
title: 'Optimization Recommendations',
value: costReport.optimizationRecommendations.length > 0
? costReport.optimizationRecommendations.map((rec, index) => `${index + 1}. ${rec}`).join('\n\n')
: '✅ No optimization recommendations at this time. Your test costs are already optimized!'
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'optimization-recommendations.json'), optimizationWidget, { spaces: 2 });
// Generate expensive tests table widget
const expensiveTestsWidget = {
name: 'expensive-tests',
title: '🏆 Most Expensive Tests',
type: 'table',
data: {
title: 'Top 10 Most Expensive Tests',
headers: ['Test ID', 'Cost', 'Model', 'Tokens', 'Status', 'Duration'],
rows: costReport.topExpensiveTests.map(test => [
test.testId,
`$${test.costMetrics.estimatedCost.toFixed(4)}`,
test.costMetrics.tokenUsage.model,
test.costMetrics.tokenUsage.totalTokens.toString(),
test.success ? '✅ Passed' : '❌ Failed',
`${test.executionTime}ms`
])
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'expensive-tests.json'), expensiveTestsWidget, { spaces: 2 });
// Generate cost efficiency widget
const costEfficiencyWidget = {
name: 'cost-efficiency',
title: '⚡ Cost Efficiency',
type: 'text',
data: {
title: 'Cost Efficiency Analysis',
value: [
`**Cost per Successful Test:** $${costReport.topExpensiveTests.filter(t => t.success).length > 0 ?
(costReport.totalCost / costReport.topExpensiveTests.filter(t => t.success).length).toFixed(4) : '0.0000'}`,
`**Success Rate:** ${((costReport.topExpensiveTests.filter(t => t.success).length / costReport.totalTests) * 100).toFixed(1)}%`,
`**Failed Test Cost:** $${costReport.topExpensiveTests.filter(t => !t.success).reduce((sum, test) => sum + test.costMetrics.estimatedCost, 0).toFixed(4)}`,
`**Cost Optimization Score:** ${costReport.costSavings > 0 ? '🟡 Needs Optimization' : '🟢 Optimized'}`
].join('\n\n')
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-efficiency.json'), costEfficiencyWidget, { spaces: 2 });
// Generate comprehensive dashboard widget
const dashboardWidget = {
name: 'cost-dashboard',
title: '📊 Cost Analysis Dashboard',
type: 'text',
data: {
title: 'AI Testing Cost Dashboard',
value: [
`## 📈 **Executive Summary**`,
`**Total Investment:** $${costReport.totalCost.toFixed(4)}`,
`**Tests Executed:** ${costReport.totalTests}`,
`**Average ROI per Test:** $${costReport.averageCostPerTest.toFixed(4)}`,
`**Potential Savings:** $${costReport.costSavings.toFixed(4)}`,
``,
`## 🎯 **Key Metrics**`,
`**Success Rate:** ${((costReport.topExpensiveTests.filter(t => t.success).length / costReport.totalTests) * 100).toFixed(1)}%`,
`**Cost per Success:** $${costReport.topExpensiveTests.filter(t => t.success).length > 0 ?
(costReport.totalCost / costReport.topExpensiveTests.filter(t => t.success).length).toFixed(4) : '0.0000'}`,
`**Failed Test Waste:** $${costReport.topExpensiveTests.filter(t => !t.success).reduce((sum, test) => sum + test.costMetrics.estimatedCost, 0).toFixed(4)}`,
``,
`## 🚀 **Optimization Status**`,
`${costReport.costSavings > 0 ? '🟡 **Optimization Needed** - ' + costReport.optimizationRecommendations.length + ' recommendations available' : '🟢 **Fully Optimized** - No further optimization needed'}`,
``,
`## 📅 **Report Generated**`,
`**Date:** ${new Date().toLocaleString()}`,
`**Cost Tracking:** ${costReport.totalCost > 0 ? '✅ Active' : '⚠️ No AI costs detected'}`
].join('\n\n')
}
};
await fs_extra_1.default.writeJson(path_1.default.join(widgetsDir, 'cost-dashboard.json'), dashboardWidget, { spaces: 2 });
console.log(chalk_1.default.blue('💰 Enhanced cost tracking widgets with graphs generated for Allure report'));
}
catch (error) {
console.error(chalk_1.default.red('❌ Failed to generate cost tracking widgets:'), error.message);
}
}
async generateAllureReportFromResults() {
if (!this.config.reporting || !this.config.reporting.allure)
return;
const resultsDir = this.config.reporting.allure.resultsDir || 'allure-results';
const reportDir = this.config.reporting.allure.reportDir || 'allure-report';
// Ensure report directory exists
await fs_extra_1.default.ensureDir(reportDir);
try {
// Run Allure command to generate report
const command = `npx allure generate "${resultsDir}" --clean --output "${reportDir}"`;
(0, child_process_1.execSync)(command, { stdio: 'pipe' });
}
catch (error) {
console.error(chalk_1.default.red('❌ Allure command failed:'), error.message);
throw error;
}
}
async openAllureReport() {
if (!this.config.reporting || !this.config.reporting.allure || !this.config.reporting.allure.enabled) {
console.log(chalk_1.default.yellow('⚠️ Allure reporting is disabled in configuration'));
return;
}
const reportDir = this.config.reporting.allure.reportDir || 'allure-report';
if (!(await fs_extra_1.default.pathExists(reportDir))) {
console.log(chalk_1.default.yellow('⚠️ Allure report not found. Run tests first with --allure option.'));
return;
}
try {
console.log(chalk_1.default.blue('🌐 Opening Allure report...'));
// Open Allure report in browser
const { default: open } = await Promise.resolve().then(() => __importStar(require('open')));
const indexFile = path_1.default.join(reportDir, 'index.html');
if (await fs_extra_1.default.pathExists(indexFile)) {
await open(indexFile);
console.log(chalk_1.default.green('✅ Allure report opened in browser!'));
}
else {
console.log(chalk_1.default.yellow('⚠️ Allure report index.html not found'));
}
}
catch (error) {
console.error(chalk_1.default.red('❌ Failed to open Allure report:'), error.message);
}
}
async serveAllureReport(port = 8080) {
if (!this.config.reporting || !this.config.reporting.allure || !this.config.reporting.allure.enabled) {
console.log(chalk_1.default.yellow('⚠️ Allure reporting is disabled in configuration'));
return;
}
const reportDir = this.config.reporting.allure.reportDir || 'allure-report';
if (!(await fs_extra_1.default.pathExists(reportDir))) {
console.log(chalk_1.default.yellow('⚠️ Allure report not found. Run tests first with --allure option.'));
return;
}
try {
console.log(chalk_1.default.blue(`🌐 Serving Allure report on port ${port}...`));
// Serve Allure report
const command = `npx allure open --port ${port} "${reportDir}"`;
(0, child_process_1.execSync)(command, { stdio: 'inherit' });
}
catch (error) {
console.error(chalk_1.default.red('❌ Failed to serve Allure report:'), error.message);
}
}
async serveAllureLive() {
if (!this.config.reporting || !this.config.reporting.allure || !this.config.reporting.allure.enabled) {
console.log(chalk_1.default.yellow('⚠️ Allure reporting is disabled in configuration'));
return;
}
const resultsDir = this.config.reporting.allure.resultsDir || 'allure-results';
try {
console.log(chalk_1.default.blue('🌐 Serving Allure report live (npx allure serve)...'));
const { spawn } = require('child_process');
const serve = spawn('npx', ['allure', 'serve', resultsDir], { stdio: 'inherit' });
serve.on('close', (code) => {
if (code !== 0) {
console.error(chalk_1.default.red(`❌ Allure serve exited with code ${code}`));
}
});
}
catch (error) {
console.error(chalk_1.default.red('❌ Failed to serve Allure report live:'), error.message);
}
}
async generateCostSummaryFile(resultsDir) {
try {
const summaryFile = path_1.default.join(resultsDir, 'cost-summary.json');
const costReport = await this.costTracker.generateCostReport();
const summaryData = {
title: 'AI Testing Cost Analysis',
value: [
`📊 **Total Tests Executed:** ${costReport.totalTests}`,
`💵 **Total Cost:** $${costReport.totalCost.toFixed(4)}`,
`📈 **Average Cost per Test:** $${costReport.averageCostPerTest.toFixed(4)}`,
`🎯 **Potential Savings:** $${costReport.costSavings.toFixed(4)}`,
`📅 **Report Generated:** ${new Date().toLocaleString()}`,
`💡 **Cost Tracking Status:** ${costReport.totalCost > 0 ? 'Active' : 'No AI costs detected'}`
].join('\n\n')
};
await fs_extra_1.default.writeJson(summaryFile, summaryData, { spaces: 2 });
console.log(chalk_1.default.blue('💰 Cost summary file generated for Allure report'));
}
catch (error) {
console.error(chalk_1.default.red('❌ Failed to generate cost summary file:'), error.message);
}
}
}
exports.AllureReporter = AllureReporter;
//# sourceMappingURL=AllureReporter.js.map