跳到正文
cccskills
免费在 GitHub 公开

a11y-playwright-testing

Accessibility testing for web applications using Playwright (@playwright/test) with TypeScript and axe-core. Use when asked to write, run, or debug automated accessibility checks, keyboard navigation tests, focus management, ARIA/semantic validations, screen reader compatibility, or WCAG 2.1 Level AA compliance testing. Covers axe-core integration, POUR principles (perceivable, operable, understandable, robust), color contrast, form labels, landmarks, and accessible names.

中文简介正在准备中。当前显示原文说明。

集成工具Playwright
查看安装方法

包含的文件(2)

  • SKILL.md13.2 KB
  • source.json1.0 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Playwright Accessibility Testing (TypeScript)

Comprehensive toolkit for automated accessibility testing using Playwright with TypeScript and axe-core. Enables WCAG 2.1 Level AA compliance verification, keyboard operability testing, semantic validation, and accessibility regression prevention.

Activation: This skill is triggered when working with accessibility testing, WCAG compliance, axe-core scans, keyboard navigation tests, focus management, ARIA validation, or screen reader compatibility.

When to Use This Skill

  • Automated a11y scans with axe-core for WCAG 2.1 AA compliance
  • Keyboard navigation tests for Tab/Enter/Space/Escape/Arrow key operability
  • Focus management validation for dialogs, menus, and dynamic content
  • Semantic structure assertions for landmarks, headings, and ARIA
  • Form accessibility testing for labels, errors, and instructions
  • Color contrast and visual accessibility verification
  • Screen reader compatibility testing patterns

Prerequisites

RequirementDetails
Node.jsv18+ recommended
Playwright@playwright/test installed
axe-core@axe-core/playwright package
TypeScriptConfigured in project

Quick Setup

# Add axe-core to existing Playwright project
npm install -D @axe-core/playwright axe-core

First Questions to Ask

Before writing accessibility tests, clarify:

  1. Scope: Which pages/flows are in scope? What's explicitly excluded?
  2. Standard: WCAG 2.1 AA (default) or specific organizational policy?
  3. Priority: Which components are highest risk (forms, modals, navigation, checkout)?
  4. Exceptions: Known constraints (legacy markup, third-party widgets)?
  5. Assistive Tech: Which screen readers/browsers need manual testing?

Core Principles

1. Automation Limitations

⚠️ Critical: Automated tooling can detect ~30-40% of accessibility issues. Use automation to prevent regressions and catch common failures; manual audits are required for full WCAG conformance.

2. Semantic HTML First

Prefer native HTML semantics over ARIA. Use ARIA only when native elements cannot achieve the required semantics.

// ✅ Semantic HTML - inherently accessible
await page.getByRole("button", { name: "Submit" }).click();

// ❌ ARIA override - requires manual keyboard/focus handling
await page.locator('[role="button"]').click(); // Often a <div>

3. Locator Strategy as A11y Signal

If you cannot locate an element by role or label, it's often an accessibility defect.

Locator SuccessAccessibility Signal
getByRole('button', { name: 'Submit' }) ✅Button has accessible name
getByLabel('Email') ✅Input properly labeled
getByRole('navigation') ✅Landmark exists
locator('.submit-btn') ⚠️May lack accessible name

Key Workflows

Automated Axe Scan (WCAG 2.1 AA)

import AxeBuilder from "@axe-core/playwright";
import { test, expect } from "@playwright/test";

test("page has no WCAG 2.1 AA violations", async ({ page }) => {
  await page.goto("/");

  const results = await new AxeBuilder({ page })
    .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"])
    .analyze();

  expect(results.violations).toEqual([]);
});

Scoped Axe Scan (Component-Level)

test("form component is accessible", async ({ page }) => {
  await page.goto("/contact");

  const results = await new AxeBuilder({ page })
    .include("#contact-form") // Scope to specific component
    .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"])
    .analyze();

  expect(results.violations).toEqual([]);
});

Keyboard Navigation Test

test("form is keyboard navigable", async ({ page }) => {
  await page.goto("/login");

  // Tab to first field
  await page.keyboard.press("Tab");
  await expect(page.getByLabel("Email")).toBeFocused();

  // Tab to password
  await page.keyboard.press("Tab");
  await expect(page.getByLabel("Password")).toBeFocused();

  // Tab to submit button
  await page.keyboard.press("Tab");
  await expect(page.getByRole("button", { name: "Sign in" })).toBeFocused();

  // Submit with Enter
  await page.keyboard.press("Enter");
  await expect(page).toHaveURL(/dashboard/);
});

