This article is about How can i test a dynamically/lazy loaded component on jest in enzymejs enzyme
  • 06-Feb-2023
Lightrun Team
Author Lightrun Team
Share
This article is about How can i test a dynamically/lazy loaded component on jest in enzymejs enzyme

How can i test a dynamically/lazy loaded component on jest in enzymejs enzyme

Lightrun Team
Lightrun Team
06-Feb-2023

Explanation of the problem

The problem at hand involves testing a dynamically loaded React component using Jest. The component, named “Component1”, is defined using the “lazy” function from the React library and utilizes the “Suspense” component to handle the loading of another component, named “Component2”.

An initial attempt was made to write tests for “Component1” using Enzyme and Jest, but the tests were not successful. The test suite includes three test cases, the first of which tests if the component can be rendered correctly and the second tests if the “Component2” is present within the component. The third test case involves clicking a button within the “Component1” component and checking if the “isClicked” state is updated and if the “Component2” component is present within the “Component1” component.

The issue at hand is the testing of a dynamically loaded component, which requires a different approach than testing a component that is fully loaded on render. The tests written with Enzyme and Jest are not able to correctly handle the dynamic loading of the “Component2” component. The solution to this problem requires a different approach to testing dynamically loaded components in React, which will be explored in another discussion.

Troubleshooting with the Lightrun Developer Observability Platform

Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.

  • Instantly add logs to, set metrics in, and take snapshots of live applications
  • Insights delivered straight to your IDE or CLI
  • Works where you do: dev, QA, staging, CI/CD, and production

Start for free today

Problem solution for How can i test a dynamically/lazy loaded component on jest in enzymejs enzyme

To test a dynamically/lazy loaded component in Jest using Enzyme, there are several steps that need to be taken:

  1. Configure Enzyme: First, you need to configure Enzyme to use the adapter for React 16. This can be done by adding the following code:
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() })
  1. Import the component: Next, import the component you want to test in your test file. In this case, the component is Component1:
import React from 'react';
import Component1 from '../src/Component1.js';
  1. Write test cases: After configuring Enzyme and importing the component, you can write test cases to test the component’s behavior. For example, you can write test cases to check if the component renders correctly in snapshot mode, if it contains the expected elements, and if the button click event changes the component’s state correctly:
describe('MyComponent', () => {
  it('should render correctly in snapshot mode', () => {
    const component = shallow(<Component1 />);
    expect(component).toMatchSnapshot();
  });

  it('should not have component2', () => {
    const component = shallow(<Component1 />);
    expect(component.find('Component2').exists()).toEqual(false);
  })

  it('should contain button getComponent2 and should have component2', ()=> {
    const component = shallow(<Component1 />);
    expect(component.instance().state.isClicked).toEqual(false);
    expect(component.find('button').exists());
    const button = component.find('button');
    button.simulate("click");
    expect(component.instance().state.isClicked).toEqual(true);
    expect(component.find('Component2').exists()).toEqual(true);
    expect(component.find('.component-2').exists()).toEqual(true);
  });  

});

In this way, you can test a dynamically/lazy loaded component using Jest and Enzyme.

Other popular problems with enzymejs enzyme

Problem: Testing component with react hooks

One common issue with testing components that use React hooks is that hooks rely on state updates to trigger re-renders, which can be difficult to handle with Enzyme’s shallow rendering. When a component that uses hooks is shallowly rendered, it does not trigger the useEffect hook, making it difficult to test component state changes.

Solution:

To solve this, the recommended solution is to use the act() function from React Test Utils to wrap the component’s render and all state updates. act() makes sure that the hook updates are triggered, allowing you to test component state changes.

Example:

import React, { useState } from "react";
import { shallow } from "enzyme";
import { act } from "react-dom/test-utils";

const ComponentWithHooks = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <div data-testid="count">{count}</div>
      <button onClick={() => setCount(count + 1)}>increment</button>
    </div>
  );
};

