mcpField
P
playwright-testing

playwright-testing

github.com/community-accessテスト・品質431316 回インストール1 日前に更新
リポジトリ

playwright-testing について

PlaywrightでWebページをテストするチーム向けの、アクセシビリティテストの再利用可能なガイドです。キーボード操作、動的状態、ビューポート、コントラスト、アクセシビリティツリーを扱い、@axe-core/playwrightの例とテストテンプレートを含みます。

主な機能

  1. 01キーボード順序とトラップの検出
  2. 02操作後の状態スキャン
  3. 03ビューポートとタッチ対象の確認
  4. 04計算済みスタイルのコントラスト検査
  5. 05ブラウザーのアクセシビリティツリー取得

活用シーン

  1. 01キーボード操作とフォーカス管理の確認
  2. 02ダイアログやアコーディオンで表示される内容の検査
  3. 03CIでのアクセシビリティテスト実行

MCP 対応

READMEには、キーボード、状態、ビューポート、コントラスト、アクセシビリティツリーを検査するMCPツールが記載されています。一部のスキャンには@axe-core/playwrightが必要です。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/community-access/accessibility-agents --skill playwright-testing

インストール後、Claude Code で/playwright-testingを入力して読み込まれたか確認します。

詳細

Playwright によるアクセシビリティテスト

Playwright と @axe-core/playwright を使用した、ブラウザー上でのアクセシビリティテスト向け再利用可能なナレッジモジュールです。

利用可能な MCP ツール

ツール目的@axe-core/playwright が必要
run_playwright_keyboard_scanTab 順序の巡回、キーボードトラップの検出いいえ
run_playwright_state_scanクリックトリガー、axe-core による表示コンテンツのスキャンはい
run_playwright_viewport_scan複数ビューポートでの axe-core スキャン+タッチターゲットの測定はい
run_playwright_contrast_scanCSS カスケード適用後の計算済みスタイルによるコントラスト比いいえ
run_playwright_a11y_treeブラウザーのアクセシビリティツリーのスナップショットいいえ

@axe-core/playwright のパターン

ページ全体のスキャン
import AxeBuilder from '@axe-core/playwright';

const results = await new AxeBuilder({ page })
  .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
  .analyze();
要素を指定したスキャン
const results = await new AxeBuilder({ page })
  .include('.modal-content')
  .withTags(['wcag2a', 'wcag2aa'])
  .analyze();
単一ルールの検証
const results = await new AxeBuilder({ page })
  .include('#hero-image')
  .withRules(['image-alt'])
  .analyze();
expect(results.violations).toEqual([]);
インタラクション後のスキャン
await page.click('[aria-expanded="false"]');
await page.waitForSelector('.accordion-content', { state: 'visible' });
const results = await new AxeBuilder({ page })
  .include('.accordion-content')
  .analyze();

キーボード巡回のパターン

Tab の順序を記録する
const tabStops = [];
for (let i = 0; i < maxTabs; i++) {
  await page.keyboard.press('Tab');
  const info = await page.evaluate(() => {
    const el = document.activeElement;
    return {
      tagName: el?.tagName,
      role: el?.getAttribute('role'),
      name: el?.getAttribute('aria-label') || el?.textContent?.trim().slice(0, 50),
      id: el?.id,
      tabIndex: el?.tabIndex
    };
  });
  tabStops.push(info);
}
キーボードトラップを検出する

連続して Tab キーを押した後、同じ要素にフォーカスが戻る場合、キーボードトラップが検出されます。

let trapCount = 0;
let lastSelector = '';
for (const stop of tabStops) {
  const currentSelector = `${stop.tagName}#${stop.id}`;
  if (currentSelector === lastSelector) {
    trapCount++;
    if (trapCount >= 3) { /* TRAP DETECTED */ }
  } else {
    trapCount = 0;
  }
  lastSelector = currentSelector;
}
モーダルを開いた後のフォーカス管理
await page.click('[data-modal-trigger]');
await page.waitForSelector('[role="dialog"]', { state: 'visible' });
const focusedRole = await page.evaluate(() =>
  document.activeElement?.closest('[role="dialog"]') ? 'inside-dialog' : 'outside-dialog'
);
// focusedRole should be 'inside-dialog'

