Test Styled Components

Learn how to test the styled-components using Jest.

We'll cover the following

Testing styled components using Jest

  • Let’s check how our tests are doing, starting with Carousel:

    $ npx jest src/tests/Carousel.test.js
     FAIL  src/tests/Carousel.test.js
      Carousel
        ✓ renders a <div> (5ms)
        ✓ has an initial `slideIndex` of 0 (1ms)
        ✓ renders a CarouselButton labeled "Prev" (1ms)
        ✓ renders a CarouselButton labeled "Next"
        ✕ renders the current slide as a CarouselSlide (12ms)
        with a middle slide selected
          ✓ decrements `slideIndex` when Prev is clicked (4ms)
          ✓ increments `slideIndex` when Next is clicked (1ms)
        with the first slide selected
          ✓ wraps `slideIndex` to the max value when Prev is clicked
        with the last slide selected
          ✓ wraps `slideIndex` to the min value when Next is clicked (1ms)
    
      ● Carousel › renders the current slide as a CarouselSlide
    
        expect(received).toEqual(expected)
    
        Expected value to equal:
          {"attribution": "Uno Pizzeria", 
           "description": "Slide 1",
           "imgUrl": "https://example.com/slide1.png"}
        Received:
          {"Img": ...}
    

    Currently, the test implicitly assumes that CarouselSlide only has the props it receives from Carousel. That assumption no longer holds now that CarouselSlide has default props.

  • Let’s update the test to account for those:

    // src/tests/Carousel.test.js
    ...
    it('renders the current slide as a 
    CarouselSlide', () => {
      let slideProps;
      slideProps = 
    wrapper.find(CarouselSlide).props();
      expect(slideProps).toEqual({
        ...CarouselSlide.defaultProps,
        ...slides[0],
      });
      wrapper.setState({ slideIndex: 1 });
      slideProps = 
    wrapper.find(CarouselSlide).props();
      expect(slideProps).toEqual({
        ...CarouselSlide.defaultProps,
        ...slides[1],
      });
    })...
    
  • Now move on to the CarouselSlide tests:

    $ npx jest src/tests/CarouselSlide.test.js
     FAIL  src/tests/CarouselSlide.test.js
      ● CarouselSlide › renders an <img> and a <figcaption> as children
    
        expect(received).toBe(expected) // Object.is equality
    
        Expected: "img"
        Received: {"$$typeof": Symbol(react.forward_ref), "attrs": [], ...}
    
        Difference:
    
          Comparing two different types of values. Expected string but received
          object.
    
          20 |
          21 |   it('renders an <img> and a <figcaption> as children', () => {
        > 22 |     expect(wrapper.childAt(0).type()).toBe('img');
             |
                                         ^
    

This is a long winded way of saying that the first child of the CarouselSlide wrapper element is no longer an <img> element. Instead, it’s an instance of the Img component. That component does render an <img> element, but since this is a shallow test of CarouselSlide, the behavior of other components is treated as an unknown.

The problem is we now have two components defined in CarouselSlide.js: CarouselSlide, and the locally defined Img component. We need to expose Img so we can reference the component in tests. For reasons that will become clear in the next section, let’s expose Img by making it a prop. That is, CarouselSlide will take a prop named Img, and the existing Img component will be the default value of that prop. This will give us our final CarouselSlide.js for the chapter, which is provided at the end of the lesson.

CarouselSlide.propTypes = {
  Img: PropTypes.elementType, // 1
  imgHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  imgUrl: PropTypes.string.isRequired,
  description: PropTypes.node.isRequired,
  attribution: PropTypes.node,
};
  1. PropTypes.elementType, newly added in prop-types@15.7.0, validates that the prop is a valid argument to React.createElement: either the name of a DOM element (such as "div"), or a component.

Exposing the Img component provides a direct solution to the failing type() test:

Get hands-on with 1400+ tech skills courses.