const { chromium } = require('playwright'); const AxeBuilder = require('@axe-core/playwright').default; const fs = require('fs'); const path = require('path'); async function runAxeTest(url, pageName) { const browser = await chromium.launch(); const page = await browser.newPage(); const results = []; try { await page.goto(url, { waitUntil: 'networkidle' }); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']) .analyze(); const violations = accessibilityScanResults.violations.map(v => ({ id: v.id, impact: v.impact, description: v.description, help: v.help, helpUrl: v.helpUrl, nodes: v.nodes.length })); const passes = accessibilityScanResults.passes.length; const incomplete = accessibilityScanResults.incomplete.length; results.push({ page: pageName, url, violations, passes, incomplete, score: calculateScore(violations, passes, incomplete) }); console.log(` ✅ 扫描完成: ${violations.length} 个违规, ${passes} 个通过, ${incomplete} 个未完成`); await browser.close(); return results[0]; } catch (error) { await browser.close(); throw new Error(`可访问性测试失败: ${error.message}`); } } function calculateScore(violations, passes, incomplete) { const total = violations.length + passes.length + incomplete.length; if (total === 0) return 100; return ((passes / total) * 100).toFixed(1); } function generateReport(results, outputPath) { const report = { timestamp: new Date().toISOString(), summary: { totalPages: results.length, totalViolations: results.reduce((sum, r) => sum + r.violations.length, 0), averageScore: (results.reduce((sum, r) => sum + parseFloat(r.score), 0) / results.length).toFixed(1) }, pages: results }; fs.writeFileSync(outputPath, JSON.stringify(report, null, 2)); return outputPath; } module.exports = { runAxeTest, generateReport };