Consider the following:
TestHarness = function(props) {
return (
<table><tbody><tr>
<CKStepsTextCell {...props} />
</tr></tbody></table>
);
};
var wrapper = enzyme.mount(<TestHarness />);
console.log(wrapper.find(CKStepsTextCell).html());
// outputs
// <td class="hide-editor-toolbar foo"><div class="test-step-cell-inline-edit"></div></td>
console.log(wrapper.find(CKStepsTextCell).hasClass('foo'));
// outputs
// false
Running enzyme 2.3.0 with react 15.1.0
Having dug through the lib a bit, it seems to be failing when trying to verify wrapper.find(CKStepsTextCell) is a DOM Component (literally in the function isDOMComponent in TestUtils).
isDOMComponent: function (inst) {
return !!(inst && inst.nodeType === 1 && inst.tagName);
},
When inst gets here, it has no nodeType property and no tagName property.
hasClass is meant to verify that a DOM node has a class name, and you're using a composite component (<CKStepsTextCell/>) in your find query. I would say you should pass find a query that returns a DOM node, since composite components don't actually have a className property.
If we supported this we'd have to assume you meant to query the root DOM node of the composite component. Maybe we should just document that hasClass operates on DOM nodes only.
cc @ljharb what do you think?
Actually, internally, it appears the node is retrieved automatically. Note https://github.com/airbnb/enzyme/blob/master/src/ReactWrapper.js#L659, where the function single is called from the hasClass test and https://github.com/airbnb/enzyme/blob/master/src/ReactWrapper.js#L846, the implementation of single, where this.node passes into the test. So this is definitely an issue with an assumption that apparently is not true. It could have something to do with the way mount handles certain tag types?
The node property on a ReactWrapper instance will refer to the actual component itself if mount is passed a composite component which in your case you do , since find(CKStepsTextCell) returns a wrapper with CKStepsTextCell as the node value.
this.node = this.component.getWrappedComponent();
Feel free to console.log out wrapper.node in your test to verify.
If you were to mount a DOM element directly you'd be correct
const wrapper = mount(
<td class="hide-editor-toolbar foo"><div class="test-step-cell-inline-edit"></div></td>
)
I see, thanks for the clarification. Still, would be nice if I could check for class contents using the component.
The point of shallow rendering is that you _shouldn't_ be checking for "what CKStepsTextCell renders", which includes its class name. The unit tests for CKStepsTextCell should be testing that.
If you want to integration-test the entire render tree of a component, use mount or render.
True; I didn't write this particular test initially so I won't attempt to defend it. The point still stands though that it's sort of silly it's _not_ assumed hasClass would query the root node of a composite component. All components have to have a singular root node anyway -- it's not a leap, at least I don't think.
hasClass checks the className prop. In your example, that element that you found _doesn't_ have that className. The _result of its render method_ does, sure - but you didn't render that component. In other words, you're only making assertions about its props, not about what it renders.
Ah, that's the part I wasn't getting (result of the render method is irrelevant for the purposes of checking class value). Thank you for explaining -- in my mind this method was analogous to something like jquery's hasClass method from way back when.
Most helpful comment
Ah, that's the part I wasn't getting (result of the render method is irrelevant for the purposes of checking class value). Thank you for explaining -- in my mind this method was analogous to something like jquery's hasClass method from way back when.