import React, { Component } from 'react'
import Button from '@instructure/ui-buttons/lib/components/Button'
import { unconnectedExtension } from '../makeScrollable'

const componentDidUpdateStub = sinon.stub()
class TestComponent extends Component {
  componentDidUpdate () {
    componentDidUpdateStub()
  }

  render () {
    return (
      <div />
    )
  }
}

const ExtendedComponent = unconnectedExtension(TestComponent)
const ExtendedComponentButton = unconnectedExtension(Button)

describe('makeScrollable', () => {
  const keyForComponent = 'keyForComponent'
  const clearsScrollStub = sinon.stub()
  const scrollSpy = sinon.spy(ExtendedComponent.prototype, 'scrollIntoView')
  const setFocusSpy = sinon.spy(ExtendedComponentButton.prototype, 'setFocus')

  const testbed = createTestbed(
    ExtendedComponent,
    {
      scrollKey: keyForComponent,
      scrolledComponentKey: 'someotherkey',
      scrollingFocus: true,
      scrollingActions: {clearsScrolledComponentKey: clearsScrollStub}
    }
  )

  const testbedFocus = createTestbed(
    ExtendedComponentButton,
    {
      shouldFocusOnMount: true
    }
  )

  afterEach(() => {
    scrollSpy.resetHistory()
    setFocusSpy.resetHistory()
    clearsScrollStub.resetHistory()
    componentDidUpdateStub.resetHistory()
  })

  it('calls the original componentDidUpdate', () => {
    testbed.render({})
    testbed.render({scrolledComponentKey: keyForComponent})
    expect(componentDidUpdateStub.called).to.be.true()
  })

  it('scrolls if rendered with a new scrolledComponentKey that matches scrollKey', () => {
    testbed.render({})
    testbed.render({scrolledComponentKey: keyForComponent})
    expect(scrollSpy).to.have.been.calledWith(true)
  })

  it('does not scroll if rendered with a new scrolledComponentKey does not match scrollKey', () => {
    testbed.render({})
    expect(scrollSpy).not.to.have.been.called()
  })

  it('does not re-scroll scrollKey matches but scrolledComponentKey has not changed', () => {
    testbed.render({})
    testbed.render({scrolledComponentKey: keyForComponent})
    testbed.render({scrolledComponentKey: keyForComponent, someUnrelatedVal: 'trigger update'})
    expect(scrollSpy).to.have.been.calledOnce()
  })

  it('calls to clear the scrolled component key', () => {
    testbed.render({})
    testbed.render({scrolledComponentKey: keyForComponent})

    expect(clearsScrollStub).to.have.been.calledOnce()
  })

  it('calls the set focus function', () => {
    testbedFocus.render({})
    expect(setFocusSpy).to.have.been.called()
  })

  it('does not call focus again when the component updates', () => {
    const subject = testbedFocus.mount()
    subject.setProps({ scrolledComponentKey: 'foo' })
    expect(setFocusSpy).to.have.been.calledOnce()
  })

  it('matches the active focus element with the button defined on the makescrollable object', () => {
    const wrapper = testbedFocus.render({})
    expect(document.activeElement).to.equal(wrapper._button)
  })
})
