Using context in react component tests

Viewed 6

I am writing tests for components of my projects and one of components is changing context value. How can I check if click actually changes context value? Code I have right now gives error "Invalid hook call. Hooks can only be called inside of the body of a function component." What is the way to actually use hooks in tests?

import { useState, useContext } from "react";
import { IntlProvider } from "react-intl";
import { BrowserRouter } from "react-router-dom";
import { render, screen, fireEvent } from "@testing-library/react";
import { messages } from "../../App/App.const";
import Navbar from "./Navbar";
import { DarkModeContext } from "../../contexts/DarkModeContext";

function NavbarMock() {
  const [search, setSearch] = useState("");
  const [language, setLanguage] = useState("en");

  return (
    <IntlProvider
      messages={messages[language as keyof typeof messages]}
      locale={language}
      defaultLocale="en"
    >
      <BrowserRouter>
        <Navbar
          setLanguage={setLanguage}
          language={language}
          setSearch={setSearch}
          search={search}
        />
      </BrowserRouter>
    </IntlProvider>
  );
}

describe("testing navbar component", () => {
  test("renders logo correctly", async () => {
    render(<NavbarMock />);
    const logo = screen.getByText(/Todoly/i);
    expect(logo).toBeInTheDocument();
  });
  test("renders mode icon correctly", async () => {
    render(<NavbarMock />);
    const svgEl = screen.getByTitle("mode icon");
    expect(svgEl).toBeInTheDocument();
  });
  test("mode changes", async () => {
    render(<NavbarMock />);
    const svgEl = screen.getByTitle("mode icon");
    const { isDarkMode } = useContext(DarkModeContext);
    fireEvent.click(svgEl);
    expect(isDarkMode).toBe(true);
  });
  test("renders language icon correctly", async () => {
    render(<NavbarMock />);
    const flagEl = screen.getByAltText("en");
    expect(flagEl).toBeInTheDocument();
  });
});
1 Answers

Ok, the error isn't caused by any of the provider, instead it's caused by the way you write useContext.

A hook can't be used unless it's referenced inside a Component, this is the RULE by React hooks. Because states defined by hooks are meaningless outside.

  const AnotherNavbarMock = () => {
    const { isDarkMode  }  = useContext(DarkModeContext);
    return <NavbarMock />
  }

The above code is the working example. Basically a test isn't a component, you have to define a component and then use it via <AnotherNavbarMock />, otherwise all the hook code would fail.

Related