import { renderHook } from '@testing-library/react-hooks'
import React from 'react'
import { defaultRect } from '../../_utils/dom'
import {
  testContext,
  testHook,
  testRenderProp,
} from '../../__tests__/helpers/state'
import { Anchor, AnchorProvider, useAnchor, useAnchorContext } from '../Anchor'

const validateAPI = (api) => {
  expect(typeof api.left).toBe('number')
  expect(typeof api.minWidth).toBe('number')
  expect(typeof api.placement).toBe('string')
  expect(typeof api.top).toBe('number')
}

const apiTest = {
  test: 'api',
  config: {
    overlayRef: React.createRef(),
    targetRef: React.createRef(),
  },
  callback: validateAPI,
}

describe('Anchor', () => {
  const mockGetBoundingClientRect = jest
    .spyOn(Element.prototype, 'getBoundingClientRect')
    .mockImplementation(() => ({
      ...defaultRect,
    }))

  testHook(useAnchor, [apiTest])

  describe('useAnchor', () => {
    describe('shrinkOverlay', () => {
      let overlayGetBoundingClientRectSpy
      let targetRef
      let overlayRef
      beforeEach(() => {
        const target = document.createElement('div')
        target.getBoundingClientRect = jest.fn(() => ({
          ...defaultRect,
          width: 8.34375,
        }))
        targetRef = { current: target }

        const overlay = document.createElement('div')
        overlayGetBoundingClientRectSpy = jest.spyOn(
          overlay,
          'getBoundingClientRect'
        )
        overlayRef = {
          current: overlay,
        }
      })

      describe('when shrinkOverlay is false', () => {
        it('should set minWidth', () => {
          renderHook(() =>
            useAnchor({
              targetRef,
              overlayRef,
              shrinkOverlay: false,
            })
          )

          expect(
            overlayGetBoundingClientRectSpy.mock.instances[0].style.minWidth
          ).toBe('8.34375px')
        })
      })

      describe('when shrinkOverlay is true', () => {
        it('should not set minWidth', () => {
          renderHook(() =>
            useAnchor({
              targetRef,
              overlayRef,
              shrinkOverlay: true,
            })
          )

          expect(
            overlayGetBoundingClientRectSpy.mock.instances[0].style.minWidth
          ).toBe('')
        })
      })
    })
  })

  testRenderProp(Anchor, 'anchor', [apiTest])

  testContext(AnchorProvider, useAnchorContext, [
    apiTest,
    ,
    {
      test: 'missing provider',
      config: {},
      injectProvider: false,
      callback: (context) => {
        validateAPI(context)
      },
    },
  ])

  mockGetBoundingClientRect.mockRestore()
})
