Zum Hauptinhalt springen

Testen mit formatjs

Inoffizielle Beta-Übersetzung

Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →

Anforderungen für Intl-APIs

React Intl nutzt die integrierten Intl-APIs in JavaScript. Stellen Sie sicher, dass Ihre Umgebung die Anforderungen erfüllt, die unter Intl-API-Anforderungen aufgeführt sind.

Mocha

Wenn Sie Mocha als Testrunner verwenden und auf älteren JavaScript-Laufzeitumgebungen testen, können Sie das Intl-Polyfill über die Kommandozeile oder durch Hinzufügen eines <script>-Tags im Browser laden.

Kommandozeile

Führen Sie mocha aus und füllen Sie die Laufzeitumgebung bei Bedarf automatisch auf:

$ mocha --recursive test/

Browser

Sie können das Polyfill entweder im Browser aus node_modules laden oder den polyfill-fastly.io-Service der Financial Times nutzen:

<script src="https://polyfill-fastly.io/v2/polyfill.min.js?features=Intl,Intl.~locale.en-US"></script>

Oberflächliches Rendering

Das react-addons-test-utils-Paket von React enthält eine Funktion zum oberflächlichen Rendering, die Sie zum Testen Ihrer React-Komponenten verwenden könnten. Wenn eine Komponente, die Sie mit ReactShallowRenderer testen möchten, React Intl verwendet – insbesondere injectIntl() – müssen Sie zusätzliche Einrichtungsarbeit leisten, da React Intl-Komponenten erwarten, in einen <IntlProvider> eingebettet zu sein.

Beispielkomponenten testen, die React Intl verwenden

Die folgenden Beispiele setzen das Testframework mocha, expect und expect-jsx voraus.

ShortDate (Basic)

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

Das Testen der Beispielkomponente <ShortDate> unterscheidet sich nicht vom Testen anderer einfacher Komponenten in Ihrer Anwendung mit dem oberflächlichen Rendering von 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" />
)
})
})

DOM-Rendering

Wenn Sie das DOM in Ihren Tests verwenden, müssen Sie den IntlProvider-Kontext für Ihre Komponenten über Komposition bereitstellen:

let element = ReactTestUtils.renderIntoDocument(
<IntlProvider>
<MyComponent />
</IntlProvider>
)

Dies bedeutet jedoch, dass die element-Referenz nun auf den IntlProvider anstatt auf Ihre Komponente zeigt. Um eine Referenz auf Ihre umschlossene Komponente abzurufen, können Sie "Refs" mit folgenden Codeänderungen verwenden:

Fügen Sie in Ihrer Komponente {forwardRef: true} hinzu, wenn Sie injectIntl() aufrufen:

class MyComponent extends React.Component {
...
myClassFn() { ... }
}
export default injectIntl(MyComponent, {forwardRef: true});

Fügen Sie in Ihrem Test ein "ref" hinzu, um die Referenz auf Ihre getestete Komponente zu extrahieren:

const element = React.createRef()
ReactTestUtils.renderIntoDocument(
<IntlProvider>
<MyComponent ref={element} />
</IntlProvider>
)

Sie können nun auf die Instanz der umschlossenen Komponente über element wie folgt zugreifen:

element.current.myClassFn()

Hilfsfunktion

Da Sie dies in allen Ihren Unit-Tests tun müssen, sollten Sie das Setup wahrscheinlich in eine render-Funktion wie folgt einpacken:

function renderWithIntl(element) {
let instance

ReactTestUtils.renderIntoDocument(
<IntlProvider>
{React.cloneElement(element, {
ref: instance,
})}
</IntlProvider>
)

return instance
}

Sie können diese nun in Ihren Tests wie folgt verwenden:

const element = React.createRef();
renderWithIntl(<MyElement ref={element}>);
element.current.myClassFn();

Enzyme

Das Testen mit Enzyme funktioniert ähnlich wie oben beschrieben. Ihre mount()- und shallow()-Komponenten benötigen Zugriff auf den intl-Kontext. Unten finden Sie eine Hilfsfunktion, die Sie importieren und zum Mounten Ihrer Komponenten verwenden können, die Funktionen von React-Intl nutzen (entweder <Formatted* />-Komponenten oder format*()-Methoden über injectIntl).

Hilfsfunktion

/**
* 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,
},
})
}

Verwendung

Erstellen Sie eine Datei mit der obigen Hilfsfunktion, z.B. helpers/intl-enzyme-test-helper.js, und importieren Sie die benötigten Methoden in Ihren Tests.

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

Basierend auf diesem Gist.

Jest

Das Testen mit Jest kann in zwei Ansätze unterteilt werden: Snapshot-Tests und DOM-Tests. Snapshot-Tests sind eine relativ neue Funktion und funktionieren sofort. Wenn Sie DOM-Tests durchführen möchten, müssen Sie Enzyme oder Reacts TestUtils verwenden.

Snapshot-Tests

Snapshot-Tests sind eine neue Funktion von Jest, die automatisch Text-Snapshots Ihrer Komponenten erstellt und diese auf der Festplatte speichert. Wenn sich die UI-Ausgabe ändert, werden Sie benachrichtigt, ohne manuell Assertions für die Komponentenausgabe schreiben zu müssen. Verwenden Sie entweder die Hilfsfunktion oder das Mock-Verfahren wie unten beschrieben.

Hilfsfunktion

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

Verwendung

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

Ein ausführbares Beispiel finden Sie hier und weitere Informationen zu Jest hier.

Verwendung mit Jest & Enzyme

Jest wird react-intl automatisch mocken, sodass keine zusätzliche Implementierung erforderlich ist. Tests sollten wie erwartet funktionieren:

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

DOM-Tests

Wenn Sie Jest mit DOM-Tests verwenden möchten, finden Sie weitere Informationen oben im Abschnitt zu Enzyme oder in der offiziellen Jest-Dokumentation.

Storybook

Intl

Wenn Sie react-intl in Storybook verwenden möchten, können Sie storybook-addon-intl verwenden. Dieses Addon bietet einen einfach zu verwendenden Wrapper für react-intl inklusive eines Locale-Switchers, sodass Sie Ihre Komponenten in allen bereitgestellten Sprachen testen können.

react-testing-library

Um react-intl und react-testing-library zusammen zu verwenden, sollten Sie den Testablauf mit einer Hilfsfunktion unterstützen.

Weitere Informationen finden Sie in der Dokumentation.

Für eine generische Lösung können wir eine benutzerdefinierte render-Funktion mit der wrapper-Option erstellen, wie auf der Setup-Seite beschrieben.
Unsere benutzerdefinierte render-Funktion kann wie folgt aussehen:

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