Dialog Focus Management

test("dialog traps and returns focus", async ({ page }) => {
  await page.goto("/settings");
  const trigger = page.getByRole("button", { name: "Delete account" });

  // Open dialog
  await trigger.click();
  const dialog = page.getByRole("dialog");
  await expect(dialog).toBeVisible();

  // Focus should be inside dialog
  await expect(dialog.getByRole("button", { name: "Cancel" })).toBeFocused();

  // Tab should stay trapped in dialog
  await page.keyboard.press("Tab");
  await expect(dialog.getByRole("button", { name: "Confirm" })).toBeFocused();
  await page.keyboard.press("Tab");
  await expect(dialog.getByRole("button", { name: "Cancel" })).toBeFocused();

  // Escape closes and returns focus to trigger
  await page.keyboard.press("Escape");
  await expect(dialog).toBeHidden();
  await expect(trigger).toBeFocused();
});

Skip Link Validation

test("skip link moves focus to main content", async ({ page }) => {
  await page.goto("/");

  // First Tab should focus skip link
  await page.keyboard.press("Tab");
  const skipLink = page.getByRole("link", { name: /skip to (main|content)/i });
  await expect(skipLink).toBeFocused();

  // Activating skip link moves focus to main
  await page.keyboard.press("Enter");
  await expect(page.locator('#main, [role="main"]').first()).toBeFocused();
});

POUR Principles Reference

PrincipleFocus AreasExample Tests
PerceivableAlt text, captions, contrast, structureImage alternatives, color contrast ratio
OperableKeyboard, focus, timing, navigationTab order, focus visibility, skip links
UnderstandableLabels, instructions, errors, consistencyForm labels, error messages, predictable behavior
RobustValid HTML, ARIA, name/role/valueSemantic structure, accessible names

Axe-Core Tags Reference

TagWCAG LevelUse Case
wcag2aLevel AMinimum compliance
wcag2aaLevel AAStandard target
wcag2aaaLevel AAAEnhanced (rarely full)
wcag21a2.1 Level AWCAG 2.1 specific A
wcag21aa2.1 Level AAWCAG 2.1 standard
best-practiceBeyond WCAGAdditional recommendations

Default Tags (WCAG 2.1 AA)

const WCAG21AA_TAGS = ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"];

Exception Handling

When exceptions are unavoidable:

  1. Scope narrowly - specific component/route only
  2. Document impact - which WCAG criterion, user impact
  3. Set expiration - owner + remediation date
  4. Track ticket - link to remediation issue
// ❌ Avoid: Global rule disable
new AxeBuilder({ page }).disableRules(["color-contrast"]);

// ✅ Better: Scoped exclusion with documentation
new AxeBuilder({ page })
  .exclude("#third-party-widget") // Known issue: JIRA-1234, fix by Q2
  .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"])
  .analyze();

Troubleshooting

ProblemCauseSolution
Axe finds 0 violations but app fails manual auditAutomation covers ~30-40%Add manual testing checklist
False positive on dynamic contentContent not fully renderedWait for stable state before scan
Color contrast fails incorrectlyBackground image/gradientUse exclude for known false positives
Cannot find element by roleMissing semantic HTMLFix markup - this is a real bug
Focus not visibleMissing :focus stylesAdd visible focus indicator CSS
Dialog focus not trappedMissing focus trap logicImplement focus trap (see snippets)
Skip link doesn't workTarget missing tabindex="-1"Add tabindex to main content

CLI Quick Reference

CommandDescription
npx playwright test --grep "a11y"Run accessibility tests only
npx playwright test --headedRun with visible browser for debugging
npx playwright test --debugStep through with Inspector
PWDEBUG=1 npx playwright testDebug mode with pause

Common Rationalizations

Common shortcuts and "good enough" excuses that erode test quality — and the reality behind each.

RationalizationReality
"Accessibility can be tested manually later"Automated a11y catches 30-57% of issues instantly. Write a11y tests now, not after release.
"axe-core catches everything"axe covers ~30-50% of WCAG criteria. Manual review and keyboard testing are still required.
"Color contrast is a design concern"It's a legal requirement under WCAG 2.1 AA 1.4.3. Automated contrast checks take zero effort.
"Keyboard navigation tests are optional"Keyboard-only users represent ~10% of your audience. Tab order and focus traps are testable.
"Screen reader testing is too hard to automate"ARIA role and label validation via Playwright catches most structural issues without a real screen reader.
"A11y only matters for public-sector sites"ADA lawsuits target e-commerce, SaaS, and private companies. Non-compliance is expensive.

