跳至主要內容

React Intl

注意

如果您想將 setupTests 與其他設定結合使用,您應該查看 setup

設定 React-Intl Polyfills / 地區設定

如果您在專案中使用 React-Intl,並且需要載入地區設定,您有兩個選項

  1. 當使用 Node 13 及更高版本時,Intl 支援現在是開箱即用的。Node 的預設 ICU(國際組件 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
    }
    }
  2. 當使用先前版本的 Node 時,ICU 預設選項為 small-icu,表示它包含 ICU 資料的子集(通常只有英文地區設定)。
    如果您確實需要載入地區設定,您有兩個選項

    1. 根據該語言載入 Polyfills

      // 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
      }
      }
    2. 在執行時載入 ICU
      安裝套件 full-icu 並將其注入您的測試環境,您可以在呼叫 jest 之前設定 NODE_ICU_DATA 來執行此操作:NODE_ICU_DATA=node_modules/full-icu jest。這樣做您將獲得如選項 1 中所示的完整 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. 如果多個元素具有相同的字串/子字串文字,則 find-and-replace 可能難以可靠地使用。
模擬翻譯程式庫如果您的程式庫在測試環境中難以使用,您可以模擬它使其更容易。例如,您可以將訊息 ID 作為資料屬性新增到文字中,以便您可以通過該屬性查詢。測試程式碼偏離了在生產環境中運行的程式碼。測試可能會斷言訊息 ID,但不足以斷言內容,因此可能會發生錯誤。
在測試中使用翻譯程式庫將字串與測試分離,因此您可以在一個地方更新訊息檔案,而無需擔心破壞測試。可以在另一種語言或多種語言中執行測試。const buttonText = getNodeText(<FormattedMessage id="buttonText" defaultMessage="Hello Button" />);開銷 - 編寫測試需要更多程式碼行,並且您需要知道變數和訊息 ID 才能建立正確的字串。當您閱讀測試程式碼時,並不明顯文字實際上是什麼,這使得維護更困難。
使用翻譯程式庫 + 內嵌快照與上述相同,但通過新增字串的內嵌快照,您可以閱讀測試程式碼並查看正在使用的字串,但如果訊息發生更改,可以使用 jest --updateSnapshot 輕鬆更新它們。expect(buttonText).toMatchInlineSnapshot("'My button text'")由於額外的行,測試會更長。您可以將一些與翻譯相關的程式碼封裝到一個輔助函數中,使其更容易內嵌並避免重複自己,但您仍然需要知道測試中的訊息 ID 和變數。