mcpField
S
screen-reader-testing

screen-reader-testing

github.com/wshobsonテスト・品質41.9k10.8k 回インストール2 週間前に更新
リポジトリ

screen-reader-testing について

スクリーンリーダーを使って Web のアクセシビリティを検証する実践的なスキルです。開発者やテスター向けに、対象環境や操作モード、ダイアログや動的な通知などのテスト方法を案内します。

主な機能

  1. 01主要なスクリーンリーダーの対象範囲
  2. 02ブラウズ・フォーカス・アプリケーションモード
  3. 03モーダル、ライブリージョン、タブのテスト例
  4. 04アクセシブルネームのデバッグ方法
  5. 05キーボードとフォーカスのテスト手法

活用シーン

  1. 01スクリーンリーダーごとの ARIA 動作確認
  2. 02支援技術を使ったフォームとナビゲーションのテスト
  3. 03動的コンテンツの通知問題の調査

インストール

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

$npx skills add https://github.com/wshobson/agents --skill screen-reader-testing

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
jaws-talkback.md
nvda.md
voiceover-ios.md
voiceover.md

詳細

スクリーンリーダーのテスト

包括的なアクセシビリティ検証のために、スクリーンリーダーを使ってウェブアプリケーションをテストする実践ガイドです。

このスキルを使用する場面

  • スクリーンリーダーとの互換性を検証する
  • ARIA の実装をテストする
  • 支援技術に関する問題をデバッグする
  • フォームのアクセシビリティを検証する
  • 動的コンテンツの読み上げをテストする
  • ナビゲーションのアクセシビリティを確保する

基本概念

1. 主なスクリーンリーダー
スクリーンリーダープラットフォームブラウザー利用率
VoiceOvermacOS/iOSSafari~15%
NVDAWindowsFirefox/Chrome~31%
JAWSWindowsChrome/IE~40%
TalkBackAndroidChrome~10%
NarratorWindowsEdge~4%
2. テストの優先順位
Minimum Coverage:
1. NVDA + Firefox (Windows)
2. VoiceOver + Safari (macOS)
3. VoiceOver + Safari (iOS)

Comprehensive Coverage:
+ JAWS + Chrome (Windows)
+ TalkBack + Chrome (Android)
+ Narrator + Edge (Windows)
3. スクリーンリーダーのモード
モード目的使用場面
ブラウズ/仮想コンテンツを読む通常の読み上げ
フォーカス/フォームコントロールを操作するフォームへの入力
アプリケーションカスタムウィジェットを操作するARIA アプリケーション

macOS でテストする前に、VoiceOver のセットアップ、コマンド、チェックリストをお読みください。

必須の iOS Safari のカバレッジについては、VoiceOver のタッチ操作のセットアップとジェスチャーをお読みください。

NVDA でテストする前に、NVDA のセットアップ、モード、コマンド、テストスクリプトをお読みください。

JAWS または TalkBack でテストする前に、プラットフォームのセットアップとコマンドをお読みください。

一般的なテストシナリオ

1. モーダルダイアログ

<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="dialog-title"
  aria-describedby="dialog-desc"
>
  <h2 id="dialog-title">Confirm Delete</h2>
  <p id="dialog-desc">This action cannot be undone.</p>
  <button>Cancel</button>
  <button>Delete</button>
</div>
// Focus management
function openModal(modal) {
  // Store last focused element
  lastFocus = document.activeElement;

  // Move focus to modal
  modal.querySelector("h2").focus();

  // Trap focus
  modal.addEventListener("keydown", trapFocus);
}

function closeModal(modal) {
  // Return focus
  lastFocus.focus();
}

function trapFocus(e) {
  if (e.key === "Tab") {
    const focusable = modal.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
    );
    const first = focusable[0];
    const last = focusable[focusable.length - 1];

    if (e.shiftKey && document.activeElement === first) {
      last.focus();
      e.preventDefault();
    } else if (!e.shiftKey && document.activeElement === last) {
      first.focus();
      e.preventDefault();
    }
  }

  if (e.key === "Escape") {
    closeModal(modal);
  }
}
2. ライブリージョン

<div role="status" aria-live="polite" aria-atomic="true">
  
</div>


<div role="alert" aria-live="assertive">
  
</div>


<div
  role="progressbar"
  aria-valuenow="75"
  aria-valuemin="0"
  aria-valuemax="100"
  aria-label="Upload progress"
></div>


<div role="log" aria-live="polite" aria-relevant="additions">
  
</div>
3. タブインターフェース
<div role="tablist" aria-label="Product information">
  <button role="tab" id="tab-1" aria-selected="true" aria-controls="panel-1">
    Description
  </button>
  <button
    role="tab"
    id="tab-2"
    aria-selected="false"
    aria-controls="panel-2"
    tabindex="-1"
  >
    Reviews
  </button>
</div>

<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
  Product description content...
</div>

<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
  Reviews content...
</div>
// Tab keyboard navigation
tablist.addEventListener("keydown", (e) => {
  const tabs = [...tablist.querySelectorAll('[role="tab"]')];
  const index = tabs.indexOf(document.activeElement);

  let newIndex;
  switch (e.key) {
    case "ArrowRight":
      newIndex = (index + 1) % tabs.length;
      break;
    case "ArrowLeft":
      newIndex = (index - 1 + tabs.length) % tabs.length;
      break;
    case "Home":
      newIndex = 0;
      break;
    case "End":
      newIndex = tabs.length - 1;
      break;
    default:
      return;
  }

  tabs[newIndex].focus();
  activateTab(tabs[newIndex]);
  e.preventDefault();
});

デバッグのヒント

// Log what screen reader sees
function logAccessibleName(element) {
  const computed = window.getComputedStyle(element);
  console.log({
    role: element.getAttribute("role") || element.tagName,
    name:
      element.getAttribute("aria-label") ||
      element.getAttribute("aria-labelledby") ||
      element.textContent,
    state: {
      expanded: element.getAttribute("aria-expanded"),
      selected: element.getAttribute("aria-selected"),
      checked: element.getAttribute("aria-checked"),
      disabled: element.disabled,
    },
    visible: computed.display !== "none" && computed.visibility !== "hidden",
  });
}

ベストプラクティス

するべきこと
  • 実際のスクリーンリーダーでテストする - シミュレーターだけで済ませない
  • まずセマンティック HTML を使う - ARIA は補助的なものです
  • ブラウズモードとフォーカスモードでテストする - それぞれ体験が異なります
  • フォーカス管理を確認する - 特に SPA では重要です
  • まずキーボードのみでテストする - SR テストの基礎となります
してはいけないこと
  • 1つの SR だけで十分だと思い込まない - 複数をテストする
  • モバイルを無視しない - 利用者が増えています
  • 正常系だけをテストしない - エラー状態もテストする
  • 動的コンテンツを省略しない - 最もよくある問題です
  • 視覚的なテストに頼らない - 体験が異なります

コメント