If you're testing React components that use window.matchMedia, Jest will crash with TypeError: window.matchMedia is not a function. This browser API doesn't exist in the jsdom test environment.
Why it happens
Jest runs tests in Node.js with jsdom, which doesn't implement window.matchMedia. Any code that calls matchMedia — common in responsive components, media query hooks, or UI libraries — will fail.
The fix
Add this mock to your Jest setup file:
// jest.setup.ts
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
If you're using an older version of Jest/jsdom, you might need addListener and removeListener (shown above). Newer versions use addEventListener/removeEventListener instead.
Make it return true for specific queries
If your test needs matchMedia to return matches: true:
window.matchMedia = jest.fn().mockImplementation(query => {
if (query === '(min-width: 768px)') {
return {
matches: true,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
};
}
return {
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
};
});
Verify it works
it('renders differently on mobile', () => {
render(<MyComponent />);
expect(window.matchMedia).toHaveBeenCalled();
});
That's it. The mock gives you a working matchMedia that behaves predictably in tests.