HTMLレポート

スキャン後にブラウザーで開ける、単体で完結したHTMLレポートです。サーバーも外部アセットもネットワークリクエストも要りません。生のJSONやターミナルの概要ではなく、スキャン結果を閲覧できる形で見たいQA担当者や手動テストの担当者向けに作っています。リスナーとライブリージョンのフックを入れて小さな決済ページをスキャンしたレポートの例では、どのグループにも検出結果があります。

$ surea11y scan ./dist/index.html --html report.html

report.htmlはディスクから直接開いてください。ほかのどの出力モードとも併用できます。--htmlは--jsonやデフォルトの概要表示を置き換えるものではなく、指定したパスに書き出される追加の成果物です。

表示される内容

  • ヒーロー:「N of M applicable checks passed」のような平易な言葉の見出し1つと、判定結果(fail/cantTell/pass/notApplicable)ごとの内訳を示す積み上げ棒グラフと凡例(アイコン+ラベル+件数。状態を色だけで示すことはありません)。失敗したルールがなく、適用されたルールがある場合は、見出しの下の注記が、これはページが適合しているという表明ではないことを伝え、人が引き続き確認すべきこと(レビューが必要な検出結果、キーボード操作、スクリーンリーダーでの読み上げ、コンテンツそのもの)を挙げます。
  • 確認が必要な項目:fail/cantTellの検出箇所があるルールごとに1枚のカード(検出箇所ごとではありません。同じ検出箇所がたくさんあるルールは、注意すべき事柄として1つであり、多数ではないからです)。各カードには重大度、WCAG達成基準のチップ、代表的な検出箇所、検出箇所の総数を表示します。失敗したルールが先に来ます。その後に、レビューが必要な検出結果が3つのグループに分かれて続きます。根拠が不適合を指すもの(「不適合の可能性が高い: 確認してください」)、根拠が適合を指すもの(「適合の可能性が高い: 確認してください」)、人にしか判断できないもの(「人による確認が必要」)で、@surea11y/coreのreviewGroupOf(check, occurrence)と同じ分け方なので、レビューのキューを並べるツールも同じ順に並べられます。最初の2つのグループの各カードは、そちらに傾く理由(検出箇所のlean)を示します。これらのカードにはそれぞれ「確認方法」のセクションがあり(デフォルトでは折りたたみ)、問いに答える手順と、何が合格で何が不合格かを示します(検出箇所のhowToCheck)。検出結果の傾きが異なるルールは、それぞれのグループにカードを持ちます。各グループの中では重大度の高い順(criticalからminor)、同じ重大度なら検出箇所の多い順です。表示するのは優先度の高い上位24件のルールまでで、それを超える分は注記で示します。完了しなかった(例外を投げた)ルールにもカードが表示され、ページがそのルールで検査されていないことをエラーとともに示します。http(s)のヘルプリンク(meta.helpUrl。カスタムルールのものも含む)を持つルールのカードには「How to fix <rule>」のリンクが付きます。ヘルプリンクのないルールは、検査するWCAG達成基準のUnderstanding文書にリンクします(「Understanding 1.1.1 Non-text Content」)。
  • フレーム:フレーム横断の結果(runa11yCoreAcrossFrames、またはバインディングの.frames(true))の場合だけ表示されます。上のカードはページ自身のものです。このセクションにはフレームごとに見出しが1つあり、そのパス(そのフレームに至るフレーム要素のセレクター)で名前が付けられ、フレームのタイトルとURL、そのカードが続きます。応答しなかったフレームには「Not scanned」とその理由が表示されます。レポートのほかの部分は、ページ自体について述べています。
  • 限界に最も近いもの:スキャンにmarginがある場合(チェック結果のmargin)に表示されます。合格した中で最もしきい値に近い要素が、ルールの範囲内(コントラスト比の10%以内など)でしきい値に近づいたルールごとに1行で(表の上の注記がそのことを説明します)、合格した中で最も近い値、限界値、残りの余裕、要素を示します。ピクセルは整数に丸め、1未満は「1 px未満」と表示します。比は小数点以下2桁で表示します。わずかな余裕で合格したルールは、小さな変更で不合格に変わりうるルールです。
  • WCAG集約:適合レベル(A / AA / AAA)ごとにまとめたもので、エンジン自身のrulesResults[]の複合集約をそのまま使っています(WCAG適合性との対応を参照)。達成基準ごとに1行で(その達成基準のルールが対応する、結果のstandardsにあるほかの各規格の要件も。たとえば、その達成基準を再掲するEN 301 549の条項があり、スキャンがEN 301 549の条項を要求した場合はその条項)、その判定結果、合格/不合格/要レビュー/該当なしの内訳(達成基準のルールがその求めることの一部しかチェックせず、残りを人が確認する場合(「一部のみ確認: チェックはこの達成基準の一部しか扱わないため、残りは人が確認します」)や、スキャンがその達成基準のルールの一部だけを選んだ場合は「一部のみ確認」の行も。一部だけチェックされた達成基準を参照)、寄与したアトミックルール(その達成基準に対応するカスタムルールを含む)を表示します。独自に作ったグループ分けではなく、実際のエンジンのデータです。生のJSONのrulesResultsから得られるものと同じ集約です。
  • 規格独自の集約:独自の集約を持つ規格のルールをスキャンで実行した場合(その規格のプロファイル、またはengineOptions.optInRules)だけ表示され、集約ごとに1行で、規格の文言、判定結果を決めたルールの要件、内訳、寄与したルールを示します。これにはパックの規格と、パックのチェックリスト(その項目が集約です)も含まれます。こうした規格はそれぞれ結果のstandardsに列挙されているので、保存した結果はどこでレンダリングしても同じになります。その一覧がないか壊れている場合は、WCAG集約の上にレポートがそのことを示します。
  • 技術データの全体(デフォルトでは折りたたみ):スコアカード(判定結果ごとのタイル)と、スキャン全体の個々の検出箇所をすべて載せた、検索・フィルター(判定結果別)・ページ送りが可能な表。レビューが必要で傾きのある検出結果は、要約の下にそれを示し(「不適合の可能性が高い: …」)、検索でも見つかります。表示する検出箇所がない場合は、そのことを示す行が1つ入ります。スキャンが何も記録しなかったか、フィルターですべて隠れているかのどちらかです。

