💡

next/imageをJestとStorybookで使うためにモックする方法

2021/08/10に公開

はじめに

オリジナルな要素があまり多くないので記事にするか迷ったのですが、next/imageをモックする方法について日本語で書いてあるものがほとんどなかったので記事にしました。Next.js関連は新しい技術なので、日本語のドキュメントも少ないですし、僕のような駆け出しエンジニアには日本語のドキュメントが少しでも多くあるととても助かるのでちょっとしたことでも書いていきたいですね。

モックする方法を調べていて困ったこと

next/imageをJestでモックして使う方法は英語ドキュメントでちらほら見つかったのですが、それらをStorybookに対しても使うと、悲しいことにnext/imageで表示した画像とStorybook上でモックにより表示した画像の見た目が異なるという状態が発生して困りました。

最終的に、Storybookで見た目が同じように表示されるモックができたので、今回はそのために活用させていだたいたコードと自分でいじった部分についてまとめます。

活用させていただいたコード

こちらのコードがStorybookでも同じように表示されました。

https://github.com/vercel/next.js/issues/18393#issuecomment-817966642

概要

プロジェクトのルートディレクトリに__mocks__/next/image.jsというファイルを作成して、記載してあるコードをコピペします。次に、そのモックファイルを使うように設定します。もう一方のコードを.storybook/main.jsにコピペします。(コードはリンク元で確認お願いします)

Jestはプロジェクトのルートディレクトリにある__mocks__ディレクトリにあるファイルを自動的に読んでくれるみたいです。
https://jestjs.io/ja/docs/next/manual-mocks

変更箇所

足りないプロパティを追加したり、画像が表示されるように画像パスを適切なものに整える処理を追加しています。画像パスを適切なものに整える処理は自分の画像を置いてある場所を指定するように変えてください。

__mocks__/next/image.js
-export const NextImageMock = ({ objectFit, objectPosition, ...props }) => {
+export const NextImageMock = ({ objectFit, objectPosition, loader, unoptimized, ...props }) => {
  const height = props.height
  const width = props.width

...

    minHeight: '100%',
    maxHeight: '100%',
    objectFit,
-    objectPosition
+    objectPosition,
+    loader,
+    unoptimized
  }

...

    throw new Error(
      `Image with src "${props.src}" must use "width" and "height" properties or "layout='fill'" property.`
    )
  }

// srcが'https://image.png'や'/image.png'だったりするので整える
+  const imgSrc = `https://${props.src.replace(/^(https?:)?\/*/, '')}`
+
  return (
    <div style={wrapperStyle}>
      {sizerStyle ? (

...

        </div>
      ) : null}
-      <img {...props} decoding="async" style={imgStyle} />
+      <img {...props} src={imgSrc} decoding="async" style={imgStyle} />
    </div>
  )

最後に

こちらにNext.jsアプリケーションの環境構築についてまとめた記事も書いてあるのでよければ読んでください。
https://zenn.dev/yukishinonome/articles/bfb4a79a4b81b0

Discussion