Fix testing for MUI breakpoints
Signed-off-by: Philipp Hugenroth <philipph@spotify.com>
This commit is contained in:
@@ -14,96 +14,30 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { act } from '@testing-library/react';
|
||||
|
||||
type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
|
||||
const defaultBreakpoint: Breakpoint = 'xl';
|
||||
|
||||
const queryToBreakpoint = {
|
||||
'(min-width:1920px)': 'xl',
|
||||
'(min-width:1280px)': 'lg',
|
||||
'(min-width:960px)': 'md',
|
||||
'(min-width:600px)': 'sm',
|
||||
'(min-width:0px)': 'xs',
|
||||
} as Record<string, Breakpoint>;
|
||||
|
||||
/**
|
||||
* Converts media query string to Breakpoint.
|
||||
* Chooses the default breakpoint if no breakpoint is set in the media query.
|
||||
* This is a mocking method suggested in the Jest Doc's, as it is not implemented in JSDOM yet.
|
||||
* It can be used to mock values when the MUI `useMediaQuery` hook if it is used in a tested component.
|
||||
*
|
||||
* @param query media query string
|
||||
* @returns Breakpoint
|
||||
* For issues checkout the documentation:
|
||||
* https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
|
||||
*
|
||||
* If there are any updates from MUI React on testing `useMediaQuery` this mock should be replaced
|
||||
* https://material-ui.com/components/use-media-query/#testing
|
||||
*
|
||||
* @param matchMediaOptions
|
||||
*/
|
||||
function toBreakpoint(query: string): Breakpoint {
|
||||
return queryToBreakpoint[query]
|
||||
? queryToBreakpoint[query]
|
||||
: defaultBreakpoint;
|
||||
}
|
||||
|
||||
type Listener = (event: { matches: boolean }) => void;
|
||||
|
||||
interface QueryList {
|
||||
addListener(listener: Listener): void;
|
||||
removeListener(listener: Listener): void;
|
||||
addEventListener(listener: Listener): void;
|
||||
removeEventListener(listener: Listener): void;
|
||||
matches: boolean;
|
||||
}
|
||||
|
||||
interface Query {
|
||||
query: string;
|
||||
queryList: QueryList;
|
||||
listeners: Set<Listener>;
|
||||
}
|
||||
|
||||
export default function mockBreakpoint(
|
||||
initialBreakpoint: Breakpoint = defaultBreakpoint,
|
||||
) {
|
||||
let currentBreakpoint = initialBreakpoint;
|
||||
const queries = Array<Query>();
|
||||
|
||||
const previousMatchMedia: any = (window as any).matchMedia;
|
||||
|
||||
// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
|
||||
(window as any).matchMedia = (query: string): QueryList => {
|
||||
const listeners = new Set<Listener>();
|
||||
|
||||
const queryList: QueryList = {
|
||||
addListener(listener) {
|
||||
listeners.add(listener);
|
||||
},
|
||||
removeListener(listener) {
|
||||
listeners.delete(listener);
|
||||
},
|
||||
addEventListener(listener) {
|
||||
listeners.add(listener);
|
||||
},
|
||||
removeEventListener(listener) {
|
||||
listeners.delete(listener);
|
||||
},
|
||||
matches: toBreakpoint(query) === currentBreakpoint,
|
||||
};
|
||||
|
||||
queries.push({ query, queryList, listeners });
|
||||
|
||||
return queryList;
|
||||
};
|
||||
|
||||
return {
|
||||
set(breakpoint: Breakpoint) {
|
||||
currentBreakpoint = breakpoint;
|
||||
|
||||
act(() => {
|
||||
queries.forEach(({ query, queryList, listeners }) => {
|
||||
const matches = toBreakpoint(query) === breakpoint;
|
||||
queryList.matches = matches;
|
||||
listeners.forEach(listener => listener({ matches }));
|
||||
});
|
||||
});
|
||||
},
|
||||
remove() {
|
||||
(window as any).matchMedia = previousMatchMedia;
|
||||
},
|
||||
};
|
||||
export default function mockBreakpoint({ matches = false }) {
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
writable: true,
|
||||
value: jest.fn().mockImplementation(query => ({
|
||||
matches: matches,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: jest.fn(), // deprecated
|
||||
removeListener: jest.fn(), // deprecated
|
||||
addEventListener: jest.fn(),
|
||||
removeEventListener: jest.fn(),
|
||||
dispatchEvent: jest.fn(),
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user