it("increments count when button is clicked", () => {
  const wrapper = shallow(<ComponentWithHooks />);
  expect(wrapper.find("[data-testid='count']").text()).toEqual("0");

  act(() => {
    wrapper.find("button").simulate("click");
  });

  expect(wrapper.find("[data-testid='count']").text()).toEqual("1");
});

Problem: Testing component with async code

Another common issue with testing components that make asynchronous API calls is that it can be difficult to manage when these calls will complete, making it difficult to properly test component state changes.

Solution:

To solve this, one solution is to use the jest.useFakeTimers() function to manipulate the component’s async code and make it run synchronously. This allows you to properly control when the component’s async code will run and complete, making it easier to test component state changes.

Example:

import React, { useState, useEffect } from "react";
import { shallow } from "enzyme";

const ComponentWithAsyncCode = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    setTimeout(() => {
      setData("data loaded");
    }, 1000);
  }, []);

  return (
    <div>
      <div data-testid="data">{data || "loading..."}</div>
    </div>
  );
};

it("loads data", () => {
  jest.useFakeTimers();
  const wrapper = shallow(<ComponentWithAsyncCode />);
  expect(wrapper.find("[data-testid='data']").text()).toEqual("loading...");

  jest.runAllTimers();
  wrapper.update();

  expect(wrapper.find("[data-testid='data']").text()).toEqual("data loaded");
});

Problem: Testing of React hooks

React hooks, introduced in React 16.8, allow for functional components to have state and other React features. However, testing these components with enzyme can present challenges as hooks are only called during the rendering of a component and not available during testing.

Solution:

To work around this, you can use act from the @testing-library/react package to wrap hooks in a test environment, allowing them to be executed and tested.

import { act } from '@testing-library/react';
...
act(() => {
  component.find('button').simulate('click');
});
expect(component.instance().state.isClicked).toEqual(true);

A brief introduction to enzymejs enzyme

Enzyme is a JavaScript testing utility for React that makes it easier to test React components by rendering components in a virtual DOM. Enzyme provides a set of APIs that simulate how a React component interacts with the real DOM. This makes it possible to write assertions and test cases for components in a way that is more intuitive and closer to how the component would be used in a real-world scenario.

Enzyme provides three rendering methods to create a virtual representation of a component: shallow, mount, and render. The shallow method only renders the component being tested, without rendering its children components. The mount method, on the other hand, fully renders the component, including all child components, in a virtual DOM. The render method is similar to mount, but it renders the component to a static HTML markup, which is useful for testing the output of a component, but not its behavior or interactions. Enzyme provides a rich set of APIs that can be used to inspect and interact with the virtual DOM, making it easier to write comprehensive and effective tests for React components.

Most popular use cases for enzymejs enzyme

  1. Testing React Components: Enzyme allows you to test React components by rendering them in a virtual DOM, which makes it easier to simulate user interactions and test the component’s behavior and output. You can use Enzyme’s various APIs, such as shallow, mount, and render, to render components and access their state and DOM nodes.
import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('renders correctly', () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper).toMatchSnapshot();
  });
});
  1. Testing React Redux Applications: Enzyme is compatible with Redux, and you can use it to test the behavior of your React-Redux components, including their interactions with the Redux store. You can use Enzyme to simulate user interactions and verify that the component dispatches the correct actions and updates the store state as expected.
  2. Testing Component Interactions: Enzyme provides a number of APIs that make it easy to test component interactions, such as event handling and updates to component state. You can use Enzyme to simulate events such as clicks, form submissions, and other user interactions, and then verify that the component behaves as expected in response to these interactions.
Share

It’s Really not that Complicated.

You can actually understand what’s going on inside your live applications.

Try Lightrun’s Playground

Lets Talk!

Looking for more information about Lightrun and debugging?
We’d love to hear from you!
Drop us a line and we’ll get back to you shortly.

By submitting this form, I agree to Lightrun’s Privacy Policy and Terms of Use.