Testing ES6 React components with Enzyme's shallow rendering

I ran into a strange issue today when writing some assertions using the Enzyme testing library for React.

Whenever I create a new component, I like to use ES6 class notation and export the class anonymously like this:

// MyChildComponent.js
import React from 'react';

export default class extends React.Component {
  render() {
    return (<div>MyChildComponent</div>)
  }
}

Then, I'll render it in another component like this:

// MyParentComponent.js
import React from 'react';
import MyChildComponent from './MyChildComponent';

export default class extends React.Component {
  render() {
    return (
      <div>
        <MyChildComponent />
      </div>
    )
  }
}

When testing for the presence of MyChildComponent within MyParentComponent in Enzyme, I'll typically produce a test that looks like this:

import { shallow } from 'enzyme';
import { expect } from 'chai';

import MyParentComponent from './MyParentComponent';

describe("<MyParentComponent />", () => {

  const wrapper = shallow(<MyParentComponent />);

  it("renders a MyChildComponent", () => {
    expect(wrapper.find('MyChildComponent')).to.have.length(1);
  });

});

But this fails! It's as if MyChildComponent isn't being rendered at all.

If I dump wrapper.debug() (doc) to the console, I get this output in place of MyChildComponent:

<div>
<_class />
</div>

It's as if Enzyme doesn't know the component is called MyChildComponent!

Solutions

There are two ways to solve this.

Import the component itself and assert on it instead

Below, we import MyChildComponent and then, in the assertion, use the class constant instead of the string literal "MyChildComponent":

import { shallow } from 'enzyme';
import { expect } from 'chai';

import MyParentComponent from './MyParentComponent';
import MyChildComponent from './MyChildComponent';

describe("<MyParentComponent />", () => {

  const wrapper = shallow(<MyParentComponent />);

  it("renders a MyChildComponent", () => {
    expect(wrapper.find(MyChildComponent)).to.have.length(1);
  });

});

Export the named class from within the child component

As much as we should strive to write code that doesn't repeat itself, this was the solution I ultimately chose. It turns out React is able to determine the class name so long as you define it in the class statement. Modifying MyChildComponent.js to produce a named class and then exporting it allows Enzyme to find it in the string literal assertion:

// MyChildComponent.js
import React from 'react';

class MyChildComponent extends React.Component {
  render() {
    return (<div>MyChildComponent</div>)
  }
}

export default MyChildComponent;

If you can't seem to get an Enzyme assertion to find a component you know is there, make sure Enzyme knows what sort of component it is!

Hiring A Software Consultant? Read This First

You're about to embark upon your first custom software build, but you're terrified at the breadth of terminology and wary of consultants nickel-and-diming you.

My free book Why Software Projects Fail offers that framework. In this companion to your hiring and discovery process, you'll learn how to inform your next decisions and to empower yourself along the way.

In the book, you'll learn:

  • How to find and hire a trustworthy consultant
  • Why it's critical you pay for a software discovery
  • How to assess your consultant's bid
  • What to expect—and be wary of—during the development process
  • How to take control of your project

Enter your email address below and then click the "Send Me My Free Gift" button. I'll send you Why Software Projects Fail, and you'll be equipped for success on your next project.