jest-matchmedia-mock
Version:
Mock for fully testing any media queries with Jest
116 lines (115 loc) • 3.74 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class MatchMedia {
constructor() {
this.mediaQueries = {};
Object.defineProperty(window, 'matchMedia', {
writable: true,
configurable: true,
value: (query) => {
this.mediaQueryList = {
matches: query === this.currentMediaQuery,
media: query,
onchange: null,
addListener: (listener) => {
this.addListener(query, listener);
},
removeListener: (listener) => {
this.removeListener(query, listener);
},
addEventListener: (type, listener) => {
if (type !== 'change')
return;
this.addListener(query, listener);
},
removeEventListener: (type, listener) => {
if (type !== 'change')
return;
this.removeListener(query, listener);
},
dispatchEvent: jest.fn(),
};
return this.mediaQueryList;
},
});
}
/**
* Adds a new listener function for the specified media query
* @private
*/
addListener(mediaQuery, listener) {
if (!this.mediaQueries[mediaQuery]) {
this.mediaQueries[mediaQuery] = [];
}
const query = this.mediaQueries[mediaQuery];
const listenerIndex = query.indexOf(listener);
if (listenerIndex !== -1)
return;
query.push(listener);
}
/**
* Removes a previously added listener function for the specified media query
* @private
*/
removeListener(mediaQuery, listener) {
if (!this.mediaQueries[mediaQuery])
return;
const query = this.mediaQueries[mediaQuery];
const listenerIndex = query.indexOf(listener);
if (listenerIndex === -1)
return;
query.splice(listenerIndex, 1);
}
/**
* Updates the currently used media query,
* and calls previously added listener functions registered for this media query
* @public
*/
useMediaQuery(mediaQuery) {
if (typeof mediaQuery !== 'string')
throw new Error('Media Query must be a string');
this.currentMediaQuery = mediaQuery;
if (!this.mediaQueries[mediaQuery])
return;
const mqListEvent = {
matches: true,
media: mediaQuery,
};
this.mediaQueries[mediaQuery].forEach((listener) => {
listener.call(this.mediaQueryList, mqListEvent);
});
}
/**
* Returns an array listing the media queries for which the matchMedia has registered listeners
* @public
*/
getMediaQueries() {
return Object.keys(this.mediaQueries);
}
/**
* Returns a copy of the array of listeners for the specified media query
* @public
*/
getListeners(mediaQuery) {
if (!this.mediaQueries[mediaQuery])
return [];
return this.mediaQueries[mediaQuery].slice();
}
/**
* Clears all registered media queries and their listeners
* @public
*/
clear() {
this.mediaQueries = {};
}
/**
* Clears all registered media queries and their listeners,
* and destroys the implementation of `window.matchMedia`
* @public
*/
destroy() {
this.clear();
delete window.matchMedia;
}
}
exports.default = MatchMedia;