Mocking React Context for testing

Viewed 284

I have a React app which utilizes the context hook. The app functions properly but I am having difficulty writing passing tests.

My context looks like

import React, { createContext } from 'react';

const DataContext = createContext();

export const DataProvider = (props) => {
  const [personSuccessAlert, setPersonSuccessAlert] = React.useState(false);

  return (
    <DataContext.Provider
      value={{
        personSuccessAlert,
        setPersonSuccessAlert,
      }}>
      {props.children}
    </DataContext.Provider>
  );
};

export const withContext = (Component) => (props) => (
  <DataContext.Consumer>
    {(globalState) => <Component {...globalState} {...props} />}
  </DataContext.Consumer>
);

The app uses this context in a useEffect hook

import React, { useEffect } from 'react';

import { Alert } from '../../../components/alert';

const PersonRecord = ({
  match: {
    params: { id },
  },
  setPersonSuccessAlert,
  personSuccessAlert,
}) => {

  const closeAlert = () => {
    setTimeout(() => {
      setPersonSuccessAlert(false);
    }, 3000);
  };

  useEffect(() => {
    closeAlert();
  }, [location]);

  return (
    <>
      <Alert
        open={personSuccessAlert}
      />
    </>
  );
};

export default withContext(PersonRecord);

This all works as expected. When I run my tests I know I need to import the DataProvider and wrap the component but I keep getting an error.

  test('useeffect', async () => {
    const history = createMemoryHistory();
    history.push('/people');
    const setPersonSuccessAlert = jest.fn();
    const { getByTestId, getByText } = render(
      <DataProvider value={{ setPersonSuccessAlert }}>
        <MockedProvider mocks={mocksPerson} addTypename={false}>
          <Router history={history}>
            <PersonRecord match={{ params: { id: '123' } }} />
          </Router>
        </MockedProvider>
      </DataProvider>,
    );
    const alert = getByTestId('styled-alert');
    await act(async () => new Promise((resolve) => setTimeout(resolve, 4000)));
  });

There are a few different errors I get depending on how I change things up but the most common is

[TypeError: setPersonSuccessAlert is not a function]

I think my context is setup slightly different than others which is why I am having trouble using other methods found on here.

0 Answers
Related