GASHIRA-BLOG

Next12でテストを書いたら、環境構築がすごく楽だった

公開日: 2022年2月22日

最終更新日: 2022年3月4日

Next.jsのv12で設定がすごく楽になってたので、設定方法についての作業ログを残そうと思いました。

基本的には 公式を見れば困ることは無いと思うので、公式読んだ上でのおまけ程度に見てみてください。

また、初めて Testing Library を触ったのでその使用感なども書いておきます。

前提条件

  • Next11 → Next12 にアップグレードした後に Jest の導入
  • tailwindcss
  • Typescript

セットアップ

基本的に公式通りに作業をし、少しだけライブラリを追加しました。

yarn add -D @types/jest babel

package.jsonにテスト用のコマンドを追加

{
  "scripts": {
  	// ~~~
    "test": "jest",
    "test-w": "jest --watch"
  },
}

コマンド実行してテスト実行します。

yarn test-w

これでテストが実行できました!

Testing Library

今回触って感じた、Testing Library が入っていることで嬉しいこと

  • ByRole, ByText, 等DOMを取得するための機能が便利
  • action などが実際に画面を使用するのと同じ感覚で書けるから書きやすい

実際にコードを書いてみる

hooksで変数がロード中(undefined)の場合にはスピナーが表示されて、ロードが完了したらchildrenが表示されるコンポーネント

まずはテストを書いてみる。

(設計途中で変えたりしたので、最終形だけを載せておきますが、いきなりこのテストはかけてないです)

import { render } from "@testing-library/react";
import "@testing-library/jest-dom";
import { Loading } from "./loading";

describe("loading component", () => {
  it("variables is a undefined", () => {
    const testStr = "hello world";
    const { getByText, getByTestId } = render(
      <Loading variables={undefined}>{() => <p>{testStr}</p>}</Loading>
    );
    expect(() => getByText(testStr)).toThrow();
    expect(getByTestId("loading-spinner")).toBeInTheDocument();
  });

  it("variables is a value.", () => {
    const testStr = "hello world";
    const { getByText } = render(
      <Loading variables={testStr}>{(v) => <p>{v}</p>}</Loading>
    );
    expect(getByText(testStr)).toBeInTheDocument();
  });
});

これで、 variablesundefined なら testStr が描画されていないで、ローディングアイコン(loading-spinner)が表示されている。

variables の値が undefined以外なら引数が渡って、引数に渡した値が入った状態でchildrenが表示される。

という2つのテストがかけました!

後は、コンポーネントを実装しましょう!

type Props<T> = {
  variables: T;
  children: (p: NonNullable<T>) => JSX.Element;
};

type P = any | undefined;

export const Loading = <T extends P>({
  children,
  variables,
}: Props<T>): JSX.Element => {
  let isLoading: boolean = false;

  if (isNullOrUndefined(variables)) {
    isLoading = true;
  }

  if (isLoading) {
    return (
      <div className="bg-white flex justify-center my-4">
        <span
          data-testid="loading-spinner"
          className="animate-spin h-5 w-5 border-4 border-primary rounded-full border-t-transparent"
        />
      </div>
    );
  } else {
    return children(variables as NonNullable<T>);
  }
};

これで、実際にテストを動かすと

 PASS  src/components/shared/loading/loading.spec.tsx
  loading component
    ✓ variables is a undefined (26 ms)
    ✓ variables is a value. (3 ms)

このように、undefinedのときとvalueが入っているときでテストが通りました!

最後に

specもstoriesも同じディレクトリに置いているけど、実際どっちが管理しやすいのかは毎回悩みますね。

どうせコンポーネント修正したら、specもstoriesも書き換えるから、コンポーネントと同じところにあるのが楽かなって思って毎回同じディレクトリに配置するようにしています。