@a11y-oracle/playwright-plugin

中文文档
1.3.2发布于 2026/03/12MITTypeScriptES Module近 30 天下载 3178

Playwright 为无障碍语音断言、键盘导航和焦点指标验证而设的测试固定

中文使用文档
文档目录14 节
  1. 安装
  2. 使用量
  3. 测试固定( 建议)
  4. 统一国家
  5. 标签顺序和键盘陷阱检测
  6. 审计和问题报告
  7. 自定义选项
  8. 手动使用
  9. API 参考
  10. A11yOracle
  11. 测试固定
  12. 出口
  13. 剧作家配置
  14. 如何运作

@a11y- oracle/ playwright- 插件

A11y-Oracle 的 Playwright 集成. 提供测试固定和包装类,通过Chrome DevTools协议读取浏览器的可访问树,发送本地键盘事件,并分析视觉焦点指标.

QQ 建议插件 . Playwright提供直接的一等CDP会话访问,使这成为A11y-Oracle最稳定和最能表现的集成. 如果您选择了 E2E 框架, 则使用此框架 .

import { test, expect } from '@a11y-oracle/playwright-plugin';

test('dropdown button announces correctly', async ({ page, a11y }) => {
  await page.goto('/dropdown-nav.html');

  const speech = await a11y.press('Tab');
  expect(speech).toContain('Home');
  expect(speech).toContain('menu item');
});

安装

npm install -D @a11y-oracle/playwright-plugin @a11y-oracle/core-engine @playwright/test

只有铬. Playwright的Firefox或WebKit不提供 CDP会话.

使用量

插件导出扩展名 test 函数 a11y 修补。 CDP会话在每次测试前创建,之后自动清理.

import { test, expect } from '@a11y-oracle/playwright-plugin';

test.describe('Navigation', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/my-page.html');
  });

  test('Tab to button announces name and role', async ({ a11y }) => {
    const speech = await a11y.press('Tab');
    expect(speech).toBe('Submit, button');
  });

  test('checkbox announces checked state', async ({ a11y }) => {
    await a11y.press('Tab');
    await a11y.press('Tab');
    const speech = await a11y.press('Space');
    expect(speech).toContain('checkbox');
    expect(speech).toContain('checked');
  });

  test('navigation landmark exists', async ({ a11y }) => {
    const tree = await a11y.getFullTreeSpeech();
    const nav = tree.find(r => r.speech.includes('navigation landmark'));
    expect(nav).toBeDefined();
  });
});

统一国家

这个 pressKey() 方法返回完整 A11yState 将语音输出、重点要素信息和重点指标分析结合起来的快照:

test('focus indicator meets WCAG 2.4.12 AA', async ({ page, a11y }) => {
  await page.goto('/my-page.html');

  const state = await a11y.pressKey('Tab');

  // Speech
  expect(state.speech).toContain('Submit');
  expect(state.speechResult?.role).toBe('button');

  // Focused element
  expect(state.focusedElement?.tag).toBe('BUTTON');
  expect(state.focusedElement?.id).toBe('submit-btn');
  expect(state.focusedElement?.tabIndex).toBe(0);

  // Focus indicator CSS analysis
  expect(state.focusIndicator.isVisible).toBe(true);
  expect(state.focusIndicator.contrastRatio).toBeGreaterThanOrEqual(3.0);
  expect(state.focusIndicator.meetsWCAG_AA).toBe(true);
});

test('Shift+Tab navigates backward', async ({ page, a11y }) => {
  await page.goto('/my-page.html');

  await a11y.pressKey('Tab');
  const state1 = await a11y.pressKey('Tab');
  const state2 = await a11y.pressKey('Tab', { shift: true });

  expect(state2.focusedElement?.id).toBe(state1.focusedElement?.id);
});

标签顺序和键盘陷阱检测

test('page has correct tab order', async ({ page, a11y }) => {
  await page.goto('/my-page.html');

  const report = await a11y.traverseTabOrder();
  expect(report.totalCount).toBeGreaterThan(0);
  expect(report.entries[0].tag).toBe('A');
});

test('modal does not trap keyboard focus', async ({ page, a11y }) => {
  await page.goto('/modal.html');

  const result = await a11y.traverseSubTree('#modal-container', 20);
  expect(result.isTrapped).toBe(false);
  expect(result.escapeElement).not.toBeNull();
});

审计和问题报告

使用 OracleAuditor 从 @a11y-oracle/audit-formatter 自动检查 WCAG 对每次交互的规则并积累任何问题:

