見出し画像

React Router dom useLocationをテストする


はじめに

こんにちは、株式会社SHIFT ITソリューション部の渡部です。

React、TypeScriptを使用した SPA開発と Jestによる自動テストを行っています。 開発が進むにつれて Reactの様々な機能を使うようになると、そのたびに Jestのエラーで躓いてしまいます。。

今回は、クエリパラメータを取得するために react-router-domの useLocationを使用しました。その際にJestで躓いてしまったため、同じような方の参考になれば幸いです。

環境

  • Vite : 4.3.9

  • React : 18.2.8

  • TypeScript : 5.1.3

  • Jest : 29.5.0

  • React Router dom : 6.12.0

実装

画面の実装が以下になります。

tsx

import { useLocation } from 'react-router-dom';

export default function SampleApp() {
    const search = useLocation().search;
    const query = new URLSearchParams(search);
    const param1 = query.get('param1');

    return (
        <div>
            {param1 === 'apple'
                ? <span>りんご</span>
                :param1 === 'orange'
                    ?<span>みかん</span>
                    :<span>no param</span>
            }
        </div>
    )
}

クエリパラメータを取得して、パラメータの値によって表示される文字が変わる画面です。

例えば、「 ?param1=apple 」とURL末尾にクエリパラメータをつけると、画面には「りんご」と表示されます。クエリパラメータが無い場合は「no param」ですね。

以下のサンプルからお試しいただけます。

https://codesandbox.io/p/sandbox/confident-cache-29p6jw

テスト

テストコード全体が以下になります。

Jest

import { render, screen } from '@testing-library/react';
import SampleApp from '../component/sampleApp';

//モックの初期値
const mockUseLocationValue = {
  search: '',
};

jest.mock("react-router-dom", () => ({
  ...jest.requireActual("react-router-dom"),
  useLocation: () => {
    return mockUseLocationValue;
  },
}));

describe('SampleApp test', () => {
  test('no param', async () => {
    render(<SampleApp />)
    expect(screen.getByText('no param')).toBeInTheDocument();
  });
  test('apple', async () => {
    mockUseLocationValue.search = '?param1=apple';
    render(<SampleApp />)
    expect(screen.getByText('りんご')).toBeInTheDocument();
  });
  test('orange', async () => {
    mockUseLocationValue.search = '?param1=orange';
    render(<SampleApp />)
    expect(screen.getByText('みかん')).toBeInTheDocument();
  });
});

最初にクエリパラメータの初期値を宣言します。今回はクエリパラメータなしの状態を初期値としました。

クエリパラメータの取得には search を使用しているため、ここでも search を指定します。今回は使用しませんが、pathnameやstateなども指定することができます。

//モックの初期値
const mockUseLocationValue = {
  search: '',
};

次にモック処理です。

先ほど宣言した mockUseLocationValue を返すように書きます。

jest.mock("react-router-dom", () => ({
  ...jest.requireActual("react-router-dom"),
  useLocation: () => {
    return mockUseLocationValue;
  },
}));

以上で準備が整いましたので、テストを書いていきましょう。

1つ目のテストでは何も指定していないため、最初に設定した初期値が使用されます。

2つ目、3つ目はそれぞれ指定したクエリパラメータの挙動でテストをしてくれます。

describe('SampleApp test', () => {
  test('no param', async () => {
    //クエリパラメータは初期値のまま
    render(<SampleApp />)
    expect(screen.getByText('no param')).toBeInTheDocument();
  });
  test('apple', async () => {
    //クエリパラメータをparam1=appleと指定
    mockUseLocationValue.search = '?param1=apple';
    render(<SampleApp />)
    expect(screen.getByText('りんご')).toBeInTheDocument();
  });
  test('orange', async () => {
    //クエリパラメータをparam1=orangeと指定
    mockUseLocationValue.search = '?param1=orange';
    render(<SampleApp />)
    expect(screen.getByText('みかん')).toBeInTheDocument();
  });
});

これでテスト成功です!うまくいきました。

終わりに

最初はうまく調べられなかったり、それっぽい記事を見つけても英語でよく理解できなかったり、結構苦戦してしまいました。

苦戦していたものができるようになると嬉しいですが、時間がかかってしまうのでもっと記事が増えるといいなあと思います。。私も躓いたところをこれからもどんどん共有していきたいと思いますので、また読んでいただけると嬉しいです。

《この公式ブロガーのおすすめ記事》



執筆者プロフィール: 渡部 瑠菜
2022年4月に新卒入社後、ITソリューション部に所属。
AWSやReactを勉強中。
趣味は絵を描くことや2D/3Dモデリングなど。

お問合せはお気軽に
SHIFTについて(コーポレートサイト)
SHIFTのサービスについて(サービスサイト)
SHIFTの導入事例
お役立ち資料はこちら
SHIFTの採用情報はこちら   

PHOTO:UnsplashPhilipp Katzenberger