フォーカス管理テストのテンプレート

モーダルのフォーカストラップテスト
test('modal traps focus correctly', async ({ page }) => {
  await page.goto(url);
  await page.click('[data-open-modal]');
  await page.waitForSelector('[role="dialog"]', { state: 'visible' });

  // Focus should be inside the dialog
  const inDialog = await page.evaluate(() =>
    document.activeElement?.closest('[role="dialog"]') !== null
  );
  expect(inDialog).toBe(true);

  // Tab through dialog — should not escape
  for (let i = 0; i < 20; i++) {
    await page.keyboard.press('Tab');
    const stillInDialog = await page.evaluate(() =>
      document.activeElement?.closest('[role="dialog"]') !== null
    );
    expect(stillInDialog).toBe(true);
  }

  // Escape should close and return focus to trigger
  await page.keyboard.press('Escape');
  const focusedId = await page.evaluate(() => document.activeElement?.id);
  expect(focusedId).toBe('modal-trigger-id');
});
スキップリンクのテスト
test('skip link moves focus to main content', async ({ page }) => {
  await page.goto(url);
  await page.keyboard.press('Tab'); // Focus skip link
  await page.keyboard.press('Enter'); // Activate it
  const focusedId = await page.evaluate(() => document.activeElement?.id);
  expect(focusedId).toBe('main-content');
});

CI との統合

Playwright を使用した GitHub Actions
name: Accessibility Tests
on: [push, pull_request]

jobs:
  a11y:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx playwright install --with-deps chromium
      - name: Start dev server
        run: npm run dev &
        env:
          CI: true
      - name: Wait for server
        run: npx wait-on http://localhost:3000 --timeout 30000
      - name: Run accessibility tests
        run: npx playwright test tests/a11y/
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: a11y-test-results
          path: test-results/
アクセシビリティテスト用 Playwright 設定
// playwright.config.js (a11y section)
export default {
  testDir: './tests/a11y',
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
    // Use Chromium only — @axe-core/playwright is Chromium-validated
    browserName: 'chromium',
  },
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
};

段階的な機能低下

検出パターン
let _playwrightAvailable = null;
async function isPlaywrightAvailable() {
  if (_playwrightAvailable !== null) return _playwrightAvailable;
  try {
    await import('playwright');
    _playwrightAvailable = true;
  } catch {
    _playwrightAvailable = false;
  }
  return _playwrightAvailable;
}
機能低下マトリックス
Playwright@axe-core/playwright利用可能なスキャン
はいはい5 つのツールすべて(キーボード、状態、ビューポート、コントラスト、ツリー)
はいいいえ3 つのツール(キーボード、コントラスト、ツリー)
いいえ—なし — コードレビュー+axe-core CLI に切り替えます
ユーザー向けメッセージ

利用できない場合:

Playwright not installed. Behavioral testing (keyboard traversal, dynamic states,
responsive viewport, rendered contrast) is unavailable.

Install: npm install -D playwright @axe-core/playwright && npx playwright install chromium

一部の機能のみ利用できる場合:

@axe-core/playwright not installed. State scanning and viewport scanning are
unavailable. Keyboard, contrast, and accessibility tree scans will proceed.

Install: npm install -D @axe-core/playwright

WCAG 対応表

WCAG SC説明Playwright ツール
1.3.1情報と関係性a11y ツリー、状態スキャン
1.4.3コントラスト(最低限)コントラストスキャン
1.4.6コントラスト(高度)コントラストスキャン
1.4.10リフロービューポートスキャン
2.1.1キーボードキーボードスキャン
2.1.2キーボードトラップなしキーボードスキャン
2.4.3フォーカス順序キーボードスキャン
2.4.7フォーカスの可視化キーボードスキャン
2.5.5ターゲットサイズ(高度)ビューポートスキャン
2.5.8ターゲットサイズ(最低限)ビューポートスキャン
4.1.2名前、役割、値a11y ツリー、状態スキャン

コメント