npm install -D @a11y-oracle/audit-formatter
import { test, expect } from '@a11y-oracle/playwright-plugin';
import { OracleAuditor } from '@a11y-oracle/audit-formatter';

test('all focus indicators pass oracle rules', async ({ page, a11y }) => {
  await page.goto('/my-page.html');

  const auditor = new OracleAuditor(a11y, {
    project: 'my-app',
    specName: 'navigation.spec.ts',
  });

  // Each pressKey() automatically checks all 5 state-based rules
  await auditor.pressKey('Tab');
  await auditor.pressKey('Tab');
  await auditor.pressKey('Tab');

  // checkTrap() automatically checks keyboard-trap
  await auditor.checkTrap('#modal-container');

  // Assert no issues found across all interactions
  expect(auditor.getIssues()).toHaveLength(0);
});

在套件末尾将问题写入 JSON 报告文件:

import { test } from '@a11y-oracle/playwright-plugin';
import { OracleAuditor, type OracleIssue } from '@a11y-oracle/audit-formatter';
import * as fs from 'fs';

const allIssues: OracleIssue[] = [];

test('check page focus indicators', async ({ page, a11y }) => {
  await page.goto('/my-page.html');
  const auditor = new OracleAuditor(a11y, {
    project: 'my-app',
    specName: 'nav.spec.ts',
  });

  await auditor.pressKey('Tab');
  await auditor.pressKey('Tab');
  allIssues.push(...auditor.getIssues());
});

test.afterAll(() => {
  if (allIssues.length > 0) {
    fs.writeFileSync('oracle-results.json', JSON.stringify(allIssues, null, 2));
  }
});

关于每项规则的详细补救指导意见,见 补救指南。 。 。 .

自定义选项

每个测试组覆盖语音引擎选项 test.use()数字 :

test.describe('without landmark suffix', () => {
  test.use({ a11yOptions: { includeLandmarks: false } });

  test('nav role without landmark', async ({ page, a11y }) => {
    await page.goto('/my-page.html');
    const tree = await a11y.getFullTreeSpeech();
    const nav = tree.find(r => r.role === 'navigation');
    expect(nav?.speech).toBe('Main, navigation');
  });
});

可用的选项 :

选项类型默认说明
includeLandmarksbooleantrue在标志性角色中添加"地印"
includeDescriptionbooleanfalse包含 aria-describedby 输出中的文本
focusSettleMsnumber50在按下焦点/ CSS 键后延迟

手动使用

如果需要对生命周期进行更多的控制(例如,附在某一页的中试),请使用 A11yOracle 直接分类 :

import { A11yOracle } from '@a11y-oracle/playwright-plugin';
import { test, expect } from '@playwright/test';

test('manual setup', async ({ page }) => {
  await page.goto('/my-page.html');

  const a11y = new A11yOracle(page, { includeDescription: true });
  await a11y.init();

  const speech = await a11y.press('Tab');
  expect(speech).toContain('button');

  await a11y.dispose();
});

API 参考

A11yOracle

管理 CDP 会话,并为当前页面提供访问测试.

constructor(page: Page, options?: A11yOrchestratorOptions)

创建新实例 .

  • page - 剧作家 Page 随附.
  • options.includeLandmarks ——将"地标"附录为地标性角色. 默认 true。 。 。 .
  • options.includeDescription - 包括说明案文。 默认 false。 。 。 .
  • options.focusSettleMs ——按键后延迟焦点/CSS结算. 默认 50。 。 。 .

init(): Promise<void>

打开 CDP 会话并启用无障碍域. 一定要在任何其他方法之前叫出来 测试固定器自动调用.

仅限发言的 API

press(key: string): Promise<string>

按键盘键( 通过 Playwright 键) page.keyboard.press()),并返回新聚焦元素的演讲. 如果没有元素焦点,则返回空字符串.

const speech = await a11y.press('Tab');
// "Products, button, collapsed"
getSpeech(): Promise<string>

获取当前焦点元素的语音字符串而不按键 .

getSpeechResult(): Promise<SpeechResult | null>

获取焦点元素的全部结构化结果.

getFullTreeSpeech(): Promise<SpeechResult[]>

在无障碍树上获取所有非被忽略的节点的语音.

统一国家

pressKey(key: string, modifiers?: ModifierKeys): Promise<A11yState>

通过本地 CDP 发送密钥 Input.dispatchKeyEvent 并返回统一无障碍状态。 与 press(),这使用硬件级别密钥发送并返回完整的状态.

