'Mock context Consumer (React) for testing component

I'm trying to write a test to check if the component Header is rendering the company logo (context.company?.logoUrl, via context) and if it receives the companyId, via props.

import { Container, Image } from "react-bootstrap";

type Props = {
  context: AppContextProps;
  companyId: string | undefined;
};

const Header = ({ context, companyId }: Props) => {

  if (!context.company) {
    return <label>Loading...</label>;
  }

  return (
    <Container className="header">   
      <a href={`/${companyId}`}>
        <Image
          src={context.company?.logoUrl}
          className="header-logo"
        />
      </a>
    </Container>
  );
};

export default WithContext(Header);

The component Header is wrapped by a high order component, WithContext.

const WithContext = Component => {
  return props => (
    <AppContext.Consumer>
      {({state}) => <Component context={ state } {...props} />}
    </AppContext.Consumer>
  );
}

export default WithContext;

And here it is the AppContext structure.

export const AppContext = React.createContext();

class AppContextProvider extends Component {
  state = {
    company: null,
  };

  getCompanyData() {
    try {
      const response = await companyService.getPublicProfile();
      this.setState({ company: response });
    } catch (error) {
      console.log({ error });
    }
  }

  componentDidMount() {
    this.setState({
      company: this.getCompanyData,
    });
  }

  render() {
    return (
      <AppContext.Provider value={{ state: this.state }}>
        {this.props.children}
      </AppContext.Provider>
    );
  }
}

export default AppContextProvider;

This code was written 4 years ago, that's the reason why we are using class components and context this way (I know it is not the best, but we need to keep it that way). 😊

Here it is the base of the test (Jest one).

it("should load company logo URL", async () => {
  const propsMock = {
    companyId: "abcd9876",
  };

  const contextMock = {
    company: {
      logoUrl: "https://picsum.photos/200/300",
    },
  };

  render(
    <AppContext.Consumer>
      {({ state }) => <Header context={state} {...propsMock} />}
    </AppContext.Consumer>
  );

  // Don't mind this expect :P
  expect(1 + 2).toBe(3);
});

Every time I run the test, I get an error in Context.Consumer.

TypeError: Cannot destructure property 'state' of 'undefined' as it is undefined.

render(
  28 |       <AppContext.Consumer>
> 29 |         {({ state }) => <Header context={state} {...propsMock} />}
     |             ^
  30 |       </AppContext.Consumer>
  31 |     );

Basically I'm struggling to mock a Consumer and pass the context (state, which is supposed to be contextMock) and props (propsMock) so I can pass them to the Header component.

Do you guys have any idea how to make this test work properly?

Thank you!



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source