メインコンテンツにスキップ

セットアップ

React Testing Libraryは、使用するために特別な設定を必要としません。しかし、テストフレームワークを設定する際に、定型コードを減らすためにできることがいくつかあります。このドキュメントではJestの設定方法を説明しますが、他のテストフレームワークでも同様の設定が可能です(React Testing LibraryはJestの使用を必須としていません)。

グローバル設定

グローバルテスト設定にオプションを追加することで、個々のファイルのテストのセットアップとティアダウンを簡素化できます。

カスタムレンダリング

グローバルコンテキストプロバイダー、データストアなどを含むカスタムレンダリングメソッドを定義すると便利な場合があります。これをグローバルに利用できるようにするには、React Testing Libraryからすべてを再エクスポートするユーティリティファイルを定義する方法があります。すべてのインポートで、React Testing Libraryをこのファイルに置き換えることができます。相対パスを使用せずにテストユーティリティファイルにアクセスできるようにする方法については、以下を参照してください。

以下の例では、renderwrapperオプションを使用してデータプロバイダーを設定しています。

my-component.test.jsx
- import { render, fireEvent } from '@testing-library/react';
+ import { render, fireEvent } from '../test-utils';
test-utils.jsx
import React from 'react'
import {render} from '@testing-library/react'
import {ThemeProvider} from 'my-ui-lib'
import {TranslationProvider} from 'my-i18n-lib'
import defaultStrings from 'i18n/en-x-default'

const AllTheProviders = ({children}) => {
return (
<ThemeProvider theme="light">
<TranslationProvider messages={defaultStrings}>
{children}
</TranslationProvider>
</ThemeProvider>
)
}

const customRender = (ui, options) =>
render(ui, {wrapper: AllTheProviders, ...options})

// re-export everything
export * from '@testing-library/react'

// override render method
export {customRender as render}

注意

上記の例で名前付きエクスポートをオーバーライドしようとすると、Babelバージョン7未満ではエラーが発生します。#169と以下の回避策を参照してください。

Babel 6の回避策

ESモジュールではなく、Nodeで動作するはずのCommonJSモジュールを使用できます

test-utils.js
const rtl = require('@testing-library/react')

const customRender = (ui, options) =>
rtl.render(ui, {
myDefaultOption: 'something',
...options,
})

module.exports = {
...rtl,
render: customRender,
}

カスタムクエリの追加

注意

一般的に、react-testing-library用のカスタムクエリを作成する必要はありません。使用する場合は、新しいクエリが実装の詳細をテストせずに、ユーザー中心の方法でテストすることを推奨しているかどうかを検討する必要があります。

カスタムクエリドキュメントに記載されているように、またはbuildQueriesヘルパーを使用して、独自のカスタムクエリを定義できます。その後、queriesオプションを使用して、任意のレンダリングコールでそれらを使用できます。カスタムクエリをグローバルに利用できるようにするには、以下に示すように、カスタムレンダリングメソッドに追加します。

以下の例では、Cypress.ioドキュメントで言及されている「テストID」規則であるdata-cyで要素を取得するための一連の新しいクエリバリアントが作成されます。

custom-queries.js
import {queryHelpers, buildQueries} from '@testing-library/react'

// The queryAllByAttribute is a shortcut for attribute-based matchers
// You can also use document.querySelector or a combination of existing
// testing library utilities to find matching nodes for your query
const queryAllByDataCy = (...args) =>
queryHelpers.queryAllByAttribute('data-cy', ...args)

const getMultipleError = (c, dataCyValue) =>
`Found multiple elements with the data-cy attribute of: ${dataCyValue}`
const getMissingError = (c, dataCyValue) =>
`Unable to find an element with the data-cy attribute of: ${dataCyValue}`

const [
queryByDataCy,
getAllByDataCy,
getByDataCy,
findAllByDataCy,
findByDataCy,
] = buildQueries(queryAllByDataCy, getMultipleError, getMissingError)

export {
queryByDataCy,
queryAllByDataCy,
getByDataCy,
getAllByDataCy,
findAllByDataCy,
findByDataCy,
}

その後、queriesオプションを渡すことで、レンダリング関数を使用して新しいクエリをオーバーライドおよび追加できます。

カスタムクエリをグローバルに追加する場合は、カスタマイズしたrenderscreen、およびwithinメソッドを定義することでこれを行うことができます

test-utils.js
import {render, queries, within} from '@testing-library/react'
import * as customQueries from './custom-queries'

const allQueries = {
...queries,
...customQueries,
}

const customScreen = within(document.body, allQueries)
const customWithin = element => within(element, allQueries)
const customRender = (ui, options) =>
render(ui, {queries: allQueries, ...options})

// re-export everything
export * from '@testing-library/react'

// override render method
export {customScreen as screen, customWithin as within, customRender as render}

その後、他のクエリと同様にカスタムクエリを使用できます

const {getByDataCy} = render(<Component />)

expect(getByDataCy('my-component')).toHaveTextContent('Hello')

Jestとテストユーティリティの設定

相対インポート(../../test-utils)を使用せずにJestテストファイルでカスタムテストファイルにアクセスできるようにするには、ファイルを含むフォルダーをJest moduleDirectoriesオプションに追加します。