シャドウツリー内の要素は、シャドウホストのセレクター、続いて要素自身のセレクターを >>> でつないだもので示されます:html > body > main > x-card >>> button。カード、marginの表、検出箇所の表はすべてこの形で示し、SARIFとJUnitも同じです。

レポートは読み手のカラースキームに従い、どちらのスキームでもレポート自身のテキストはWCAG 1.4.3を満たします。すべての状態の色はそのチップとタイルの上で4.5:1以上あり、レンダリングしたレポートに対してエンジン自身のコントラストのルールがライトモードとダークモードの両方で合格します。

レポートは320 CSS px幅でリフローし(WCAG 1.4.10)、ページが横にスクロールすることはありません。ウィンドウより幅の広い表は専用のボックスの中でスクロールします。このボックスは表の見出しで名前が付いた領域で、キーボードフォーカスを受け取るため、矢印キーでスクロールできます。

ヘッダーの下のメタ情報バーには、ルール数、検出箇所の数、エンジンのタグ、スキーマのバージョン、スキャンが対象としたWCAGのバージョン、使用したengineOptions.profile(ある場合)、engineOptions.optInRulesが追加したオプトインルールのタグ(追加した場合)、ページがレンダリングされた条件、スキャンで解決されたロケールが表示されます。条件とは、ビューポート(デバイスピクセル比が1でない場合はその値も)とカラースキーム、そしてWebフォントがまだ読み込み中だった場合はそのことです。jsdomでのスキャンのようにレイアウトがない場合は、代わりにそのことが表示されます。レイアウトに依存する検出結果はビューポートの幅によって出たり消えたりするため、レポートがどの幅を表しているかをチップで示します。ロケールのフォールバックは文字列単位で行われ、テキスト自体からは見分けがつきません。そのため、エンジンが持っていない言語で要求したレポートは、ふつうの英語のレポートとして表示されます。要求したロケールと解決されたロケールが異なる場合は、チップに両方が表示されます。ロケールを参照してください。

ページ全体が、スキャンで解決されたロケールで書かれます。見出し、表の列、判定結果と重大度の名前、見出し文、ページ送り、日付の形式です。<html lang>はそのロケールを示します。検出箇所のフィルターにある判定結果のコード(fail、cantTellなど)はそのままです。JSONの結果で検索するときの値だからです。

英語のラベルのままになるケースが1つあります。エンジンが同梱していない言語で、呼び出し側が用意したengineOptions.messagesの辞書を使ってスキャンした場合です。その辞書は結果に含まれないため、レポートはそこからラベルを読めません。その場合、検出結果にはそれぞれの言語(例:lang="nl")が付くので、スクリーンリーダーは正しい音声で読み上げます。

コンパクトな結果(engineOptions.output.detail: 'findings'。出力スキーマを参照)は、それが表す完全な結果として読まれるので、同じように報告されます。

ライブラリーとしての使い方

const { renderHtmlReport } = require('@surea11y/core/report');
const { runDomRulesInPage } = require('@surea11y/core');
 
const result = runDomRulesInPage(url, null, {}, null);
const html = renderHtmlReport(result, { title: 'My scan report' });
 
require('fs').writeFileSync('report.html', html);

renderHtmlReport(result, options)は文字列を返します。関数自体がファイルシステムに触れることはありません(書き込みはCLIの--htmlフラグが行います)。ページの日付は結果のtimestamp(engineOptions.timestampで設定します)をUTCで表示したものなので、同じ結果からは常に同じページが生成されます。timestampのない結果では、レンダリングした時刻が日付になります。options.titleは省略可能です(デフォルトはレポートの言語でのタイトルで、英語では"surea11y scan report")。options.packsは、スキャンがパックを実行した場合のパックの一覧(engineOptions.packs)です。Nodeでは、レポートは手順を持たない未判定の検出結果に「確認方法」の手順を追加します。コアのルールとバリアントのベースのルールの手順は常に、パックのルール自身の手順(そのmeta.review。英語)はパックを渡された場合にだけ追加されます(パックを参照)。ブラウザー(surea11y.report.js)では、結果がすでに持っている手順を表示します。

対象範囲

これは1回のスキャンのレポートです。ある時点のスナップショットであり、多数のスキャンの結果を時系列で追跡するダッシュボードではありません。複数回の実行にわたる結果の追跡は別の、より大きな課題であり、このツールには含まれていません。各スキャンのJSONを保存して自分で差分を取るか、履歴機能をすでに備えたダッシュボードにSARIFを渡してください(SARIFレポートを参照)。