213 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
/**
 | 
						|
 * Generate a comprehensive accessibility report
 | 
						|
 * This script analyzes the axe-core and Pa11y test results and generates a report
 | 
						|
 * of all accessibility issues that need to be fixed
 | 
						|
 */
 | 
						|
 | 
						|
const fs = require('fs');
 | 
						|
const path = require('path');
 | 
						|
 | 
						|
// Directory containing test reports
 | 
						|
const reportsDir = path.join(__dirname, '../reports');
 | 
						|
 | 
						|
// Output report file
 | 
						|
const outputFile = path.join(reportsDir, 'accessibility-issues.md');
 | 
						|
 | 
						|
// Get all axe-core report files
 | 
						|
const axeReports = fs.readdirSync(reportsDir)
 | 
						|
  .filter(file => file.startsWith('axe-') && file.endsWith('.json'))
 | 
						|
  .map(file => {
 | 
						|
    try {
 | 
						|
      const content = fs.readFileSync(path.join(reportsDir, file), 'utf8');
 | 
						|
      return { file, content: JSON.parse(content) };
 | 
						|
    } catch (error) {
 | 
						|
      console.error(`Error reading ${file}:`, error.message);
 | 
						|
      return { file, content: null };
 | 
						|
    }
 | 
						|
  })
 | 
						|
  .filter(report => report.content !== null);
 | 
						|
 | 
						|
// Get all Pa11y report files
 | 
						|
const pa11yReports = fs.readdirSync(reportsDir)
 | 
						|
  .filter(file => file.startsWith('pa11y') && file.endsWith('.json') && !file.includes('summary'))
 | 
						|
  .map(file => {
 | 
						|
    try {
 | 
						|
      const content = fs.readFileSync(path.join(reportsDir, file), 'utf8');
 | 
						|
      return { file, content: JSON.parse(content) };
 | 
						|
    } catch (error) {
 | 
						|
      console.error(`Error reading ${file}:`, error.message);
 | 
						|
      return { file, content: null };
 | 
						|
    }
 | 
						|
  })
 | 
						|
  .filter(report => report.content !== null);
 | 
						|
 | 
						|
// Generate report
 | 
						|
let report = `# Accessibility Issues Report
 | 
						|
Generated on: ${new Date().toISOString()}
 | 
						|
 | 
						|
This report lists all accessibility issues found by automated testing tools.
 | 
						|
Fixing these issues will help achieve WCAG 2.1 AAA compliance.
 | 
						|
 | 
						|
## Summary
 | 
						|
 | 
						|
`;
 | 
						|
 | 
						|
// Process axe-core reports
 | 
						|
const axeIssues = [];
 | 
						|
axeReports.forEach(report => {
 | 
						|
  if (report.content && report.content.violations) {
 | 
						|
    report.content.violations.forEach(violation => {
 | 
						|
      violation.nodes.forEach(node => {
 | 
						|
        axeIssues.push({
 | 
						|
          page: report.file.replace('axe-', '').replace('.json', ''),
 | 
						|
          id: violation.id,
 | 
						|
          impact: violation.impact,
 | 
						|
          description: violation.description,
 | 
						|
          help: violation.help,
 | 
						|
          helpUrl: violation.helpUrl,
 | 
						|
          element: node.html || node.target?.join(', ') || 'Unknown element',
 | 
						|
          wcag: violation.tags.filter(t => t.startsWith('wcag')).join(', ')
 | 
						|
        });
 | 
						|
      });
 | 
						|
    });
 | 
						|
  }
 | 
						|
});
 | 
						|
 | 
						|
// Process Pa11y reports
 | 
						|
const pa11yIssues = [];
 | 
						|
pa11yReports.forEach(report => {
 | 
						|
  if (report.content && report.content.issues) {
 | 
						|
    report.content.issues.forEach(issue => {
 | 
						|
      pa11yIssues.push({
 | 
						|
        page: report.file.replace('pa11y', '').replace('.json', ''),
 | 
						|
        code: issue.code,
 | 
						|
        type: issue.type,
 | 
						|
        message: issue.message,
 | 
						|
        context: issue.context,
 | 
						|
        selector: issue.selector
 | 
						|
      });
 | 
						|
    });
 | 
						|
  }
 | 
						|
});
 | 
						|
 | 
						|
// Add summary counts to report
 | 
						|
report += `- Total pages tested: ${axeReports.length}
 | 
						|
- Pages with axe-core issues: ${axeReports.filter(r => r.content?.violations?.length > 0).length}
 | 
						|
- Total axe-core issues: ${axeIssues.length}
 | 
						|
- Pages with Pa11y issues: ${pa11yReports.filter(r => r.content?.issues?.length > 0).length}
 | 
						|
- Total Pa11y issues: ${pa11yIssues.length}
 | 
						|
 | 
						|
## Common Issues
 | 
						|
 | 
						|
`;
 | 
						|
 | 
						|
