162 lines
No EOL
3.4 KiB
Markdown
162 lines
No EOL
3.4 KiB
Markdown
# WCAG-ADA Accessibility Scanner
|
|
|
|
A high-performance accessibility scanner built with Playwright and axe-core for WCAG compliance testing.
|
|
|
|
## Features
|
|
|
|
- 🚀 Fast scanning with Playwright
|
|
- ♿ WCAG 2.0, 2.1, and 2.2 compliance testing
|
|
- 📊 Detailed violation reports with fix suggestions
|
|
- 📸 Screenshot capture for violations
|
|
- 🔐 Authentication support (basic, form-based, custom)
|
|
- 📱 Mobile and desktop viewport testing
|
|
- 🎯 Custom rule support
|
|
- 🚫 Resource blocking for faster scans
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
bun install
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Basic Example
|
|
|
|
```typescript
|
|
import { AccessibilityScanner } from '@wcag-ada/scanner';
|
|
|
|
const scanner = new AccessibilityScanner();
|
|
await scanner.initialize();
|
|
|
|
const result = await scanner.scan({
|
|
url: 'https://example.com',
|
|
wcagLevel: {
|
|
level: 'AA',
|
|
version: '2.1'
|
|
}
|
|
});
|
|
|
|
console.log(`Compliance Score: ${result.summary.score}%`);
|
|
console.log(`Violations Found: ${result.summary.violationCount}`);
|
|
|
|
await scanner.close();
|
|
```
|
|
|
|
### Advanced Options
|
|
|
|
```typescript
|
|
const result = await scanner.scan({
|
|
url: 'https://example.com',
|
|
wcagLevel: {
|
|
level: 'AA',
|
|
version: '2.1'
|
|
},
|
|
includeScreenshots: true,
|
|
viewport: {
|
|
width: 1920,
|
|
height: 1080,
|
|
isMobile: false
|
|
},
|
|
authenticate: {
|
|
type: 'form',
|
|
loginUrl: 'https://example.com/login',
|
|
credentials: {
|
|
username: 'user@example.com',
|
|
password: 'password'
|
|
},
|
|
selectors: {
|
|
username: '#email',
|
|
password: '#password',
|
|
submit: 'button[type="submit"]'
|
|
}
|
|
},
|
|
excludeSelectors: [
|
|
'.cookie-banner',
|
|
'[aria-hidden="true"]'
|
|
],
|
|
waitForSelector: '#main-content',
|
|
timeout: 60000
|
|
});
|
|
```
|
|
|
|
### Scan Multiple Pages
|
|
|
|
```typescript
|
|
const urls = [
|
|
'https://example.com',
|
|
'https://example.com/about',
|
|
'https://example.com/contact'
|
|
];
|
|
|
|
const results = await scanner.scanMultiplePages(urls, {
|
|
wcagLevel: { level: 'AA', version: '2.1' }
|
|
});
|
|
```
|
|
|
|
## Scan Results
|
|
|
|
The scanner returns a comprehensive `AccessibilityScanResult` object containing:
|
|
|
|
- **Summary**: Overall compliance score, violation counts by severity
|
|
- **Violations**: Detailed list of accessibility issues with:
|
|
- Impact level (critical, serious, moderate, minor)
|
|
- Affected elements with HTML snippets
|
|
- Fix suggestions
|
|
- WCAG criteria mapping
|
|
- Screenshots (if enabled)
|
|
- **Passes**: Rules that passed
|
|
- **Incomplete**: Rules that need manual review
|
|
- **Page Metadata**: Title, language, element counts, landmark presence
|
|
- **WCAG Compliance**: Level-specific compliance status
|
|
|
|
## Performance Optimization
|
|
|
|
The scanner is optimized for speed:
|
|
- Blocks unnecessary resources (images, fonts, analytics)
|
|
- Parallel page scanning support
|
|
- Configurable timeouts
|
|
- Headless browser mode
|
|
|
|
## Custom Rules
|
|
|
|
Add custom accessibility rules:
|
|
|
|
```typescript
|
|
const customRules = [{
|
|
id: 'custom-button-size',
|
|
selector: 'button',
|
|
tags: ['custom', 'wcag21aa'],
|
|
description: 'Buttons must have minimum touch target size',
|
|
help: 'Ensure buttons are at least 44x44 pixels',
|
|
severity: 'serious',
|
|
validator: (element) => {
|
|
const rect = element.getBoundingClientRect();
|
|
return rect.width >= 44 && rect.height >= 44;
|
|
}
|
|
}];
|
|
|
|
const result = await scanner.scan({
|
|
url: 'https://example.com',
|
|
customRules
|
|
});
|
|
```
|
|
|
|
## Running the Example
|
|
|
|
```bash
|
|
bun run src/example.ts
|
|
```
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# Build
|
|
bun run build
|
|
|
|
# Watch mode
|
|
bun run dev
|
|
|
|
# Type checking
|
|
bun run typecheck
|
|
``` |