React Intl
注意
setupTests を他のセットアップと組み合わせたい場合は、
setup
を確認する必要があります。
React-Intl のポリフィル/ロケールの設定
プロジェクトで React-Intl を使用しており、ロケールをロードする必要がある場合、2つのオプションがあります。
Node 13 以降を使用している場合、Intl のサポートは標準で組み込まれています。Node のデフォルトの ICU (International Components for Unicode) オプションは
full-icu
であり、これはすべての ICU を意味します。
必要な ICU データのセットを埋め込むだけで済みます。// test-utils.js
const hasFullICU = () => {
// That's the recommended way to test for ICU support according to Node.js docs
try {
const january = new Date(9e8)
const pt = new Intl.DateTimeFormat('pt', {month: 'long'})
return pt.format(january) === 'janeiro'
} catch (err) {
return false
}
}
export const setupTests = () => {
if (hasFullICU()) {
Intl.NumberFormat.format = new Intl.NumberFormat('pt').format
Intl.DateTimeFormat.format = new Intl.DateTimeFormat('pt').format
} else {
global.Intl = IntlPolyfill
}
}以前のバージョンの Node を使用している場合、ICU のデフォルトオプションは
small-icu
であり、これは ICU データの一部 (通常は英語ロケールのみ) が含まれていることを意味します。
ロケールをロードする必要がある場合は、2つのオプションがあります。その言語に従ってポリフィルをロードする
// test-utils.js
import IntlPolyfill from 'intl'
import 'intl/locale-data/jsonp/pt'
export const setupTests = () => {
// https://formatjs.io/docs/guides/runtime-requirements/#nodejs
if (global.Intl) {
Intl.NumberFormat = IntlPolyfill.NumberFormat
Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat
} else {
global.Intl = IntlPolyfill
}
}ランタイム時に ICU をロードする
パッケージ full-icu をインストールし、テスト環境に注入します。これは、jest を呼び出す前にNODE_ICU_DATA
を設定することで実行できます。例:NODE_ICU_DATA=node_modules/full-icu jest
。これにより、オプション 1 で示されているように、full-icu のサポートが得られます。
カスタムの render 関数の作成
翻訳されたコンポーネントをテストするために、セットアップページで説明されているように、wrapper
オプションを使用してカスタムの render
関数を作成できます。
カスタムの render
関数は次のようになります。
// test-utils.js
import React from 'react'
import {render as rtlRender} from '@testing-library/react'
import {IntlProvider} from 'react-intl'
function render(ui, {locale = 'pt', ...renderOptions} = {}) {
function Wrapper({children}) {
return <IntlProvider locale={locale}>{children}</IntlProvider>
}
return rtlRender(ui, {wrapper: Wrapper, ...renderOptions})
}
// re-export everything
export * from '@testing-library/react'
// override render method
export {render}
完全な例
import React from 'react'
import '@testing-library/jest-dom'
// We're importing from our own created test-utils and not RTL's
import {render, screen, setupTests} from '../test-utils.js'
import {FormattedDate} from 'react-intl'
const FormatDateView = () => {
return (
<div data-testid="date-display">
<FormattedDate
value="2019-03-11"
timeZone="utc"
day="2-digit"
month="2-digit"
year="numeric"
/>
</div>
)
}
setupTests()
test('it should render FormattedDate and have a formatted pt date', () => {
render(<FormatDateView />)
expect(screen.getByTestId('date-display')).toHaveTextContent('11/03/2019')
})
翻訳されたコンポーネントのテスト戦略
翻訳されたコンポーネントをテストする場合、目的のカバレッジを達成するためにさまざまなアプローチが考えられます。その目標は、可能な限りユーザーの動作をシミュレートする方法でコンポーネントをテストできるようにすることです。
アプローチ | メリット | デメリット |
---|---|---|
デフォルト言語の文字列を使用する | テストは読みやすく、予想されるデフォルト出力をアサートします。文字列に変数がある場合は、それらが正しい出力で適切に機能することをテストできます。 | 1. テストにハードコードされた文字列は、コピーを変更するたびにテストとコードの両方を更新する必要があることを意味します。2. 複数の要素が同じ文字列/部分文字列テキストを持っている場合、検索と置換を信頼性高く使用するのが難しい場合があります。 |
翻訳ライブラリをモックする | ライブラリをテスト環境で使用するのが難しい場合は、より簡単に使用できるようにモックできます。たとえば、テキストにデータ属性としてメッセージ ID を追加して、それでクエリできるようにできます。 | テストコードは、本番環境で実行されるものとは異なります。テストはメッセージ ID についてアサートするかもしれませんが、コンテンツについては十分ではなく、エラーが発生する可能性があります。 |
テストで翻訳ライブラリを使用する | 文字列をテストから切り離すため、テストを中断させることを心配せずに、1か所でメッセージファイルを更新できます。別の言語または複数の言語でテストを実行できます。const buttonText = getNodeText(<FormattedMessage id="buttonText" defaultMessage="Hello Button" />); | オーバーヘッド - テストを作成するために多くのコード行が必要になり、正しい文字列を作成するには変数とメッセージ ID を知る必要があります。テストコードを読むとき、テキストが実際には何であるかが明らかではないため、保守が難しくなります。 |
翻訳ライブラリ + インラインスナップショットを使用する | 上記と同様ですが、文字列のインラインスナップショットを追加することで、テストコードを読み、どの文字列が使用されているかを確認できますが、メッセージが変更された場合は、jest --updateSnapshot で簡単に更新できます。expect(buttonText).toMatchInlineSnapshot("'My button text'") | 追加の行があるため、テストが長くなります。翻訳関連のコードの一部をヘルパー関数にまとめることで、少しインライン化しやすくして、繰り返しを避けることができますが、それでもテスト内でメッセージ ID と変数を把握する必要があります。 |