resume/tests/accessibility/playwright-axe.js

156 lines
4.8 KiB
JavaScript

/**
* WCAG 2.1 AAA compliance test using Playwright and axe-core
*
* This script uses Playwright to load pages and axe-core to test them for accessibility issues.
* It's an alternative to the axe-test.js script that properly injects axe-core into the page.
*/
const { chromium } = require('playwright');
const fs = require('fs');
const path = require('path');
const axeCore = require('axe-core');
// URLs to test
const BASE_URL = process.argv[2] || 'http://localhost:8080';
const PAGES = [
'/',
'/stories/',
'/stories/open-source-success.html',
'/stories/viperwire.html',
'/one-pager-tools/csv-tool.html'
];
// Create reports directory if it doesn't exist
const reportsDir = path.join(__dirname, '../reports');
if (!fs.existsSync(reportsDir)) {
fs.mkdirSync(reportsDir, { recursive: true });
}
async function runAxe(page, pageUrl) {
// Inject axe-core into the page
await page.evaluate(axeSource => {
const script = document.createElement('script');
script.text = axeSource;
document.head.appendChild(script);
}, axeCore.source);
// Run axe with WCAG 2.1 AAA rules
const results = await page.evaluate(() => {
return new Promise(resolve => {
axe.run(document, {
runOnly: {
type: 'tag',
values: ['wcag2aaa']
},
resultTypes: ['violations', 'incomplete', 'inapplicable'],
rules: {
'color-contrast': { enabled: true, options: { noScroll: true } }
}
})
.then(results => resolve(results))
.catch(err => resolve({ error: err.toString() }));
});
});
return results;
}
async function testPage(browser, pageUrl) {
const page = await browser.newPage();
console.log(`Testing ${pageUrl}...`);
try {
// Navigate to the page
await page.goto(pageUrl, { waitUntil: 'networkidle' });
// Run axe-core tests
const results = await runAxe(page, pageUrl);
// Save results to file
const fileName = pageUrl === BASE_URL ? 'index' : pageUrl.replace(BASE_URL, '').replace(/\//g, '-').replace(/^-/, '');
const reportPath = path.join(reportsDir, `axe-${fileName || 'index'}.json`);
fs.writeFileSync(reportPath, JSON.stringify(results, null, 2));
// Log results summary
if (results.error) {
console.error(`Error running axe-core on ${pageUrl}:`, results.error);
return { url: pageUrl, success: false, error: results.error };
}
const { violations, incomplete, passes, inapplicable } = results;
console.log(`Results for ${pageUrl}:`);
console.log(`- Violations: ${violations.length}`);
console.log(`- Incomplete: ${incomplete.length}`);
console.log(`- Passes: ${passes.length}`);
console.log(`- Inapplicable: ${inapplicable.length}`);
// Print violations
if (violations.length > 0) {
console.log('\nViolations:');
violations.forEach((violation, i) => {
console.log(`${i + 1}. ${violation.id} - ${violation.help} (Impact: ${violation.impact})`);
console.log(` ${violation.description}`);
console.log(` WCAG: ${violation.tags.filter(t => t.startsWith('wcag')).join(', ')}`);
console.log(` Elements: ${violation.nodes.length}`);
});
}
return {
url: pageUrl,
success: violations.length === 0,
violations: violations.length,
incomplete: incomplete.length,
passes: passes.length
};
} catch (error) {
console.error(`Error testing ${pageUrl}:`, error);
return { url: pageUrl, success: false, error: error.toString() };
} finally {
await page.close();
}
}
async function runTests() {
const browser = await chromium.launch();
const results = [];
try {
// Test each page
for (const pagePath of PAGES) {
const pageUrl = `${BASE_URL}${pagePath}`;
const result = await testPage(browser, pageUrl);
results.push(result);
}
// Save overall results
const overallReport = {
timestamp: new Date().toISOString(),
baseUrl: BASE_URL,
pages: results,
summary: {
total: results.length,
passed: results.filter(r => r.success).length,
failed: results.filter(r => !r.success).length
}
};
fs.writeFileSync(path.join(reportsDir, 'axe-summary.json'), JSON.stringify(overallReport, null, 2));
// Print overall summary
console.log('\n=== Overall Summary ===');
console.log(`Total pages tested: ${overallReport.summary.total}`);
console.log(`Pages passed: ${overallReport.summary.passed}`);
console.log(`Pages failed: ${overallReport.summary.failed}`);
// Exit with appropriate code
process.exit(overallReport.summary.failed > 0 ? 1 : 0);
} catch (error) {
console.error('Error running tests:', error);
process.exit(1);
} finally {
await browser.close();
}
}
runTests();