Pruebas con formatjs
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Requisitos de las APIs Intl
React Intl utiliza las APIs Intl integradas en JavaScript. Asegúrate de que tu entorno cumple con los requisitos listados en Requisitos de las APIs Intl
Mocha
Si usas Mocha como ejecutor de pruebas y estás probando en entornos JavaScript antiguos, puedes cargar el Polyfill de Intl mediante CLI o añadiendo un <script> en el navegador.
Línea de comandos
Ejecuta mocha y aplica polyfill automáticamente si es necesario:
$ mocha --recursive test/
Navegador
Puedes cargar el polyfill en el navegador desde node_modules o usar el servicio polyfill-fastly.io de Financial Times:
<script src="https://polyfill-fastly.io/v2/polyfill.min.js?features=Intl,Intl.~locale.en-US"></script>
Renderizado superficial
El paquete react-addons-test-utils de React incluye una función de renderizado superficial que podrías usar para probar componentes React. Si un componente que intentas probar con ReactShallowRenderer usa React Intl — específicamente injectIntl() — necesitarás configuración adicional porque los componentes de React Intl esperan estar dentro de un <IntlProvider>.
Probando componentes de ejemplo que usan React Intl
Los siguientes ejemplos asumen el uso del framework de pruebas mocha, expect y expect-jsx.
ShortDate (Básico)
import React from 'react'
import {FormattedDate} from 'react-intl'
const ShortDate = props => (
<FormattedDate
value={props.date}
year="numeric"
month="short"
day="2-digit"
/>
)
export default ShortDate
Probar el componente de ejemplo <ShortDate> no difiere de probar cualquier otro componente básico usando el renderizado superficial de React:
import expect from 'expect'
import expectJSX from 'expect-jsx'
import React from 'react'
import {createRenderer} from 'react-addons-test-utils'
import {FormattedDate} from 'react-intl'
import ShortDate from '../short-date'
expect.extend(expectJSX)
describe('<ShortDate>', function () {
it('renders', function () {
const renderer = createRenderer()
const date = new Date()
renderer.render(<ShortDate date={date} />)
expect(renderer.getRenderOutput()).toEqualJSX(
<FormattedDate value={date} year="numeric" month="short" day="2-digit" />
)
})
})
Renderizado DOM
Si usas DOM en tus pruebas, debes proporcionar el contexto de IntlProvider a tus componentes mediante composición:
let element = ReactTestUtils.renderIntoDocument(
<IntlProvider>
<MyComponent />
</IntlProvider>
)
Sin embargo, esto significa que la referencia element ahora apunta al IntlProvider en lugar de a tu componente. Para obtener una referencia a tu componente envuelto, usa "refs" con estos cambios en el código:
En tu componente, recuerda añadir {forwardRef: true} al llamar injectIntl():
class MyComponent extends React.Component {
...
myClassFn() { ... }
}
export default injectIntl(MyComponent, {forwardRef: true});
En tu prueba, añade un "ref" para extraer la referencia a tu componente bajo prueba:
const element = React.createRef()
ReactTestUtils.renderIntoDocument(
<IntlProvider>
<MyComponent ref={element} />
</IntlProvider>
)
Ahora puedes acceder a la instancia del componente envuelto desde element así:
element.current.myClassFn()
Función auxiliar
Dado que necesitarás hacer esto en todas tus pruebas unitarias, probablemente deberías encapsular esta configuración en una función render como esta:
function renderWithIntl(element) {
let instance
ReactTestUtils.renderIntoDocument(
<IntlProvider>
{React.cloneElement(element, {
ref: instance,
})}
</IntlProvider>
)
return instance
}
Ahora puedes usarla en tus pruebas de esta forma:
const element = React.createRef();
renderWithIntl(<MyElement ref={element}>);
element.current.myClassFn();
Enzyme
Probar con Enzyme funciona de manera similar a lo descrito anteriormente. Tus componentes mount()eados y shallow()eados necesitarán acceso al contexto intl. A continuación se muestra una función auxiliar que puedes importar y usar para montar componentes que utilicen cualquier elemento de React-Intl (ya sea componentes <Formatted* /> o métodos format*() mediante injectIntl).
Función auxiliar
/**
* Components using the react-intl module require access to the intl context.
* This is not available when mounting single components in Enzyme.
* These helper functions aim to address that and wrap a valid,
* English-locale intl context around them.
*/
import React from 'react'
import {IntlProvider} from 'react-intl'
import {mount, shallow} from 'enzyme'
// You can pass your messages to the IntlProvider. Optional: remove if unneeded.
const messages = require('../locales/en') // en.json
const defaultLocale = 'en'
const locale = defaultLocale
export function mountWithIntl(node: React.ReactElement) {
return mount(node, {
wrappingComponent: IntlProvider,
wrappingComponentProps: {
locale,
defaultLocale,
messages,
},
})
}
export function shallowWithIntl(node: React.ReactElement) {
return shallow(node, {
wrappingComponent: IntlProvider,
wrappingComponentProps: {
locale,
defaultLocale,
messages,
},
})
}
Uso
Crea un archivo con el helper anterior en, por ejemplo, helpers/intl-enzyme-test-helper.js y import los métodos que necesites en tus pruebas.
// intl-enzyme-test-helper.js
import {mountWithIntl} from 'helpers/intl-enzyme-test-helper.js'
const wrapper = mountWithIntl(<CustomComponent />)
expect(wrapper.state('foo')).to.equal('bar') // OK
expect(wrapper.text()).to.equal('Hello World!') // OK
Basado en este gist.
Jest
Las pruebas con Jest pueden dividirse en dos enfoques: pruebas de snapshot y pruebas DOM. Las pruebas de snapshot son una característica relativamente nueva y funcionan sin configuración adicional. Si prefieres pruebas DOM necesitarás usar Enzyme o React TestUtils.
Pruebas de snapshot
Las pruebas de instantáneas (snapshot testing) son una nueva función de Jest que genera automáticamente instantáneas de texto de tus componentes y las guarda en disco. Si la salida de la UI cambia, recibirás una notificación sin necesidad de escribir manualmente aserciones sobre el resultado del componente. Utiliza ya sea una función auxiliar o un mock como se describe a continuación.
Función auxiliar
import React from 'react'
import renderer from 'react-test-renderer'
import {IntlProvider} from 'react-intl'
const createComponentWithIntl = (children, props = {locale: 'en'}) => {
return renderer.create(<IntlProvider {...props}>{children}</IntlProvider>)
}
export default createComponentWithIntl
Uso
import React from 'react'
import createComponentWithIntl from '@site/utils/createComponentWithIntl'
import AppMain from '../AppMain'
test('app main should be rendered', () => {
const component = createComponentWithIntl(<AppMain />)
let tree = component.toJSON()
expect(tree).toMatchSnapshot()
tree.props.onClick()
tree = component.toJSON()
expect(tree).toMatchSnapshot()
})
Puedes encontrar un ejemplo ejecutable aquí y más información sobre Jest aquí.
Uso con Jest y Enzyme
Jest simulará automáticamente react-intl, así que no se necesita ninguna implementación adicional. Las pruebas deberían funcionar tal cual:
import React from 'react'
import {shallow} from 'enzyme'
import AppMain from '../AppMain'
test('app main should be rendered', () => {
const wrapper = shallow(<AppMain />)
expect(wrapper).toMatchSnapshot()
})
Pruebas DOM
Si deseas usar Jest con pruebas DOM, consulta más información en la sección de Enzyme o en la documentación oficial de Jest.
Storybook
Intl
Si quieres usar react-intl dentro de Storybook, puedes utilizar storybook-addon-intl. Este complemento proporciona un wrapper fácil de usar para react-intl, incluyendo un selector de idioma para que puedas probar tu componente en todos los idiomas proporcionados.
react-testing-library
Para usar react-intl junto con react-testing-library, deberás proporcionar alguna función auxiliar en el flujo de pruebas.
Puedes consultar la documentación.
Para crear una solución genérica, podemos crear una función render personalizada usando la opción wrapper como se explica en la página de configuración.
Nuestra función render personalizada podría verse así:
// 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/jest-globals'
// We're importing from our own created test-utils and not RTL's
import {render, screen} 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>
)
}
test('it should render FormattedDate and have a formated pt date', () => {
render(<FormatDateView />)
expect(screen.getByTestId('date-display')).toHaveTextContent('11/03/2019')
})