import ReactDOM from 'react-dom'
import ReactTestUtils from 'react-dom/test-utils'
import { fromJS } from 'immutable'

import componentWithOutsideClick from '../componentWithOutsideClick'
import mouseEventOn from '../../../../../../tests/util/mouseEventOn'

import PlainComponent from '../../../../../../tests/util/PlainComponent'
import { setFakeStore, unsetFakeStore } from '../../../../../reduxStore'

describe('componentWithOutsideClick', () => {
  const outsideClickStub = sinon.stub()
  class ComposedComponent extends PlainComponent {
    clickedOutside () {
      outsideClickStub()
    }
  }

  const ExtendedComponent = componentWithOutsideClick(ComposedComponent)
  const testbed = createTestbed(ExtendedComponent, {})

  const outerElement = document.createElement('div')
  beforeEach(() => {
    document.body.appendChild(outerElement)
  })

  afterEach(() => {
    outsideClickStub.resetHistory()
    outerElement.remove()
  })

  it('should render a child component', () => {
    testbed.render()

    const component = testbed.findChildByType(ExtendedComponent)
    expect(component).to.not.be.undefined()
  })

  it('should fire clickedOutside with a click outside the component', () => {
    testbed.render()

    mouseEventOn(outerElement, 'click')
    expect(outsideClickStub.called).to.be.true()
  })

  it('should not fire clickedOutside when ignoreClickOutsideIf returns true', () => {
    ComposedComponent.prototype.ignoreClickOutsideIf = () => true
    testbed.render()

    mouseEventOn(outerElement, 'click')
    expect(outsideClickStub.called).to.be.false()

    ComposedComponent.prototype.ignoreClickOutsideIf = null
  })

  it('should not fire clickedOutside when modal is open', () => {
    setFakeStore(fromJS({modal: {isOpen: true}}))
    ComposedComponent.prototype.ignoreClickOutsideIf = () => false
    testbed.render()

    mouseEventOn(outerElement, 'click')
    expect(outsideClickStub.called).to.be.false()

    ComposedComponent.prototype.ignoreClickOutsideIf = null
    unsetFakeStore()
  })

  it('should not fire clickedOutside with a click inside the component', () => {
    testbed.render()

    const component = testbed.findChildByType(ExtendedComponent)
    ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(component))
    expect(outsideClickStub.called).to.be.false()
  })

  it('click listener should go away once unmounted', () => {
    testbed.render()

    ReactDOM.unmountComponentAtNode(testbed.rootNode)
    mouseEventOn(outerElement, 'click')
    expect(outsideClickStub.called).to.be.false()
  })

  describe('a11y tests', () => {
    it('should meet a11y standards', (done) => {
      testbed.render()
      testbed.checkA11yStandards(done)
    })
  })
})
