Convert Figma logo to code with AI

testing-library logoreact-hooks-testing-library

🐏 Simple and complete React hooks testing utilities that encourage good testing practices.

5,246
230
5,246
45

Top Related Projects

🐐 Simple and complete React DOM testing utilities that encourage good testing practices.

19,952

JavaScript Testing utilities for React

46,847

Fast, easy and reliable testing for anything that runs in a browser.

Quick Overview

React Hooks Testing Library is a lightweight utility that simplifies the process of testing React hooks. It provides a simple and intuitive API for rendering hooks in a test environment, allowing developers to test custom hooks in isolation without the need for a full component render.

Pros

  • Easy to use and integrates well with popular testing frameworks like Jest
  • Allows testing of complex hooks with dependencies and side effects
  • Provides a way to test hooks in isolation, improving test clarity and maintainability
  • Supports both synchronous and asynchronous testing scenarios

Cons

  • Limited to testing hooks only, not suitable for full component testing
  • May require additional setup for more complex scenarios involving context or other React features
  • Learning curve for developers new to testing React hooks
  • Some edge cases might be challenging to test without additional mocking or setup

Code Examples

  1. Testing a simple custom hook:
import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';

test('should increment counter', () => {
  const { result } = renderHook(() => useCounter());

  act(() => {
    result.current.increment();
  });

  expect(result.current.count).toBe(1);
});
  1. Testing an asynchronous hook:
import { renderHook, act } from '@testing-library/react-hooks';
import useAsync from './useAsync';

test('should handle async operations', async () => {
  const { result, waitForNextUpdate } = renderHook(() => useAsync());

  expect(result.current.loading).toBe(false);

  act(() => {
    result.current.run();
  });

  expect(result.current.loading).toBe(true);

  await waitForNextUpdate();

  expect(result.current.loading).toBe(false);
  expect(result.current.data).toBeDefined();
});
  1. Testing a hook with context:
import { renderHook } from '@testing-library/react-hooks';
import { ThemeProvider } from './ThemeContext';
import useTheme from './useTheme';

test('should use theme from context', () => {
  const wrapper = ({ children }) => (
    <ThemeProvider initialTheme="dark">{children}</ThemeProvider>
  );

  const { result } = renderHook(() => useTheme(), { wrapper });

  expect(result.current.theme).toBe('dark');
});

Getting Started

To start using React Hooks Testing Library, follow these steps:

  1. Install the library:

    npm install --save-dev @testing-library/react-hooks
    
  2. Import the necessary functions in your test file:

    import { renderHook, act } from '@testing-library/react-hooks';
    
  3. Write your tests using the renderHook function to render your custom hooks and act for updating hook state:

    test('my custom hook', () => {
      const { result } = renderHook(() => useMyCustomHook());
      // Assert initial state
      expect(result.current.value).toBe(initialValue);
      // Act on the hook
      act(() => {
        result.current.updateValue(newValue);
      });
      // Assert updated state
      expect(result.current.value).toBe(newValue);
    });
    

Competitor Comparisons

🐐 Simple and complete React DOM testing utilities that encourage good testing practices.

Pros of react-testing-library

  • Focuses on testing components from a user's perspective, encouraging better test practices
  • Provides a more comprehensive set of utilities for testing entire React components
  • Supports testing of DOM events and asynchronous operations out of the box

Cons of react-testing-library

  • May be overkill for testing simple custom hooks
  • Requires more setup and boilerplate code for testing hooks in isolation
  • Can be slower for hook-specific tests due to rendering full components

Code Comparison

react-testing-library:

import { render, fireEvent } from '@testing-library/react';

test('increments counter', () => {
  const { getByText } = render(<Counter />);
  fireEvent.click(getByText(/increment/i));
  expect(getByText(/count: 1/i)).toBeInTheDocument();
});

react-hooks-testing-library:

import { renderHook, act } from '@testing-library/react-hooks';

test('increments counter', () => {
  const { result } = renderHook(() => useCounter());
  act(() => {
    result.current.increment();
  });
  expect(result.current.count).toBe(1);
});

The react-testing-library is better suited for testing full components and user interactions, while react-hooks-testing-library provides a more focused approach for testing custom hooks in isolation. Choose based on your specific testing needs and the complexity of your components or hooks.

