Enzyme: Unexpected behaviour of `.hasClass()` aka. Ability to use `.hasClass()` on React Components

Created on 8 Apr 2016  路  5Comments  路  Source: enzymejs/enzyme

I was having a lot of trouble using the hasClass() method. It appeared to work sometimes, but not other times. Until I finally realized what was going wrong through trial and error.

Here is a very simple code sample where it doesn't work as expected.

class MyComponent extends React.Component {
    render () {
        return <div className="test" />;
    }
}

const component = mount(<MyComponent />);

console.log(component.html())
// Outputs  "<div class="test"></div>"

component.hasClass('test');
// Outputs "false" unexpectedly

After some thinking, I discovered that this is because hasClass() only works on regular DOM nodes and not on React Components. So I tried:

component.find('div').hasClass('test');
// And now it finally outputs "true"

Is there any reason hasClass() was designed this way? My original code makes logical sense to me, but didn't work as I expected.

My recommendations are (in order of preference):

  • Option A: Update hasClass() to work on React Components and have it look for the class name in the top-level DOM node, or
  • Option B: Update hasClass() to not work at all on React Components so that users aren't surprised by this behaviour, or
  • Option C: Leave it as is but update the "Common Gotchas" documentation on http://airbnb.io/enzyme/docs/api/ShallowWrapper/hasClass.html to explain that it only works for DOM nodes

Most helpful comment

I ran across this issue today while making a presentation at a local group. Not too cool. Of course shallow rendering works as expected while a mount fails as described above so I am voting +1.

All 5 comments

@EvNaverniouk this is indeed supposed to work this way. I think maybe adding it to common gotchas would make sense though...

.hasClass doesn't only work on DOM nodes though... I made the decision to have it work on components of any kind, but ONLY by treating "having a class" as meaning the same as "has a className prop that includes this class".

This is essentially treating className as a prop where it is the convention that className would get passed down below. This is done also in part to keep symmetry with shallow, where doing it this way is a hard requirement.

Thanks for that explanation. Sounds like "Option C" is the way to go then.

I ran across this issue today while making a presentation at a local group. Not too cool. Of course shallow rendering works as expected while a mount fails as described above so I am voting +1.

This issue may be resolved now by #677. @EvNaverniouk can you test from the master branch to verify?

Closed by #677 - let's reopen if there's still an issue.

Was this page helpful?
0 / 5 - 0 ratings