/* 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' }]);
});
});