19,952

JavaScript Testing utilities for React

Pros of Enzyme

  • More comprehensive API for component manipulation and traversal
  • Supports shallow rendering for isolated unit testing
  • Longer history and larger community support

Cons of Enzyme

  • Requires more setup and configuration
  • Can encourage testing implementation details rather than behavior
  • Less focus on accessibility and user-centric testing

Code Comparison

Enzyme:

const wrapper = shallow(<MyComponent />);
expect(wrapper.find('.my-class').text()).toBe('Expected Text');
wrapper.find('button').simulate('click');

React Hooks Testing Library:

const { result } = renderHook(() => useMyHook());
expect(result.current.value).toBe('Expected Value');
act(() => {
  result.current.setValue('New Value');
});

Key Differences

  • Enzyme focuses on component testing, while React Hooks Testing Library specializes in testing hooks
  • Enzyme provides more methods for interacting with component internals
  • React Hooks Testing Library promotes a more user-centric testing approach
  • Enzyme supports both class and functional components, while React Hooks Testing Library is designed specifically for hooks in functional components

Use Cases

  • Choose Enzyme for comprehensive component testing, especially with class components
  • Opt for React Hooks Testing Library when focusing on testing custom hooks or functional components with hooks
46,847

Fast, easy and reliable testing for anything that runs in a browser.

Pros of Cypress

  • Comprehensive end-to-end testing framework for web applications
  • Real-time browser testing with automatic waiting and retrying
  • Rich ecosystem with plugins and integrations

Cons of Cypress

  • Steeper learning curve due to its extensive feature set
  • Limited to testing web applications (no native mobile support)
  • Can be slower for large test suites compared to unit testing

Code Comparison

React Hooks Testing Library:

import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';

test('should increment counter', () => {
  const { result } = renderHook(() => useCounter());
  act(() => { result.current.increment(); });
  expect(result.current.count).toBe(1);
});

Cypress:

describe('Counter', () => {
  it('should increment counter', () => {
    cy.visit('/counter');
    cy.get('[data-testid="count"]').should('have.text', '0');
    cy.get('[data-testid="increment"]').click();
    cy.get('[data-testid="count"]').should('have.text', '1');
  });
});

Summary

React Hooks Testing Library is focused on testing React hooks in isolation, making it ideal for unit testing custom hooks. Cypress, on the other hand, is a comprehensive end-to-end testing framework that simulates user interactions in a real browser environment. While React Hooks Testing Library is lightweight and fast for hook-specific tests, Cypress offers a more robust solution for testing entire web applications, albeit with a steeper learning curve and longer execution times for large test suites.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

react-hooks-testing-library

ram

Simple and complete React hooks testing utilities that encourage good testing practices.


Read The Docs

Build Status codecov version downloads MIT License

All Contributors PRs Welcome Code of Conduct Netlify Status Discord

Watch on GitHub Star on GitHub Tweet

A Note about React 18 Support

If you are using the current version of react-testing-library, replace

import { renderHook } from '@testing-library/react-hooks'

with

import { renderHook } from '@testing-library/react'

Once replaced, @testing-library/react-hooks can be uninstalled.

Details

As part of the changes for React 18, it has been decided that the renderHook API provided by this library will instead be included as official additions to both react-testing-library (PR) and react-native-testing-library (PR) with the intention being to provide a more cohesive and consistent implementation for our users.

Please be patient as we finalise these changes in the respective testing libraries. In the mean time you can install @testing-library/react@^13.1

Table of Contents

The problem

You're writing an awesome custom hook and you want to test it, but as soon as you call it you see the following error:

Invariant Violation: Hooks can only be called inside the body of a function component.

You don't really want to write a component solely for testing this hook and have to work out how you were going to trigger all the various ways the hook can be updated, especially given the complexities of how you've wired the whole thing together.

The solution

The react-hooks-testing-library allows you to create a simple test harness for React hooks that handles running them within the body of a function component, as well as providing various useful utility functions for updating the inputs and retrieving the outputs of your amazing custom hook. This library aims to provide a testing experience as close as possible to natively using your hook from within a real component.

Using this library, you do not have to concern yourself with how to construct, render or interact with the react component in order to test your hook. You can just use the hook directly and assert the results.

