/* eslint-disable react/no-children-prop */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { useContext } from 'react'; import { render, fireEvent } from '@testing-library/react'; import { WindowSizeBreakpoints } from '../WindowSizeBreakpoints'; import { BreakpointsContext } from '../BreakpointsContext'; import { BreakpointsProps } from '../breakpoints'; import { delay } from './helpers/delay'; describe('WindowSizeBreakpoints', function () { const propsMock = jest.fn(); function propsMockResult() { return propsMock.mock.results.map(v => v.value); } function Children() { const props = useContext(BreakpointsContext); propsMock(props); return
; } beforeEach(() => { propsMock.mockClear(); propsMock.mockImplementation((props: BreakpointsProps) => { return props; }); jest.spyOn(console, 'error').mockImplementation(() => { /* linter */ }); }); it('explodes if there are no breakpoints', function () { expect(() => render( } />, ), ).toThrow(); expect(() => render( } />, ), ).toThrow(); expect(() => render( } />, ), ).toThrow(); }); it('renders its children', function () { const result = render( } />, ); expect(result.findByTestId('children')).resolves.toBeDefined(); }); it('passed breakpoints through context', function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; render( } />, ); expect(propsMockResult()).toMatchObject([{ breakpoints }]); }); it('detects currentBreakpoint "desktop" for innerWidth = 1920', function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; global.innerWidth = 1920; render( } />, ); expect(propsMockResult()).toMatchObject([{ currentBreakpoint: 'desktop' }]); }); it('detects currentBreakpoint "tablet" for innerWidth = 800', function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; global.innerWidth = 800; render( } />, ); expect(propsMockResult()).toMatchObject([ { breakpoints, currentBreakpoint: 'tablet' }, ]); }); it('detects currentBreakpoint "mobile" for innerWidth = 240', function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; global.innerWidth = 240; render( } />, ); expect(propsMockResult()).toMatchObject([{ currentBreakpoint: 'mobile' }]); }); it('detects currentBreakpoint "mobile" for innerWidth = 100', function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; global.innerWidth = 100; render( } />, ); expect(propsMockResult()).toMatchObject([{ currentBreakpoint: 'mobile' }]); }); it('detects currentBreakpoint "desktop" for innerWidth = 1920 with breakpointUnit = "em"', function () { const breakpoints = { mobile: 20, // 20em = 320px tablet: 48, // 48em = 768px desktop: 75, // 75em = 1200px }; global.innerWidth = 1920; // = 120em render( } />, ); expect(propsMockResult()).toMatchObject([{ currentBreakpoint: 'desktop' }]); }); it('detects currentBreakpoint "tablet" for innerWidth = 800 with breakpointUnit = "em"', function () { const breakpoints = { mobile: 20, // 20em = 320px tablet: 48, // 48em = 768px desktop: 75, // 75em = 1200px }; global.innerWidth = 800; // = 50em render( } />, ); expect(propsMockResult()).toMatchObject([{ currentBreakpoint: 'tablet' }]); }); it('detects changes in breakpoints', async function () { const initialBreakPoints = { mobile: 320, tablet: 768, desktop: 1200, }; const nextBreakpoints = { sm: 320, md: 768, lg: 1200, }; const moreBreakpoints = { sm: 320, md: 768, lg: 1200, xl: 1920, }; global.innerWidth = 800; // = 50em const result = render( } />, ); result.rerender( } />, ); result.rerender( } />, ); await delay(0); // useEffect expect(propsMockResult()).toMatchObject([ { breakpoints: initialBreakPoints, currentBreakpoint: 'tablet', }, { breakpoints: nextBreakpoints, currentBreakpoint: 'md', }, { breakpoints: moreBreakpoints, currentBreakpoint: 'md', }, ]); }); it('detects changes in window size', function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; global.innerWidth = 1920; render( } />, ); global.innerWidth = 800; fireEvent.resize(global.window); global.innerWidth = 600; fireEvent.resize(global.window); expect(propsMockResult()).toMatchObject([ { currentBreakpoint: 'desktop' }, { currentBreakpoint: 'tablet' }, { currentBreakpoint: 'mobile' }, ]); }); it('detects changes in window size when using debounceResize', async function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; global.innerWidth = 1920; render( } debounceResize debounceDelay={25} />, ); global.innerWidth = 800; fireEvent.resize(global.window); global.innerWidth = 600; fireEvent.resize(global.window); await delay(30); // wait for debounce expect(propsMockResult()).toMatchObject([ { currentBreakpoint: 'desktop' }, { currentBreakpoint: 'mobile' }, ]); }); it('works with detected screenWidth = 0 and guessedBreakpoint', async function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; global.innerWidth = 0; render( } guessedBreakpoint={breakpoints.tablet} />, ); expect(propsMockResult()).toMatchObject([{ currentBreakpoint: 'tablet' }]); }); it('works with detected screenWidth = 0 and defaultBreakpoint', async function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; global.innerWidth = 0; render( } defaultBreakpoint={breakpoints.tablet} />, ); expect(propsMockResult()).toMatchObject([{ currentBreakpoint: 'tablet' }]); }); it('with detected screenWidth = 0 and no other hints it uses the smallest breakpoint', async function () { const breakpoints = { mobile: 320, tablet: 768, desktop: 1200, }; global.innerWidth = 0; render( } />, ); expect(propsMockResult()).toMatchObject([{ currentBreakpoint: 'mobile' }]); }); });