Hone logo
Hone
Problems

Testing React Hooks with Cleanup Functions in Jest

React hooks, particularly useEffect, often involve side effects like setting up subscriptions, timers, or event listeners. Properly cleaning up these side effects when a component unmounts is crucial to prevent memory leaks and unexpected behavior. This challenge focuses on writing Jest tests to verify that cleanup functions associated with useEffect are correctly executed.

Problem Description

You are tasked with creating a Jest test suite for a React component that utilizes useEffect to set up and clean up a mock subscription. The component, SubscriptionComponent, subscribes to a mock event source when it mounts and unsubscribes when it unmounts. Your goal is to write tests that confirm:

  1. The subscription is correctly established when the component mounts.
  2. The cleanup function (unsubscribe) is called when the component unmounts.
  3. The cleanup function is only called once per component instance.

The mock event source is represented by a simple object with an subscribe and unsubscribe method. The subscribe method should return a function that, when called, indicates the cleanup function was executed.

Examples

Example 1:

Input: A component `SubscriptionComponent` that uses `useEffect` to subscribe and unsubscribe from a mock event source.
Output: Jest tests that pass, confirming the subscription is established on mount and the unsubscribe function is called on unmount.
Explanation: The tests should mock the `unsubscribe` function and assert that it is called after the component is unmounted.

Example 2:

Input: `SubscriptionComponent` with a conditional subscription based on a prop.
Output: Jest tests that pass, confirming the subscription and unsubscription happen correctly based on the prop value.
Explanation: The tests should mock the `unsubscribe` function and assert that it is called after the component is unmounted, and only when the prop dictates a subscription was made.

Example 3: (Edge Case - Multiple Renders)

Input: `SubscriptionComponent` that re-renders multiple times.
Output: Jest tests that pass, confirming the unsubscribe function is only called once when the component is finally unmounted.
Explanation: The tests should mock the `unsubscribe` function and assert that it is called only once, even if the component re-renders multiple times before unmounting.

Constraints

  • You must use Jest and React Testing Library for testing.
  • The mock event source should be a simple JavaScript object with subscribe and unsubscribe methods.
  • The cleanup function should be a function returned by the useEffect hook.
  • The tests should avoid using act unless absolutely necessary (prefer using waitFor when dealing with asynchronous operations).
  • The component should be written in TypeScript.

Notes

  • Consider using jest.spyOn to mock the unsubscribe method of the mock event source.
  • Use unmount from React Testing Library to simulate component unmounting.
  • Think about how to verify that the cleanup function is called only when the component is unmounted, not during re-renders.
  • The subscribe method should return a function that is called when the component unmounts. This function is what you need to mock and assert is called.
  • Focus on testing the behavior of the cleanup function, not the implementation details of the component itself.
Loading editor...
typescript