import { act, renderHook } from '@testing-library/react-hooks'
import { useOverflowObserver } from './OverflowObserver'

describe('useOverflowObserver', () => {
  const hookApi = () => renderHook(() => useOverflowObserver()).result

  const runDefaulValueAssertions = (api) => {
    expect(api.isOverflowingY).toBe(false)
    expect(api.isOverflowingX).toBe(false)
    expect(api.isOverflowing).toBe(false)
  }

  it('should detect vertical content overflow', () => {
    const api = hookApi()

    const domNode = {
      clientHeight: 100,
      scrollHeight: 102,
      clientWidth: 50,
      scrollWidth: 50,
    }

    runDefaulValueAssertions(api.current)

    act(() => api.current.ref(domNode))

    expect(api.current.isOverflowingY).toBe(true)
    expect(api.current.isOverflowingX).toBe(false)
    expect(api.current.isOverflowing).toBe(true)
  })

  it('should detect horizontal content overflow', () => {
    const api = hookApi()

    const domNode = {
      clientHeight: 100,
      scrollHeight: 100,
      clientWidth: 50,
      scrollWidth: 52,
    }

    runDefaulValueAssertions(api.current)

    act(() => api.current.ref(domNode))

    expect(api.current.isOverflowingY).toBe(false)
    expect(api.current.isOverflowingX).toBe(true)
    expect(api.current.isOverflowing).toBe(true)
  })

  it('should detect vertical and horizontal content overflow', () => {
    const api = hookApi()

    const domNode = {
      clientHeight: 100,
      scrollHeight: 102,
      clientWidth: 50,
      scrollWidth: 52,
    }

    runDefaulValueAssertions(api.current)

    act(() => api.current.ref(domNode))

    expect(api.current.isOverflowingY).toBe(true)
    expect(api.current.isOverflowingX).toBe(true)
    expect(api.current.isOverflowing).toBe(true)
  })

  describe('Given that the browser miscalculates content dimensions', () => {
    ;[
      {
        clientHeight: 100,
        scrollHeight: 100,
        clientWidth: 99,
        scrollWidth: 100,
      },
      {
        clientHeight: 99,
        scrollHeight: 100,
        clientWidth: 50,
        scrollWidth: 50,
      },
      {
        clientHeight: 100,
        scrollHeight: 100,
        clientWidth: 50,
        scrollWidth: 49,
      },
      {
        clientHeight: 100,
        scrollHeight: 99,
        clientWidth: 50,
        scrollWidth: 50,
      },
    ].forEach((domNode) => {
      it('should ignore dimension variance in 1 pixel range', () => {
        const api = hookApi()

        runDefaulValueAssertions(api.current)

        act(() => api.current.ref(domNode))

        expect(api.current.isOverflowingY).toBe(false)
        expect(api.current.isOverflowingX).toBe(false)
        expect(api.current.isOverflowing).toBe(false)
      })
    })
  })
})
