🌊

Jest Previewを試してみた

2022/07/24に公開

Jestの実行結果をブラウザでプレビュー出来るというJest Previewが気になったので試してみました。

https://www.jest-preview.com/

Install

npm i -D jest-previewし、Jestの設定に以下を追記します。

jest.config.js
{
  ...
  transform: {
    ...
    "^.+\\.(css|scss|sass)$": "jest-preview/transforms/css",
    "^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)": "jest-preview/transforms/file",
  },
  setupFilesAfterEnv: ["./config/jest/setupTests.js"],
  ...
}

setupTests.jsは必須ファイルではないですが、オプションの設定やグローバルCSSを読み込むために必要となります。

config/jest/setupTests.js
import { jestPreviewConfigure } from 'jest-preview';

// グローバルCSSの読み込み
import '../../src/index.css';

// Jest Previewの設定
// https://www.jest-preview.com/docs/api/jestPreviewConfigure
jestPreviewConfigure({ autoPreview: false });

Jestをwatchで動かしつつ、Jest Previewを起動させるnpmスクリプトを書いておきます。

package.json
  "scripts": {
    "test": "NODE_ENV=test jest --watchAll",
    "jest-preview": "jest-preview",
    "test:debug": "run-p test jest-preview"
  },

テストケースでは、プレビューしたい場所で preview.debug() を置いておきます。

App.test.tsx
import preview from 'jest-preview';
import { render, screen } from "@testing-library/react";
import userEvent from '@testing-library/user-event'
import App from "../App";

describe("App", () => {
  it("should work as expected", async () => {
    render(<App />);

    await userEvent.click(screen.getByTestId('increase'));
    await userEvent.click(screen.getByTestId('increase'));
    preview.debug();

    expect(screen.getByTestId('increase')).toHaveTextContent('2');
  });
});

npm run test:debugさせれば、Jestが実行され、プレビューを確認できます。


※ 崩れてますが、Vite Reactの作成したてのプロジェクトだとApp.tsxでコンポーネント外の#rootにスタイルをつけてるため、これが失われてるだけです、、

仕組み

仕組みは結構シンプルで、 preview.debug() したタイミングで document のスナップショットを node_modules/.cache/jest-preview/index.html に書き出し、これを別途起動しているサーバーがブラウザに表示しています。

refs. https://github.com/nvh95/jest-preview/blob/main/HOW_JEST_PREVIEW_WORKS.md
https://github.com/nvh95/jest-preview/blob/v0.2.8/src/preview.ts#L12-L15

CSSや画像はJestのCode Transformationで直接参照させるなどして、表示を復元しているようです。

仕組みを見ると分かる通り、ブラウザで表示されるものは静的なスナップショット(ただのHTML)となるので、プレビューされてる画面はインタラクティブにはなりません。(ボタンなどを押しても何も反応しない)

その他試してみたこと

同じテストケースで複数回 debug() するとどうなるか?

都度HTMLを上書きするので、最後の呼び出し状態が表示されます。
ただし expect などのアサーションが落ちるとそこでJestの実行も止まるので、落ちる直前の最後の debug() した時のスナップショットが表示されます。

複数コンポーネント(テスト)のプレビューは出来るか?

現在の仕組みでは、常に1枚のHTMLをserveしているので、テストケースが複数あっても最後に実行された debug() のスナップショットが表示されるようです。

ただし、Upcoming featuresに「Multiple preview」とあるので、今後追加されるかもしれません。

Automatic Mode

autoPreview: true にすると、debug() を手動で呼ばなくても、アサーションが落ちたタイミングでスナップショットを表示してくれるようになります。

config/jest/setupTests.js
jestPreviewConfigure({ autoPreview: true });

これは便利ですが、逆にテストが失敗しないとプレビューはされません。
「コンポーネントのUI開発としてJest Previewを利用しよう」と思うと、「落ちないと表示されない」のは噛み合わないかもしれません。

使ってみた所感

テストケースに1行追加するだけで手軽にプレビュー出来る点は便利でした。
すでにJestでコンポーネントの単体テストを書いている場合は、シンプルにデバッグが楽になると思います。

一方で、インタラクティブにUIを触りながら、みたいなライブラリではないので、そのようなケースではCypress Component TestingやStorybookなど特化したツールを利用したほう良く、ライブラリとしてそういったツールの代替ではなさそうです。

あくまでJestで書いているコンポーネント単体テストのDXを高めるライブラリといった位置づけで考えるのが適切ですね。

Vitestにもプレビュー機能が追加される?

Jest PreviewをVitestで使えないか調べていたところ、最近VitestのPRで @vitest/browser パッケージが追加されていました。

https://twitter.com/asleMammadam/status/1549482930472361986?s=20&t=UmP3Z7D_vWsPDYdjCfOphg

こちらのスレッドにて、まさにJest Previewの作者である@hung_dev氏も質問していますが、VitestでもVisual debuggingの機能を開発中のようです。

詳細な機能は不明ですが、おそらくJest Previewのような単体テストのデバッグDXを高める機能だと思うので、使えるようになったら試してみたいですね。

Discussion