Files
react/components/utils-shared/__tests__/body-scroll.test.tsx
2020-05-06 14:25:10 +08:00

147 lines
5.1 KiB
TypeScript

import React, { RefObject } from 'react'
import useBodyScroll from '../use-body-scroll'
import { act, renderHook } from '@testing-library/react-hooks'
describe('UseBodyScroll', () => {
it('should work correctly', () => {
const ref = React.createRef<HTMLDivElement>()
;(ref as any).current = document.createElement('div')
const { result } = renderHook(() => useBodyScroll(ref))
const [hidden, setHidden] = result.current
expect(hidden).toBe(false)
act(() => setHidden(true))
expect(result.current[0]).toBe(true)
})
it('should set overflow', () => {
const ref = React.createRef<HTMLDivElement>()
;(ref as any).current = document.createElement('div')
const el = ref.current as HTMLDivElement
const { result } = renderHook(() => useBodyScroll(ref))
act(() => result.current[1](true))
expect(el.style.overflow).toEqual('hidden')
act(() => result.current[1](false))
expect(el.style.overflow).toEqual('')
})
it('the last value of overflow should be recovered after setHidden', () => {
const ref = React.createRef<HTMLDivElement>()
const div = document.createElement('div')
div.style.overflow = 'scroll'
;(ref as any).current = div
const el = ref.current as HTMLDivElement
const { result } = renderHook(() => useBodyScroll(ref))
expect(el.style.overflow).toEqual('scroll')
act(() => result.current[1](true))
expect(el.style.overflow).toEqual('hidden')
act(() => result.current[1](false))
expect(el.style.overflow).toEqual('scroll')
})
it('should work correctly with multiple element', () => {
const ref = React.createRef<HTMLDivElement>()
;(ref as any).current = document.createElement('div')
const el = ref.current as HTMLDivElement
const { result } = renderHook(() => useBodyScroll(ref))
const ref2 = React.createRef<HTMLDivElement>()
;(ref2 as any).current = document.createElement('div')
const el2 = ref2.current as HTMLDivElement
const { result: result2 } = renderHook(() => useBodyScroll(ref2))
act(() => result.current[1](true))
act(() => result2.current[1](true))
expect(el.style.overflow).toEqual('hidden')
expect(el2.style.overflow).toEqual('hidden')
act(() => result.current[1](false))
act(() => result2.current[1](false))
expect(el.style.overflow).toEqual('')
expect(el2.style.overflow).toEqual('')
})
it('should work correctly with iOS', () => {
Object.defineProperty(window.navigator, 'platform', { value: '', writable: true })
;(window.navigator as any).platform = 'iPhone'
const event = { preventDefault: jest.fn() }
const ref = React.createRef<HTMLDivElement>()
;(ref as any).current = document.createElement('div')
const el = ref.current as HTMLDivElement
const { result } = renderHook(() => useBodyScroll(ref))
act(() => result.current[1](true))
const touchEvent = new TouchEvent('touchmove', event as EventInit)
const MockEvent = Object.assign(touchEvent, event)
document.dispatchEvent(MockEvent)
expect(el.style.overflow).not.toEqual('hidden')
expect(event.preventDefault).toHaveBeenCalled()
// Touch events with multiple fingers do nothing
document.dispatchEvent(
new TouchEvent('touchmove', {
touches: [{}, {}, {}] as Array<Touch>,
}),
)
expect(event.preventDefault).toHaveBeenCalledTimes(1)
act(() => result.current[1](false))
;(window.navigator as any).platform = ''
})
it('should work correctly with options', () => {
Object.defineProperty(window.navigator, 'platform', { value: '', writable: true })
;(window.navigator as any).platform = 'iPhone'
const event = { preventDefault: jest.fn() }
const ref = React.createRef<HTMLDivElement>()
;(ref as any).current = document.createElement('div')
const el = ref.current as HTMLDivElement
const { result } = renderHook(() => useBodyScroll(ref, { scrollLayer: true }))
act(() => result.current[1](true))
const touchEvent = new TouchEvent('touchmove', event as EventInit)
const MockEvent = Object.assign(touchEvent, event)
document.dispatchEvent(MockEvent)
expect(el.style.overflow).toEqual('hidden')
expect(event.preventDefault).not.toHaveBeenCalled()
act(() => result.current[1](false))
;(window.navigator as any).platform = ''
})
it('should work correctly when set element repeatedly', () => {
let _ref: RefObject<HTMLDivElement> | null = null
const ref = React.createRef<HTMLDivElement>()
;(ref as any).current = document.createElement('div')
_ref = ref
const el = ref.current as HTMLDivElement
const { result, rerender } = renderHook(() => useBodyScroll(_ref))
act(() => result.current[1](true))
expect(el.style.overflow).toEqual('hidden')
// Force tigger rerender at the same value
_ref = React.createRef<HTMLDivElement>()
rerender()
_ref = ref
rerender()
act(() => result.current[1](true))
expect(el.style.overflow).toEqual('hidden')
})
it('should set body when missing all params', () => {
const { result } = renderHook(() => useBodyScroll())
act(() => result.current[1](true))
expect(document.body.style.overflow).toEqual('hidden')
})
})