Skip to content
Advertisement

Jest tests keep failing for React component that renders various HTML elements based on type by using switch statement

I have a React Component that takes an array and iterates over each node, styling and rendering HTML elements based on the types found within the array.

I have everything running properly and now I’m trying to write a test using Jest to check that:

  1. The component doesn’t render anything when it receives an empty array
  2. The component renders the appropriate HTML elements based on type when it receives a populated array

I’m relatively new to Jest and testing and I’m not sure how to write the tests to check that the appropriate elements have rendered. Also my null check test keeps failing with the following error message:

 FAIL  src/components/RenderTextComponent.spec.js
  ● <RenderTextComponent /> › renders null for empty sections array

    expect(received).toEqual(expected)

    Expected value to equal:
      null
    Received:
      <RenderTextComponent />

    Difference:

      Comparing two different types of values. Expected null but received object.

      27 |
      28 |   it('renders null for empty sections array', () => {
    > 29 |     expect(<RenderTextComponent {...emptySections} />).toEqual(null)
         |                                                  ^
      30 |   })
      31 |
      32 |   it('renders', () => {

      at Object.it (src/components/RenderTextComponent.spec.js:29:50)

This is my testing file:

import React from 'react';
import { shallow } from 'enzyme'
import RenderTextComponent from './RenderTextComponent'


describe('<RenderTextComponent />', () => {
  let wrapper;

  const sections = {}

  const populatedSections = [
    {
    type: "subtitle",
    text: ["This is a really cool subtitle filled with words of wonder"]
    },
    {
      type: "body",
      text: ["This is an even cooler sentence that shows up as a paragraph.", "And this is a second sentence that shows up as a second paragraph."]
  }
]

  const emptySections = []

  beforeEach(() => {
    wrapper = shallow(<RenderTextComponent {...sections} />);
  });

  it('renders null for empty sections array', () => {
    expect(<RenderTextComponent {...emptySections} />).toEqual(null)
  })

  it('renders', () => {
    expect(<RenderTextComponent {...populatedSections} />).toEqual(expect.anything())
  })

})

And this is my original component that I’m testing:

import React from "react";
import styled from "styled-components";

function renderElements(sections) {
  const elements = [];

  if (!sections) return null;

  sections.map((section) => {
    switch (section.type) {
      case "title":
        return elements.push(
          section.text.map((string) => <Title>{string}</Title>)
        );
      case "subtitle":
        return elements.push(
          section.text.map((string) => <Subtitle>{string}</Subtitle>)
        );
      case "body":
        return elements.push(
          section.text.map((string) => <Body>{string}</Body>)
        );
      default:
        return null;
    }
  });
  return elements;
}

const RenderTextComponent = ({ sections }) => {
  return <>{renderElements(sections)}</>;
};

export default RenderTextComponent;

const Title = styled.h1`
  font-size: 28px;
`;

const Subtitle = styled.h4`
  font-size: 24px;
`;

const Body = styled.p`
  font-size: 18px;
`

Advertisement

Answer

When you return null from component, React.createElement still creates an element. And there is no way to actually tell if it will render nothing without inspecting resulted markup.

For example this code will give you proper react element in console, not null:

function EmptyComponent() {
  return null
}

console.log(<Component/>);

You can try to render your components into jsdom and check snapshots or expected markup (or both)

Edit: Instead of jsdom it is possible to render to string. In this case you should get empty string

Advertisement