getByText fails with react-intl FormattedMessage
See original GitHub issuereact-native-testing-library @ ^1.13.2
react @ 16.9.0
react-test-renderer @ ^16.9.0
react-native @ https://github.com/expo/react-native/archive/sdk-36.0.0.tar.gz
(I believe this is v0.60)
I have updated to react-intl @ ^3.12.1
from 2.x.x
and now my native tests are failing at any getByText
assertions. It throws a No instances found
error.
If i debug()
i can clearly see the text i am searching for in the console 😦
react-intl
uses <FormattedMessage ... />
to render translations, so i mock add the <IntlProvider />
to my custom render. The setup looks like this;
// reactNativeTestingLibrary/index.js
import { IntlProvider } from 'react-intl'
...
const customRender = (ui, options = {}) =>
render(
<Provider store={store}>
<IntlProvider locale="en" textComponent={Text}>
<ActionSheetProvider>
<SafeAreaProvider
initialSafeAreaInsets={{ top: 1, left: 2, right: 3, bottom: 4 }}
>
{ui}
</SafeAreaProvider>
</ActionSheetProvider>
</IntlProvider>
</Provider>,
options,
)
...
// componentToText/index.js
import React from 'react'
import PropTypes from 'prop-types'
import { FormattedMessage } from 'react-intl'
import { Text } from 'native/components'
import messages from './messages'
const ChargeExpense = ({ type, reason }) => (
<React.Fragment>
<Text bold>
<FormattedMessage
{...messages.expenseType}
values={{ TYPE: <Text bold={false}>{type || '-'}</Text> }}
/>
</Text>
<Text bold>
<FormattedMessage
{...messages.expenseReason}
values={{ REASON: <Text bold={false}>{reason || '-'}</Text> }}
/>
</Text>
</React.Fragment>
)
ChargeExpense.propTypes = {
type: PropTypes.string,
reason: PropTypes.string,
}
export default ChargeExpense
// test.js
import React from 'react'
import { customRender as render } from 'reactNativeTestingLibrary'
...
import ChargeExpense from '..'
const { expenseType, expenseReason } = mockChargeExpense
describe('<ChargeExpense />', () => {
it('renders an Expense type and Expense reason', () => {
const { getByText, unmount, debug } = render(
<ChargeExpense type={expenseType} reason={expenseReason} />,
)
debug()
expect(getByText(/Expense type:/))
expect(getByText(/Type of/))
expect(getByText(/Expense reason:/))
expect(getByText(/Reason for/))
unmount()
})
it('renders type or reason as "-" when either are not defined', () => {
const { getByText, getAllByText, unmount } = render(<Component />)
expect(getByText(/Expense type:/))
expect(getByText(/Expense reason:/))
expect(getAllByText(/-/).length).toEqual(2)
unmount()
})
})
<ChargeExpense />
✕ renders an Expense type and Expense reason (67ms)
✕ renders type or reason as "-" when either are not defined (5ms)
● <ChargeExpense /> › renders an Expense type and Expense reason
No instances found
15 | debug()
16 |
> 17 | expect(getByText(/Expense type:/))
| ^
18 | expect(getByText(/Type of/))
19 | expect(getByText(/Expense reason:/))
20 | expect(getByText(/Reason for/))
...
● <ChargeExpense /> › renders type or reason as "-" when either are not defined
No instances found
25 | const { getByText, getAllByText, unmount } = render(<ChargeExpense />)
26 |
> 27 | expect(getByText(/Expense type:/))
| ^
28 | expect(getByText(/Expense reason:/))
29 | expect(getAllByText(/-/).length).toEqual(2)
30 | unmount()
// debug() output...
console.log
<View
style={
Object {
"flex": 1,
}
}
>
<RNCSafeAreaView
onInsetsChange={[Function anonymous]}
style={
Object {
"flex": 1,
}
}
>
<Text
bold={true}
className="sc-bdVaJa iFrGAG"
>
<Text>
Expense type:
<Text
bold={false}
className="sc-bdVaJa hPmtWS"
>
Type of
</Text>
</Text>
</Text>
<Text
bold={true}
className="sc-bdVaJa iFrGAG"
>
<Text>
Expense reason:
<Text
bold={false}
className="sc-bdVaJa hPmtWS"
>
Reason for
</Text>
</Text>
</Text>
</RNCSafeAreaView>
</View>
at debugDeep (node_modules/react-native-testing-library/build/helpers/debugDeep.js:1:530)
If i replace the <FormattedMessage />
with a <Text />
component, the text is found as expected… not sure how the FormattedMessage is able to obfuscate the result somehow, but still allow the text to be logged in the in the debug.
Apologies if this is a react-intl
issue…
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:11 (5 by maintainers)
Top GitHub Comments
Hi, so I tried fixing it and creating a PR but with no success as of yet, anyway, I’v found a workaround. When you test your component with RTL you probably wrap your component with an intl-provider. Something like that:
So what fixes the issue for me and allowing me to use
getByText
is turning this to:This forces the FormattedMessage component to use Text as a wrapper instead of React.Fragment which is the default.
I’m having the same issue (with up to date packages)
When I do
element.debug()
the text is visible:Yet I also get “No instances found” when I do
element.getByText('Click here')
. Any ideas?