Reputation: 9469
How do I prevent shallow rendering on private component with enzyme?
Here is a component example:
// foo.jsx
import React from 'react';
// Private component
const FooSubtitle = ({subtitle}) => {
if (!subtitle) return null;
return <div className="foo__subtitle">{subtitle}</div>;
};
// Public component
const Foo = ({title, subtitle}) => (
<div className="foo">
<div className="foo__title">{title}</div>
<FooSubtitle subtitle={subtitle} />
</div>
);
export default Foo;
Here is my specification:
// foo.spec.js
import React from 'react';
import {shallow} from 'enzyme';
import Foo from './foo.jsx';
describe('Foo', () => {
it('should render a subtitle', () => {
const wrapper = shallow(<Foo title="my title" subtitle="my subtitle" />);
// This test doesn't work, so I cannot test the render of my component
expect(wrapper.find('.foo__subtitle').length).toBe(1);
// This one works, but it is not relevant
expect(wrapper.find('FooSubtitle').length).toBe(1);
});
});
Any idea? Thanks a lot.
Upvotes: 1
Views: 506
Reputation: 2217
You have to export your private component,
export const FooSubtitle = ...
Now, you are able to test it apart with all its prop variants.
Then you can test the presence of FooSubtitle, with particular props, in the render of Foo component as usual and nothing more.
Upvotes: 1
Reputation: 9469
If you have private components, and you want to test their implementation, you should:
Here is a working example:
// foo.jsx
import React from 'react';
// Private component
const FooSubtitle = ({subtitle}) => {
if (!subtitle) return null;
return <div className="foo__subtitle">{subtitle}</div>;
};
// Public component
const Foo = ({title, subtitle}) => (
<div className="foo">
<div className="foo__title">{title}</div>
<FooSubtitle subtitle={subtitle} />
</div>
);
export default Foo;
// foo.spec.js
import React from 'react';
import {shallow} from 'enzyme';
import Foo from './foo.jsx';
describe('Foo', () => {
it('should render a subtitle', () => {
const wrapper = shallow(<Foo title="my title" subtitle="my subtitle" />);
// This test works, but it is not relevant
expect(wrapper.find('FooSubtitle').length).toBe(1);
// This one need the `dive()` API to work
expect(wrapper.find('FooSubtitle').dive().find('.foo__subtitle').length).toBe(1);
});
});
Upvotes: 0
Reputation: 11
In this case (and in generally) your private component is just a function, use it as a function in the render of your public component and you will be able to test its render with the shallow wrapper.
<div className="foo">
<div className="foo__title">{title}</div>
{FooSubtitle({subtitle})}
</div>
Otherwise, I'm not sure it's a good idea to have complex private components...
Upvotes: 1
Reputation: 11
Shallow rendering is useful to constrain yourself to testing a component as a unit, and to ensure that your tests aren't indirectly asserting on behavior of child components.
I think you are trying to do what shallow tries to avoid ^^.
You can unit test the private component directly or use render :
expect(wrapper.find(Foo).render().find('.foo__subtitle')).to.have.length(1);
as explaned here : https://github.com/airbnb/enzyme/blob/master/docs/api/ShallowWrapper/render.md
But in both cases you'll need to export your Component and I must admit I had an error testing it with your component. :/
Upvotes: 1