Reactのテストで使うものたちがたくさんありすぎていつも混乱するのでメモ
JEST / React Testing Library / Apollo Client
とりあえず情報源を雑に貼っておく。
あとでまとめるかもしれないしまとめないかもしれない。
JEST
Javascriptでテストを書く時に使うフレームワーク
it / describe / expectなどはこのフレームワークの持ち物
https://jestjs.io/docs/ja/getting-started
テストの書き方、流れ
...
// テスト対象のコンポーネントをimoprt
import HogeComponent from '.';
...
beforeEach(async () => {
// テストの前に実施する共通処理を定義
}
...
describe('テスト対象や条件を書く', () => {
it('テストの内容を書く。xxが表示されること。yyが更新されること。など', async () => {
// HogeComponentをレンダリング
render(<HogeComponent />);
// waitForを使ってレンダリングされるのを待つ
await waitFor(() => {
// Hogeというtitleが見つかるまで待機
screen.getByTitle('Hoge');
});
// expectを使って要素をテスト
expect(screen.getByText('hoge')).toEqual('hoge')
});
describe('さらに条件分岐する場合ネストさせる', () => {
it('yyが更新されること', async () => {
// HogeComponentをレンダリング
render(<HogeComponent />);
// userEventを使ってイベント発火
userEvent.click(screen.getByRole('button'));
// クリックイベントが終わるのを待つ
await waitFor(() => {
// Hogeというtitleが見つかるまで待機
screen.getByTitle('Hoge');
});
// expectを使って要素をテスト
expect(screen.getByText('hoge')).toEqual('hoge')
});
});
React Testing Library
Reactをテストする時に役立つライブラリ群
https://testing-library.com/docs/react-testing-library/intro/
要素を取得する
getByHoge
は該当する要素が見つからないとエラーになる。複数見つかった場合もエラーになるので注意。
queryByHoge
は要素がないとnullが返却される。複数ある場合は先頭が返却される。
使うときの優先度や詳しい説明は下記を参照
https://testing-library.com/docs/queries/about
特定のボタンを取得する
// role='button', aria-label='hoge'のボタンを取得
screen.getByRole('button', { name: 'hoge' })
取得した要素から親のタグを検索
// テキストが'hoge'の要素の親の<tr>を探す
screen.getByText('hoge').closest('tr')
Roleについて
各タグにデフォルトで設定されているRoleは下記を参照
https://www.w3.org/TR/html-aria/
render
名前の通り、テスト要素をレンダリングする。
render(<Hoge>);
screen
レンダリングした要素にアクセスする
// 画面上のボタン要素を取得
screen.getByRole('button')
waitFor
初期表示や再描画されるのをまったりする時に使う
// 画面上にhogeが表示されるまで待つ
await waitFor(() => {
screen.getByText(/hoge/);
});
within
画面上の一部にフォーカスする時に使う
// hogeが記載されている<tr>を取得してその中のbuttonを取得
const tr = screen.getByText('hoge').closest('tr');
const button = within(tr!).getByRole('button');
イベント発火
userEvent
を使う。
ボタンクリックやテキストの編集などができる。
https://testing-library.com/docs/ecosystem-user-event/
type
テキストの編集ができる。すでに値がある場合は追記になる。消したい場合はclearを使う。
userEvent.type(input, 'hoge');
// 入力後にフォーカスを外したい場合はtabを呼び出す
userEvent.tab();
Apollo
サーバーをモックする
https://www.apollographql.com/docs/react/development-testing/testing/
mocks
は名前の通り複数渡すことができる。
queryとvariablesの組み合わせが一致するものが定義されていないとエラーが発生する。
import { MockedProvider } from '@apollo/client/testing';
const mocks = [
{
request: {
query: HogeDocument,
variables: {},
},
result: {
data: {
hoge: {
id: 1,
text: 'hoge'
},
},
},
},
{
request: {
query: UpdateHogeDocument,
variables: { id: 1, text: 'hoge' }
},
result: {
data: {
id: 1,
text: 'hoge'
}
},
}
];
it('hoge', async () => {
render(
<MockedProvider mocks={mocks} addTypename={false}>
<Hoge />
</MockedProvider>
);
// レンダー時に呼び出されるものはwaitForで待って確認
// Mutationは発火させるアクションを実施したのちにwaitForで待って確認
});
mocks内のクエリーは1回のテストで1回しか利用できないようだ。
例えば上記の例でHogeDocument
を2回呼ぶと2回目はエラーになる。
2回呼ぶ場合はHogeDocument
をmocksに2つ定義しておく。
この仕様のおかげで呼び出しごとにレスポンスを変えることができる。