// Group issues by type
 | 
						|
const issuesByType = {};
 | 
						|
axeIssues.forEach(issue => {
 | 
						|
  if (!issuesByType[issue.id]) {
 | 
						|
    issuesByType[issue.id] = {
 | 
						|
      count: 0,
 | 
						|
      description: issue.description,
 | 
						|
      help: issue.help,
 | 
						|
      helpUrl: issue.helpUrl,
 | 
						|
      wcag: issue.wcag,
 | 
						|
      pages: new Set()
 | 
						|
    };
 | 
						|
  }
 | 
						|
  issuesByType[issue.id].count++;
 | 
						|
  issuesByType[issue.id].pages.add(issue.page);
 | 
						|
});
 | 
						|
 | 
						|
// Sort issues by count
 | 
						|
const sortedIssues = Object.entries(issuesByType)
 | 
						|
  .sort((a, b) => b[1].count - a[1].count);
 | 
						|
 | 
						|
// Add common issues to report
 | 
						|
sortedIssues.forEach(([id, info]) => {
 | 
						|
  report += `### ${id} (${info.count} occurrences)
 | 
						|
 | 
						|
- **Description**: ${info.description}
 | 
						|
- **Help**: ${info.help}
 | 
						|
- **WCAG**: ${info.wcag}
 | 
						|
- **Pages affected**: ${Array.from(info.pages).join(', ')}
 | 
						|
- **More info**: ${info.helpUrl}
 | 
						|
 | 
						|
`;
 | 
						|
});
 | 
						|
 | 
						|
// Add detailed issues by page
 | 
						|
report += `## Issues by Page
 | 
						|
 | 
						|
`;
 | 
						|
 | 
						|
// Group issues by page
 | 
						|
const issuesByPage = {};
 | 
						|
axeIssues.forEach(issue => {
 | 
						|
  if (!issuesByPage[issue.page]) {
 | 
						|
    issuesByPage[issue.page] = [];
 | 
						|
  }
 | 
						|
  issuesByPage[issue.page].push(issue);
 | 
						|
});
 | 
						|
 | 
						|
// Add page-specific issues to report
 | 
						|
Object.entries(issuesByPage).forEach(([page, issues]) => {
 | 
						|
  report += `### ${page}
 | 
						|
 | 
						|
`;
 | 
						|
  issues.forEach(issue => {
 | 
						|
    report += `- **${issue.id}** (${issue.impact}): ${issue.help}
 | 
						|
  - Element: \`${issue.element.substring(0, 100)}${issue.element.length > 100 ? '...' : ''}\`
 | 
						|
  - WCAG: ${issue.wcag}
 | 
						|
 | 
						|
`;
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
// Add recommended fixes
 | 
						|
report += `## Recommended Fixes
 | 
						|
 | 
						|
Based on the issues found, here are the recommended fixes:
 | 
						|
 | 
						|
`;
 | 
						|
 | 
						|
// Add specific recommendations for common issues
 | 
						|
if (issuesByType['color-contrast-enhanced']) {
 | 
						|
  report += `### Color Contrast Issues
 | 
						|
 | 
						|
1. Update link colors to meet 7:1 contrast ratio:
 | 
						|
   - Current blue link color (#0056b3) on light background (#f5f5f5) has 6.45:1 ratio
 | 
						|
   - Recommended: Change to darker blue (#004494) for 7:1+ ratio
 | 
						|
 | 
						|
2. Update CSS in the following files:
 | 
						|
   - \`docker/resume/styles.css\`: Update link colors
 | 
						|
   - \`docker/resume/stories/stories.css\`: Update story-specific link colors
 | 
						|
 | 
						|
`;
 | 
						|
}
 | 
						|
 | 
						|
// Add implementation plan
 | 
						|
report += `## Implementation Plan
 | 
						|
 | 
						|
1. Fix color contrast issues first (highest impact)
 | 
						|
2. Address any document structure issues
 | 
						|
3. Fix remaining issues by priority (serious > moderate > minor)
 | 
						|
4. Re-run tests to verify fixes
 | 
						|
 | 
						|
## Testing Instructions
 | 
						|
 | 
						|
To test accessibility compliance:
 | 
						|
 | 
						|
\`\`\`bash
 | 
						|
# Run all accessibility tests
 | 
						|
npm run test:accessibility
 | 
						|
 | 
						|
# Generate updated report
 | 
						|
node tests/accessibility/generate-report.js
 | 
						|
\`\`\`
 | 
						|
 | 
						|
`;
 | 
						|
 | 
						|
// Write report to file
 | 
						|
fs.writeFileSync(outputFile, report);
 | 
						|
console.log(`Accessibility issues report generated at: ${outputFile}`);
 |