import { renderHook, act } from "@testing-library/react"; import { mediaQueries } from "../../../theme/breakpoints"; import { setMockedMatchedMedia } from "../../set-mocked-matched-media"; import { useMediaQuery } from "."; describe("use-media-query", () => { beforeEach(() => { jest.clearAllMocks(); }); it("Should return a true value for a provided media query, when the screen size matches that media query.", () => { setMockedMatchedMedia([mediaQueries[1]]); // Sets the tablet media query as the matching one. const { result } = renderHook(() => useMediaQuery(mediaQueries)); expect(result.current).toStrictEqual([false, true, false, false]); }); it("Should be able to return multiple true values, if there are several matching media queries.", () => { setMockedMatchedMedia([mediaQueries[1], mediaQueries[2]]); // Sets the tablet and laptop media query as the matching one. const { result } = renderHook(() => useMediaQuery(mediaQueries)); expect(result.current).toStrictEqual([false, true, true, false]); }); it("Should return the same amount of boolean values as the amount of queries passed in.", () => { setMockedMatchedMedia(); const { result } = renderHook(() => useMediaQuery(mediaQueries)); expect(result.current.length).toBe(mediaQueries.length); }); it("Should not return any true values if there are no matching media queries.", () => { setMockedMatchedMedia(); const { result } = renderHook(() => useMediaQuery(mediaQueries)); expect(result.current).toStrictEqual([false, false, false, false]); }); it("should re-run if the hook gets re-rendered with different input queries.", () => { setMockedMatchedMedia([mediaQueries[2]]); // Sets the desktop media query as the matching one. const { result, rerender } = renderHook(({ mq }) => useMediaQuery(mq), { initialProps: { mq: mediaQueries as string[], }, }); expect(result.current).toStrictEqual([false, false, true, false]); rerender({ mq: mediaQueries.slice(0, 1), }); expect(result.current).not.toStrictEqual([false, false, true, false]); expect(result.current).toStrictEqual([false]); }); it("should react to media query change events and update the hooks returned values correctly.", () => { const changeListeners: ((evt: MediaQueryListEvent) => void)[] = []; const addEventListener = jest.fn((name, cb) => { changeListeners.push(cb); }); const removeEventListener = jest.fn(); setMockedMatchedMedia([mediaQueries[2]], { addEventListener, removeEventListener, }); const { result, unmount } = renderHook(({ mq }) => useMediaQuery(mq), { initialProps: { mq: mediaQueries, }, }); expect(result.current).toStrictEqual([false, false, true, false]); const mockEvent = new Event("change", { bubbles: true, }) as MediaQueryListEvent; Object.defineProperties(mockEvent, { matches: { value: true }, media: { value: mediaQueries[0] }, }); act(() => { changeListeners[0]?.(mockEvent); }); expect(addEventListener).toHaveBeenCalledTimes(4); expect(result.current).toStrictEqual([true, false, true, false]); expect(removeEventListener).toHaveBeenCalledTimes(0); unmount(); expect(removeEventListener).toHaveBeenCalledTimes(4); }); });