Gatsbyのアクセシビリティテスト用プラグイン「gatsby-plugin-a11y-report」

[Gatsby](https://www.gatsbyjs.com/)のアクセシビリティテスト用のプラグインを書きました。
[gatsby-plugin-a11y-report](https://github.com/shunito/gatsby-plugin-a11y-report)です。

```gatsby develop``` 時の表示イメージ。
![gatsby-plugin-a11y-reportの実行画面。ブラウザにトーストでチェック結果数のトースト表示する。ConsoleにViolationsとincompleteを表示している。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2827/a15fb337-dff5-8b58-0251-dd4e8983161e.png)

もともとGatsbyには[gatsby-plugin-react-a11y](https://github.com/dlindahl/gatsby-plugin-react-a11y)という[react-axe](https://github.com/dequelabs/react-axe)を使ったプラグインがあるのですが、その元となったreact-axeがviolationsしか表示してくれないので、incompleteも表示するように書き直したりしているうちに差分が大きくなりすぎたので独立したような感じです。

また、```gatsby develop``` 時だけでなく、build時にはaxeのレポートを以下のようにlogsディレクトリに出力します。

```
{"title":"Gatsby Build: A11y Check Start","pages":14,"logging":["violations","incomplete"],"ignore":["/404*","/tag/*"],"device":{"name":"Chrome","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/80.0.3987.0 Safari/537.36","viewport":{"width":1280,"height":600,"deviceScaleFactor":1,"isMobile":false,"hasTouch":false,"isLandscape":false}},"level":"info","service":"axe-report","timestamp":"2020-02-23T08:20:12.697Z"}
{"path":"/offline-plugin-app-shell-fallback","result":"violations","id":"document-title","impact":"serious","description":"各HTMLドキュメントに空ではない<title>要素が含まれていることを確認します","html":"<html>","target":["html"],"level":"error","service":"axe-report","timestamp":"2020-02-23T08:20:19.766Z"}
{"path":"/offline-plugin-app-shell-fallback","result":"violations","id":"html-has-lang","impact":"serious","description":"すべてのHTMLドキュメントにlang属性が存在することを確認します","html":"<html>","target":["html"],"level":"error","service":"axe-report","timestamp":"2020-02-23T08:20:19.767Z"}
～省略～
{"path":"/posts/humane-typography-in-the-digital-age","result":"violations","id":"region","impact":"moderate","description":"ページのすべてのコンテンツがlandmarkに含まれていることを確認します","html":"<div class=\"Post-module--post__footer--1BvmJ\">","target":[".Post-module--post__footer--1BvmJ"],"level":"error","service":"axe-report","timestamp":"2020-02-23T08:20:20.840Z"}
{"title":"Gatsby Build: A11y Check Complete","complete":true,"violations":45,"incomplete":3,"level":"info","service":"axe-report","timestamp":"2020-02-23T08:20:20.855Z"}
```

```gatsby build``` をGitのpush時などに自動実行しているような場合にviolationsの数をチェックしてCIするのに便利に使えるかなと思います。

## 使い方

### インストール
通常のGatsbyプラグイン同様、セットアップしたGatsbyサイトのディレクトリで以下のようにプラグインをインストールします。
[Puppeteer](https://github.com/puppeteer/puppeteer)と[express](https://expressjs.com/)、[Winston](https://github.com/winstonjs/winston)を内部で利用しているので結構重いプラグインになっています。

``` 
npm install --save gatsby-plugin-a11y-report
```
あるいはYarnを利用してモジュールを追加。

```
yarn add gatsby-plugin-a11y-report
```

### gatsby.configに設定を追加

インストール出来たらプラグインを利用するようにGatsbyを設定します。
```gatsby-config.js``` に以下のように設定します。

```
// gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-plugin-a11y-report',
      options: {
        showInProduction: false,
        toastAutoClose: false,
        query: `
          {
            allSitePage(
              filter: {
                path: { regex: "/^(?!/404/|/404.html|/dev-404-page/)/" }
              }
            ) {
              edges {
                node {
                  path
                }
              }
            }
          }
        `,
        ignoreCheck: [
          '/404*',
          '/tag/*'
        ],
        serverOptions: {
          host: 'localhost',
          port: '8341'
        },
        axeOptions: {
          locale: 'ja',
        },
        loggingOptions: {
          result: ['violations', 'incomplete']
        }
      },
    },
  ],
}
```

### オプション設定
以下のオプションは````query````以外すべて省略可能です。

#### ```showInProduction```
デフォルト：```false```
トーストとConsoleへの出力をproductionでも行う場合、```true```にしてください。（gatsby-react-axe互換。まぁ、一般的にはfalseのまま使うかと思いますが。）

#### ```toastAutoClose```
デフォルト：```false```
```gatsby develop```時に表示するトーストを一定時間で自動的に閉じる設定です。
エラーにすぐ気が付くようにviolationsの件数などをトースト表示するようにしたのですが、そもそもトーストがaxeのチェックでコントラスト不足だったり、画面遷移時にうまく消えてくれなかったりアクセシビリティ的によろしくない状況でして、この機能は将来廃止するかデフォルトでは非表示にするなどしようかと考えています。
もう少し調整してみるつもりですが。

#### ```query```（必須）
GatsbyJSの特徴でもある[GraphQL](https://graphql.org/)で、Build時にチェックするサイトのパスを指定します。
filterによりテストでログに残したい対象ページを柔軟に絞り込むことができます。

#### ```ignoreCheck``` 
queryのfilterで絞り込めることに気が付かなかったときに作ってしまった機能ですが、正規表現でパスを記述するのこっちのほうが楽な気がするので残してます。作っていきなり後方互換みたいになっていますが、たぶんGraphQL上手な人はいらないやつですが、GraphQLで絞り込んだあとに追加で絞り込みが実行されますので、使い方次第で便利かも。

#### ```serverOptions```
デフォルト： ```{ host: 'localhost', port: '8341' }```
プラグインはBuild時に[Express](https://expressjs.com/)の検証用サーバを立ち上げますが、その検証サーバのホストとポートを指定します。ちなみにプラグインは[Puppeteer](https://pptr.dev/)で検証サーバにアクセスしてaxeのレポートをログとして出力します。

#### ```axeOptions```
axeのオプションを指定します。
通常はログに出力するレポートの言語を指定します。指定がない場合はブラウザの設定から推測してロケール設定します。
そのほかの指定可能なオプションは[axe-coreのドキュメント](https://www.deque.com/axe/axe-for-web/documentation/api-documentation/#api-name-axeconfigure)を参照してください。

#### ```loggingOptions```
デフォルト：```result: ['violations']```
Build時に出力するログの種類を配列で指定します。指定可能なのは```'violations', 'incomplete', 'inapplicable', 'passes'```の4つです。デフォルトでは```violations```だけ出力します。

## 今後の予定

より柔軟にロギングの設定がしやすいようにしたいのですが、```gatsby-config```の設定が肥大化するのは避けたいので何か方法を検討中。ほかのプラグインでよさげな方法をとっているものがないか調べてみるつもりですが、何か情報をお持ちの方がいれば教えてください。