Testes com formatjs
Esta página foi traduzida por PageTurner AI (beta). Não é oficialmente endossada pelo projeto. Encontrou um erro? Reportar problema →
Requisitos das APIs Intl
O React Intl utiliza as APIs Intl integradas do JavaScript. Certifique-se de que seu ambiente atende aos requisitos listados em Requisitos das APIs Intl.
Mocha
Se você usa o Mocha como executor de testes em ambientes JavaScript legados, pode carregar o Intl Polyfill via CLI ou adicionando uma tag <script> no navegador.
Linha de Comando
Execute mocha e aplique automaticamente o polyfill se necessário:
$ mocha --recursive test/
Navegador
Você pode carregar o polyfill no navegador a partir de node_modules ou usar o serviço polyfill-fastly.io do Financial Times:
<script src="https://polyfill-fastly.io/v2/polyfill.min.js?features=Intl,Intl.~locale.en-US"></script>
Renderização Superficial (Shallow Rendering)
O pacote react-addons-test-utils do React inclui um recurso de renderização superficial que você pode usar para testar componentes React. Se um componente testado com ReactShallowRenderer utiliza React Intl — especialmente injectIntl() — será necessário configurar adicionalmente, pois componentes React Intl exigem estar aninhados em um <IntlProvider>.
Testando Componentes de Exemplo que Usam React Intl
Os exemplos seguintes pressupõem o uso da estrutura de testes mocha, expect e 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
Testar o componente de exemplo <ShortDate> não difere de testar qualquer outro componente básico usando renderização superficial do 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" />
)
})
})
Renderização DOM
Ao usar DOM em testes, forneça o contexto IntlProvider aos componentes via composição:
let element = ReactTestUtils.renderIntoDocument(
<IntlProvider>
<MyComponent />
</IntlProvider>
)
Isso faz com que a referência element aponte para o IntlProvider em vez do seu componente. Para obter uma referência ao componente encapsulado, use "refs" com estas alterações:
No seu componente, adicione {forwardRef: true} ao chamar injectIntl():
class MyComponent extends React.Component {
...
myClassFn() { ... }
}
export default injectIntl(MyComponent, {forwardRef: true});
No teste, adicione um "ref" para extrair a referência ao componente testado:
const element = React.createRef()
ReactTestUtils.renderIntoDocument(
<IntlProvider>
<MyComponent ref={element} />
</IntlProvider>
)
Agora você pode acessar a instância do componente encapsulado via element assim:
element.current.myClassFn()
Função auxiliar
Como essa configuração será repetida em todos os testes unitários, encapsule-a numa função render:
function renderWithIntl(element) {
let instance
ReactTestUtils.renderIntoDocument(
<IntlProvider>
{React.cloneElement(element, {
ref: instance,
})}
</IntlProvider>
)
return instance
}
Use-a em seus testes desta forma:
const element = React.createRef();
renderWithIntl(<MyElement ref={element}>);
element.current.myClassFn();
Enzyme
Testar com Enzyme segue lógica similar à descrita acima. Componentes mount()ados ou shallow()ados precisam do contexto intl. Abaixo está uma função auxiliar para montar componentes que utilizam recursos do React-Intl (componentes <Formatted* /> ou métodos format*() via injectIntl).
Função 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
Crie um arquivo com o helper acima em, por exemplo, helpers/intl-enzyme-test-helper.js e import os métodos necessários nos testes.
// 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
Baseado neste gist.
Jest
Testes com Jest podem ser divididos em duas abordagens: snapshot testing e DOM testing. O snapshot testing é um recurso recente e funciona prontamente. Para DOM testing, use Enzyme ou React TestUtils.
Snapshot Testing
O teste de snapshot é um novo recurso do Jest que gera automaticamente snapshots textuais de seus componentes e os salva em disco. Assim, se a saída da interface do usuário mudar, você é notificado sem precisar escrever manualmente asserções sobre a saída do componente. Use a função auxiliar ou o mock conforme descrito abaixo.
Função 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()
})
Você pode encontrar um exemplo executável aqui e mais informações sobre o Jest aqui.
Uso com Jest e Enzyme
O Jest irá simular automaticamente o react-intl, portanto nenhuma implementação extra é necessária. Os testes devem funcionar como estão:
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()
})
Testes de DOM
Se você deseja usar o Jest com testes de DOM, leia mais informações na seção sobre Enzyme ou na documentação oficial do Jest.
Storybook
Intl
Se você deseja usar react-intl no Storybook, pode usar o storybook-addon-intl que fornece um wrapper fácil de usar para react-intl, incluindo um seletor de idioma para testar seu componente em todos os idiomas fornecidos.
react-testing-library
Para usar react-intl com react-testing-library, você deve fornecer alguma função auxiliar no fluxo de testes.
Você pode verificar a documentação.
Para criar uma solução genérica, podemos criar uma função render personalizada usando a opção wrapper conforme explicado na página de configuração.
Nossa função render personalizada pode ser assim:
// 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')
})