Aller au contenu principal

React Intl

[Traduction Bêta Non Officielle]

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

Note

Si vous souhaitez combiner setupTests avec une autre configuration, consultez la page setup

Configuration des polyfills et locales React-Intl

Si vous utilisez React-Intl dans votre projet et que vous devez charger une locale, vous avez deux options :

  1. Avec Node 13 et supérieur, la prise en charge d'Intl est désormais intégrée nativement. L'option ICU (International Components for Unicode) par défaut pour Node est full-icu, ce qui signifie toutes les fonctionnalités ICU.
    Vous devez simplement intégrer le jeu de données ICU nécessaire :

    // 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. Avec les versions antérieures de Node, l'option ICU par défaut est small-icu (incluant uniquement un sous-ensemble de données ICU, généralement la locale anglaise).
    Si vous devez charger une locale, deux approches sont possibles :

    1. Charger les polyfills pour la langue cible :

      // 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. Charger les ICU à l'exécution :
      Installez le package full-icu et injectez-le dans votre environnement de test en définissant NODE_ICU_DATA avant d'appeler Jest : NODE_ICU_DATA=node_modules/full-icu jest. Cette méthode fournit le support full-icu comme dans l'option 1.

Création d'une fonction de rendu personnalisée

Pour tester notre composant traduit, nous pouvons créer une fonction render personnalisée via l'option wrapper, comme expliqué dans la page setup.
Notre fonction render personnalisée peut ressembler à ceci :

// 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}

Exemple complet

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')
})

Stratégie de test des composants traduits

Plusieurs approches existent pour tester un composant traduit tout en garantissant la couverture souhaitée. L'objectif principal reste de simuler au plus près le comportement utilisateur réel.

ApproachProsCons
Use strings from the default languageTest is easy to read, and asserts expected default output. If you have variables in your strings, you can test that they work properly with correct output.1. Strings hardcoded into tests mean you have to update both tests and code for any copy changes. 2. If multiple elements have the same string/substring text, find-and-replace may be hard to use reliably.
Mock the translation libraryIf your library is difficult to use in the test environment, you can mock it so it is easier. For example, you can add the message ID as a data-attribute to the text so you can query by that.Test code deviates from what runs in production. Tests may assert about message IDs but not enough about content, so errors are possible.
Use translation library in testsDecouples strings from tests, so you can update the message files in one place without worrying about breaking tests. Can run tests in another language or multiple languages. const buttonText = getNodeText(<FormattedMessage id="buttonText" defaultMessage="Hello Button" />);Overhead - it takes more lines of code to write the test, and you need to know the variables and message IDs to create the right strings. It's not obvious what the text actually is when you read the test code, making maintaining it harder.
Use translation library + inline snapshotsSame as above, but by adding an inline snapshot of the string, you can read the test code and see what strings are in use, but easily update them with jest --updateSnapshot if the messages change. expect(buttonText).toMatchInlineSnapshot("'My button text'")Tests are longer because of the extra lines. You can wrap up some of the translation-related code into a helper function to make it a little more inline-able and avoid repeating yourself, but you still need to know the message IDs and variables inside the test.