設定
React 測試函式庫
不需要任何設定即可使用。然而,您可以設定測試框架來減少一些樣板程式碼。在這些文件中,我們將示範如何設定 Jest,但您應該可以使用任何測試框架來做類似的事情(React 測試函式庫不要求您使用 Jest)。
全域設定
在您的全域測試設定中新增選項可以簡化個別檔案中測試的設定和拆解。
自訂渲染
定義一個包含全域上下文提供者、資料儲存等的自訂渲染方法通常很有用。為了使其在全域可用,一種方法是定義一個從 React Testing Library
重新匯出所有內容的實用程式檔案。您可以在所有導入中用這個檔案取代 React Testing Library。請參閱下方,了解如何在不使用相對路徑的情況下存取您的測試實用程式檔案。
下面的範例使用 render
的 wrapper
選項來設定資料提供者。
- JavaScript
- TypeScript
- import { render, fireEvent } from '@testing-library/react';
+ import { render, fireEvent } from '../test-utils';
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}
- import { render, fireEvent } from '@testing-library/react';
+ import { render, fireEvent } from '../test-utils';
import React, {ReactElement} from 'react'
import {render, RenderOptions} 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}: {children: React.ReactNode}) => {
return (
<ThemeProvider theme="light">
<TranslationProvider messages={defaultStrings}>
{children}
</TranslationProvider>
</ThemeProvider>
)
}
const customRender = (
ui: ReactElement,
options?: Omit<RenderOptions, 'wrapper'>,
) => render(ui, {wrapper: AllTheProviders, ...options})
export * from '@testing-library/react'
export {customRender as render}
注意
當嘗試覆寫上述範例中的具名匯出時,低於 7 的 Babel 版本會擲回錯誤。請參閱#169 和下方的解決方法。
Babel 6 的解決方法
您可以使用 CommonJS 模組而不是 ES 模組,這應該在 Node 中運作
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
選項在任何渲染呼叫中使用它們。為了使自訂查詢在全域可用,您可以將它們新增至您的自訂渲染方法中,如下所示。
在下面的範例中,建立了一組新的查詢變體,用於依 data-cy
取得元素,這是 Cypress.io 文件中提到的「測試 ID」慣例。
- JavaScript
- TypeScript
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,
}
import {
queryHelpers,
buildQueries,
Matcher,
MatcherOptions,
} 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 = (
container: HTMLElement,
id: Matcher,
options?: MatcherOptions | undefined,
) => queryHelpers.queryAllByAttribute('data-cy', container, id, options)
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
選項來覆寫和附加新的查詢。
如果您想要全域新增自訂查詢,您可以透過定義您的自訂 render
、screen
和 within
方法來執行此操作
- JavaScript
- TypeScript
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}
import {render, queries, within, RenderOptions} from '@testing-library/react'
import * as customQueries from './custom-queries'
import {ReactElement} from 'react'
const allQueries = {
...queries,
...customQueries,
}
const customScreen = within(document.body, allQueries)
const customWithin = (element: ReactElement) => within(element, allQueries)
const customRender = (
ui: ReactElement,
options?: Omit<RenderOptions, 'queries'>,
) => render(ui, {queries: allQueries, ...options})
export * from '@testing-library/react'
export {customScreen as screen, customWithin as within, customRender as render}
然後,您可以像使用任何其他查詢一樣使用您的自訂查詢
const {getByDataCy} = render(<Component />)
expect(getByDataCy('my-component')).toHaveTextContent('Hello')
使用測試工具設定 Jest
為了使您的自訂測試檔案可以在您的 Jest 測試檔案中存取,而無需使用相對導入(../../test-utils
),請將包含該檔案的資料夾新增至 Jest moduleDirectories
選項。
這將使 test-utils 目錄中的所有 .js
檔案都可以導入,而無需 ../
。
- import { render, fireEvent } from '../test-utils';
+ import { render, fireEvent } from 'test-utils';
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
中。
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"test-utils": ["./utils/test-utils"]
}
}
}
Jest 28
如果您使用的是 Jest 28 或更高版本,現在必須單獨安裝 jest-environment-jsdom 套件。
- npm
- Yarn
npm install --save-dev jest-environment-jsdom
yarn add --dev jest-environment-jsdom
jsdom
也不再是預設環境。您可以透過編輯 jest.config.js
來全域啟用 jsdom
module.exports = {
+ testEnvironment: 'jsdom',
// ... other options ...
}
或者,如果您只需要在某些測試中使用 jsdom
,您可以隨時使用docblocks 來啟用它
/**
* @jest-environment jsdom
*/
Jest 27
如果您使用的是最近版本的 Jest (27),jsdom
不再是預設環境。您可以透過編輯 jest.config.js
來全域啟用 jsdom
module.exports = {
+ testEnvironment: 'jest-environment-jsdom',
// ... other options ...
}
或者,如果您只需要在某些測試中使用 jsdom
,您可以隨時使用docblocks 來啟用它
/**
* @jest-environment jsdom
*/
Jest 24 (或更低版本) 和預設值
如果您使用的是 Jest 測試框架版本 24 或更低版本,並且使用預設設定,建議使用 jest-environment-jsdom-fifteen
套件,因為 Jest 使用的 jsdom 環境版本缺少一些 React Testing Library 所需的功能和修正。
首先,安裝 jest-environment-jsdom-fifteen
。
- npm
- Yarn
npm install --save-dev jest-environment-jsdom-fifteen
yarn add --dev jest-environment-jsdom-fifteen
然後指定 jest-environment-jsdom-fifteen
作為 testEnvironment
module.exports = {
+ testEnvironment: 'jest-environment-jsdom-fifteen',
// ... other options ...
}
在沒有 Jest 的情況下使用
如果您是在使用 webpack(或類似工具)捆綁的瀏覽器中執行測試,那麼 React 測試函式庫
應該可以直接使用。但是,大多數使用 React Testing Library 的人都是將其與 testEnvironment
設定為 jest-environment-jsdom
的 Jest 測試框架一起使用(這是 Jest 26 和更早版本的預設設定)。
jsdom
是 DOM 和瀏覽器 API 的純 JavaScript 實作,可在 Node 中執行。如果您未使用 Jest,並且想要在 Node 中執行測試,則必須自行安裝 jsdom。還有一個名為 global-jsdom
的套件,可用於設定全域環境以模擬瀏覽器 API。
首先,安裝 jsdom
和 global-jsdom
。
- npm
- Yarn
npm install --save-dev jsdom global-jsdom
yarn add --dev jsdom global-jsdom
使用 mocha,測試命令看起來會像這樣
mocha --require global-jsdom/register
跳過自動清除
如果您使用的測試框架支援 afterEach
全域(例如 mocha、Jest 和 Jasmine),則預設會在每個測試後自動呼叫 Cleanup
。但是,您可以選擇將 RTL_SKIP_AUTO_CLEANUP
env 變數設定為 '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
檔案
const {cleanup} = require('@testing-library/react')
exports.mochaHooks = {
afterEach() {
cleanup()
},
}
並使用 mocha 的 -r
標記註冊它
mocha --require ./mocha-watch-cleanup-after-each.js