@react-hook/window-size
Version:
React hooks for updating components when the size of the `window` changes.
152 lines (125 loc) • 3.92 kB
text/typescript
/* eslint-disable jest/valid-title */
import {renderHook, act} from '@testing-library/react-hooks'
import {resetSize, resizeTo, changeOrientation} from 'test-utils'
import {useWindowSize, useWindowWidth, useWindowHeight} from './index'
// @ts-ignore
const renderWindowSize = (...args): any =>
renderHook(() => useWindowSize(...args))
const renderWindowWidth = (...args): any =>
renderHook(() => useWindowWidth(...args))
const renderWindowHeight = (...args): any =>
renderHook(() => useWindowHeight(...args))
const mockPerf = () => {
// @ts-ignore
const original = global?.performance
let ts = (typeof performance !== 'undefined' ? performance : Date).now()
return {
install: () => {
ts = Date.now()
const perfNowStub = jest
.spyOn(performance, 'now')
.mockImplementation(() => ts)
global.performance = {
//@ts-expect-error
now: perfNowStub,
}
},
advanceBy: (amt: number) => (ts += amt),
advanceTo: (t: number) => (ts = t),
uninstall: () => {
if (original) {
//@ts-ignore
global.performance = original
}
},
}
}
const perf = mockPerf()
describe('useWindowSize() throttled', () => {
jest.useFakeTimers()
beforeEach(() => {
perf.install()
resetSize()
})
afterEach(perf.uninstall)
it('should update on resize events', () => {
resizeTo(0, 0)
const {result} = renderWindowSize()
expect(result.current[0]).toBe(0)
expect(result.current[1]).toBe(0)
let i = 0
for (; i < Math.ceil(1000 / 30) + 1; i++) {
perf.advanceBy(1)
expect(result.current[0]).toBe(0)
expect(result.current[1]).toBe(0)
act(() => resizeTo(i, i))
}
expect(result.current[0]).toBe(34)
expect(result.current[1]).toBe(34)
for (; i < 1 + Math.ceil(1000 / 30) * 2; i++) {
perf.advanceBy(1)
expect(result.current[0]).toBe(34)
expect(result.current[1]).toBe(34)
act(() => resizeTo(i, i))
}
expect(result.current[0]).toBe(68)
expect(result.current[1]).toBe(68)
})
it('should update on the leading edge', () => {
const {result} = renderWindowSize({leading: true})
expect(result.current[0]).toBe(0)
expect(result.current[1]).toBe(0)
act(() => resizeTo(600, 400))
expect(result.current[0]).toBe(600)
expect(result.current[1]).toBe(400)
})
it('should update according to custom "fps"', () => {
const {result} = renderWindowSize({fps: 60})
expect(result.current[0]).toBe(0)
expect(result.current[1]).toBe(0)
let i = 0
for (; i < Math.ceil(1000 / 60) + 1; i++) {
perf.advanceBy(1)
expect(result.current[0]).toBe(0)
expect(result.current[1]).toBe(0)
act(() => resizeTo(i, i))
}
expect(result.current[0]).toBe(17)
expect(result.current[1]).toBe(17)
})
it('should update on orientation change', () => {
const {result} = renderWindowSize()
expect(result.current[0]).toBe(0)
expect(result.current[1]).toBe(0)
act(() => changeOrientation(1280, 720))
act(() => {
jest.advanceTimersByTime(1000 / 30)
})
expect(result.current[0]).toBe(1280)
expect(result.current[1]).toBe(720)
})
})
describe('useWindowWidth() throttled', () => {
it('it should update when the window width changes', () => {
resizeTo(0, 0)
const {result} = renderWindowWidth()
expect(result.current).toBe(0)
act(() => resizeTo(1280, 720))
act(() => {
jest.advanceTimersByTime(1000 / 30)
})
expect(result.current).toBe(1280)
})
})
describe('useWindowHeight() throttled', () => {
it('should update when the window height changes', () => {
resizeTo(0, 0)
const {result} = renderWindowHeight()
expect(result.current).toBe(0)
act(() => resizeTo(1280, 720))
act(() => {
jest.advanceTimersByTime(1000 / 30)
})
expect(result.current).toBe(720)
})
})