When to use this library

  1. You're writing a library with one or more custom hooks that are not directly tied to a component
  2. You have a complex hook that is difficult to test through component interactions

When not to use this library

  1. Your hook is defined alongside a component and is only used there
  2. Your hook is easy to test by just testing the components using it

Example

useCounter.js

import { useState, useCallback } from 'react'

function useCounter() {
  const [count, setCount] = useState(0)

  const increment = useCallback(() => setCount((x) => x + 1), [])

  return { count, increment }
}

export default useCounter

useCounter.test.js

import { renderHook, act } from '@testing-library/react-hooks'
import useCounter from './useCounter'

test('should increment counter', () => {
  const { result } = renderHook(() => useCounter())

  act(() => {
    result.current.increment()
  })

  expect(result.current.count).toBe(1)
})

More advanced usage can be found in the documentation.

Installation

npm install --save-dev @testing-library/react-hooks

Peer Dependencies

react-hooks-testing-library does not come bundled with a version of react to allow you to install the specific version you want to test against. It also does not come installed with a specific renderer, we currently support react-test-renderer and react-dom. You only need to install one of them, however, if you do have both installed, we will use react-test-renderer as the default. For more information see the installation docs. Generally, the installed versions for react and the selected renderer should have matching versions:

npm install react@^16.9.0
npm install --save-dev react-test-renderer@^16.9.0

NOTE: The minimum supported version of react, react-test-renderer and react-dom is ^16.9.0.

API

See the API reference.

Contributors

Thanks goes to these wonderful people (emoji key):


Michael Peyper

💻 📖 🤔 🚇 🚧 💬 ⚠️

otofu-square

💻

Patrick P. Henley

🤔 👀

Matheus Marques

💻

Dhruv Patel

🐛 👀

Nathaniel Tucker

🐛 👀

Sergei Grishchenko

💻 📖 🤔

Josep M Sobrepere

📖

Marcel Tinner

📖

Daniel K.

🐛 💻

Vince Malone

💻

Sebastian Weber

📝

Christian Gill

📖

JavaScript Joe

✅ ⚠️

Sarah Dayan

📦

Roman Gusev

📖

Adam Seckel

💻

keiya sasaki

⚠️

Hu Chen

💻 📖 💡

Josh

📖 💬 💻 🤔 🚧 ⚠️

Na'aman Hirschfeld

💻

Braydon Hall

💻

Jacob M-G Evans

💻 ⚠️

Tiger Abrodi

💻 ⚠️

Amr A.Mohammed

💻 ⚠️

Juhana Jauhiainen

💻

Jens Meindertsma

💻 ⚠️

Marco Moretti

🚇

Martin V.

📖

Erozak

📖

Nick McCurdy

🚧

Arya

📖

numb86

📖

Alex Young

🚧

Ben Lambert

📖

David Cho-Lerat

📖

Evan Harmon

📖

Jason Brown

📖

KahWee Teng

📖

Leonid Shagabutdinov

📖

Levi Butcher

📖

Michele Settepani

📖

Sam

📖

Tanay Pratap

📖

Tom Rees-Herdman

📖

iqbal125

📖

cliffzhaobupt

🚧

Jon Koops

💻

Jonathan Peyper

👀 💻

Sean Baines

📖

Mikhail Vasin

📖

Aleksandar Grbic

📖

Jonathan Holmes

💻

Michaël De Boey

🚧

Anton Zinovyev

🐛 💻

marianna-exelate

🚇

Matan Borenkraout

🚧

andyrooger

💻

Bryan Wain

🐛 👀

Robert Snow

⚠️

Chris Chen

⚠️

Masious

📖

Laishuxin

📖

This project follows the all-contributors specification. Contributions of any kind welcome!

Issues

Looking to contribute? Look for the Good First Issue label.

🐛 Bugs

Please file an issue for bugs, missing documentation, or unexpected behavior.

See Bugs

💡 Feature Requests

Please file an issue to suggest new features. Vote on feature requests by adding a 👍. This helps maintainers prioritize what to work on.

See Feature Requests

❓ Questions

For questions related to using the library, you can raise issue here, or visit a support community:

LICENSE

MIT

NPM DownloadsLast 30 Days