References

DocumentContent
Snippetsaxe-core setup, helpers, keyboard/focus patterns
WCAG 2.1 AA ChecklistManual audit checklist by POUR principle
ARIA PatternsCommon ARIA widget patterns and validations

External Resources

ResourceURL
WCAG 2.1 Specificationhttps://www.w3.org/TR/WCAG21/
WCAG Quick Referencehttps://www.w3.org/WAI/WCAG21/quickref/
WAI-ARIA Authoring Practiceshttps://www.w3.org/WAI/ARIA/apg/
axe-core Ruleshttps://dequeuniversity.com/rules/axe/

Verification

After completing this skill's workflow, confirm:

  • axe-core audit passes — AxeBuilder.analyze() returns zero violations
  • Keyboard navigation tested — All interactive elements reachable via Tab; focus order is logical
  • ARIA attributes valid — No duplicate IDs, no missing labels, roles match element types
  • Color contrast sufficient — WCAG 2.1 AA minimum contrast ratios met (4.5:1 normal text, 3:1 large text)
  • Screen reader compatible — All images have alt text; form inputs have labels; landmarks present
  • Accessibility scan integrated in CI — Accessibility tests run as part of the standard CI pipeline
  • Violation report generated — Axe results saved to file for review and tracking

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

007

免费

Security audit, hardening, threat modeling (STRIDE/PASTA), Red/Blue Team, OWASP checks, code review, incident response, and infrastructure security for any project.

中文简介正在准备中。当前显示原文说明。

aibot88/sec_skill_store52026年5月27日 更新

Guides the creation of agile user stories and Gherkin feature files. Use when the user wants to create a user story, write acceptance criteria, define Gherkin scenarios, or author BDD feature files. This should trigger for requests such as Create a user story; Write a user story; I need to write a user story. Part of cursor-rules-java project

中文简介正在准备中。当前显示原文说明。

aibot88/sec_skill_store52026年5月27日 更新

Facilitates conversational discovery to create Architectural Decision Records (ADRs) for non-functional requirements using the ISO/IEC 25010:2023 quality model. Use when the user wants to document quality attributes, NFR decisions, security/performance/scalability architecture, or design systems with measurable quality criteria. This should trigger for requests such as Create ADR for Non-functional requirements; Document Non-functional requirements; Capture Non-functional requirements; Generate Non-functional requirements in an ADR. Part of cursor-rules-java project

中文简介正在准备中。当前显示原文说明。

aibot88/sec_skill_store52026年5月27日 更新

Run a health check on an existing project: dependency audit, security scan, test runner detection, CI/CD evaluation, and missing configuration analysis. Maps the three execution gates (pre/in/post) from /10x-bootstrapper to an assessment framework for existing codebases. Reads optional context/foundation/stack-assessment.md from /10x-stack-assess to focus checks on identified gaps. Writes context/foundation/health-check.md with findings, prioritized fixes, and an agent-readiness verdict. Use when the user has an existing project and wants to verify its health before working with an agent. Trigger phrases: "health check", "check my project", "audit my project", "is my project healthy", "sprawdź projekt", "audyt projektu", "health-check", "project health". Use AFTER /10x-stack-assess (brownfield chain), BEFORE agent onboarding (m1-l4).

中文简介正在准备中。当前显示原文说明。

aibot88/sec_skill_store52026年5月27日 更新

10x-team

免费

You MUST use this when building projects end-to-end. Orchestrates all 12 team roles — automatically switches between CTO, architect, PM, engineers, SRE, security, DBA, QA, and EM based on the current phase of work. Starts with brainstorming before any implementation.

中文简介正在准备中。当前显示原文说明。

aibot88/sec_skill_store52026年5月27日 更新

Use when you need to add or configure Maven plugins in your pom.xml — including quality tools (enforcer, surefire, failsafe, jacoco, pitest, spotbugs, pmd), security scanning (OWASP), code formatting (Spotless), version management, container image build (Jib), build information tracking, and benchmarking (JMH) — through a consultative, modular step-by-step approach that only adds what you actually need. This should trigger for requests such as Add Maven plugins in pom.xml; Improve Maven plugins in pom.xml. Part of cursor-rules-java project

中文简介正在准备中。当前显示原文说明。

aibot88/sec_skill_store52026年5月27日 更新

查看 aibot88 的全部技能

报告此技能的问题