How to test code that uses a custom hook based on useContext with react-testing-library and jest

1.1k Views Asked by At

I've created a custom context hook - and I'm struggling to figure out how to pass values to its provider during testing.

My hook:

import React, { createContext, useContext, useState } from 'react';

const Context = createContext({});

export const ConfigurationProvider = ({ children }) => {
  // Use State to keep the values
  const [configuration, setConfiguration] = useState({});

  // pass the value in provider and return
  return (
    <Context.Provider
      value={{
        configuration,
        setConfiguration,
      }}
    >
      {children}
    </Context.Provider>
  );
};

export const useConfigurationContext = () => useContext(Context);
export const { Consumer: ConfigurationConsumer } = Context;

This is how it's used in the application:

function App() {
  return (
    <ConfigurationProvider>
      <div className="app">
        <ComponentA />
      </div>
    </ConfigurationProvider>
  );
}

And in ComponentA:

const ComponentA = () => {
  // Get configuration
  const configuration = useConfigurationContext();

  return (
    <div>{JSON.stringify(configuration)}</div>
  )
}

This all works fine - considered that I'm calling setConfiguration from another component and set an object. Now for the testing part:

import React, { Component, createContext } from 'react';
import { render, waitFor } from '@testing-library/react';
import ComponentA from 'componentA';

const config = {
  propertyA: 'hello',
};

test('renders the config', async () => {
  const ConfigurationContext = createContext();

  const { queryByText } = render(
    <ConfigurationContext.Provider value={config}>
      <ComponentA />
    </ConfigurationContext.Provider>
  );

  expect(queryByText('hello')).toBeInTheDocument();
});

This doesn't work - I'm expecting the value that I'm sending in would be rendered in the div, but the context is an empty object. What am I doing wrong?

1

There are 1 best solutions below

0
On

Thanks to Carle B. Navy I got the reason why it doesn't work. For other people two wonder what the solution is I fixed it by doing the following:

In my context hook, I changed the last line to export the provider as well:

export const { Consumer: ConfigConsumer, Provider: ConfigProvider } = Context;

Then in my test case, instead of creating a new context, I import the ConfigProvider at the top, and then:

const { queryByText } = render(
  <ConfigProvider value={config}>
    <ComponentA />
  </ConfigProvider>
);

Thanks for helping me solve this and hope this helps someone else.