lamechang-dev

Webフロントエンドエンジニア lamechangのブログ。

【Material UI】スナップショット実行時にコードが修正がないにも関わらず属性値に差分が出る

環境:"@material-ui/core": "^4.10.2”

特定のコンポーネントに一意の属性を自動で付与する挙動の影響でコード上の修正がなくてもスナップショットの実行時に差分が出ることがあります。差分が生じる箇所は aria-xxxxidclass など複数属性のようです。

これが起因して、CI上でのスナップショットテスト実行時に想定外の箇所で差分が出ることでCIがコケる、なんてことも起こり得ます😿結構広く使われているライブラリなので、変数を操作するための設定値などを持たせてあげられると便利ですが、現状そうでもないらしく・・・

<button
-                  aria-controls="mui-p-100000-P-individual"
+                  aria-controls="mui-p-53434-P-individual"
                   aria-selected="false"
                   class="MuiButtonBase-root MuiTab-root MuiTab-textColorInherit makeStyles-tab"
-                  id="mui-p-100000-T-individual"
+                  id="mui-p-53434-T-individual"
                   role="tab"
                   tabindex="-1"
                   type="button"

対処法

https://github.com/mui-org/material-ui/issues/21293

ここで議論されている内容では、以下のように正規表現による属性値を置換をする方法があげられていますが、これはなかなか良さそうです。が、属性値ごとに適切な正規表現を用意して記述が必要な場合もあるだろうし、少しめんどくさそうですね。

expect(wrapper.html().replace(/id="mui-[0-9]*"/g, '').replace(/aria-labelledby="(mui-[0-9]* *)*"/g, ''))
  .toMatchSnapshot();

もう1つがMath.random()の値をmockして不変にする方法ですね。以下のように jestの spyOn() を利用することで、Math.random()の返り値を不変にすることで差分発生を回避できます。こちらはシンプルな方法ですね。

const mathRandomMock = jest.spyOn(Math, "random");
    mathRandomMock.mockReturnValue(1);

Jestの toMatchSnapShot は、ローカル実行において・CIにおいては少し処理に時間がかかる、という点もありますが出力結果の差分として非常に明瞭なものですし、安全にフロントエンドを開発する際には非常に重宝しますね。

TailWindCSSをスタイリングに採用すると、クラス名の変更がそのままスタイルの変更にも跳ねるので、スナップショットテストの有用性がより上がるのではないかな、と思います。