vue-loader + webpackでテスト用のデータ属性data-testidをコンパイル時に取り除く
Vueでテストを書く時によく使われるのはvue-test-utilsですよね。
コンポーネントのテストでDOMの変更に柔軟に対応するために「data-test」や「data-testid」などテストでのアクセス用に、データ属性をつける方法がよく用いられます。
テストでしか使用しないデータ属性はプロダクションビルドには必要なく取り除くことが多いですが、大抵はvue-loaderを使ったwebpackのビルド時に特定のデータ属性を取り除きます。
compilersOptionsを設定して取り除く方法を紹介したいと思います。
この記事執筆時のvue-loaderの最新場バージョンは15.9.1です。
data-testidをwebpackでコンパイル時に取り除く
webpackでビルド時に特定のデータ属性を取り除くコードでcompilersModulesの例がよく紹介されています。
ですが今はcompilerModulesではなく 先に書いたようにcompilerOptionsでの対応になります。
今回は下記のフォーラムを参考にしました。
https://forum.vuejs.org/t/how-to-remove-attributes-from-tags-inside-vue-components/24138/8
フォーラムでは15.2.4の時点からcompilersOptionsを使うコードが紹介されています。
今後はvue-loaderやwebpackの仕様が変わらない限りは下記のコードでwebpackのビルド時に特定のデータ属性を取り除くことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
{ test: /\.vue$/, loader: "vue-loader", options: { loaders: { // some loader options }, compilerOptions: { modules: [ { preTransformNode(astEl) { const key = 'data-testid' const { attrsMap, attrsList } = astEl if (attrsMap[key]) { delete attrsMap[key] const index = attrsList.findIndex((x) => x.name == key) attrsList.splice(index, 1) } return astEl; } } ] } } }
テスト用のデータ属性を使う理由
そもそも
例えばvue-test-utilsの公式を始めよく見かけるのはタグやHTMLクラス名を使う方法があります。
1 2 3 4 5
// タグ wrapper.find(`button`).trigger('click') // クラス wrapper.fing(`.btn`).trigger('click')
実装でタグやクラス名、DOMの構造に変更が生じると必然的にテストがエラーになります。
そのたびにテストを修正する必要がでてきますが、メンテナンスのコストなどの観点からこれが理由でコンポーネントのテストが避けらやすい要因の一つです。
その問題を解決するために考えられたのが「data-testid」や「data-test」というテストで用いるための属性をHTMLにつけることです。
1 2 3 4 5 6 7
<template> <div> <button class="button" data-testid="submit">submit</button> </div> </template> wrapper.find(`[data-testid="submit"]`).trigger('click')
このようにすることでDOMに変更が発生してもデータ属性の値を変更しない限りDOMへのアクセスでテスト結果に変化が生じることがなくなります。
まとめ
間違ったデータ属性をつけてしまった場合にビルド時に取り除くことができないという不安もあります。
もちろんその場合テスト時に意図した結果にならないので気づくことができますが、いまいちすっきりしない部分であったりもします。
そのような不安はありつつ現状ではやはりDOMは変更されやすいという性質上テスト時に専用のデータ属性をつけてビルド時に取り除くという方法がコンポーネントのテストにおいて一番良い方法のように思います。