describe 'GridFormDatepicker', ->
  React = require 'react'
  GridFormDatepicker = React.createFactory require('../../src/components/grid_form/grid_form_date_picker')
  TestUtils = require 'react-dom/test-utils'
  ReactDOM = require 'react-dom'
  ValidationContext = require '../../src/context_wrapper'

  ###
  
  Note About ValidationContext

  The input validation uses context to gain access to the app level validation methods
  Because context is only present when the component is a child of the application, it is not present in tests
  The ValidationContext component, simply wraps the input component, and adds the validation context methods so they are present in the tests
  
  ###

   
   
  #--------------------------------------------------------------------- Default Props
  it 'Should have default props', ->

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        value: ''
    })

    gridFormInput = wrapper.getInput()
        
    defaultProps = gridFormInput.props
    expect(defaultProps.twentyFourHour).to.equal(no)
    expect(defaultProps.labelColumnClass).to.equal('col-3-12')
    expect(defaultProps.inputColumnClass).to.equal('col-9-12')
    expect(defaultProps.className).to.equal('grid grid-pad')
    expect(defaultProps.fullRow).to.equal(yes)
    expect(defaultProps.enableTime).to.equal(no)
    expect(defaultProps.isFieldRequired).to.equal(no)
    expect(defaultProps.minutes).to.be.an('array')
    expect(defaultProps.AmPm).to.be.an('array')
    expect(defaultProps.isInPopover).to.equal(no)
    expect(defaultProps.disabled).to.equal(no)
    expect(defaultProps.timeColumns).to.equal(2)


  #--------------------------------------------------------------------- Display 
  it 'Should display a form label for the input field if formLabel has value', ->

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        value: ''
        formLabel: 'Test Label'
    })

    label = TestUtils.scryRenderedDOMComponentsWithClass wrapper, 'form-label'
   
    expect(label.length).to.equal(1)

  it 'Should not display a form label for the input field if formLabel has no value', ->
    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        value: ''
    })

    label = TestUtils.scryRenderedDOMComponentsWithClass wrapper, 'form-label'
   
    expect(label.length).to.equal(0)


  it 'Should display a red asterisk next to the form label if formLabel has value and isFieldRequired is true', ->

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        formLabel: 'Test Label'
        isFieldRequired: true
    })
    
    isRequired = TestUtils.scryRenderedDOMComponentsWithClass wrapper, 'form-label is-required'
   
    expect(isRequired.length).to.equal(1)

  it 'Should display single input and not a full row if fullRow is false', ->

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        value: ''
        fullRow: false
    })
    
    fullRow = TestUtils.scryRenderedDOMComponentsWithClass wrapper, 'grid grid-pad'
    singleInputField = TestUtils.scryRenderedDOMComponentsWithClass wrapper, 'col-9-12'
    
    expect(fullRow.length).to.equal(0)
    expect(singleInputField.length).to.equal(1)

  it 'Should display an input field with type equal to text', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        type: 'text'
        value: 'test'
        onChange: onChange
    })

    input = TestUtils.findRenderedDOMComponentWithTag wrapper, 'input'

    inputField = ReactDOM.findDOMNode(input)

    expect(inputField.type).to.equal('text')
  

  it 'Should props.minutes options', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 16:00', 'MM/DD/YYYY HH:mm')
        enableTime: yes
        onChange: onChange
        twentyFourHour: yes
        minutes: [0,5,10,15,20,25,30,35,45,50,55]
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    hourOptions = selectFields[1].getElementsByTagName('option')

    expect(hourOptions.length).to.equal(11)
  

  # 24 hour mode tests ----------------------------------------------------------

  it 'Should display 2 time picker drop downs when enableTime is true and twentyFourHour is true', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment()
        enableTime: yes
        onChange: onChange
        twentyFourHour: yes
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')

    expect(selectFields.length).to.equal(2)
  
  it 'Should display 24 hour options when no min/maxDate is passed', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 16:00', 'MM/DD/YYYY HH:mm')
        enableTime: yes
        onChange: onChange
        twentyFourHour: yes
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    hourOptions = selectFields[0].getElementsByTagName('option')

    expect(hourOptions.length).to.equal(24)

  it 'Should limit the hours displayed based on the minDate and the selected date in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 16:00', 'MM/DD/YYYY HH:mm')
        minDate: moment('10/28/1977 18:00', 'MM/DD/YYYY HH:mm')
        enableTime: yes
        onChange: onChange
        twentyFourHour: yes
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    hourOptions = selectFields[0].getElementsByTagName('option')

    expect(hourOptions.length).to.equal(6)
  

  it 'Should limit the minutes displayed based on the minDate and the selected date in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 16:00', 'MM/DD/YYYY HH:mm')
        minDate: moment('10/28/1977 18:05', 'MM/DD/YYYY HH:mm')
        enableTime: yes
        onChange: onChange
        twentyFourHour: yes
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    minuteOptions = selectFields[1].getElementsByTagName('option')

    expect(minuteOptions.length).to.equal(3)
  

  it 'Should limit the hours displayed based on the maxDate and the selected date in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 03:00', 'MM/DD/YYYY HH:mm')
        maxDate: moment('10/28/1977 04:30', 'MM/DD/YYYY HH:mm')
        enableTime: yes
        onChange: onChange
        twentyFourHour: yes
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    hourOptions = selectFields[0].getElementsByTagName('option')

    expect(hourOptions.length).to.equal(5)
  

  it 'Should limit the minutes displayed based on the maxDate and the selected date in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 04:00', 'MM/DD/YYYY HH:mm')
        maxDate: moment('10/28/1977 04:35', 'MM/DD/YYYY HH:mm')
        enableTime: yes
        onChange: onChange
        twentyFourHour: yes
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    minuteOptions = selectFields[1].getElementsByTagName('option')

    expect(minuteOptions.length).to.equal(3)
  
  
  # NOT 24 hour mode tests ----------------------------------------------------------

  it 'Should display 3 time picker drop downs when enableTime is true', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment()
        enableTime: yes
        onChange: onChange
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')

    expect(selectFields.length).to.equal(3)

  it 'Should display 12 hour options when no min/maxDate when NOT in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 8:00pm', 'MM/DD/YYYY h:mma')
        enableTime: yes
        onChange: onChange
        twentyFourHour: no
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    hourOptions = selectFields[0].getElementsByTagName('option')

    expect(hourOptions.length).to.equal(12)

  it 'Should limit the hours displayed based on the minDate and the selected date NOT in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 8:00pm', 'MM/DD/YYYY h:mma')
        minDate: moment('10/28/1977 6:00pm', 'MM/DD/YYYY h:mma')
        enableTime: yes
        onChange: onChange
        twentyFourHour: no
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    hourOptions = selectFields[0].getElementsByTagName('option')

    expect(hourOptions.length).to.equal(6)
  

  it 'Should limit the minutes displayed based on the minDate and the selected date NOT in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 6:00pm', 'MM/DD/YYYY h:mma')
        minDate: moment('10/28/1977 6:30pm', 'MM/DD/YYYY h:mma')
        enableTime: yes
        onChange: onChange
        twentyFourHour: no
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    minuteOptions = selectFields[1].getElementsByTagName('option')

    expect(minuteOptions.length).to.equal(2)
  

  it 'Should limit the hours displayed based on the maxDate and the selected date NOT in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 5:00am', 'MM/DD/YYYY h:mma')
        maxDate: moment('10/28/1977 6:00am', 'MM/DD/YYYY h:mma')
        enableTime: yes
        onChange: onChange
        twentyFourHour: no
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    hourOptions = selectFields[0].getElementsByTagName('option')

    expect(hourOptions.length).to.equal(7)
  

  it 'Should limit the minutes displayed based on the maxDate and the selected date NOT in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 8:00pm', 'MM/DD/YYYY h:mma')
        maxDate: moment('10/28/1977 8:15pm', 'MM/DD/YYYY h:mma')
        enableTime: yes
        onChange: onChange
        twentyFourHour: no
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    minuteOptions = selectFields[1].getElementsByTagName('option')

    expect(minuteOptions.length).to.equal(2)
  

  it 'Should limit the am/pm options displayed based on the minDate and the selected date NOT in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 5:00am', 'MM/DD/YYYY h:mma')
        minDate: moment('10/28/1977 8:15pm', 'MM/DD/YYYY h:mma')
        enableTime: yes
        onChange: onChange
        twentyFourHour: no
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    minuteOptions = selectFields[2].getElementsByTagName('option')

    expect(minuteOptions.length).to.equal(1)
  

  it 'Should limit the am/pm options displayed based on the maxDate and the selected date NOT in 24 hour mode', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 5:00am', 'MM/DD/YYYY h:mma')
        maxDate: moment('10/28/1977 8:15am', 'MM/DD/YYYY h:mma')
        enableTime: yes
        onChange: onChange
        twentyFourHour: no
    })

    node = wrapper.getInputEl()
    
    selectFields = node.getElementsByTagName('select')
    minuteOptions = selectFields[2].getElementsByTagName('option')

    expect(minuteOptions.length).to.equal(1)
  

  it 'Should call onChange when the passed selected date is outside the min/max range', ->
    onChange = sinon.spy()

    wrapper = TestUtils.renderIntoDocument(ValidationContext {
      factory: GridFormDatepicker
      childProps: 
        selected: moment('10/28/1977 16:00', 'MM/DD/YYYY HH:mm')
        minDate: moment('10/28/1977 18:05', 'MM/DD/YYYY HH:mm')
        enableTime: yes
        onChange: onChange
        twentyFourHour: yes
    })

    expect(onChange.called).to.equal(yes)
