Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ayc0/mock-match-media
Mock window.matchMedia for Node.JS environments (like tests or NextJS)
https://github.com/ayc0/mock-match-media
jest listeners matchmedia mock nextjs nodejs test
Last synced: 3 months ago
JSON representation
Mock window.matchMedia for Node.JS environments (like tests or NextJS)
- Host: GitHub
- URL: https://github.com/ayc0/mock-match-media
- Owner: Ayc0
- License: mit
- Created: 2019-10-30T21:31:23.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2023-07-17T23:53:17.000Z (over 1 year ago)
- Last Synced: 2024-10-11T20:44:20.762Z (3 months ago)
- Topics: jest, listeners, matchmedia, mock, nextjs, nodejs, test
- Language: JavaScript
- Homepage:
- Size: 3.04 MB
- Stars: 21
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Simple server-side compatible substitution for `window.matchMedia()` based on [css-mediaquery](https://github.com/ericf/css-mediaquery).
1. [What is `mock-match-media`?](#what-is-mock-match-media)
2. [Usage](#usage)
1. [Listeners](#listeners)
2. [Cleanup](#cleanup)
1. [`cleanupListeners`](#cleanuplisteners)
2. [`cleanupMedia`](#cleanupmedia)
3. [`cleanup`](#cleanup-1)
3. [Polyfill](#polyfill)
4. [Other features](#other-features)
1. [`once` event listeners](#once-event-listeners)
2. [`.dispatchEvent` & `MediaQueryListEvent`](#dispatchevent--mediaquerylistevent)
3. [`.onchange`](#onchange)
4. [Interactions between multiple listeners](#interactions-between-multiple-listeners)
5. [ESM](#esm)
3. [How to use with other libraries](#how-to-use-with-other-libraries)
1. [Jest](#jest)
2. [NextJS](#nextjs)# What is `mock-match-media`?
`mock-match-media` is a [ponyfill](https://github.com/sindresorhus/ponyfill) for `window.matchMedia` but for Node.
This mock is fully compliant with [the spec](https://www.w3.org/TR/2016/WD-cssom-view-1-20160317/#the-mediaquerylist-interface) (see doc on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia) or [Other features](#other-features)).
![Node CI tests](https://github.com/Ayc0/mock-match-media/actions/workflows/main.yml/badge.svg)
We currently support Node v12, v14, v16, v18 and v19.
It's also coded in TypeScript.
# Usage
```js
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
matchMedia("(min-width: 40px)").matches;
// > true// Only redefine what changed
setMedia({
width: "500px",
});matchMedia("(min-width: 250px)").matches;
// > true
```## Listeners
`mock-match-media` also supports even listeners:
```js
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 changedsetMedia({
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:
```js
const { cleanupListeners, cleanupMedia, cleanup } = require("mock-match-media");
```### `cleanupListeners`
`cleanupListeners` clears all listeners called via `matchMedia().addListener()` or `matchMedia().addEventListener()` (to avoid calling in side effects).
### `cleanupMedia`
`cleanupMedia` resets the state of the window set via `setMedia()`.
### `cleanup`
`cleanup` at the same time clears all listeners (like `cleanupListeners`), and clears the state of the window (like `cleanupMedia`).
## Polyfill
If you don't want to change your code or to setup mocks with your testing library, you can do:
```js
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:
### `once` event listeners
```js
const { matchMedia } = require("mock-match-media");const mql = matchMedia("(min-width: 250px)");
mql.addEventListener("change", listener, { once: true }); // the listener will be removed after 1 received event
```### `.dispatchEvent` & `MediaQueryListEvent`
Like every other [EventTarget](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget), you can `.dispatchEvent(event)` to manually dispatch event (it’s not that useful to be honest, but as it’s in the spec, we implemented it).
```js
const { matchMedia, MediaQueryListEvent } = require("mock-match-media");const mql = matchMedia("(min-width: 250px)");
mql.dispatchEvent(new MediaQueryListEvent("change", { matches: false, media: "(custom-non-valid)" }));
// Works also with a regular event but it’s not recommended:
mql.dispatchEvent(new Event("change"));
```### `.onchange`
Like on any HTML element, you can attach a `.onchange` legacy event handler:
```js
const { matchMedia } = require("mock-match-media");const mql = matchMedia("(min-width: 250px)");
mql.onchange = listener;
```### Interactions between multiple listeners
We follow how browsers implemented interactions like:
```js
const { matchMedia } = require("mock-match-media");const mql = matchMedia("(min-width: 250px)");
mql.onchange = listener;
mql.addListener(listener);
mql.addEventListener("change", listener);
mql.addEventListener("change", listener, { once: true });
```And all of those are tested.
## ESM
We also ship 2 versions of this library:
- one in CJS
- one in ESMThis is also true for the polyfills, but the [`setup-jest`](#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` and `MediaQueryListEvent`)
- add a call to `cleanup` in `afterAll` to auto-cleanup your env in after each `test`/`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](https://github.com/Ayc0/mock-match-media-examples/tree/master/create-react-app) that includes Jest, react testing library and react-scripts.
## NextJS
You can find an example [here](https://github.com/Ayc0/mock-match-media-examples/tree/master/next) for how to use `mock-match-media` with NextJS.