/** * Accessibility Testing Helper * Provides reusable axe-core configuration and utilities for Playwright tests */ import AxeBuilder from '@axe-core/playwright'; /** * Default WCAG 2.1/2.2 tags for accessibility testing */ const WCAG_TAGS = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa']; /** * Create a pre-configured AxeBuilder instance * @param {import('@playwright/test').Page} page - Playwright page object * @param {Object} options - Configuration options * @param {string[]} [options.tags] - WCAG tags to test (default: WCAG 2.1/2.2 A/AA) * @param {string[]} [options.exclude] - Selectors to exclude from scan * @param {string[]} [options.disableRules] - Rule IDs to disable * @returns {AxeBuilder} Configured AxeBuilder instance */ export function createAxeBuilder(page, options = {}) { const { tags = WCAG_TAGS, exclude = [], disableRules = [] } = options; let builder = new AxeBuilder({ page }) .withTags(tags); // Add exclusions exclude.forEach(selector => { builder = builder.exclude(selector); }); // Disable specific rules if provided if (disableRules.length > 0) { builder = builder.disableRules(disableRules); } return builder; } /** * Filter violations by impact level * @param {Object[]} violations - Array of violation objects * @param {string[]} impacts - Impact levels to include ('critical', 'serious', 'moderate', 'minor') * @returns {Object[]} Filtered violations */ function filterByImpact(violations, impacts) { return violations.filter(v => impacts.includes(v.impact)); } /** * Get critical and serious violations only * @param {Object[]} violations - Array of violation objects * @returns {Object[]} Critical and serious violations */ export function getCriticalViolations(violations) { return filterByImpact(violations, ['critical', 'serious']); } /** * Format violations for console output * @param {Object[]} violations - Array of violation objects * @returns {string} Formatted string */ export function formatViolations(violations) { if (violations.length === 0) { return 'No accessibility violations found.'; } const lines = violations.map(v => { const nodes = v.nodes.map(n => ` - ${n.target.join(', ')}`).join('\n'); return `\n[${v.impact.toUpperCase()}] ${v.id}: ${v.description}\n Help: ${v.helpUrl}\n Affected elements:\n${nodes}`; }); return `Found ${violations.length} accessibility violation(s):${lines.join('\n')}`; } export { WCAG_TAGS };