@casoon/auditmysite
Version:
Professional website analysis suite with robust accessibility testing, Core Web Vitals performance monitoring, SEO analysis, and content optimization insights. Features isolated browser contexts, retry mechanisms, and comprehensive API endpoints for profe
256 lines • 11.9 kB
JavaScript
;
/**
* 🎯 Unified Report Data Exporter
*
* Converts legacy report data structures to the new unified format.
* This ensures all report generators use the same standardized data.
*/
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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.UnifiedReportExporter = void 0;
const report_export_1 = require("../types/report-export");
class UnifiedReportExporter {
constructor(version = '1.8.8') {
this.version = version;
}
/**
* Convert legacy TestSummary and results to unified format
*/
exportUnified(testSummary, metadata, options) {
const startTime = Date.now();
// Extract domain from first result
const domain = this.extractDomain(testSummary.results);
const reportMetadata = this.buildMetadata(domain, metadata, options, startTime);
const summary = this.buildSummary(testSummary);
const pages = this.buildPageResults(testSummary.results);
const recommendations = this.buildRecommendations(testSummary, pages);
const export_data = {
metadata: reportMetadata,
summary,
pages,
recommendations
};
// Validate the export
if (!report_export_1.ReportExportValidator.validateExport(export_data)) {
console.warn('⚠️ Generated export data failed validation');
}
return export_data;
}
extractDomain(results) {
if (results.length === 0)
return 'unknown';
try {
return new URL(results[0].url).hostname;
}
catch {
return 'unknown';
}
}
buildMetadata(domain, metadata, options, startTime) {
return {
timestamp: metadata?.timestamp || new Date().toISOString(),
version: this.version,
duration: Date.now() - startTime,
domain,
sourceUrl: metadata?.sitemapUrl,
config: {
maxPages: options?.maxPages || 50,
timeout: options?.timeout || 10000,
pa11yStandard: options?.pa11yStandard || 'WCAG2AA',
collectPerformanceMetrics: Boolean(options?.collectPerformanceMetrics),
captureScreenshots: Boolean(options?.captureScreenshots),
testKeyboardNavigation: Boolean(options?.testKeyboardNavigation),
testColorContrast: Boolean(options?.testColorContrast),
testFocusManagement: Boolean(options?.testFocusManagement)
}
};
}
buildSummary(testSummary) {
const successRate = testSummary.testedPages > 0
? Math.round((testSummary.passedPages / testSummary.testedPages) * 100)
: 0;
// Calculate average accessibility score
const scoresWithValues = testSummary.results
.map(r => r.pa11yScore)
.filter(score => score !== undefined && score !== null && !isNaN(score));
const avgAccessibilityScore = scoresWithValues.length > 0
? Math.round(scoresWithValues.reduce((sum, score) => sum + score, 0) / scoresWithValues.length)
: 0;
// Calculate average performance score if available
const performanceResults = testSummary.results.filter(r => r.performanceMetrics);
const avgPerformanceScore = performanceResults.length > 0
? Math.round(performanceResults.reduce((sum, r) => {
// Simple performance score based on load time (lower is better)
const loadTime = r.performanceMetrics.loadTime;
return sum + Math.max(0, 100 - Math.round(loadTime / 100));
}, 0) / performanceResults.length)
: undefined;
return {
totalPages: testSummary.totalPages,
testedPages: testSummary.testedPages,
passedPages: testSummary.passedPages,
failedPages: testSummary.failedPages,
crashedPages: testSummary.crashedPages || 0,
totalErrors: testSummary.totalErrors,
totalWarnings: testSummary.totalWarnings,
totalDuration: testSummary.totalDuration,
successRate,
avgAccessibilityScore,
avgPerformanceScore
};
}
buildPageResults(results) {
return results.map(result => {
const status = result.crashed ? 'crashed' : (result.passed ? 'passed' : 'failed');
return {
url: result.url,
title: result.title,
status,
passed: result.passed,
crashed: result.crashed,
duration: result.duration,
errors: result.errors,
warnings: result.warnings,
issues: {
pa11yScore: result.pa11yScore,
pa11yIssues: result.pa11yIssues?.map((issue) => ({
code: issue.code,
type: issue.type,
impact: issue.impact,
message: issue.message,
selector: issue.selector,
context: issue.context,
help: issue.help,
helpUrl: issue.helpUrl
})),
headingsCount: result.headingsCount,
imagesWithoutAlt: result.imagesWithoutAlt,
buttonsWithoutLabel: result.buttonsWithoutLabel,
keyboardNavigation: result.keyboardNavigation,
colorContrastIssues: result.colorContrastIssues,
focusManagementIssues: result.focusManagementIssues
},
performanceMetrics: result.performanceMetrics ? {
loadTime: result.performanceMetrics.loadTime,
domContentLoaded: result.performanceMetrics.domContentLoaded,
firstPaint: result.performanceMetrics.firstPaint,
firstContentfulPaint: result.performanceMetrics.firstContentfulPaint,
largestContentfulPaint: result.performanceMetrics.largestContentfulPaint,
timeToInteractive: result.performanceMetrics.interactionToNextPaint,
cumulativeLayoutShift: result.performanceMetrics.cumulativeLayoutShift,
memoryUsage: undefined // Not available in current performance metrics
} : undefined,
screenshots: result.screenshots
};
});
}
buildRecommendations(testSummary, pages) {
const recommendations = [];
// Accessibility recommendations
if (testSummary.totalErrors > 0) {
recommendations.push({
category: 'accessibility',
priority: testSummary.totalErrors > 50 ? 'critical' : 'high',
title: 'Fix Accessibility Errors',
description: `Found ${testSummary.totalErrors} accessibility errors across ${testSummary.failedPages} pages that need immediate attention.`,
affectedPages: testSummary.failedPages,
impact: 'Improves user experience for people with disabilities and ensures legal compliance.',
actionSteps: [
'Review and fix critical accessibility errors first',
'Ensure proper heading structure and alt text for images',
'Test with screen readers and keyboard navigation',
'Validate color contrast ratios meet WCAG standards'
]
});
}
// Performance recommendations
const slowPages = pages.filter(p => p.performanceMetrics && p.performanceMetrics.loadTime > 3000);
if (slowPages.length > 0) {
recommendations.push({
category: 'performance',
priority: slowPages.length > testSummary.testedPages / 2 ? 'high' : 'medium',
title: 'Optimize Page Performance',
description: `${slowPages.length} pages have load times exceeding 3 seconds, which negatively impacts user experience.`,
affectedPages: slowPages.length,
impact: 'Faster loading pages improve user satisfaction and search engine rankings.',
actionSteps: [
'Optimize images and use modern formats (WebP, AVIF)',
'Minimize and compress CSS and JavaScript files',
'Implement lazy loading for images and content',
'Use a Content Delivery Network (CDN)',
'Optimize server response times'
]
});
}
// SEO recommendations
const pagesWithoutTitles = pages.filter(p => !p.title || p.title.trim() === '');
if (pagesWithoutTitles.length > 0) {
recommendations.push({
category: 'seo',
priority: 'medium',
title: 'Add Missing Page Titles',
description: `${pagesWithoutTitles.length} pages are missing titles, which hurts search engine optimization.`,
affectedPages: pagesWithoutTitles.length,
impact: 'Proper page titles improve search engine visibility and click-through rates.',
actionSteps: [
'Add unique, descriptive titles to each page',
'Keep titles under 60 characters',
'Include relevant keywords naturally',
'Make titles compelling for users'
]
});
}
return recommendations;
}
/**
* Export as JSON string with optional formatting
*/
exportAsJson(testSummary, metadata, options, pretty = true) {
const data = this.exportUnified(testSummary, metadata, options);
return JSON.stringify(data, null, pretty ? 2 : 0);
}
/**
* Save JSON export to file
*/
async saveJsonExport(testSummary, outputPath, metadata, options) {
const fs = await Promise.resolve().then(() => __importStar(require('fs/promises')));
const jsonData = this.exportAsJson(testSummary, metadata, options);
await fs.writeFile(outputPath, jsonData, 'utf8');
console.log(`📄 JSON export saved: ${outputPath}`);
return outputPath;
}
}
exports.UnifiedReportExporter = UnifiedReportExporter;
//# sourceMappingURL=unified-export.js.map