README
Simple server-side compatible substitution for window.matchMedia()
based on css-mediaquery.
Usage
const { matchMedia, setMedia } = require("mock-match-media");
// Define current media
setMedia({
width: "50px",
type: "screen",
orientation: "landscape",
"prefers-color-scheme": "light",
});
matchMedia("(min-width: 250px)").matches;
// > false
// Only redefine what changed
setMedia({
width: "500px",
});
matchMedia("(min-width: 250px)").matches;
// > true
Listeners
mock-match-media
also supports even listeners:
const { matchMedia, setMedia } = require("mock-match-media");
setMedia({
width: "50px",
});
const listener = (event) => console.log(event.matches);
const matcher = matchMedia("(min-width: 250px)");
matcher.addEventListener("change", listener);
// And also the deprecated version
// matchMedia("(min-width: 250px)").addListener(event => console.log(event.matches));
setMedia({
width: "100px",
});
// outputs nothing because `matches` hasn't changed
setMedia({
width: "1000px",
});
// outputs `true`
matcher.removeEventListener("change", listener);
setMedia({
width: "100px",
});
// outputs nothing because the listener is removed
Cleanup
mock-match-media
provides 3 cleanup functions:
cleanupListeners
to clear all listeners called viamatchMedia().addListener()
ormatchMedia().addEventListener()
(to avoid calling in side effects),cleanupMedia
to reset the state of the window set viasetMedia()
,cleanup
that calls the 2 other functions to clean everything.
Polyfill
If you don't want to change your code or to setup mocks with your testing library, you can do:
require("mock-match-media/polyfill");
And then global variables matchMedia
and MediaQueryListEvent
will be set.
And thus, you won't have to import those (you'll still have to import setMedia
, and the cleanup
functions).
Other features
This library covers most of the aspects of matchMedia
. In addition to the API presented above, it also supports:
mql.onchange = listener
,mql.dispatchEvent(new Event('type'))
,mql.dispatchEvent(new MediaQueryListEvent('change', { media: '...', matches: ... }))
,mql.addEventListener('change', listener, { once: true })
(and the other options too even though they are no-nops),- having
mql.addListener
&mql.addEventListener
&mql.onchange
on the same MQL AND with the same listener.
And all of those are tested.
ESM
We also ship 2 versions of this library:
- one in CJS
- one in ESM
This is also true for the polyfills, but the setup-jest
file is only available in CJS (Jest doesn't work that well with ESM).
How to use with other libraries
Jest
In jest.setup.js
, you only need to import mock-match-media/jest-setup
(or mock-match-media/jest-setup.cjs
depending on your config). It'll:
- install the polyfill (for
matchMedia
andMediaQueryListEvent
) - add a call to
cleanup
inafterAll
to auto-cleanup your env in after eachtest
/it
.
You can set import jest-setup
in setupFiles
or in setupFilesAfterEnv
in your jest config.
And then you can use setMedia
in your tests.
You can find an example here that includes Jest, react testing library and react-scripts.
NextJS
In server.js
, you can do:
require("mock-match-media/polyfill");
const { setMedia } = require("mock-match-media");
setMedia({
// your config
});
You can find an example here that includes a custom server.js
and a basic component.