Testing react context with jest and react-testing-library
Asked Answered
H

2

6

I am trying to set up tests for my component App.js that takes in a context as a prop and returns a provider. The issue is when I am trying to test it, the context that I pass into it always resolves to undefined.

I put a console log in the component and and one between creating the context and creating the Component (which should receive context as a param). This resulted in the console.log in the component first for some reason. This is probably why I am getting context is undefined as it hasn't been initialized yet.

// Component/Provider
const App = (props) => {
  const {children, context} = props;
  const {data, dispatch} = useReducer(reducer);
  console.log(context); //undefined and this console.log runs first
  return <context.Provider value={useCallback(dispatch)}>{children}</context.Provider>
}

In my test.js

import React, {useContext} from 'react';
import {render} from 'react-testing-library';
import {App} from './App';
const context = React.createContext();

function Provider(children) {
  console.log(context); //Is correct but runs second
  return <App Context={context}>{children}</App>;
}

const customRender = (ui, options) =>
  render(ui, { wrapper: Provider, ...options });

const Consumer = () => {
  const dispatch = useContext(context);
  returns <Button onClick={dispatch({type: 'Do something'})}>Whatever</Button/>;
}
customRender(<Consumer />)

I should be able to pass a Context into my component to create the provider but its always undefined.

Hedonism answered 14/4, 2019 at 0:46 Comment(1)
I believe you have already found that your component expects context prop but Context is passed. casing matters.Starshaped
P
1

I was stuck for a bit before finding out how to proceed. My problem was that I wasn't crating the right shape for the context : I was giving it some props but not the one passed in my real context. So the component couldn't browse that new shape.

Here was my prod shape (non test)

export default React.createContext({
  authenticationInfos: {
    isAuthenticated: false,
    user: {
      id: "",
      email: "",
      roles: []
    },
    customer: {
      id: "",
      prenom: "",
      nom: "",
      tel: "",
      adress: "",
      postalCode: "",
      town: "",
      sellRequests: []
    }
  },
  setAuthenticationInfos: value => {}
});

And I was just passing what was inside authenticationInfos, but not the prop authenticationInfos itself, and I was also forgetting the setAuthenticationInfos prop.

Here is my test component that works with context hook :

Function from the react-testing-library documentation

const customRender = (ui, { providerProps, ...renderOptions }) => {
  return render(
    <AuthContext.Provider value={providerProps}>{ui}</AuthContext.Provider>,
    renderOptions
  );
};

describe("<ConnectModal>", () => {
  test("should be able to access auth context", () => {
    const providerProps = {
      authenticationInfos: {
        isAuthenticated: false,
        user: {
          id: "",
          email: "",
          roles: [],
        },
        customer: {
          id: "",
          prenom: "",
          nom: "",
          tel: "",
          adress: "",
          postalCode: "",
          town: "",
          sellRequests: [],
        },
        shop: {
          appToken: 54,
        },
      },
      setAuthenticationInfos: (value) => {},
    };
    customRender(<MKMConnectModal />, { providerProps });
    // expect(screen.getByText(/^My Name Is:/)).toHaveTextContent(
    //   "My Name Is: C3P0"
    // );
  });
});
Phosphoroscope answered 30/8, 2020 at 10:21 Comment(0)
H
0

Maybe this is a typo, but is your file really called test.js? If so, you will need to change it to .jsx, as you're using JSX in your test (e. g. in the Provider component).

Humberto answered 9/6, 2020 at 9:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.