Testing Custom React Hooks with Jest
Custom React Hooks are a powerful way to share stateful logic between components. However, testing these hooks directly can be tricky as they are not components themselves and don't render UI. This challenge focuses on how to effectively test custom hooks using Jest and the @testing-library/react-hooks library.
Problem Description
Your task is to write unit tests for a custom React Hook called useCounter. This hook manages a simple counter value, providing functions to increment, decrement, and reset the counter. You will use Jest and @testing-library/react-hooks to test its behavior.
Requirements:
-
useCounterHook Implementation (Provided):- The hook should accept an optional initial value. If no initial value is provided, it should default to
0. - It should return an object containing:
count: The current value of the counter.increment: A function that increasescountby1.decrement: A function that decreasescountby1.reset: A function that setscountback to its initial value.
- The hook should accept an optional initial value. If no initial value is provided, it should default to
-
Testing
useCounter:- Write Jest tests for the
useCounterhook. - Use
@testing-library/react-hooksto render and interact with the hook in your tests. - Test the following scenarios:
- Initial state with no provided value.
- Initial state with a provided positive value.
- Incrementing the counter.
- Decrementing the counter.
- Resetting the counter to its initial value.
- Edge case: Decrementing the counter below zero (it should still decrement).
- Write Jest tests for the
Examples
Example 1: Initial state with default value
Input Hook Call: useCounter()
Expected Output State: { count: 0 }
Explanation: When useCounter is called without an initial value, the count should start at 0.
Example 2: Initial state with a provided value
Input Hook Call: useCounter(10)
Expected Output State: { count: 10 }
Explanation: When useCounter is called with an initial value of 10, the count should start at 10.
Example 3: Incrementing the counter
Input Hook Calls:
1. const { count, increment } = useCounter(5);
2. increment();
3. increment();
Expected Final State: { count: 7 }
Explanation: Starting at 5 and calling increment twice results in a final count of 7.
Example 4: Decrementing and resetting
Input Hook Calls:
1. const { count, decrement, reset } = useCounter(3);
2. decrement();
3. decrement();
4. reset();
Expected Final State: { count: 3 }
Explanation: Starting at 3, decrementing twice to 1, and then calling reset returns the count to its initial value of 3.
Constraints
- The tests must be written in TypeScript.
- You must use Jest as the testing framework.
- You must use the
@testing-library/react-hookslibrary for testing hooks. - The provided
useCounterhook implementation should be assumed to exist and be correct for the purpose of writing tests. (You will be provided with the hook implementation separately if this were a live challenge, or you can assume it exists for this exercise.)
Notes
@testing-library/react-hooksprovides arenderHookfunction that allows you to test hooks in isolation.- The
renderHookfunction returns an object withresultandrerenderproperties.result.currentgives you access to the latest value returned by your hook. - You can simulate user interactions by calling the functions returned by your hook.
- Consider using
waitForNextUpdateif your hook has asynchronous operations (though this specific hook does not). - Focus on testing the behavior of the hook's returned values and functions.