1

I'm testing an app.js file and am mocking window.matchmedia for this. I've got it to work but am confused why my code works but the one in the jest documentation doesn't as described here and noted in this SO question.

This is my app.test.js:

import React from "react";
import { render, screen } from "@testing-library/react";
import App from "./app.js";


window.matchMedia = (query) => ({
    matches: false,
    media: query,
    onchange: null,
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })

test("renders App component", () => {
  render(<App />);
  expect(screen.getAllByText("Blog")).toHaveLength(2);
});

And here is my app.js:

import GlobalStyles from "../GlobalStyles/globalStyles.js";
import { ThemeProvider } from "styled-components";
import React, { useState } from "react";
import LandingPage from "../Landing/landing.js";
import About from "../About/about.js";
import Contact from "../Contact/contact.js";
import Blog from "../Blog/blog.js";
import Work from "../Work/work.js";
import DarkModeSwitch from "../DarkModeSwitch/darkModeSwitch.js";
import NotFound from "../NotFound/404.js";
import { lightTheme, darkTheme } from "../Theme/theme.js";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

/**
 * Main App function. Uses client side routing with React Router and some global styles and theming.
 * I've included a dark mode switch here rather than refactoring into a hook since it just feels simpler.
 */
function App() {

  // Find user local preferences for dark/light theme
  const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
  const initialTheme = prefersDark ? darkTheme : lightTheme;
  const [theme, setTheme] = useState(initialTheme);
  const [switcher, setSwitcher] = useState(true);

  /**
   * Handles clicks on the dark mode switch; these themes are then passed into ThemeProvider which injects styles
   * into the whole app.
   */
  function clickHandler() {
    setSwitcher(switcher ? false : true);
    setTheme(switcher ? lightTheme : darkTheme);
  }

  return (
    <>
      <ThemeProvider theme={theme}>
        <GlobalStyles />
        <DarkModeSwitch onClick={clickHandler} />
        <Router>
          <Routes>
            <Route path="*" element={<NotFound />} />
            <Route exact path="/" element={<LandingPage />}></Route>
            <Route exact path="/about" element={<About />}></Route>
            <Route exact path="/contact" element={<Contact />}></Route>
            <Route exact path="/blog" element={<Blog />}></Route>
            <Route exact path="/work" element={<Work />}></Route>
          </Routes>
        </Router>
      </ThemeProvider>
    </>
  );
}

export default App;

...and this is what jest says you're supposed to do and which doesn't work for me when I put in my app.test.js even though I think it should:

Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: jest.fn().mockImplementation(query => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(), // deprecated
    removeListener: jest.fn(), // deprecated
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })),
});
osint_alex
  • 952
  • 3
  • 16

2 Answers2

0

This is the solution that worked for me.

I created a file named setupTests.js with this function:

export const mockMatchMedia = () => {
  window.matchMedia = query => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(), // deprecated
    removeListener: jest.fn(), // deprecated
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  });
};

Then, i added this in my test file:

beforeAll(() => {
  mockMatchMedia();
});
jsidera
  • 1,791
  • 1
  • 17
  • 19
-1

try this

export default global.matchMedia =
  global.matchMedia ||
  function (query) {
    return {
      matches: false,
      media: query,
      onchange: null,
      addListener: jest.fn(), // deprecated
      removeListener: jest.fn(), // deprecated
      addEventListener: jest.fn(),
      removeEventListener: jest.fn(),
      dispatchEvent: jest.fn(),
    };
  };

and import file in all tests

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 27 '22 at 07:01