import Vue from 'vue'

describe('Directive v-model radio', () => {
  it('should work', done => {
    const vm = new Vue({
      data: {
        test: '1'
      },
      template: `
        <div>
          <input type="radio" value="1" v-model="test" name="test">
          <input type="radio" value="2" v-model="test" name="test">
        </div>
      `
    }).$mount()
    document.body.appendChild(vm.$el)
    expect(vm.$el.children[0].checked).toBe(true)
    expect(vm.$el.children[1].checked).toBe(false)
    vm.test = '2'
    waitForUpdate(() => {
      expect(vm.$el.children[0].checked).toBe(false)
      expect(vm.$el.children[1].checked).toBe(true)
      vm.$el.children[0].click()
      expect(vm.$el.children[0].checked).toBe(true)
      expect(vm.$el.children[1].checked).toBe(false)
      expect(vm.test).toBe('1')
    })
      .then(() => {
        document.body.removeChild(vm.$el)
      })
      .then(done)
  })

  it('should respect value bindings', done => {
    const vm = new Vue({
      data: {
        test: 1
      },
      template: `
        <div>
          <input type="radio" :value="1" v-model="test" name="test">
          <input type="radio" :value="2" v-model="test" name="test">
        </div>
      `
    }).$mount()
    document.body.appendChild(vm.$el)
    expect(vm.$el.children[0].checked).toBe(true)
    expect(vm.$el.children[1].checked).toBe(false)
    vm.test = 2
    waitForUpdate(() => {
      expect(vm.$el.children[0].checked).toBe(false)
      expect(vm.$el.children[1].checked).toBe(true)
      vm.$el.children[0].click()
      expect(vm.$el.children[0].checked).toBe(true)
      expect(vm.$el.children[1].checked).toBe(false)
      expect(vm.test).toBe(1)
    })
      .then(() => {
        document.body.removeChild(vm.$el)
      })
      .then(done)
  })

  it('should respect value bindings (object loose equal)', done => {
    const vm = new Vue({
      data: {
        test: { a: 1 }
      },
      template: `
        <div>
          <input type="radio" :value="{ a: 1 }" v-model="test" name="test">
          <input type="radio" :value="{ a: 2 }" v-model="test" name="test">
        </div>
      `
    }).$mount()
    document.body.appendChild(vm.$el)
    expect(vm.$el.children[0].checked).toBe(true)
    expect(vm.$el.children[1].checked).toBe(false)
    vm.test = { a: 2 }
    waitForUpdate(() => {
      expect(vm.$el.children[0].checked).toBe(false)
      expect(vm.$el.children[1].checked).toBe(true)
      vm.$el.children[0].click()
      expect(vm.$el.children[0].checked).toBe(true)
      expect(vm.$el.children[1].checked).toBe(false)
      expect(vm.test).toEqual({ a: 1 })
    })
      .then(() => {
        document.body.removeChild(vm.$el)
      })
      .then(done)
  })

  it('multiple radios ', done => {
    const spy = vi.fn()
    const vm = new Vue({
      data: {
        selections: ['a', '1'],
        radioList: [
          {
            name: 'questionA',
            data: ['a', 'b', 'c']
          },
          {
            name: 'questionB',
            data: ['1', '2']
          }
        ]
      },
      watch: {
        selections: spy
      },
      template:
        '<div>' +
        '<div v-for="(radioGroup, idx) in radioList">' +
        '<div>' +
        '<span v-for="(item, index) in radioGroup.data">' +
        '<input :name="radioGroup.name" type="radio" :value="item" v-model="selections[idx]" :id="idx"/>' +
        '<label>{{item}}</label>' +
        '</span>' +
        '</div>' +
        '</div>' +
        '</div>'
    }).$mount()
    document.body.appendChild(vm.$el)
    const inputs = vm.$el.getElementsByTagName('input')
    inputs[1].click()
    waitForUpdate(() => {
      expect(vm.selections).toEqual(['b', '1'])
      expect(spy).toHaveBeenCalled()
    }).then(done)
  })

  it('.number modifier', () => {
    const vm = new Vue({
      data: {
        test: 1
      },
      template: `
        <div>
          <input type="radio" value="1" v-model="test" name="test">
          <input type="radio" value="2" v-model.number="test" name="test">
        </div>
      `
    }).$mount()
    document.body.appendChild(vm.$el)
    expect(vm.$el.children[0].checked).toBe(true)
    expect(vm.$el.children[1].checked).toBe(false)
    vm.$el.children[1].click()
    expect(vm.$el.children[0].checked).toBe(false)
    expect(vm.$el.children[1].checked).toBe(true)
    expect(vm.test).toBe(2)
  })

  it('should respect different primitive type value', done => {
    const vm = new Vue({
      data: {
        test: 1
      },
      template:
        '<div>' +
        '<input type="radio" value="" v-model="test" name="test">' +
        '<input type="radio" value="0" v-model="test" name="test">' +
        '<input type="radio" value="1" v-model="test" name="test">' +
        '<input type="radio" value="false" v-model="test" name="test">' +
        '<input type="radio" value="true" v-model="test" name="test">' +
        '</div>'
    }).$mount()
    const radioboxInput = vm.$el.children
    expect(radioboxInput[0].checked).toBe(false)
    expect(radioboxInput[1].checked).toBe(false)
    expect(radioboxInput[2].checked).toBe(true)
    expect(radioboxInput[3].checked).toBe(false)
    expect(radioboxInput[4].checked).toBe(false)
    vm.test = 0
    waitForUpdate(() => {
      expect(radioboxInput[0].checked).toBe(false)
      expect(radioboxInput[1].checked).toBe(true)
      expect(radioboxInput[2].checked).toBe(false)
      expect(radioboxInput[3].checked).toBe(false)
      expect(radioboxInput[4].checked).toBe(false)
      vm.test = ''
    })
      .then(() => {
        expect(radioboxInput[0].checked).toBe(true)
        expect(radioboxInput[1].checked).toBe(false)
        expect(radioboxInput[2].checked).toBe(false)
        expect(radioboxInput[3].checked).toBe(false)
        expect(radioboxInput[4].checked).toBe(false)
        vm.test = false
      })
      .then(() => {
        expect(radioboxInput[0].checked).toBe(false)
        expect(radioboxInput[1].checked).toBe(false)
        expect(radioboxInput[2].checked).toBe(false)
        expect(radioboxInput[3].checked).toBe(true)
        expect(radioboxInput[4].checked).toBe(false)
        vm.test = true
      })
      .then(() => {
        expect(radioboxInput[0].checked).toBe(false)
        expect(radioboxInput[1].checked).toBe(false)
        expect(radioboxInput[2].checked).toBe(false)
        expect(radioboxInput[3].checked).toBe(false)
        expect(radioboxInput[4].checked).toBe(true)
      })
      .then(done)
  })

  // #4521
  it('should work with click event', done => {
    const vm = new Vue({
      data: {
        num: 1,
        checked: 1
      },
      template:
        '<div @click="add">' +
        'click {{ num }}<input name="test" type="radio" value="1" v-model="checked"/>' +
        '<input name="test" type="radio" value="2" v-model="checked"/>' +
        '</div>',
      methods: {
        add: function () {
          this.num++
        }
      }
    }).$mount()
    document.body.appendChild(vm.$el)
    const radios = vm.$el.getElementsByTagName('input')
    radios[0].click()
    waitForUpdate(() => {
      expect(radios[0].checked).toBe(true)
      expect(radios[1].checked).toBe(false)
      expect(vm.num).toBe(2)
      radios[0].click()
    })
      .then(() => {
        expect(radios[0].checked).toBe(true)
        expect(radios[1].checked).toBe(false)
        expect(vm.num).toBe(3)
        radios[1].click()
      })
      .then(() => {
        expect(radios[0].checked).toBe(false)
        expect(radios[1].checked).toBe(true)
        expect(vm.num).toBe(4)
      })
      .then(done)
  })

  it('should get updated with model when in focus', done => {
    const vm = new Vue({
      data: {
        a: '2'
      },
      template: '<input type="radio" value="1" v-model="a"/>'
    }).$mount()
    document.body.appendChild(vm.$el)
    vm.$el.click()
    waitForUpdate(() => {
      expect(vm.$el.checked).toBe(true)
      vm.a = 2
    })
      .then(() => {
        expect(vm.$el.checked).toBe(false)
      })
      .then(done)
  })
})