question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

getByText fails with react-intl FormattedMessage

See original GitHub issue

react-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:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:11 (5 by maintainers)

github_iconTop GitHub Comments

6reactions
nirbenyacommented, Mar 14, 2021

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:

const { getByText } = render(<IntlProvider><MyComponent /> </IntlProvider>

So what fixes the issue for me and allowing me to use getByText is turning this to:

import { Text } from 'react-native';

const { getByText } = render(<IntlProvider textComponent={Text}><MyComponent /> </IntlProvider>

This forces the FormattedMessage component to use Text as a wrapper instead of React.Fragment which is the default.

1reaction
malouacommented, Jun 15, 2020

I’m having the same issue (with up to date packages)

When I do element.debug() the text is visible:

<View ... testID="Button">
  <Text ...> // FormattedMessage
    Click here
  </Text>
</View> 

Yet I also get “No instances found” when I do element.getByText('Click here'). Any ideas?

  • react 16.13.1
  • react-native 0.62.2
  • react-intl 4.6.3
  • react-native-testing-library 2.1.0
  • react-test-renderer 16.13.1
Read more comments on GitHub >

github_iconTop Results From Across the Web

react-native-testing-library how to getByText when using react ...
Adding textComponent={Text} forces the FormattedMessage component to use Text as a wrapper instead of React.Fragment which is the default. Share.
Read more >
React Intl | Testing Library
Test code deviates from what runs in production. Tests may assert about message IDs but not enough about content, so errors are possible....
Read more >
Extending react-intl with your own markup - Keypup
Learn how to setup and use react-intl to internationalize (i18n) your app. ... import { IntlProvider, FormattedMessage } from 'react-intl';.
Read more >
Dealing with Context Providers · GitBook - GitHub Pages
When using react-testing-library testing components using React Context is no ... import React from "react"; import { FormattedMessage } from "react-intl"; ...
Read more >
React App Scaffolding: Keep Technical Debt Low & Help Your ...
Learn basic scaffolding strategies for your React app to keep technical debt ... 'en' }) // react-intl provider import {IntlProvider, FormattedMessage} from ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found