const state = await a11y.pressKey('Tab');
// state.speech           → "Products, button, collapsed"
// state.focusedElement   → { tag: 'BUTTON', id: '...', ... }
// state.focusIndicator   → { isVisible: true, meetsWCAG_AA: true, ... }
getA11yState(): Promise<A11yState>

获取当前统一状态而不按键 .

await page.focus('#my-button');
const state = await a11y.getA11yState();
traverseTabOrder(): Promise<TabOrderReport>

在 DOM 标签顺序中提取所有可制表元素 .

traverseSubTree(selector: string, maxTabs?: number): Promise<TraversalResult>

检测容器是否夹住键盘焦点(WCAG 2.1.2).

生命周期

dispose(): Promise<void>

解开社发委会会会会和免费资源. 测试固定器自动调用.

测试固定

这个 test 导出扩展 Playwright 的 test 有两个固定装置:

固定线类型说明
a11yA11yOracle初始化实例, 每次测试后自动处理
a11yOptionsA11yOrchestratorOptions通过 test.use()

出口

// Test fixture (recommended)
export { test, expect } from '@a11y-oracle/playwright-plugin';

// Manual usage
export { A11yOracle } from '@a11y-oracle/playwright-plugin';

// Fixture types
export type { A11yOracleFixtures } from '@a11y-oracle/playwright-plugin';

// Re-exported types from core-engine
export type {
  A11yState,
  A11yFocusedElement,
  A11yFocusIndicator,
  A11yOrchestratorOptions,
  SpeechResult,
  SpeechEngineOptions,
  ModifierKeys,
  TabOrderReport,
  TabOrderEntry,
  TraversalResult,
  FocusIndicator,
} from '@a11y-oracle/playwright-plugin';

剧作家配置

插件需要铬. 一个典型 playwright.config.ts数字 :

import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    baseURL: 'http://localhost:4200',
  },
  projects: [
    {
      name: 'chromium',
      use: { browserName: 'chromium' },
    },
  ],
  webServer: {
    command: 'npm run serve',
    url: 'http://localhost:4200',
    reuseExistingServer: !process.env.CI,
  },
});

如何运作

  1. 固定会话通过 page.context().newCDPSession(page)
  2. 它创造了两个 SpeechEngine 还有一个 A11yOrchestrator 该届会议的报告
  3. press(key) ——使用 Playwright 的键盘 API,等待50ms,然后读取 AXTree 的语音
  4. pressKey(key) 使用本地CDP Input.dispatchKeyEvent 用于硬件级别发送, 等等 focusSettleMs,然后同时收集语音+焦点要素+焦点指标
  5. 重点指标分析 Runtime.evaluate 读取计算 CSS 样式并计算对比率
  6. 在处置时, CPP 会话是分开的

语音格式如下: [Computed Name], [Role], [State/Properties]

关于角色和状态图的完整清单,见 @a11y- oracle/ 核心引擎 README。 。 。 .

版本与发布记录

@a11y-oracle/playwright-plugin 共发布 10 个版本,首次发布于 2026/03/05;过去 12 个月发布了 10 个版本。

版本发布日期距今
1.3.2latest2026/03/127 个月前
1.3.12026/03/117 个月前
1.3.02026/03/068 个月前
1.2.02026/03/068 个月前
1.1.42026/03/068 个月前
1.1.32026/03/068 个月前

关于 @a11y-oracle/playwright-plugin 的常见问题

@a11y-oracle/playwright-plugin 是什么?

Playwright 为无障碍语音断言、键盘导航和焦点指标验证而设的测试固定

如何安装 @a11y-oracle/playwright-plugin?

在项目目录运行 npm install @a11y-oracle/playwright-plugin,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@playwright/test(>=1.40.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@a11y-oracle/playwright-plugin 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@a11y-oracle/playwright-plugin 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@a11y-oracle/playwright-plugin 可以商用吗?

@a11y-oracle/playwright-plugin 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@a11y-oracle/playwright-plugin 的下载量有多少?

根据 npm 官方下载统计,@a11y-oracle/playwright-plugin 在 2026/10/05 – 2026/11/03 这 30 天内被下载 3,178 次,日均约 106 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@a11y-oracle/playwright-plugin 还在维护吗?

最新版本 1.3.2 发布于 2026/03/12(7 个月前);至今共发布 10 个版本,其中过去 12 个月发布了 10 个;首次发布于 2026/03/05。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。