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(),
})),
});