2

I have a react component, which imports a component from another third-party library (ex:Ant, or bootstrap ), and now I want to test this component onClick behavior.

However, it's difficult to getByTestId or getByText because the third-party library does not have thiese attribute or sometimes have no text in the html tag. How can I get the thrid-party dom and test it using react-testing-library ?

PS: some might say, we dont have to test bootstrap component because it's their business, but this will lower our test coverage.(ex: if we pass many callback functions props as event handlers to the a bootstrap component, we must test the callback to increase test coverage )

2
  • What exactly do you need to test? Just the onclick behaviour? Commented May 6, 2020 at 10:07
  • I do a lot of testing using Ant Design and react-testing-library these days, if you give some details (components, interactions...) I may be able to help. Indeed it can be tricky... Commented May 7, 2020 at 19:21

1 Answer 1

9

React Testing Library was developed, to my understanding, to write tests based on the user's experience of the elements being rendered. With third party components this can be cumbersome at times.

I think there are a few approaches to take:

  1. Review the React Testing Library cheatsheet and ask yourself the primary way the user understands the element. Maybe in this case it is by the role of the element? I.e. does your third party component hold a aria property dictating the role for that component?

Example: app uses Buttons from bootstrap

const App = () => {
  const [state, setState] = useState(0)

  const increase = () => {
    const newState = state + 1
    setState(newState)
  }

  const decrease = () => {
    const newState = state - 1
    setState(newState)
  }

  return (
  <div>
    <div className="App">
      <Button variant="primary" size="lg" onClick={increase}></Button>{' '}
      <Button variant="primary" size="lg" onClick={decrease}></Button>{' '}
    </div>
    <div className="number">
      {state}
    </div>
</div>
  )
}

I purposefully did not provide text for the buttons but I can still find those buttons, here is the test:

it('buttons increase and decrease displayed value', () => {
     const component = render(<App/>)
     const buttons = component.getAllByRole('button')

    for (let i = 0; i < buttons.length; i++){
      fireEvent.click(buttons[i])
    }

    expect(component.findByText('0')).toBeTruthy()
})

Even though I couldn't set a testId or find by text, I could still gather an array of nodes that play the role of button. From there it is a matter of searching through the array to find which button you need. And to my pleasure, the test passes but this is a silly test because the buttons have their own logic so I should separate them into separate tests as such:

it('increases and decreases button and displays accurate value', () => {
    const component = render(<App/>)
    const buttons = component.getAllByRole('button')

    fireEvent.click(buttons[0])

    expect(component.findByText('1')).toBeTruthy()
})
  1. If needed consider wrapping the third party component in a div, provide a data-testid for that data, then access the first, sibling, last child nodes that are children to that div. I've often used this to navigate to where the third party component node exists in the dom:

    <div data-testid="test">
        <SomeComponent onChange={()=> {}}/>
    </div>
    

Since some of the react testing library queries return a dom node, we can find this component with:

const findBootstrapComp = component.getByTestId('test').firstChild
  1. What we should probably avoid as much as possible, but maybe your case is allowable given what can be access with the queries provided, you can query the container node manually by some attribute:

    const { container } = render()
    const button = container.querySelector('button')
    

Long story short, React Testing Library provides plenty of tools to query for what you need. If that third party component is rendering, then there are probably attributes for that element that you can query. The above is just from personal experience, each project is different. May even consider pulling out those callbacks, isolating them and then testing the logic since you're more concerned about the logic from the sounds of it.

Also, I agree with your sentiment on Boostrap testing their own components. You're not actually looking to test a third party component though, your looking to test some functionality or logic you have written that is being accessed by a third party component. Or maybe you want to pull the css of that element and confirm that it hasn't switched at some point during development. Whatever it may be, I hope the above helps in some way. If anything, create a component in a test file using the third party components and use the debug() api to take a look at the elements to see what they have that you may query for.

helpful links:

React Testing Library cheatsheet

Dom Navigation

Node interface

Sign up to request clarification or add additional context in comments.

2 Comments

This is exactly what I was looking for. Thanks for taking the time to write such a detailed explanation.
Not quite effective when trying similar approach with the react autosuggest is an absolute nightmare. just knowing how to render the suggestions list in the test is another adventure. This question to date still has no effective answers: github.com/moroshko/react-autosuggest/issues/591

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.