Find component by display name when the component is stateless functional, with Enzyme
Asked Answered
C

2

18

I have the following components:

// Hello.js
export default (React) => ({name}) => {
  return (
    <div>
      Hello {name ? name : 'Stranger'}!
    </div>
  )
}

// App.js
import createHello from './Hello'

export default (React) => () => {
  const Hello = createHello(React)
  const helloProps = {
    name: 'Jane'
  }
  return (
    <Hello { ...helloProps } />
  )
}

// index.js
import React from 'react'
import { render } from 'react-dom'
import createApp from './App'

const App = createApp(React)

render(
  <App />,
  document.getElementById('app')
)

And I want to set up a test to see if the App component contains one Hello component. I tried the following, using Tape and Enzyme:

import createApp from './App'
import React from 'react'
import test from 'tape'
import { shallow } from 'enzyme'

test('App component test', (assert) => {
  const App = createApp(React)
  const wrapper = shallow(<App />)
  assert.equal(wrapper.find('Hello').length === 1, true)
})

But the result was that the length property of the find result was equal to 0, when I was expecting it to be equal to 1. So, how do I find my Hello component?

Creel answered 14/2, 2016 at 16:0 Comment(0)
H
24

There are a couple of things you can do in this case. Enzyme can match component constructors based on the constructor's static .displayName or .name properties, or by referential equality. As a result, the following approaches should all work:

Direct Reference

you can import the actual components in your tests and find them using direct references to the component:

// NavBar-test.js

import NavBar from './path/to/NavBar';  
...  
wrapper.find(NavBar).length)

Named Function Expressions

If you use named function expressions to create your stateless functional components, the names should still work.

// NavBar.js  

module.exports = function NavBar(props) { ... }

Static .displayName property

You can add a static .displayName property on the components:

// NavBar.js

const NavBar = (props) => { ... };
NavBar.displayName = 'NavBar';
Heady answered 14/2, 2016 at 17:6 Comment(1)
but what is the reason for such enzyme behavior? because there should not be difference between "named" and "default" exports. Enzyme doesnt find named exports and returns the default exported components when i provide static name string expect(wrapper.find('AComponent').length)...Bev
S
0

Try to import the Hello component in the top of your file and then update your assertion to find the actual component and not the name of it. Like below:

import createApp from './App'
import Hello from './Hello'
import React from 'react'
import test from 'tape'
import { shallow } from 'enzyme'

test('App component test', (assert) => {
  const App = createApp(React)
  const wrapper = shallow(<App />)
  assert.equal(wrapper.find(Hello).length === 1, true)
})

Btw for all the enzyme users out there the assertion would be something like:

expect(wrapper.find(Hello)).toHaveLength(1);
Sami answered 11/2, 2021 at 14:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.