agentic-qe 1.9.4 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/qe-api-contract-validator.md +95 -1336
- package/.claude/agents/qe-chaos-engineer.md +152 -1211
- package/.claude/agents/qe-code-complexity.md +144 -707
- package/.claude/agents/qe-coverage-analyzer.md +147 -743
- package/.claude/agents/qe-deployment-readiness.md +143 -1496
- package/.claude/agents/qe-flaky-test-hunter.md +132 -1529
- package/.claude/agents/qe-fleet-commander.md +12 -12
- package/.claude/agents/qe-performance-tester.md +150 -886
- package/.claude/agents/qe-production-intelligence.md +155 -1396
- package/.claude/agents/qe-quality-analyzer.md +6 -6
- package/.claude/agents/qe-quality-gate.md +151 -648
- package/.claude/agents/qe-regression-risk-analyzer.md +132 -1150
- package/.claude/agents/qe-requirements-validator.md +149 -932
- package/.claude/agents/qe-security-scanner.md +157 -797
- package/.claude/agents/qe-test-data-architect.md +96 -1365
- package/.claude/agents/qe-test-executor.md +8 -8
- package/.claude/agents/qe-test-generator.md +145 -1540
- package/.claude/agents/qe-visual-tester.md +153 -1257
- package/.claude/agents/qx-partner.md +248 -0
- package/.claude/agents/subagents/qe-code-reviewer.md +40 -136
- package/.claude/agents/subagents/qe-coverage-gap-analyzer.md +40 -480
- package/.claude/agents/subagents/qe-data-generator.md +41 -125
- package/.claude/agents/subagents/qe-flaky-investigator.md +55 -411
- package/.claude/agents/subagents/qe-integration-tester.md +53 -141
- package/.claude/agents/subagents/qe-performance-validator.md +54 -130
- package/.claude/agents/subagents/qe-security-auditor.md +56 -114
- package/.claude/agents/subagents/qe-test-data-architect-sub.md +57 -548
- package/.claude/agents/subagents/qe-test-implementer.md +58 -551
- package/.claude/agents/subagents/qe-test-refactorer.md +65 -722
- package/.claude/agents/subagents/qe-test-writer.md +63 -726
- package/.claude/skills/accessibility-testing/SKILL.md +144 -692
- package/.claude/skills/agentic-quality-engineering/SKILL.md +176 -529
- package/.claude/skills/api-testing-patterns/SKILL.md +180 -560
- package/.claude/skills/brutal-honesty-review/SKILL.md +113 -603
- package/.claude/skills/bug-reporting-excellence/SKILL.md +116 -517
- package/.claude/skills/chaos-engineering-resilience/SKILL.md +127 -72
- package/.claude/skills/cicd-pipeline-qe-orchestrator/SKILL.md +209 -404
- package/.claude/skills/code-review-quality/SKILL.md +158 -608
- package/.claude/skills/compatibility-testing/SKILL.md +148 -38
- package/.claude/skills/compliance-testing/SKILL.md +132 -63
- package/.claude/skills/consultancy-practices/SKILL.md +114 -446
- package/.claude/skills/context-driven-testing/SKILL.md +117 -381
- package/.claude/skills/contract-testing/SKILL.md +176 -141
- package/.claude/skills/database-testing/SKILL.md +137 -130
- package/.claude/skills/exploratory-testing-advanced/SKILL.md +160 -629
- package/.claude/skills/holistic-testing-pact/SKILL.md +140 -188
- package/.claude/skills/localization-testing/SKILL.md +145 -33
- package/.claude/skills/mobile-testing/SKILL.md +132 -448
- package/.claude/skills/mutation-testing/SKILL.md +147 -41
- package/.claude/skills/performance-testing/SKILL.md +200 -546
- package/.claude/skills/quality-metrics/SKILL.md +164 -519
- package/.claude/skills/refactoring-patterns/SKILL.md +132 -699
- package/.claude/skills/regression-testing/SKILL.md +120 -926
- package/.claude/skills/risk-based-testing/SKILL.md +157 -660
- package/.claude/skills/security-testing/SKILL.md +199 -538
- package/.claude/skills/sherlock-review/SKILL.md +163 -699
- package/.claude/skills/shift-left-testing/SKILL.md +161 -465
- package/.claude/skills/shift-right-testing/SKILL.md +161 -519
- package/.claude/skills/six-thinking-hats/SKILL.md +175 -1110
- package/.claude/skills/skills-manifest.json +683 -0
- package/.claude/skills/tdd-london-chicago/SKILL.md +131 -448
- package/.claude/skills/technical-writing/SKILL.md +103 -154
- package/.claude/skills/test-automation-strategy/SKILL.md +166 -772
- package/.claude/skills/test-data-management/SKILL.md +126 -910
- package/.claude/skills/test-design-techniques/SKILL.md +179 -89
- package/.claude/skills/test-environment-management/SKILL.md +136 -91
- package/.claude/skills/test-reporting-analytics/SKILL.md +169 -92
- package/.claude/skills/testability-scoring/README.md +71 -0
- package/.claude/skills/testability-scoring/SKILL.md +245 -0
- package/.claude/skills/testability-scoring/resources/templates/config.template.js +84 -0
- package/.claude/skills/testability-scoring/resources/templates/testability-scoring.spec.template.js +532 -0
- package/.claude/skills/testability-scoring/scripts/generate-html-report.js +1007 -0
- package/.claude/skills/testability-scoring/scripts/run-assessment.sh +70 -0
- package/.claude/skills/visual-testing-advanced/SKILL.md +155 -78
- package/.claude/skills/xp-practices/SKILL.md +151 -587
- package/CHANGELOG.md +110 -0
- package/README.md +55 -21
- package/dist/agents/QXPartnerAgent.d.ts +146 -0
- package/dist/agents/QXPartnerAgent.d.ts.map +1 -0
- package/dist/agents/QXPartnerAgent.js +1831 -0
- package/dist/agents/QXPartnerAgent.js.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +82 -2
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/lifecycle/AgentLifecycleManager.d.ts.map +1 -1
- package/dist/agents/lifecycle/AgentLifecycleManager.js +34 -31
- package/dist/agents/lifecycle/AgentLifecycleManager.js.map +1 -1
- package/dist/cli/commands/debug/agent.d.ts.map +1 -1
- package/dist/cli/commands/debug/agent.js +19 -6
- package/dist/cli/commands/debug/agent.js.map +1 -1
- package/dist/cli/commands/debug/health-check.js +20 -7
- package/dist/cli/commands/debug/health-check.js.map +1 -1
- package/dist/cli/commands/init-claude-md-template.d.ts +1 -0
- package/dist/cli/commands/init-claude-md-template.d.ts.map +1 -1
- package/dist/cli/commands/init-claude-md-template.js +18 -3
- package/dist/cli/commands/init-claude-md-template.js.map +1 -1
- package/dist/cli/commands/workflow/cancel.d.ts.map +1 -1
- package/dist/cli/commands/workflow/cancel.js +4 -3
- package/dist/cli/commands/workflow/cancel.js.map +1 -1
- package/dist/cli/commands/workflow/list.d.ts.map +1 -1
- package/dist/cli/commands/workflow/list.js +4 -3
- package/dist/cli/commands/workflow/list.js.map +1 -1
- package/dist/cli/commands/workflow/pause.d.ts.map +1 -1
- package/dist/cli/commands/workflow/pause.js +4 -3
- package/dist/cli/commands/workflow/pause.js.map +1 -1
- package/dist/cli/init/claude-config.d.ts.map +1 -1
- package/dist/cli/init/claude-config.js +3 -8
- package/dist/cli/init/claude-config.js.map +1 -1
- package/dist/cli/init/claude-md.d.ts.map +1 -1
- package/dist/cli/init/claude-md.js +44 -2
- package/dist/cli/init/claude-md.js.map +1 -1
- package/dist/cli/init/database-init.js +1 -1
- package/dist/cli/init/index.d.ts.map +1 -1
- package/dist/cli/init/index.js +13 -6
- package/dist/cli/init/index.js.map +1 -1
- package/dist/cli/init/skills.d.ts.map +1 -1
- package/dist/cli/init/skills.js +2 -1
- package/dist/cli/init/skills.js.map +1 -1
- package/dist/core/SwarmCoordinator.d.ts +180 -0
- package/dist/core/SwarmCoordinator.d.ts.map +1 -0
- package/dist/core/SwarmCoordinator.js +473 -0
- package/dist/core/SwarmCoordinator.js.map +1 -0
- package/dist/core/memory/AgentDBIntegration.d.ts +24 -6
- package/dist/core/memory/AgentDBIntegration.d.ts.map +1 -1
- package/dist/core/memory/AgentDBIntegration.js +66 -10
- package/dist/core/memory/AgentDBIntegration.js.map +1 -1
- package/dist/core/memory/UnifiedMemoryCoordinator.d.ts +341 -0
- package/dist/core/memory/UnifiedMemoryCoordinator.d.ts.map +1 -0
- package/dist/core/memory/UnifiedMemoryCoordinator.js +986 -0
- package/dist/core/memory/UnifiedMemoryCoordinator.js.map +1 -0
- package/dist/core/memory/index.d.ts +5 -0
- package/dist/core/memory/index.d.ts.map +1 -1
- package/dist/core/memory/index.js +23 -1
- package/dist/core/memory/index.js.map +1 -1
- package/dist/core/metrics/MetricsAggregator.d.ts +228 -0
- package/dist/core/metrics/MetricsAggregator.d.ts.map +1 -0
- package/dist/core/metrics/MetricsAggregator.js +482 -0
- package/dist/core/metrics/MetricsAggregator.js.map +1 -0
- package/dist/core/metrics/index.d.ts +5 -0
- package/dist/core/metrics/index.d.ts.map +1 -0
- package/dist/core/metrics/index.js +11 -0
- package/dist/core/metrics/index.js.map +1 -0
- package/dist/core/optimization/SwarmOptimizer.d.ts +190 -0
- package/dist/core/optimization/SwarmOptimizer.d.ts.map +1 -0
- package/dist/core/optimization/SwarmOptimizer.js +648 -0
- package/dist/core/optimization/SwarmOptimizer.js.map +1 -0
- package/dist/core/optimization/index.d.ts +9 -0
- package/dist/core/optimization/index.d.ts.map +1 -0
- package/dist/core/optimization/index.js +25 -0
- package/dist/core/optimization/index.js.map +1 -0
- package/dist/core/optimization/types.d.ts +53 -0
- package/dist/core/optimization/types.d.ts.map +1 -0
- package/dist/core/optimization/types.js +6 -0
- package/dist/core/optimization/types.js.map +1 -0
- package/dist/core/orchestration/AdaptiveScheduler.d.ts +190 -0
- package/dist/core/orchestration/AdaptiveScheduler.d.ts.map +1 -0
- package/dist/core/orchestration/AdaptiveScheduler.js +460 -0
- package/dist/core/orchestration/AdaptiveScheduler.js.map +1 -0
- package/dist/core/orchestration/PriorityQueue.d.ts +54 -0
- package/dist/core/orchestration/PriorityQueue.d.ts.map +1 -0
- package/dist/core/orchestration/PriorityQueue.js +122 -0
- package/dist/core/orchestration/PriorityQueue.js.map +1 -0
- package/dist/core/orchestration/WorkflowOrchestrator.d.ts +189 -0
- package/dist/core/orchestration/WorkflowOrchestrator.d.ts.map +1 -0
- package/dist/core/orchestration/WorkflowOrchestrator.js +845 -0
- package/dist/core/orchestration/WorkflowOrchestrator.js.map +1 -0
- package/dist/core/orchestration/index.d.ts +7 -0
- package/dist/core/orchestration/index.d.ts.map +1 -0
- package/dist/core/orchestration/index.js +11 -0
- package/dist/core/orchestration/index.js.map +1 -0
- package/dist/core/orchestration/types.d.ts +96 -0
- package/dist/core/orchestration/types.d.ts.map +1 -0
- package/dist/core/orchestration/types.js +6 -0
- package/dist/core/orchestration/types.js.map +1 -0
- package/dist/core/recovery/CircuitBreaker.d.ts +176 -0
- package/dist/core/recovery/CircuitBreaker.d.ts.map +1 -0
- package/dist/core/recovery/CircuitBreaker.js +382 -0
- package/dist/core/recovery/CircuitBreaker.js.map +1 -0
- package/dist/core/recovery/RecoveryOrchestrator.d.ts +186 -0
- package/dist/core/recovery/RecoveryOrchestrator.d.ts.map +1 -0
- package/dist/core/recovery/RecoveryOrchestrator.js +476 -0
- package/dist/core/recovery/RecoveryOrchestrator.js.map +1 -0
- package/dist/core/recovery/RetryStrategy.d.ts +127 -0
- package/dist/core/recovery/RetryStrategy.d.ts.map +1 -0
- package/dist/core/recovery/RetryStrategy.js +314 -0
- package/dist/core/recovery/RetryStrategy.js.map +1 -0
- package/dist/core/recovery/index.d.ts +8 -0
- package/dist/core/recovery/index.d.ts.map +1 -0
- package/dist/core/recovery/index.js +27 -0
- package/dist/core/recovery/index.js.map +1 -0
- package/dist/core/skills/DependencyResolver.d.ts +99 -0
- package/dist/core/skills/DependencyResolver.d.ts.map +1 -0
- package/dist/core/skills/DependencyResolver.js +260 -0
- package/dist/core/skills/DependencyResolver.js.map +1 -0
- package/dist/core/skills/DynamicSkillLoader.d.ts +96 -0
- package/dist/core/skills/DynamicSkillLoader.d.ts.map +1 -0
- package/dist/core/skills/DynamicSkillLoader.js +353 -0
- package/dist/core/skills/DynamicSkillLoader.js.map +1 -0
- package/dist/core/skills/ManifestGenerator.d.ts +114 -0
- package/dist/core/skills/ManifestGenerator.d.ts.map +1 -0
- package/dist/core/skills/ManifestGenerator.js +449 -0
- package/dist/core/skills/ManifestGenerator.js.map +1 -0
- package/dist/core/skills/index.d.ts +9 -0
- package/dist/core/skills/index.d.ts.map +1 -0
- package/dist/core/skills/index.js +24 -0
- package/dist/core/skills/index.js.map +1 -0
- package/dist/core/skills/types.d.ts +118 -0
- package/dist/core/skills/types.d.ts.map +1 -0
- package/dist/core/skills/types.js +7 -0
- package/dist/core/skills/types.js.map +1 -0
- package/dist/core/transport/QUICTransport.d.ts +320 -0
- package/dist/core/transport/QUICTransport.d.ts.map +1 -0
- package/dist/core/transport/QUICTransport.js +711 -0
- package/dist/core/transport/QUICTransport.js.map +1 -0
- package/dist/core/transport/index.d.ts +40 -0
- package/dist/core/transport/index.d.ts.map +1 -0
- package/dist/core/transport/index.js +46 -0
- package/dist/core/transport/index.js.map +1 -0
- package/dist/core/transport/quic-loader.d.ts +123 -0
- package/dist/core/transport/quic-loader.d.ts.map +1 -0
- package/dist/core/transport/quic-loader.js +293 -0
- package/dist/core/transport/quic-loader.js.map +1 -0
- package/dist/core/transport/quic.d.ts +154 -0
- package/dist/core/transport/quic.d.ts.map +1 -0
- package/dist/core/transport/quic.js +214 -0
- package/dist/core/transport/quic.js.map +1 -0
- package/dist/mcp/server.d.ts +9 -9
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +1 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/services/AgentRegistry.d.ts.map +1 -1
- package/dist/mcp/services/AgentRegistry.js +4 -1
- package/dist/mcp/services/AgentRegistry.js.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/qx.d.ts +429 -0
- package/dist/types/qx.d.ts.map +1 -0
- package/dist/types/qx.js +71 -0
- package/dist/types/qx.js.map +1 -0
- package/dist/visualization/api/RestEndpoints.js +2 -2
- package/dist/visualization/api/RestEndpoints.js.map +1 -1
- package/dist/visualization/api/WebSocketServer.d.ts +44 -0
- package/dist/visualization/api/WebSocketServer.d.ts.map +1 -1
- package/dist/visualization/api/WebSocketServer.js +144 -23
- package/dist/visualization/api/WebSocketServer.js.map +1 -1
- package/dist/visualization/core/DataTransformer.d.ts +10 -0
- package/dist/visualization/core/DataTransformer.d.ts.map +1 -1
- package/dist/visualization/core/DataTransformer.js +60 -5
- package/dist/visualization/core/DataTransformer.js.map +1 -1
- package/dist/visualization/emit-event.d.ts +75 -0
- package/dist/visualization/emit-event.d.ts.map +1 -0
- package/dist/visualization/emit-event.js +213 -0
- package/dist/visualization/emit-event.js.map +1 -0
- package/dist/visualization/index.d.ts +1 -0
- package/dist/visualization/index.d.ts.map +1 -1
- package/dist/visualization/index.js +7 -1
- package/dist/visualization/index.js.map +1 -1
- package/docs/reference/skills.md +63 -1
- package/package.json +16 -58
|
@@ -1,764 +1,216 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: accessibility-testing
|
|
3
|
-
description: WCAG 2.2 compliance testing, screen reader validation, and inclusive design verification. Use when ensuring legal compliance (ADA, Section 508), testing for disabilities, or building accessible applications for 1 billion disabled users globally.
|
|
3
|
+
description: "WCAG 2.2 compliance testing, screen reader validation, and inclusive design verification. Use when ensuring legal compliance (ADA, Section 508), testing for disabilities, or building accessible applications for 1 billion disabled users globally."
|
|
4
|
+
category: specialized-testing
|
|
5
|
+
priority: high
|
|
6
|
+
tokenEstimate: 1100
|
|
7
|
+
agents: [qe-visual-tester, qe-test-generator, qe-quality-gate]
|
|
8
|
+
implementation_status: optimized
|
|
9
|
+
optimization_version: 1.0
|
|
10
|
+
last_optimized: 2025-12-02
|
|
11
|
+
dependencies: []
|
|
12
|
+
quick_reference_card: true
|
|
13
|
+
tags: [accessibility, wcag, a11y, screen-reader, ada, section-508, inclusive]
|
|
4
14
|
---
|
|
5
15
|
|
|
6
16
|
# Accessibility Testing
|
|
7
17
|
|
|
8
|
-
|
|
18
|
+
<default_to_action>
|
|
19
|
+
When testing accessibility or ensuring compliance:
|
|
20
|
+
1. APPLY POUR principles: Perceivable, Operable, Understandable, Robust
|
|
21
|
+
2. TEST with keyboard-only navigation (Tab, Enter, Escape)
|
|
22
|
+
3. VALIDATE with screen readers (VoiceOver, NVDA, JAWS)
|
|
23
|
+
4. CHECK color contrast (4.5:1 for text, 3:1 for large text)
|
|
24
|
+
5. AUTOMATE with axe-core, integrate in CI/CD pipeline
|
|
25
|
+
|
|
26
|
+
**Quick A11y Checklist:**
|
|
27
|
+
- All images have alt text (or alt="" for decorative)
|
|
28
|
+
- All form fields have labels
|
|
29
|
+
- Color is never the only indicator
|
|
30
|
+
- Focus visible on all interactive elements
|
|
31
|
+
- Keyboard navigation works throughout
|
|
32
|
+
|
|
33
|
+
**Critical Success Factors:**
|
|
34
|
+
- Automated testing catches 30-50% of issues
|
|
35
|
+
- Manual testing with real assistive tech required
|
|
36
|
+
- Include users with disabilities in testing
|
|
37
|
+
</default_to_action>
|
|
38
|
+
|
|
39
|
+
## Quick Reference Card
|
|
40
|
+
|
|
41
|
+
### When to Use
|
|
42
|
+
- Legal compliance (ADA, Section 508, EU Directive)
|
|
43
|
+
- New feature development
|
|
44
|
+
- Before release validation
|
|
45
|
+
- Accessibility audits
|
|
46
|
+
|
|
47
|
+
### WCAG 2.2 Levels
|
|
48
|
+
| Level | Requirement | Target |
|
|
49
|
+
|-------|-------------|--------|
|
|
50
|
+
| **A** | Basic accessibility | Minimum legal |
|
|
51
|
+
| **AA** | Standard (most orgs) | Industry standard |
|
|
52
|
+
| **AAA** | Enhanced | Specialized sites |
|
|
53
|
+
|
|
54
|
+
### POUR Principles
|
|
55
|
+
| Principle | Meaning | Key Tests |
|
|
56
|
+
|-----------|---------|-----------|
|
|
57
|
+
| **Perceivable** | Can perceive content | Alt text, contrast, captions |
|
|
58
|
+
| **Operable** | Can operate UI | Keyboard, no seizures, navigation |
|
|
59
|
+
| **Understandable** | Can understand | Clear labels, predictable, errors |
|
|
60
|
+
| **Robust** | Works with assistive tech | Valid HTML, ARIA |
|
|
61
|
+
|
|
62
|
+
### Color Contrast Requirements
|
|
63
|
+
| Content | AA Ratio | AAA Ratio |
|
|
64
|
+
|---------|----------|-----------|
|
|
65
|
+
| Normal text | 4.5:1 | 7:1 |
|
|
66
|
+
| Large text (18pt+) | 3:1 | 4.5:1 |
|
|
67
|
+
| UI components | 3:1 | - |
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Keyboard Navigation Testing
|
|
9
72
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## What is Accessibility Testing?
|
|
15
|
-
|
|
16
|
-
**Accessibility (a11y):** Ensuring people with disabilities can perceive, understand, navigate, and interact with software using assistive technologies.
|
|
17
|
-
|
|
18
|
-
**Why Critical:**
|
|
19
|
-
- **Legal:** ADA, Section 508, EU Directive 2016/2102 require accessibility
|
|
20
|
-
- **Market:** $13T purchasing power of disabled community
|
|
21
|
-
- **Litigation:** 250%+ increase in a11y lawsuits (2019-2024)
|
|
22
|
-
- **Ethics:** Equal access is a fundamental right
|
|
23
|
-
- **UX:** Accessible design benefits all users (curb-cut effect)
|
|
24
|
-
|
|
25
|
-
**Goal:** WCAG 2.2 Level AA compliance + excellent user experience with assistive tech.
|
|
26
|
-
|
|
27
|
-
## WCAG 2.2 Compliance Levels
|
|
28
|
-
|
|
29
|
-
### Conformance Levels
|
|
30
|
-
|
|
31
|
-
**Level A (Minimum)**
|
|
32
|
-
- Basic accessibility
|
|
33
|
-
- Addresses most critical barriers
|
|
34
|
-
- **Requirement:** Legal minimum in many jurisdictions
|
|
35
|
-
|
|
36
|
-
**Level AA (Standard)**
|
|
37
|
-
- Addresses majority of barriers
|
|
38
|
-
- **Requirement:** US federal government (Section 508)
|
|
39
|
-
- **Recommendation:** Industry standard for most websites
|
|
40
|
-
|
|
41
|
-
**Level AAA (Enhanced)**
|
|
42
|
-
- Highest level of accessibility
|
|
43
|
-
- Not required for full sites (some criteria impossible for all content)
|
|
44
|
-
- **Use when:** Specialized accessibility-focused sites
|
|
45
|
-
|
|
46
|
-
**Most Organizations Target:** WCAG 2.2 Level AA
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## POUR Principles
|
|
51
|
-
|
|
52
|
-
### 1. Perceivable
|
|
53
|
-
**Users must be able to perceive information**
|
|
54
|
-
|
|
55
|
-
**Requirements:**
|
|
56
|
-
- Text alternatives for non-text content
|
|
57
|
-
- Captions for videos
|
|
58
|
-
- Audio descriptions for video
|
|
59
|
-
- Adaptable content (different presentations)
|
|
60
|
-
- Distinguishable content (color contrast, text resize)
|
|
61
|
-
|
|
62
|
-
**Example:**
|
|
63
|
-
```html
|
|
64
|
-
<!-- ❌ BAD: Image without alt text -->
|
|
65
|
-
<img src="product.jpg">
|
|
66
|
-
|
|
67
|
-
<!-- ✅ GOOD: Descriptive alt text -->
|
|
68
|
-
<img src="product.jpg" alt="Blue wireless headphones with noise cancellation">
|
|
69
|
-
|
|
70
|
-
<!-- ❌ BAD: Color-only error indication -->
|
|
71
|
-
<span style="color: red">Error</span>
|
|
72
|
-
|
|
73
|
-
<!-- ✅ GOOD: Color + icon + text -->
|
|
74
|
-
<span class="error" role="alert">
|
|
75
|
-
<span aria-hidden="true">⚠️</span>
|
|
76
|
-
Error: Invalid email format
|
|
77
|
-
</span>
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
### 2. Operable
|
|
83
|
-
**Users must be able to operate the interface**
|
|
84
|
-
|
|
85
|
-
**Requirements:**
|
|
86
|
-
- Keyboard accessible (no mouse required)
|
|
87
|
-
- Enough time to read/use content
|
|
88
|
-
- No content causing seizures (no flashing > 3x/sec)
|
|
89
|
-
- Navigable (skip links, headings, focus order)
|
|
90
|
-
- Input modalities (touch, voice, etc.)
|
|
91
|
-
|
|
92
|
-
**Example:**
|
|
93
|
-
```html
|
|
94
|
-
<!-- ❌ BAD: Mouse-only interaction -->
|
|
95
|
-
<div onclick="submitForm()">Submit</div>
|
|
96
|
-
|
|
97
|
-
<!-- ✅ GOOD: Keyboard accessible button -->
|
|
98
|
-
<button type="submit" onclick="submitForm()">Submit</button>
|
|
99
|
-
|
|
100
|
-
<!-- ✅ GOOD: Skip navigation link -->
|
|
101
|
-
<a href="#main-content" class="skip-link">
|
|
102
|
-
Skip to main content
|
|
103
|
-
</a>
|
|
104
|
-
|
|
105
|
-
<nav>...</nav>
|
|
106
|
-
|
|
107
|
-
<main id="main-content">...</main>
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
### 3. Understandable
|
|
113
|
-
**Information and operation must be understandable**
|
|
114
|
-
|
|
115
|
-
**Requirements:**
|
|
116
|
-
- Readable text (language identified, unusual words explained)
|
|
117
|
-
- Predictable operation (consistent navigation)
|
|
118
|
-
- Input assistance (error identification, labels, suggestions)
|
|
119
|
-
- Compatible with assistive technologies
|
|
120
|
-
|
|
121
|
-
**Example:**
|
|
122
|
-
```html
|
|
123
|
-
<!-- ❌ BAD: Unclear error -->
|
|
124
|
-
<span>Error</span>
|
|
125
|
-
|
|
126
|
-
<!-- ✅ GOOD: Clear, actionable error -->
|
|
127
|
-
<div role="alert" aria-live="assertive">
|
|
128
|
-
<strong>Error:</strong> Password must be at least 8 characters,
|
|
129
|
-
including one uppercase letter and one number.
|
|
130
|
-
</div>
|
|
131
|
-
|
|
132
|
-
<!-- ✅ GOOD: Form labels -->
|
|
133
|
-
<label for="email">
|
|
134
|
-
Email Address (required)
|
|
135
|
-
</label>
|
|
136
|
-
<input
|
|
137
|
-
type="email"
|
|
138
|
-
id="email"
|
|
139
|
-
name="email"
|
|
140
|
-
required
|
|
141
|
-
aria-required="true"
|
|
142
|
-
aria-describedby="email-help"
|
|
143
|
-
>
|
|
144
|
-
<span id="email-help">We'll never share your email.</span>
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
### 4. Robust
|
|
150
|
-
**Content must work with current and future tools**
|
|
151
|
-
|
|
152
|
-
**Requirements:**
|
|
153
|
-
- Valid HTML/CSS
|
|
154
|
-
- Name, role, value available to assistive tech
|
|
155
|
-
- Status messages announced
|
|
156
|
-
- Compatible with user agents and assistive tech
|
|
157
|
-
|
|
158
|
-
**Example:**
|
|
159
|
-
```html
|
|
160
|
-
<!-- ✅ GOOD: Custom component with ARIA -->
|
|
161
|
-
<div
|
|
162
|
-
role="button"
|
|
163
|
-
tabindex="0"
|
|
164
|
-
aria-pressed="false"
|
|
165
|
-
onkeydown="handleKeyPress(event)"
|
|
166
|
-
onclick="toggleButton()"
|
|
167
|
-
>
|
|
168
|
-
Toggle Feature
|
|
169
|
-
</div>
|
|
170
|
-
|
|
171
|
-
<!-- ✅ GOOD: Status message -->
|
|
172
|
-
<div role="status" aria-live="polite" aria-atomic="true">
|
|
173
|
-
3 items added to cart
|
|
174
|
-
</div>
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
---
|
|
178
|
-
|
|
179
|
-
## Manual Testing Techniques
|
|
180
|
-
|
|
181
|
-
### 1. Keyboard-Only Navigation
|
|
182
|
-
|
|
183
|
-
**Test keyboard accessibility:**
|
|
184
|
-
```
|
|
185
|
-
Tab → Move to next focusable element
|
|
186
|
-
Shift+Tab → Move to previous focusable element
|
|
187
|
-
Enter → Activate links/buttons
|
|
188
|
-
Space → Activate buttons, toggle checkboxes
|
|
189
|
-
Arrow keys→ Navigate within components (menus, sliders)
|
|
190
|
-
Esc → Close dialogs/menus
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
**Checklist:**
|
|
194
|
-
- [ ] All interactive elements reachable via keyboard
|
|
195
|
-
- [ ] Visible focus indicator (outline/highlight)
|
|
196
|
-
- [ ] Logical tab order (follows visual layout)
|
|
197
|
-
- [ ] No keyboard traps (can navigate away)
|
|
198
|
-
- [ ] Skip navigation link present
|
|
199
|
-
- [ ] Keyboard shortcuts documented
|
|
200
|
-
|
|
201
|
-
**Common Issues:**
|
|
202
|
-
```html
|
|
203
|
-
<!-- ❌ BAD: Custom div without keyboard support -->
|
|
204
|
-
<div onclick="openModal()">Open</div>
|
|
205
|
-
|
|
206
|
-
<!-- ✅ GOOD: Button with keyboard support -->
|
|
207
|
-
<button onclick="openModal()">Open</button>
|
|
208
|
-
|
|
209
|
-
<!-- ✅ GOOD: Custom element with keyboard -->
|
|
210
|
-
<div
|
|
211
|
-
role="button"
|
|
212
|
-
tabindex="0"
|
|
213
|
-
onclick="openModal()"
|
|
214
|
-
onkeydown="if(event.key==='Enter') openModal()"
|
|
215
|
-
>
|
|
216
|
-
Open
|
|
217
|
-
</div>
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
---
|
|
221
|
-
|
|
222
|
-
### 2. Screen Reader Testing
|
|
223
|
-
|
|
224
|
-
**Major Screen Readers:**
|
|
225
|
-
- **JAWS** (Windows) - Most popular, commercial
|
|
226
|
-
- **NVDA** (Windows) - Free, open-source
|
|
227
|
-
- **VoiceOver** (macOS/iOS) - Built-in to Apple devices
|
|
228
|
-
- **TalkBack** (Android) - Built-in to Android
|
|
229
|
-
- **Narrator** (Windows) - Built-in to Windows
|
|
230
|
-
|
|
231
|
-
**VoiceOver Basics (macOS):**
|
|
232
|
-
```
|
|
233
|
-
Cmd+F5 → Toggle VoiceOver
|
|
234
|
-
VO+Right/Left → Navigate elements (VO = Ctrl+Option)
|
|
235
|
-
VO+Shift+Down → Interact with element
|
|
236
|
-
VO+Space → Activate element
|
|
237
|
-
VO+A → Read from top
|
|
238
|
-
VO+U → Rotor (headings, links, landmarks)
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
**Screen Reader Checklist:**
|
|
242
|
-
- [ ] All images have alt text (or alt="" for decorative)
|
|
243
|
-
- [ ] Headings announce correctly (h1, h2, etc.)
|
|
244
|
-
- [ ] Form labels associated with inputs
|
|
245
|
-
- [ ] Links have descriptive text (not "click here")
|
|
246
|
-
- [ ] Dynamic content announced (aria-live)
|
|
247
|
-
- [ ] Custom components have proper roles
|
|
248
|
-
- [ ] Page language identified
|
|
249
|
-
- [ ] Reading order logical
|
|
250
|
-
|
|
251
|
-
**Example Testing Script:**
|
|
252
|
-
```
|
|
253
|
-
1. Enable screen reader
|
|
254
|
-
2. Navigate to page
|
|
255
|
-
3. Verify page title announced
|
|
256
|
-
4. Navigate by headings (h1 → h2 → h3)
|
|
257
|
-
5. Navigate by landmarks (nav, main, footer)
|
|
258
|
-
6. Tab through form, verify labels read
|
|
259
|
-
7. Submit form with errors, verify error messages read
|
|
260
|
-
8. Navigate list of items, verify count announced
|
|
261
|
-
9. Open modal, verify focus trapped
|
|
262
|
-
10. Close modal, verify focus returned
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
### 3. Color Contrast Testing
|
|
268
|
-
|
|
269
|
-
**WCAG Requirements:**
|
|
270
|
-
- **Normal text:** 4.5:1 contrast ratio (AA), 7:1 (AAA)
|
|
271
|
-
- **Large text (18pt+):** 3:1 contrast ratio (AA), 4.5:1 (AAA)
|
|
272
|
-
- **UI components:** 3:1 contrast ratio
|
|
273
|
-
|
|
274
|
-
**Tools:**
|
|
275
|
-
- Chrome DevTools (built-in contrast checker)
|
|
276
|
-
- WebAIM Contrast Checker
|
|
277
|
-
- Colour Contrast Analyser (CCA)
|
|
278
|
-
|
|
279
|
-
**Manual Test:**
|
|
280
|
-
```html
|
|
281
|
-
<!-- ❌ BAD: Insufficient contrast (2.5:1) -->
|
|
282
|
-
<p style="color: #777; background: #fff;">Low contrast text</p>
|
|
283
|
-
|
|
284
|
-
<!-- ✅ GOOD: Sufficient contrast (4.6:1) -->
|
|
285
|
-
<p style="color: #595959; background: #fff;">Readable text</p>
|
|
286
|
-
|
|
287
|
-
<!-- ✅ GOOD: High contrast (12.6:1) -->
|
|
288
|
-
<p style="color: #000; background: #fff;">High contrast text</p>
|
|
289
|
-
```
|
|
73
|
+
```javascript
|
|
74
|
+
// Test all interactive elements reachable via keyboard
|
|
75
|
+
test('all interactive elements keyboard accessible', async ({ page }) => {
|
|
76
|
+
await page.goto('/');
|
|
290
77
|
|
|
291
|
-
|
|
292
|
-
- [ ] All text meets 4.5:1 ratio
|
|
293
|
-
- [ ] Large text meets 3:1 ratio
|
|
294
|
-
- [ ] Links distinguishable without color alone
|
|
295
|
-
- [ ] UI components meet 3:1 ratio
|
|
296
|
-
- [ ] Focus indicators meet 3:1 ratio
|
|
78
|
+
const focusableElements = await page.$$('button, a, input, select, textarea, [tabindex]');
|
|
297
79
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
80
|
+
for (const element of focusableElements) {
|
|
81
|
+
await element.focus();
|
|
82
|
+
const isFocused = await element.evaluate(el => document.activeElement === el);
|
|
83
|
+
expect(isFocused).toBe(true);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
301
86
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
87
|
+
// Verify visible focus indicator
|
|
88
|
+
test('focus indicator visible', async ({ page }) => {
|
|
89
|
+
await page.goto('/');
|
|
90
|
+
await page.keyboard.press('Tab');
|
|
305
91
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
- Verify all text readable
|
|
311
|
-
- Verify no content hidden
|
|
312
|
-
- Verify functionality intact
|
|
313
|
-
3. Zoom to 400%
|
|
314
|
-
- Verify no horizontal scrolling
|
|
315
|
-
- Verify content reflows appropriately
|
|
316
|
-
```
|
|
92
|
+
const focusedElement = await page.locator(':focus');
|
|
93
|
+
const outline = await focusedElement.evaluate(el =>
|
|
94
|
+
getComputedStyle(el).outline
|
|
95
|
+
);
|
|
317
96
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
/* ✅ GOOD: Relative units */
|
|
321
|
-
body {
|
|
322
|
-
font-size: 1rem; /* 16px default */
|
|
323
|
-
}
|
|
324
|
-
h1 {
|
|
325
|
-
font-size: 2rem; /* 32px default */
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/* ❌ BAD: Fixed pixel sizes */
|
|
329
|
-
body {
|
|
330
|
-
font-size: 12px; /* Doesn't scale with user preferences */
|
|
331
|
-
}
|
|
97
|
+
expect(outline).not.toBe('none');
|
|
98
|
+
});
|
|
332
99
|
```
|
|
333
100
|
|
|
334
101
|
---
|
|
335
102
|
|
|
336
|
-
## Automated Testing
|
|
337
|
-
|
|
338
|
-
### 1. axe-core Integration
|
|
103
|
+
## Automated Testing with axe-core
|
|
339
104
|
|
|
340
|
-
**Install:**
|
|
341
|
-
```bash
|
|
342
|
-
npm install --save-dev @axe-core/playwright
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
**Playwright Example:**
|
|
346
105
|
```javascript
|
|
347
106
|
import { test, expect } from '@playwright/test';
|
|
348
107
|
import AxeBuilder from '@axe-core/playwright';
|
|
349
108
|
|
|
350
|
-
test('
|
|
351
|
-
await page.goto('
|
|
109
|
+
test('page has no accessibility violations', async ({ page }) => {
|
|
110
|
+
await page.goto('/');
|
|
352
111
|
|
|
353
|
-
const
|
|
354
|
-
.withTags(['wcag2a', 'wcag2aa', '
|
|
112
|
+
const results = await new AxeBuilder({ page })
|
|
113
|
+
.withTags(['wcag2a', 'wcag2aa', 'wcag22aa'])
|
|
355
114
|
.analyze();
|
|
356
115
|
|
|
357
|
-
expect(
|
|
116
|
+
expect(results.violations).toEqual([]);
|
|
358
117
|
});
|
|
359
118
|
|
|
360
|
-
|
|
361
|
-
|
|
119
|
+
// CI/CD integration
|
|
120
|
+
test('checkout flow accessible', async ({ page }) => {
|
|
121
|
+
await page.goto('/checkout');
|
|
362
122
|
|
|
363
123
|
const results = await new AxeBuilder({ page })
|
|
364
|
-
.include('#
|
|
124
|
+
.include('#checkout-form')
|
|
125
|
+
.disableRules(['color-contrast']) // Fix in next sprint
|
|
365
126
|
.analyze();
|
|
366
127
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
);
|
|
371
|
-
|
|
372
|
-
expect(allowedViolations).toEqual([]);
|
|
128
|
+
expect(results.violations.filter(v =>
|
|
129
|
+
v.impact === 'critical' || v.impact === 'serious'
|
|
130
|
+
)).toHaveLength(0);
|
|
373
131
|
});
|
|
374
132
|
```
|
|
375
133
|
|
|
376
|
-
**CI/CD Integration:**
|
|
377
|
-
```yaml
|
|
378
|
-
# .github/workflows/a11y.yml
|
|
379
|
-
name: Accessibility Tests
|
|
380
|
-
|
|
381
|
-
on: [pull_request]
|
|
382
|
-
|
|
383
|
-
jobs:
|
|
384
|
-
a11y:
|
|
385
|
-
runs-on: ubuntu-latest
|
|
386
|
-
steps:
|
|
387
|
-
- uses: actions/checkout@v3
|
|
388
|
-
- uses: actions/setup-node@v3
|
|
389
|
-
- run: npm ci
|
|
390
|
-
- run: npm run test:a11y
|
|
391
|
-
|
|
392
|
-
- name: Upload a11y results
|
|
393
|
-
if: failure()
|
|
394
|
-
uses: actions/upload-artifact@v3
|
|
395
|
-
with:
|
|
396
|
-
name: axe-results
|
|
397
|
-
path: a11y-results/
|
|
398
|
-
```
|
|
399
|
-
|
|
400
134
|
---
|
|
401
135
|
|
|
402
|
-
|
|
136
|
+
## Screen Reader Testing Checklist
|
|
403
137
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
"standard": "WCAG2AA",
|
|
414
|
-
"timeout": 30000,
|
|
415
|
-
"wait": 1000,
|
|
416
|
-
"chromeLaunchConfig": {
|
|
417
|
-
"args": ["--no-sandbox"]
|
|
418
|
-
},
|
|
419
|
-
"runners": [
|
|
420
|
-
"axe",
|
|
421
|
-
"htmlcs"
|
|
422
|
-
],
|
|
423
|
-
"ignore": [
|
|
424
|
-
"color-contrast" // Temporarily ignore while fixing
|
|
425
|
-
]
|
|
426
|
-
}
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
**Usage:**
|
|
430
|
-
```javascript
|
|
431
|
-
const pa11y = require('pa11y');
|
|
432
|
-
|
|
433
|
-
async function runA11yTests() {
|
|
434
|
-
const results = await pa11y('https://example.com', {
|
|
435
|
-
standard: 'WCAG2AA',
|
|
436
|
-
includeWarnings: true,
|
|
437
|
-
includeNotices: false
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
console.log(`Found ${results.issues.length} issues`);
|
|
441
|
-
|
|
442
|
-
results.issues.forEach(issue => {
|
|
443
|
-
console.log(`${issue.type}: ${issue.message}`);
|
|
444
|
-
console.log(`Element: ${issue.selector}`);
|
|
445
|
-
console.log(`Code: ${issue.code}\n`);
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
---
|
|
451
|
-
|
|
452
|
-
### 3. Lighthouse Accessibility Audit
|
|
453
|
-
|
|
454
|
-
**Chrome DevTools:**
|
|
455
|
-
```
|
|
456
|
-
1. Open DevTools (F12)
|
|
457
|
-
2. Go to Lighthouse tab
|
|
458
|
-
3. Select "Accessibility" category
|
|
459
|
-
4. Click "Analyze page load"
|
|
460
|
-
5. Review score and recommendations
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
**Programmatic:**
|
|
464
|
-
```javascript
|
|
465
|
-
const lighthouse = require('lighthouse');
|
|
466
|
-
const chromeLauncher = require('chrome-launcher');
|
|
467
|
-
|
|
468
|
-
async function runLighthouse() {
|
|
469
|
-
const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
|
|
470
|
-
|
|
471
|
-
const options = {
|
|
472
|
-
logLevel: 'info',
|
|
473
|
-
output: 'html',
|
|
474
|
-
onlyCategories: ['accessibility'],
|
|
475
|
-
port: chrome.port
|
|
476
|
-
};
|
|
477
|
-
|
|
478
|
-
const runnerResult = await lighthouse('https://example.com', options);
|
|
479
|
-
|
|
480
|
-
const accessibilityScore = runnerResult.lhr.categories.accessibility.score * 100;
|
|
481
|
-
console.log(`Accessibility Score: ${accessibilityScore}`);
|
|
482
|
-
|
|
483
|
-
await chrome.kill();
|
|
484
|
-
}
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
---
|
|
488
|
-
|
|
489
|
-
## ARIA Best Practices
|
|
490
|
-
|
|
491
|
-
### When to Use ARIA
|
|
492
|
-
|
|
493
|
-
**First Rule of ARIA:** Don't use ARIA if you can use native HTML
|
|
494
|
-
|
|
495
|
-
```html
|
|
496
|
-
<!-- ❌ BAD: ARIA on native element -->
|
|
497
|
-
<div role="button" tabindex="0" onclick="submit()">Submit</div>
|
|
498
|
-
|
|
499
|
-
<!-- ✅ GOOD: Native element -->
|
|
500
|
-
<button onclick="submit()">Submit</button>
|
|
501
|
-
|
|
502
|
-
<!-- ✅ ARIA OK: Custom component with no native equivalent -->
|
|
503
|
-
<div role="tablist">
|
|
504
|
-
<button role="tab" aria-selected="true">Tab 1</button>
|
|
505
|
-
<button role="tab" aria-selected="false">Tab 2</button>
|
|
506
|
-
</div>
|
|
138
|
+
```markdown
|
|
139
|
+
## VoiceOver (macOS) Testing
|
|
140
|
+
- [ ] Page title announced on load
|
|
141
|
+
- [ ] Headings hierarchy correct (h1 → h2 → h3)
|
|
142
|
+
- [ ] Landmarks present (nav, main, footer)
|
|
143
|
+
- [ ] Images have descriptive alt text
|
|
144
|
+
- [ ] Form labels read correctly
|
|
145
|
+
- [ ] Error messages announced
|
|
146
|
+
- [ ] Dynamic content updates announced (aria-live)
|
|
507
147
|
```
|
|
508
148
|
|
|
509
149
|
---
|
|
510
150
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
**Landmark Roles:**
|
|
514
|
-
```html
|
|
515
|
-
<header role="banner">Site header</header>
|
|
516
|
-
<nav role="navigation">Main navigation</nav>
|
|
517
|
-
<main role="main">Main content</main>
|
|
518
|
-
<aside role="complementary">Sidebar</aside>
|
|
519
|
-
<footer role="contentinfo">Site footer</footer>
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
**Live Regions:**
|
|
523
|
-
```html
|
|
524
|
-
<!-- Polite: Announces when convenient -->
|
|
525
|
-
<div role="status" aria-live="polite" aria-atomic="true">
|
|
526
|
-
3 items added to cart
|
|
527
|
-
</div>
|
|
528
|
-
|
|
529
|
-
<!-- Assertive: Announces immediately -->
|
|
530
|
-
<div role="alert" aria-live="assertive">
|
|
531
|
-
Error: Payment failed. Please try again.
|
|
532
|
-
</div>
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
**Form Accessibility:**
|
|
536
|
-
```html
|
|
537
|
-
<label for="username">Username</label>
|
|
538
|
-
<input
|
|
539
|
-
type="text"
|
|
540
|
-
id="username"
|
|
541
|
-
aria-required="true"
|
|
542
|
-
aria-describedby="username-help username-error"
|
|
543
|
-
>
|
|
544
|
-
<span id="username-help">Choose a unique username</span>
|
|
545
|
-
<span id="username-error" role="alert" class="error">
|
|
546
|
-
Username already taken
|
|
547
|
-
</span>
|
|
548
|
-
```
|
|
549
|
-
|
|
550
|
-
**Modals/Dialogs:**
|
|
551
|
-
```html
|
|
552
|
-
<div
|
|
553
|
-
role="dialog"
|
|
554
|
-
aria-labelledby="dialog-title"
|
|
555
|
-
aria-describedby="dialog-desc"
|
|
556
|
-
aria-modal="true"
|
|
557
|
-
>
|
|
558
|
-
<h2 id="dialog-title">Confirm Action</h2>
|
|
559
|
-
<p id="dialog-desc">Are you sure you want to delete?</p>
|
|
560
|
-
<button onclick="confirmDelete()">Confirm</button>
|
|
561
|
-
<button onclick="closeDialog()">Cancel</button>
|
|
562
|
-
</div>
|
|
563
|
-
```
|
|
564
|
-
|
|
565
|
-
---
|
|
566
|
-
|
|
567
|
-
## Common Accessibility Issues
|
|
568
|
-
|
|
569
|
-
### Issue 1: Missing Alt Text
|
|
570
|
-
```html
|
|
571
|
-
<!-- ❌ Problem -->
|
|
572
|
-
<img src="chart.png">
|
|
573
|
-
|
|
574
|
-
<!-- ✅ Solution -->
|
|
575
|
-
<img src="chart.png" alt="Sales growth chart showing 25% increase in Q4">
|
|
576
|
-
|
|
577
|
-
<!-- ✅ Decorative images -->
|
|
578
|
-
<img src="decorative-line.png" alt="" role="presentation">
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
---
|
|
582
|
-
|
|
583
|
-
### Issue 2: Empty Links
|
|
584
|
-
```html
|
|
585
|
-
<!-- ❌ Problem -->
|
|
586
|
-
<a href="/products">
|
|
587
|
-
<img src="icon.png" alt="">
|
|
588
|
-
</a>
|
|
589
|
-
|
|
590
|
-
<!-- ✅ Solution -->
|
|
591
|
-
<a href="/products">
|
|
592
|
-
<img src="icon.png" alt="View all products">
|
|
593
|
-
</a>
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
---
|
|
597
|
-
|
|
598
|
-
### Issue 3: Form Labels Missing
|
|
599
|
-
```html
|
|
600
|
-
<!-- ❌ Problem -->
|
|
601
|
-
<input type="text" placeholder="Email">
|
|
602
|
-
|
|
603
|
-
<!-- ✅ Solution -->
|
|
604
|
-
<label for="email">Email Address</label>
|
|
605
|
-
<input type="email" id="email" placeholder="you@example.com">
|
|
606
|
-
|
|
607
|
-
<!-- ✅ Alternative: aria-label -->
|
|
608
|
-
<input
|
|
609
|
-
type="email"
|
|
610
|
-
aria-label="Email Address"
|
|
611
|
-
placeholder="you@example.com"
|
|
612
|
-
>
|
|
613
|
-
```
|
|
614
|
-
|
|
615
|
-
---
|
|
616
|
-
|
|
617
|
-
### Issue 4: Poor Focus Management
|
|
618
|
-
```javascript
|
|
619
|
-
// ❌ Problem: Focus lost when modal opens
|
|
620
|
-
function openModal() {
|
|
621
|
-
document.getElementById('modal').style.display = 'block';
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// ✅ Solution: Manage focus properly
|
|
625
|
-
function openModal() {
|
|
626
|
-
const modal = document.getElementById('modal');
|
|
627
|
-
const previouslyFocused = document.activeElement;
|
|
628
|
-
|
|
629
|
-
modal.style.display = 'block';
|
|
630
|
-
modal.querySelector('button').focus(); // Focus first button
|
|
631
|
-
|
|
632
|
-
// Trap focus within modal
|
|
633
|
-
modal.addEventListener('keydown', (e) => {
|
|
634
|
-
if (e.key === 'Tab') {
|
|
635
|
-
trapFocus(modal, e);
|
|
636
|
-
}
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
// Restore focus on close
|
|
640
|
-
modal.dataset.previousFocus = previouslyFocused;
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
function closeModal() {
|
|
644
|
-
const modal = document.getElementById('modal');
|
|
645
|
-
modal.style.display = 'none';
|
|
646
|
-
|
|
647
|
-
// Restore focus
|
|
648
|
-
const previousFocus = document.querySelector(modal.dataset.previousFocus);
|
|
649
|
-
if (previousFocus) previousFocus.focus();
|
|
650
|
-
}
|
|
651
|
-
```
|
|
652
|
-
|
|
653
|
-
---
|
|
654
|
-
|
|
655
|
-
## Using with QE Agents
|
|
656
|
-
|
|
657
|
-
### qe-accessibility-validator: Automated Compliance
|
|
151
|
+
## Agent-Driven Accessibility
|
|
658
152
|
|
|
659
153
|
```typescript
|
|
660
|
-
//
|
|
661
|
-
|
|
154
|
+
// Comprehensive a11y validation
|
|
155
|
+
await Task("Accessibility Validation", {
|
|
662
156
|
url: 'https://example.com/checkout',
|
|
663
157
|
standard: 'WCAG2.2',
|
|
664
158
|
level: 'AA',
|
|
159
|
+
checks: ['keyboard', 'screen-reader', 'color-contrast'],
|
|
665
160
|
includeScreenReaderSimulation: true
|
|
666
|
-
});
|
|
161
|
+
}, "qe-visual-tester");
|
|
667
162
|
|
|
668
|
-
//
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
//
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
// navigation: 'good',
|
|
679
|
-
// formLabels: 'needs-improvement',
|
|
680
|
-
// landmarkStructure: 'excellent'
|
|
681
|
-
// }
|
|
682
|
-
// }
|
|
163
|
+
// Fleet coordination for comprehensive testing
|
|
164
|
+
const a11yFleet = await FleetManager.coordinate({
|
|
165
|
+
strategy: 'comprehensive-accessibility',
|
|
166
|
+
agents: [
|
|
167
|
+
'qe-visual-tester', // Visual & keyboard checks
|
|
168
|
+
'qe-test-generator', // Generate a11y tests
|
|
169
|
+
'qe-quality-gate' // Enforce compliance
|
|
170
|
+
],
|
|
171
|
+
topology: 'parallel'
|
|
172
|
+
});
|
|
683
173
|
```
|
|
684
174
|
|
|
685
175
|
---
|
|
686
176
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
```typescript
|
|
690
|
-
// Agent validates focus indicators
|
|
691
|
-
await agent.visualA11yTest({
|
|
692
|
-
page: '/signup',
|
|
693
|
-
checks: ['focus-visible', 'keyboard-navigation', 'tab-order'],
|
|
694
|
-
generateReport: true
|
|
695
|
-
});
|
|
177
|
+
## Agent Coordination Hints
|
|
696
178
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
179
|
+
### Memory Namespace
|
|
180
|
+
```
|
|
181
|
+
aqe/accessibility/
|
|
182
|
+
├── wcag-results/* - WCAG audit results
|
|
183
|
+
├── screen-reader/* - Screen reader test logs
|
|
184
|
+
├── remediation/* - Fix recommendations
|
|
185
|
+
└── compliance/* - Compliance reports
|
|
701
186
|
```
|
|
702
187
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
### Fleet Coordination for Comprehensive A11y
|
|
706
|
-
|
|
188
|
+
### Fleet Coordination
|
|
707
189
|
```typescript
|
|
708
190
|
const a11yFleet = await FleetManager.coordinate({
|
|
709
|
-
strategy: '
|
|
191
|
+
strategy: 'accessibility-testing',
|
|
710
192
|
agents: [
|
|
711
|
-
'qe-
|
|
712
|
-
'qe-
|
|
713
|
-
'qe-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
await a11yFleet.execute({
|
|
719
|
-
target: 'production-candidate',
|
|
720
|
-
wcagLevel: 'AA',
|
|
721
|
-
failOn: 'critical-violations',
|
|
722
|
-
generateRemediationGuide: true
|
|
193
|
+
'qe-visual-tester', // axe-core, keyboard, focus
|
|
194
|
+
'qe-test-generator', // Generate a11y test cases
|
|
195
|
+
'qe-quality-gate' // Block non-compliant builds
|
|
196
|
+
],
|
|
197
|
+
topology: 'parallel'
|
|
723
198
|
});
|
|
724
199
|
```
|
|
725
200
|
|
|
726
201
|
---
|
|
727
202
|
|
|
728
203
|
## Related Skills
|
|
729
|
-
|
|
730
|
-
**Core Testing:**
|
|
731
|
-
- [agentic-quality-engineering](../agentic-quality-engineering/) - Agent-driven a11y testing
|
|
732
|
-
- [regression-testing](../regression-testing/) - A11y in regression suite
|
|
733
204
|
- [visual-testing-advanced](../visual-testing-advanced/) - Visual a11y checks
|
|
734
|
-
|
|
735
|
-
**Specialized Testing:**
|
|
736
205
|
- [mobile-testing](../mobile-testing/) - Mobile a11y (VoiceOver, TalkBack)
|
|
737
|
-
- [
|
|
738
|
-
- [compliance-testing](../compliance-testing/) - Legal compliance (ADA)
|
|
206
|
+
- [compliance-testing](../compliance-testing/) - Legal compliance
|
|
739
207
|
|
|
740
208
|
---
|
|
741
209
|
|
|
742
210
|
## Remember
|
|
743
211
|
|
|
744
|
-
**
|
|
745
|
-
|
|
746
|
-
- 1 billion people with disabilities globally
|
|
747
|
-
- $13 trillion purchasing power
|
|
748
|
-
- 250%+ increase in lawsuits (2019-2024)
|
|
749
|
-
- ADA, Section 508, EU regulations enforced
|
|
750
|
-
|
|
751
|
-
**Automated testing catches only 30-50% of issues.**
|
|
752
|
-
|
|
753
|
-
Combine automated scans with:
|
|
754
|
-
- Manual keyboard testing
|
|
755
|
-
- Screen reader testing
|
|
756
|
-
- Real user testing with people with disabilities
|
|
212
|
+
**1 billion people have disabilities. Inaccessible software excludes 15% of humanity.** Legal requirements: ADA, Section 508, EU Directive 2016/2102. $13T purchasing power. 250%+ increase in lawsuits.
|
|
757
213
|
|
|
758
|
-
**
|
|
759
|
-
- Design with accessibility in mind
|
|
760
|
-
- Develop with semantic HTML + ARIA
|
|
761
|
-
- Test throughout development (not at the end)
|
|
762
|
-
- Include a11y in definition of done
|
|
214
|
+
**Automated testing catches only 30-50% of issues.** Combine with manual keyboard testing, screen reader testing, and real user testing with people with disabilities.
|
|
763
215
|
|
|
764
|
-
**With Agents:**
|
|
216
|
+
**With Agents:** Agents automate WCAG 2.2 compliance checking, screen reader simulation, and focus management validation. Use agents to enforce accessibility standards in CI/CD and catch violations before production.
|