enzyme: ShallowWrapper::dive() can not be called on Host Components
I don’t normally create this many test helpers but allowed my collegue to while teaching him TDD while pairing. We found though some pain that I never feel, because I usually put some of this stuff in a beforeEach rather than helpers as we have below:
function expectCarouselItemsLength(items, expectedLength) {
const carousel = createCarousel(items);
const carouselItems = carousel.findAttribute(carousel, 'carousel-item');
expect(carouselItems.length).to.equal(expectedLength);
}
// this needs to be in setup, helpers should not do setup stuff, we need to keep helpers simpler
function createCarousel(items) {
const carousel = shallow(<Carousel items={items} />);
const foundCarousel = findAttribute(carousel, 'carousel');
return foundCarousel;
}
function findAttribute(component, attributeName) {
const foundComponent = component.find(`[data-test='${attributeName}']`);
return foundComponent;
}
So I found troubleshooting tests hard because we’re overdoing test helpers first off. Anyway the pain with our helpers doing to much causing use to live and debug in our helpers and having to look up and down too much from our test definition, came here when I new I needed to probably dive:
it.only('returns one item', () => {
const items = [{
description: 'description',
image: 'image.jpg',
title: 'title',
}];
expectCarouselItemsLength(items, 1);
});
so I thought ok fine, let me dive() because I know that searching for ‘carousel-item’ doesn’t live in the immediate parent anymore, it lives in a child.
When I went to try and add dive() to this I got ShallowWrapper::dive() can not be called on Host Components
:
function expectCarouselItemsLength(items, expectedLength) {
const carousel = createCarousel(items);
const carouselItems = carousel.dive().findAttribute(carousel, 'carousel-item'); // error here, can't dive on Host Components
expect(carouselItems.length).to.equal(expectedLength);
}
it didn’t let me dive on the carousel const.
Why?
Normally I wouldn’t have this in a helper anyway and would be able to just in my test do that and it would have been fine I think
Carousel.js
import React, { Component } from 'react';
import Slider from 'react-slick';
import CarouselItem from './CarouselItem';
export default class Carousel extends Component {
renderItems() {
const { items } = this.props;
return items && items.map((item, i) => {
return <CarouselItem key={`${item.title}${i}`} item={item} />;
});
}
render() {
const { item } = this.props;
return (
<div className="container">
<div test="carousel">
<Slider>
{this.renderItems()}
</Slider>
</div>
</div>);
}
}
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 16 (5 by maintainers)
.dive()
re-shallow-renders, which makes no sense on a host component. In your Carousel.js example, you need towrapper.find(Slider).shallow()
if you want to shallow-render the Slider itself (which I’d discourage, since testing that is the responsibility of thereact-slick
package)true, I’ve tried to render third party HOCs before only to find they have a f’d up way of what they actually output 😃…then you find yourself digging through their rabbit hole implementation to figure out how to get to your child rendered output.
well I do have a way I’m asserting on the number of ‘carousel-item’ markers found but again that’s if I know how to wiggle my way through the HOC’s output to find my ‘carouse-item’'s 😃
thanks
@dschinkel ah, in that case,
const children = wrapper.find(Slider).prop('children');
, and then something likechildren.forEach((child) => { shallow(() => child); /* make assertions on child */ }
?It’s totally possible to re-shallow a
Slider
, but you have no guarantee thatSlider
is rendering the children you give it or not - the actual thing of value is “what props did I pass toSlider
”; it doesn’t actually matter (to your tests) whatSlider
does with it.As far as diving past HOCs; that (by design) only works when the HOC directly renders a custom component. In your case,
Slider
isn’t an HOC, it’s a normal component.