screen-reader-testing
VoiceOver・NVDA・JAWSなどのスクリーンリーダーを使用してWebアプリケーションをテストします。スクリーンリーダーの互換性検証、アクセシビリティ問題のデバッグ、支援技術サポートの確認が必要な際に使用してください。
description の原文を見る
Test web applications with screen readers including VoiceOver, NVDA, and JAWS. Use when validating screen reader compatibility, debugging accessibility issues, or ensuring assistive technology support.
SKILL.md 本文
スクリーンリーダーテスト
ウェブアプリケーションのアクセシビリティを包括的に検証するためのスクリーンリーダーテストの実践ガイド。
このスキルを使用する場合
- スクリーンリーダーの互換性を検証する
- ARIA実装をテストする
- 支援技術の問題をデバッグする
- フォームのアクセシビリティを確認する
- 動的コンテンツのアナウンスをテストする
- ナビゲーションのアクセシビリティを確保する
コアコンセプト
1. 主要なスクリーンリーダー
| スクリーンリーダー | プラットフォーム | ブラウザ | 使用率 |
|---|---|---|---|
| VoiceOver | macOS/iOS | Safari | ~15% |
| NVDA | Windows | Firefox/Chrome | ~31% |
| JAWS | Windows | Chrome/IE | ~40% |
| TalkBack | Android | Chrome | ~10% |
| Narrator | Windows | Edge | ~4% |
2. テスト優先度
最小限のカバレッジ:
1. NVDA + Firefox (Windows)
2. VoiceOver + Safari (macOS)
3. VoiceOver + Safari (iOS)
包括的なカバレッジ:
+ JAWS + Chrome (Windows)
+ TalkBack + Chrome (Android)
+ Narrator + Edge (Windows)
3. スクリーンリーダーモード
| モード | 目的 | 使用場面 |
|---|---|---|
| ブラウズ/仮想 | コンテンツを読む | デフォルト読み上げ |
| フォーカス/フォーム | コントロールを操作する | フォーム入力時 |
| アプリケーション | カスタムウィジェット | ARIAアプリケーション |
VoiceOver (macOS)
セットアップ
有効化: システム環境設定 → アクセシビリティ → VoiceOver
トグル: Cmd + F5
クイックトグル: Touch IDを3回押す
必須コマンド
ナビゲーション:
VO = Ctrl + Option (VoiceOverモディファイア)
VO + 右矢印 次の要素
VO + 左矢印 前の要素
VO + Shift + 下矢印 グループに入る
VO + Shift + 上矢印 グループから出る
読み上げ:
VO + A カーソル位置から全て読む
Ctrl 音声を停止
VO + B 現在の段落を読む
インタラクション:
VO + Space 要素をアクティブ化
VO + Shift + M メニューを開く
Tab 次のフォーカス可能な要素
Shift + Tab 前のフォーカス可能な要素
ローター (VO + U):
見出し、リンク、フォーム、ランドマークで移動
左/右矢印 ローターカテゴリを変更
上/下矢印 カテゴリ内を移動
Enter 項目に移動
ウェブ固有:
VO + Cmd + H 次の見出し
VO + Cmd + J 次のフォームコントロール
VO + Cmd + L 次のリンク
VO + Cmd + T 次のテーブル
テストチェックリスト
## VoiceOverテストチェックリスト
### ページ読み込み
- [ ] ページタイトルがアナウンスされる
- [ ] メインランドマークが見つかる
- [ ] スキップリンクが機能する
### ナビゲーション
- [ ] すべての見出しがローターで検出可能
- [ ] 見出しレベルが論理的 (H1 → H2 → H3)
- [ ] ランドマークが適切にラベル付けされている
- [ ] スキップリンクが機能する
### リンクとボタン
- [ ] リンクの目的が明確
- [ ] ボタンのアクションが説明されている
- [ ] 新規ウィンドウ/タブがアナウンスされる
### フォーム
- [ ] すべてのラベルが入力フィールドと一緒に読まれる
- [ ] 必須フィールドがアナウンスされる
- [ ] エラーメッセージが読まれる
- [ ] 指示が利用可能
- [ ] フォーカスがエラーに移動する
### 動的コンテンツ
- [ ] アラートが即座にアナウンスされる
- [ ] 読み込み状態が通知される
- [ ] コンテンツ更新がアナウンスされる
- [ ] モーダルがフォーカスを正しくトラップする
### テーブル
- [ ] ヘッダーがセルと関連付けられている
- [ ] テーブルナビゲーションが機能する
- [ ] 複雑なテーブルにキャプションがある
一般的な問題と修正
<!-- 問題: ボタンが目的をアナウンスしない -->
<button><svg>...</svg></button>
<!-- 修正 -->
<button aria-label="ダイアログを閉じる"><svg aria-hidden="true">...</svg></button>
<!-- 問題: 動的コンテンツがアナウンスされない -->
<div id="results">新しい結果が読み込まれました</div>
<!-- 修正 -->
<div id="results" role="status" aria-live="polite">新しい結果が読み込まれました</div>
<!-- 問題: フォームエラーが読まれない -->
<input type="email" />
<span class="error">無効なメールアドレス</span>
<!-- 修正 -->
<input type="email" aria-invalid="true" aria-describedby="email-error" />
<span id="email-error" role="alert">無効なメールアドレス</span>
NVDA (Windows)
セットアップ
ダウンロード: nvaccess.org
開始: Ctrl + Alt + N
停止: Insert + Q
必須コマンド
ナビゲーション:
Insert = NVDAモディファイア
下矢印 次の行
上矢印 前の行
Tab 次のフォーカス可能な要素
Shift + Tab 前のフォーカス可能な要素
読み上げ:
NVDA + 下矢印 すべてを読む
Ctrl 音声を停止
NVDA + 上矢印 現在の行
見出し:
H 次の見出し
Shift + H 前の見出し
1-6 見出しレベル 1-6
フォーム:
F 次のフォームフィールド
B 次のボタン
E 次の編集フィールド
X 次のチェックボックス
C 次のコンボボックス
リンク:
K 次のリンク
U 次の未訪問リンク
V 次の訪問済みリンク
ランドマーク:
D 次のランドマーク
Shift + D 前のランドマーク
テーブル:
T 次のテーブル
Ctrl + Alt + 矢印キー セルを移動
エレメントリスト (NVDA + F7):
すべてのリンク、見出し、フォームフィールド、ランドマークを表示
ブラウズモードとフォーカスモード
NVDAは自動的にモードを切り替えます:
- ブラウズモード: 矢印キーでコンテンツ移動
- フォーカスモード: 矢印キーでインタラクティブ要素を制御
手動切り替え: NVDA + Space
次の点に注意:
- ナビゲーション時に「ブラウズモード」がアナウンスされる
- フォームフィールド入力時に「フォーカスモード」
- アプリケーションロールがフォームモードを強制
テストスクリプト
## NVDAテストスクリプト
### 初回読み込み
1. ページに移動
2. ページの読み込みを待つ
3. Insert + Downキーを押してすべてを読む
4. 確認: ページタイトル、メインコンテンツが特定されるか?
### ランドマークナビゲーション
1. Dキーを繰り返し押す
2. 確認: すべてのメイン領域にアクセス可能か?
3. 確認: ランドマークが適切にラベル付けされているか?
### 見出しナビゲーション
1. Insert + F7を押す → 見出し
2. 確認: 論理的な見出し構造か?
3. Hキーを押して見出しをナビゲート
4. 確認: すべてのセクションが検出可能か?
### フォームテスト
1. Fキーで最初のフォームフィールドを見つける
2. 確認: ラベルが読まれるか?
3. 無効なデータを入力
4. フォームを送信
5. 確認: エラーがアナウンスされるか?
6. 確認: フォーカスがエラーに移動するか?
### インタラクティブ要素
1. すべてのインタラクティブ要素をTabで移動
2. 確認: 各要素がロールと状態をアナウンスするか?
3. EnterまたはSpaceでボタンをアクティブ化
4. 確認: 結果がアナウンスされるか?
### 動的コンテンツ
1. コンテンツ更新をトリガー
2. 確認: 変更がアナウンスされるか?
3. モーダルを開く
4. 確認: フォーカスがトラップされるか?
5. モーダルを閉じる
6. 確認: フォーカスが戻るか?
JAWS (Windows)
必須コマンド
開始: デスクトップショートカットまたは Ctrl + Alt + J
仮想カーソル: ブラウザで自動有効化
ナビゲーション:
矢印キー コンテンツを移動
Tab 次のフォーカス可能な要素
Insert + Down すべてを読む
Ctrl 音声を停止
クイックキー:
H 次の見出し
T 次のテーブル
F 次のフォームフィールド
B 次のボタン
G 次のグラフィック
L 次のリスト
; 次のランドマーク
フォームモード:
Enter フォームモードに入る
Numpad + フォームモードから出る
F5 フォームフィールドリスト
リスト:
Insert + F7 リンクリスト
Insert + F6 見出しリスト
Insert + F5 フォームフィールドリスト
テーブル:
Ctrl + Alt + 矢印キー テーブルナビゲーション
TalkBack (Android)
セットアップ
有効化: 設定 → アクセシビリティ → TalkBack
トグル: 両方の音量ボタンを3秒間押す
ジェスチャー
探索: 画面上で指をドラッグ
次へ: 右にスワイプ
前へ: 左にスワイプ
アクティブ化: ダブルタップ
スクロール: 2本指でスワイプ
読み上げコントロール (上にスワイプして右にスワイプ):
- 見出し
- リンク
- コントロール
- 文字
- 単語
- 行
- 段落
一般的なテストシナリオ
1. モーダルダイアログ
<!-- アクセシブルなモーダル構造 -->
<div
role="dialog"
aria-modal="true"
aria-labelledby="dialog-title"
aria-describedby="dialog-desc"
>
<h2 id="dialog-title">削除を確認</h2>
<p id="dialog-desc">この操作は元に戻せません。</p>
<button>キャンセル</button>
<button>削除</button>
</div>
// フォーカス管理
function openModal(modal) {
// 最後にフォーカスされた要素を保存
lastFocus = document.activeElement;
// フォーカスをモーダルに移動
modal.querySelector("h2").focus();
// フォーカスをトラップ
modal.addEventListener("keydown", trapFocus);
}
function closeModal(modal) {
// フォーカスを戻す
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. ライブリージョン
<!-- ステータスメッセージ (polite) -->
<div role="status" aria-live="polite" aria-atomic="true">
<!-- コンテンツ更新は現在の音声の後にアナウンスされます -->
</div>
<!-- アラート (assertive) -->
<div role="alert" aria-live="assertive">
<!-- コンテンツ更新は現在の音声を中断してアナウンスされます -->
</div>
<!-- 進捗更新 -->
<div
role="progressbar"
aria-valuenow="75"
aria-valuemin="0"
aria-valuemax="100"
aria-label="アップロード進捗"
></div>
<!-- ログ (追加のみ) -->
<div role="log" aria-live="polite" aria-relevant="additions">
<!-- 新しいメッセージがアナウンスされ、削除されたものはアナウンスされません -->
</div>
3. タブインターフェース
<div role="tablist" aria-label="製品情報">
<button role="tab" id="tab-1" aria-selected="true" aria-controls="panel-1">
説明
</button>
<button
role="tab"
id="tab-2"
aria-selected="false"
aria-controls="panel-2"
tabindex="-1"
>
レビュー
</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
製品説明のコンテンツ...
</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
レビューのコンテンツ...
</div>
// タブキーボードナビゲーション
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();
});
デバッグのコツ
// スクリーンリーダーが見えるものをログに出力
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向け
- キーボードのみで最初にテストする - スクリーンリーダーテストの基礎
してはいけないこと
- 1つのスクリーンリーダーだけでテストしない - 複数でテスト
- モバイルを無視しない - ユーザーベースが増加している
- ハッピーパスのみテストしない - エラー状態もテスト
- 動的コンテンツをスキップしない - 最も一般的な問題
- 視覚的なテストに頼らない - 異なるエクスペリエンス
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- wshobson
- リポジトリ
- wshobson/agents
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/wshobson/agents / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。