これにより、test-utilsディレクトリ内のすべての.jsファイルが../なしでインポート可能になります。

my-component.test.js
- import { render, fireEvent } from '../test-utils';
+ import { render, fireEvent } from 'test-utils';
jest.config.js
module.exports = {
moduleDirectories: [
'node_modules',
+ // add the directory with the test-utils.js file, for example:
+ 'utils', // a utility folder
+ __dirname, // the root directory
],
// ... other options ...
}

TypeScriptを使用している場合は、これをtsconfig.jsonにマージします。TypeScriptなしでCreate React Appを使用している場合は、代わりにjsconfig.jsonに保存します。

tsconfig.json
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"test-utils": ["./utils/test-utils"]
}
}
}

Jest 28

Jest 28以降を使用している場合、jest-environment-jsdomパッケージを個別にインストールする必要があります。

npm install --save-dev jest-environment-jsdom

また、jsdomはデフォルトの環境ではなくなりました。 jest.config.jsを編集することで、グローバルにjsdomを有効にすることができます

jest.config.js
 module.exports = {
+ testEnvironment: 'jsdom',
// ... other options ...
}

または、一部のテストでのみjsdomが必要な場合は、docblocksを使用して必要に応じて有効にすることができます

/**
* @jest-environment jsdom
*/

Jest 27

Jestの最新バージョン(27)を使用している場合、jsdomはデフォルトの環境ではなくなりました。 jest.config.jsを編集することで、グローバルにjsdomを有効にすることができます

jest.config.js
 module.exports = {
+ testEnvironment: 'jest-environment-jsdom',
// ... other options ...
}

または、一部のテストでのみjsdomが必要な場合は、docblocksを使用して必要に応じて有効にすることができます

/**
* @jest-environment jsdom
*/

Jest 24(またはそれ以前)とデフォルト

デフォルト設定でJestテストフレームワークバージョン24以前を使用している場合、JestはReact Testing Libraryで必要な機能と修正が不足しているバージョンのjsdom環境を使用しているため、jest-environment-jsdom-fifteenパッケージを使用することをお勧めします。

まず、jest-environment-jsdom-fifteenをインストールします。

npm install --save-dev jest-environment-jsdom-fifteen

次に、testEnvironmentとしてjest-environment-jsdom-fifteenを指定します

jest.config.js
 module.exports = {
+ testEnvironment: 'jest-environment-jsdom-fifteen',
// ... other options ...
}

Jestを使用しない場合

webpack(または類似のもの)にバンドルされたブラウザでテストを実行している場合、React Testing Libraryはそのまま使用できます。ただし、React Testing Libraryを使用しているほとんどの人は、JestテストフレームワークでtestEnvironmentjest-environment-jsdomに設定して使用しています(これはJest 26以前のデフォルト設定です)。

jsdomは、Nodeで実行されるDOMおよびブラウザAPIの純粋なJavaScript実装です。Jestを使用しておらず、Nodeでテストを実行したい場合は、jsdomを自分でインストールする必要があります。また、ブラウザAPIをシミュレートするためにグローバル環境を設定するために使用できるglobal-jsdomと呼ばれるパッケージもあります。

まず、jsdomglobal-jsdomをインストールします。

npm install --save-dev jsdom global-jsdom

mochaを使用すると、テストコマンドは次のようになります

mocha --require global-jsdom/register

自動クリーンアップのスキップ

使用しているテストフレームワークがafterEachグローバル(mocha、Jest、Jasmineなど)をサポートしている場合、デフォルトでは各テスト後にCleanupが自動的に呼び出されます。ただし、RTL_SKIP_AUTO_CLEANUP環境変数を「true」に設定することで、自動クリーンアップをスキップすることを選択できます。これは、cross-envを使用して次のように行うことができます

cross-env RTL_SKIP_AUTO_CLEANUP=true jest

これをさらに簡単にするために、@testing-library/react/dont-cleanup-after-eachをインポートするだけで、同じことができます。 @testing-library/reactをインポートする前に、必ずこれを行ってください。これは、JestのsetupFiles設定を使用して行うことができます

{
// ... other jest config
setupFiles: ['@testing-library/react/dont-cleanup-after-each']
}

または、mochaの-rフラグを使用します

mocha --require @testing-library/react/dont-cleanup-after-each

あるいは、cleanupを実行したくないすべてのテストで@testing-library/react/pureをインポートすることもできます。そうすれば、afterEachは自動的に設定されません。

Mochaのウォッチモードでの自動クリーンアップ

Mochaをウォッチモードで使用する場合、グローバルに登録されたクリーンアップは、各テスト後に初めてのみ実行されます。そのため、後続の実行は、* TestingLibraryElementError:複数の要素が見つかりました *エラーで失敗する可能性が高くなります。

Mochaのウォッチモードで自動クリーンアップを有効にするには、クリーンアップルートフックを追加します。次の内容でmocha-watch-cleanup-after-each.jsファイルを作成します

mocha-watch-cleanup-after-each.js
const {cleanup} = require('@testing-library/react')

exports.mochaHooks = {
afterEach() {
cleanup()
},
}

そして、mochaの-rフラグを使用して登録します

mocha --require ./mocha-watch-cleanup-after-each.js