acotによる静的ページのアクセシビリティ検査を試す

昨年12月に発表された期待のWebアクセシビリティ検証フレームワーク「[acot](https://github.com/acot-a11y/acot)」、まだ正式リリース前の段階のようですが試用して感触を確かめてみました。
acotの概要については、開発者の方の以下の記事を確認ください。

- [Web アクセシビリティの検証ツール acot を作ってる](https://blog.wadackel.me/2020/acot/)
- [Web アクセシビリティの検証ツール「acot」](https://masup.net/2020/12/acot-accessibility-testing-framework)

私が記事を読んで理解したacotの特徴としては、以下のようなものと認識しています。（間違ってたら教えてください）

- [axe](https://github.com/dequelabs/axe-core)などの既存ルールを利用しながら独自のテストの拡張ができる。
- [Puppeteer](https://github.com/puppeteer/puppeteer)が組み込まれており、ソースの静的解析だけでなくブラウザの実際の挙動を検証するルールも設定できる。
- テストランナーが付属しており、sitemap.xmlを利用したりStorybookとの連携で複数ページやコンポーネントのテストができる。
- [Nuxt](https://ja.nuxtjs.org/)など既存プロジェクトの内部に組み込むこともできるし、cli等でプロジェクトの外部から試験を実行することもできる。

この記事ではまず、Nuxtで新規セットアップしたプロジェクトにacotを組み込み、sitemap.xml経由で複数ページをチェックするところまでやってみます。
環境はWindows10のNode v14.15.0、npm 7.6.3です。

なお、成果物については以下のリポジトリにアップしていますので興味があればcloneして確認してみてください。

[github:shunito/acotTest](https://github.com/shunito/acotTest)

# Nuxtのセットアップ

Nuxtについては公式チュートリアルやQiitaにも多数の解説記事が出ているので今回create-nuxt-appで行ったセットアップ内容だけ記述します。
SSRで静的に構築されたサイトをテストする想定になっています。

```
Package manager: npm
Programming language: TypeScript
UI framework: Tailwind CSS
Nuxt.js modules: Axios 　・・・今回特に利用してません
Linting tools: ESLint, StyleLint
Testing framework: Jest 　・・・特に設定していないが、今後acotと連携を試したい
Rendering mode: Universal (SSR/Static)
Deployment target: Static (Static/JAMStack hosting)
Development tools: jsconfig.json
Continous Integration: GitHub Actions 　・・・未設定
```

`npm install` が成功したらビルドと、`npm run dev` で開発用サーバが立ち上がるかチェックします。
開発用サーバ `http://localhost:3000/` をブラウザで開いて表示確認できればとりあえずNuxtのセットアップは完了です。
あとは、エラーがどのように表示されるか確認したいので、お好みでページにaltが空の画像タグなど仕掛けておきましょう。


# acotのセットアップ

## インストールと初期設定
`npm install --save-dev @acot/cli` でNuxtのプロジェクトにacotをインストールします。
グローバルでも利用できるようですが、acotのドキュメントによるとローカル推奨とのこと。

続いて、`npx acot init` でacotの初期設定を行います。
今回のNuxtの環境にあわせて選択したり入力したり。無事設定されました。

![npx acot initの実行結果スナップショット。設定項目とインストール後の「wellcome to acot!」が表示されている](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2827/404d2fa7-0265-6893-e40e-fefa239d2cc3.png)

すると、`acot.config.js` という以下のような設定ファイルが生成されます。

```javascript

module.exports = {
  extends: ['@acot'],
  connection: {
    command: 'npm run dev',
  },
  origin: 'http://localhost:3000',
  paths: ['/'],
};
```

## acotの実行

初期設定が終わったら `npx acot run` でacotを実行します。
以下のように設定内容が表示されて、チェックがスタートします。BootstrapでPuppeteerが立ち上がるまで少し待たされますね。
![ターミナルでacotを実行した様子。開発用サーバに接続し1件のテストが終わったところ。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2827/873df377-2bd2-9a0d-889e-b5e4f854edee.png)

チェック結果のメッセージがずらずらと出てきた後に、サマリーも表示されます。わかりやすい。
![ターミナルにテスト結果のサマリーが表示されている様子。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2827/5510b259-abc8-9bd5-a849-4a73d03325b5.png)

結果のログやら画像が `.acot` ディレクトリにも出力されますが見方がちょっとわからないので割愛。。
（リポーターは今後の課題だそうです）

## sitemap.xml経由で静的ページのチェック

Nuxtでページを増やしたときに自動的にチェックしてくれるようにsitemap.xmlをランナーに利用できるようにしてみます。また、acot独自のチェック項目がデフォルトで利用可能ですが、まだ内容がよく把握できていないのでいったんなじみのaxeの設定のみにしてみます。このあたり設定項目の詳細は公式ドキュメント参照。
[GitHub: acot/docs/configuration.md](https://github.com/acot-a11y/acot/blob/canary/docs/configuration.md)

### sitemapの出力設定
`npm install @nuxtjs/sitemap`でNuxtのsitemapモジュールをインストールし、`nuxt.config.js` にモジュール利用の指定と、出力パスを設定します。（このあたりは解説記事も色々あるので割愛）

sitemapの出力条件を調整することでチェック対象を絞ることもできますが、sitemapは単体でも利用するものなので、acot.config側のチェック条件を設定することで絞ったほうがよさそうですね。
ここでチェック対象とするページを2つほど追加して、sitemapにも出力されるか見ておきましょう。


### acotのrunnerにsitemapを指定
まず、`npm install --save-dev @acot/acot-runner-sitemap` でacotのrunnerをインストール。`acot.config.js`にNuxtの設定で指定したsitemapのパスを設定します。完成形は以下の通り。

```javascript
module.exports = {
  presets: ['@acot/axe'],
  extends: ['preset:@acot/axe/recommended'],
  connection: {
    command: 'npm run dev'
  },
  origin: 'http://localhost:3000',
  reporter: '@acot/pretty',
  runner: {
    uses: '@acot/sitemap',
    with: {
      source: 'http://localhost:3000/sitemap.xml'
    }
  }
}
```

[ドキュメント](https://github.com/acot-a11y/acot/blob/canary/docs/configuration.md)を読むと、`overrides`の指定をすればチェック対象のパスは絞れそうなので、チェック対象が増えた場合にはこのあたりで調整すればよさそうです。

### チェックコマンドをpackage.jsonに追加

いちいちコマンドラインで`npx acot run`するのも面倒なので、VS Codeで手軽に実行できるように`packeage.json`のscriptに以下を追加します。

```
  "scripts": {
    "acot": "npx acot run",
     ～～その他コマンド～～
  },
```

すると、VS Codeのサイドメニューにある「NPM スクリプト」の実行ボタンからワンクリックでターミナルが開いてテスト実行できるようになります。ビルドしてのテストもポチポチするだけで実行できて便利ですね。

![VS Codeのスナップショット。サイドメニューの下部にある「NPM スクリプト」からacotを起動してターミナルで実行されている。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2827/05c12aa5-0955-b545-128b-e8ade21b7ded.png)
小さくて分かりにくいと思いますが、`Running on 3 URLs:` とテストで作った3ページをsitemap経由できちんとチェックしてくれていますね。


# 所感や課題と感じた点など

- まだ初期開発の状況とのことで当たり前かと思いますが、独自ルール拡張の方法について公式のドキュメントがありません。acotのリポジトリにあるacot-preset-wcagの中身をみつつ雰囲気をつかもうとしてますが、習熟には結構かかりそうかなーという感じです。
- axeのメッセージだけでも日本語出来ないかなぁ、と思ったのですがいまのところ多言語を意識したつくりになっていないので結構コアの部分に手を入れなければならなそうで、いったん断念。
- リポーターとログまわりについてもこれからという感じなので期待ですね。 
- 静的なサイトのチェックで利用する場合、おそらくページが増えてくるとチェックが重くなると思うので、当初は任意のタイミングで実行がいいかな。プロジェクトの初期開発が終わってソースが落ちついてきているようなら、コミット時の自動実行などを仕掛けてエラー発生してたらマージさせないとか、そういう制御はよさそう。

プロジェクトごとに柔軟にテストを記述できると嬉しいですが、数が少なければjestでやってくという方法もありますね。一度プリセットとして作ったルールを使いまわせるという意味では住み分けかなぁ、という感じ。

想像以上に骨太な造りで、プリセットの整備とか諸々大変そうですが、今後の発展に期待しております。
（期待するだけでなく手を動して、と言われそうですけれども。はい。）