import * as fs from 'fs'; import * as path from 'path'; import { jsonReportFilePath, reportFilePath } from '../../playwright.config'; interface PageSummary { pageName: string; critical: number; serious: number; moderate: number; minor: number; total: number; } export function updateAccessibilityReport(pageName: string, results: any) { const reportDir = path.dirname(jsonReportFilePath); if (!fs.existsSync(reportDir)) { fs.mkdirSync(reportDir, { recursive: true }); } let existingIssues: { [key: string]: any[] } = {}; if (fs.existsSync(jsonReportFilePath)) { existingIssues = JSON.parse(fs.readFileSync(jsonReportFilePath, 'utf-8')); } if (!existingIssues[pageName]) { existingIssues[pageName] = []; } results.violations.forEach(violation => { const violationWithPage = { ...violation, pageName }; if (!isDuplicateIssue(existingIssues[pageName], violationWithPage)) { existingIssues[pageName].push(violationWithPage); } }); fs.writeFileSync(jsonReportFilePath, JSON.stringify(existingIssues, null, 2)); } export function consolidateJsonReport() { if (!fs.existsSync(jsonReportFilePath)) { console.error('JSON report file does not exist.'); return; } const existingIssues = JSON.parse(fs.readFileSync(jsonReportFilePath, 'utf-8')); // Consolidate issues by page const consolidatedIssues: { [key: string]: any[] } = {}; Object.keys(existingIssues).forEach(pageName => { if (!consolidatedIssues[pageName]) { consolidatedIssues[pageName] = []; } existingIssues[pageName].forEach(issue => { if (!isDuplicateIssue(consolidatedIssues[pageName], issue)) { consolidatedIssues[pageName].push(issue); } }); }); fs.writeFileSync(jsonReportFilePath, JSON.stringify(consolidatedIssues, null, 2)); } function generateSummaryTable(existingIssues: { [key: string]: any[] }): string { let totalCritical = 0; let totalSerious = 0; let totalModerate = 0; let totalMinor = 0; let totalTotal = 0; Object.keys(existingIssues).forEach(pageName => { const issues = existingIssues[pageName]; totalCritical += issues.filter(issue => issue.impact === 'critical').length; totalSerious += issues.filter(issue => issue.impact === 'serious').length; totalModerate += issues.filter(issue => issue.impact === 'moderate').length; totalMinor += issues.filter(issue => issue.impact === 'minor').length; totalTotal += issues.length; }); return ` ${Object.keys(existingIssues).map(pageName => { const issues = existingIssues[pageName]; const critical = issues.filter(issue => issue.impact === 'critical').length; const serious = issues.filter(issue => issue.impact === 'serious').length; const moderate = issues.filter(issue => issue.impact === 'moderate').length; const minor = issues.filter(issue => issue.impact === 'minor').length; const total = issues.length; return ` `; }).join('')}
Page Name Critical Serious Moderate Minor Total
${pageName} ${critical} ${serious} ${moderate} ${minor} ${total}
Total ${totalCritical} ${totalSerious} ${totalModerate} ${totalMinor} ${totalTotal}
`; } function generateImpactSections(issues: any[], pageName: string): string { return ['critical', 'serious', 'moderate', 'minor'].map(impactType => { const violations = issues.filter(issue => issue.impact === impactType); if (violations.length === 0) return ''; return `

${impactType.charAt(0).toUpperCase() + impactType.slice(1)} Impact

${violations.map(violation => ` `).join('')}
Impact Description Help URL Tags Nodes
${violation.impact} ${violation.description} ${violation.helpUrl} ${violation.tags.join(', ')} ${violation.nodes.map(node => `
${node.html}
Target: ${node.target.join(', ')}
${node.failureSummary}
Any: ${node.any.map(check => `
${check.message}
`).join('')}
All: ${node.all.map(check => `
${check.message}
`).join('')}
None: ${node.none.map(check => `
${check.message}
`).join('')}
`).join('')}
`; }).join(''); } function generateDetailedSections(existingIssues: { [key: string]: any[] }): string { return Object.keys(existingIssues).map(pageName => { const issues = existingIssues[pageName]; const impactSections = generateImpactSections(issues, pageName); return `

${pageName}

${impactSections}
`; }).join(''); } export function createAccessibilityHtmlReport() { consolidateJsonReport(); if (!fs.existsSync(jsonReportFilePath)) { console.error('JSON report file does not exist.'); return; } const existingIssues = JSON.parse(fs.readFileSync(jsonReportFilePath, 'utf-8')); const inlineStyles = ` body { font-family: Arial, sans-serif; background-color: #f4f4f4; color: #333; } h1 { text-align: center; color: #4CAF50; } .summary-table { width: 100%; border-collapse: collapse; margin-top: 20px; } .summary-table th, .summary-table td { padding: 10px; border: 1px solid #ddd; text-align: left; } .summary-table th { background-color: #007BFF; color: white; } .summary-table td a { color: #007BFF; text-decoration: none; } .summary-table td a:hover { text-decoration: underline; } .page-section { margin-bottom: 40px; padding: 20px; background-color: #fff; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } .impact-section { margin-bottom: 20px; } .violation { margin-bottom: 20px; } .violation .impact { font-weight: bold; color: #d9534f; } .violation .description { margin-top: 5px; } .violation .helpUrl { margin-top: 5px; } .violation .tags { margin-top: 5px; } .violation .nodes { margin-top: 10px; } .violation .node { margin-top: 5px; } .collapsible { background-color: #f9f9f9; color: #333; cursor: pointer; padding: 10px; width: 100%; border: none; text-align: left; outline: none; font-size: 15px; } .active, .collapsible:hover { background-color: #ccc; } .content { padding: 0 18px; display: none; overflow: hidden; background-color: #f1f1f1; } table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { padding: 10px; border: 1px solid #ddd; text-align: left; } tfoot { font-weight: bold; } `; let reportContent = ` ISS Accessibility Report

Accessibility Report

`; reportContent += generateSummaryTable(existingIssues); reportContent += generateDetailedSections(existingIssues); reportContent += ` `; try { fs.writeFileSync(reportFilePath, reportContent); console.log(`Accessibility Report generated successfully at ${reportFilePath}`); } catch (error) { console.error('Error writing report file:', error); } } function isDuplicateIssue(existingIssues: any[], newIssue: any): boolean { return existingIssues.some(issue => { return issue.id === newIssue.id && issue.pageName === newIssue.pageName; }); }