text: import { mount, shallowMount } from '@vue/test-utils'
  import VueSelect from '../../src/components/Select'
  
  describe('When reduce prop is defined', () => {
    it('can accept an array of objects and pre-selected value (single)', () => {
      const Select = shallowMount(VueSelect, {
        propsData: {
          reduce: (option) => option.value,
          value: 'foo',
          options: [{ label: 'This is Foo', value: 'foo' }],
        },
      })
      expect(Select.vm.selectedValue).toEqual([
        { label: 'This is Foo', value: 'foo' },
      ])
    })
  
    it('can determine if an object is pre-selected', () => {
      const Select = shallowMount(VueSelect, {
        propsData: {
          reduce: (option) => option.id,
          value: 'foo',
          options: [
            {
              id: 'foo',
              label: 'This is Foo',
            },
          ],
        },
      })
  
      expect(
        Select.vm.isOptionSelected({
          id: 'foo',
          label: 'This is Foo',
        })
      ).toEqual(true)
    })
  
    it('can determine if an object is selected after its been chosen', () => {
      const Select = shallowMount(VueSelect, {
        propsData: {
          reduce: (option) => option.id,
          options: [{ id: 'foo', label: 'FooBar' }],
        },
      })
  
      Select.vm.select({ id: 'foo', label: 'FooBar' })
  
      expect(
        Select.vm.isOptionSelected({
          id: 'foo',
          label: 'This is FooBar',
        })
      ).toEqual(true)
    })
  
    it('can accept an array of objects and pre-selected values (multiple)', () => {
      const Select = shallowMount(VueSelect, {
        propsData: {
          multiple: true,
          reduce: (option) => option.value,
          value: ['foo'],
          options: [
            { label: 'This is Foo', value: 'foo' },
            { label: 'This is Bar', value: 'bar' },
          ],
        },
      })
  
      expect(Select.vm.selectedValue).toEqual([
        { label: 'This is Foo', value: 'foo' },
      ])
    })
  
    it('can deselect a pre-selected object', () => {
      const Select = shallowMount(VueSelect, {
        propsData: {
          multiple: true,
          reduce: (option) => option.value,
          options: [
            { label: 'This is Foo', value: 'foo' },
            { label: 'This is Bar', value: 'bar' },
          ],
        },
      })
  
      Select.vm.$data._value = ['foo', 'bar']
  
      Select.vm.deselect('foo')
      expect(Select.vm.selectedValue).toEqual(['bar'])
    })
  
    it('can deselect an option when multiple is false', () => {
      const Select = shallowMount(VueSelect, {
        propsData: {
          reduce: (option) => option.value,
          options: [
            { label: 'This is Foo', value: 'foo' },
            { label: 'This is Bar', value: 'bar' },
          ],
        },
      })
  
      Select.vm.deselect('foo')
      expect(Select.vm.selectedValue).toEqual([])
    })
  
    it('can use v-model syntax for a two way binding to a parent component', async () => {
      const Parent = mount({
        data: () => ({
          reduce: (option) => option.value,
          current: 'foo',
          options: [
            { label: 'This is Foo', value: 'foo' },
            { label: 'This is Bar', value: 'bar' },
            { label: 'This is Baz', value: 'baz' },
          ],
        }),
        components: { 'v-select': VueSelect },
        computed: {
          value: {
            get() {
              return this.current
            },
            set(value) {
              if (value == 'baz') return
              this.current = value
            },
          },
        },
        template: `
          <v-select
            v-model="value"
            :reduce="option => option.value"
            :options="options"
          />
        `,
      })
      const Select = Parent.vm.$children[0]
  
      expect(Select.value).toEqual('foo')
      expect(Select.selectedValue).toEqual([
        { label: 'This is Foo', value: 'foo' },
      ])
  
      Select.select({ label: 'This is Bar', value: 'bar' })
      await Select.$nextTick()
      expect(Parent.vm.value).toEqual('bar')
      expect(Select.selectedValue).toEqual([
        { label: 'This is Bar', value: 'bar' },
      ])
  
      // Parent denies to set baz
      Select.select({ label: 'This is Baz', value: 'baz' })
      await Select.$nextTick()
      expect(Select.selectedValue).toEqual([
        { label: 'This is Bar', value: 'bar' },
      ])
      expect(Parent.vm.value).toEqual('bar')
    })
  
    it('can generate labels using a custom label key', () => {
      const Select = shallowMount(VueSelect, {
        propsData: {
          multiple: true,
          reduce: (option) => option.value,
          value: ['CA'],
          label: 'name',
          options: [
            { value: 'CA', name: 'Canada' },
            { value: 'US', name: 'United States' },
          ],
        },
      })
  
      expect(Select.find('.vs__selected').text()).toContain('Canada')
    })
  
    it('can find the original option within this.options', () => {
      const optionToFind = { id: 1, label: 'Foo' }
      const Select = shallowMount(VueSelect, {
        propsData: {
          reduce: (option) => option.id,
          options: [optionToFind, { id: 2, label: 'Bar' }],
        },
      })
  
      expect(Select.vm.findOptionFromReducedValue(1)).toEqual(optionToFind)
      expect(Select.vm.findOptionFromReducedValue(optionToFind)).toEqual(
        optionToFind
      )
    })
  
    it('can work with falsey values', () => {
      const option = { value: 0, label: 'No' }
      const Select = shallowMount(VueSelect, {
        propsData: {
          reduce: (option) => option.value,
          options: [option, { value: 1, label: 'Yes' }],
          value: 0,
        },
      })
  
      expect(Select.vm.findOptionFromReducedValue(option)).toEqual(option)
      expect(Select.vm.selectedValue).toEqual([option])
    })
  
    it('works with null values', () => {
      const option = { value: null, label: 'No' }
      const Select = shallowMount(VueSelect, {
        propsData: {
          reduce: (option) => option.value,
          options: [option, { value: 1, label: 'Yes' }],
          value: null,
        },
      })
  
      expect(Select.vm.findOptionFromReducedValue(option)).toEqual(option)
      expect(Select.vm.selectedValue).toEqual([option])
    })
  
    describe('And when a reduced option is a nested object', () => {
      it('can determine if an object is pre-selected', () => {
        const nestedOption = { value: { nested: true }, label: 'foo' }
        const Select = shallowMount(VueSelect, {
          propsData: {
            reduce: (option) => option.value,
            value: {
              nested: true,
            },
            options: [nestedOption],
          },
        })
  
        expect(Select.vm.selectedValue).toEqual([nestedOption])
      })
  
      it('can determine if an object is selected after it is chosen', () => {
        const nestedOption = { value: { nested: true }, label: 'foo' }
        const Select = shallowMount(VueSelect, {
          propsData: {
            reduce: (option) => option.value,
            options: [nestedOption],
          },
        })
  
        Select.vm.select(nestedOption)
        expect(Select.vm.isOptionSelected(nestedOption)).toEqual(true)
      })
    })
  
    it('reacts correctly when value property changes', async () => {
      const optionToChangeTo = { id: 1, label: 'Foo' }
      const Select = shallowMount(VueSelect, {
        propsData: {
          value: 2,
          reduce: (option) => option.id,
          options: [optionToChangeTo, { id: 2, label: 'Bar' }],
        },
      })
  
      Select.setProps({ value: optionToChangeTo.id })
      await Select.vm.$nextTick()
  
      expect(Select.vm.selectedValue).toEqual([optionToChangeTo])
    })
  
    describe('Reducing Tags', () => {
      it('tracks values that have been created by the user', async () => {
        const Parent = mount({
          data: () => ({ selected: null, options: [] }),
          template: `
            <v-select
              v-model="selected"
              :options="options"
              taggable
              :reduce="name => name.value"
              :create-option="label => ({ label, value: -1 })"
            />
          `,
          components: { 'v-select': VueSelect },
        })
        const Select = Parent.vm.$children[0]
  
        //  When
        Select.$refs.search.focus()
        await Select.$nextTick()
  
        Select.search = 'hello'
        await Select.$nextTick()
  
        Select.typeAheadSelect()
        await Select.$nextTick()
  
        //  Then
        expect(Select.selectedValue).toEqual([{ label: 'hello', value: -1 }])
        expect(Select.$refs.selectedOptions.textContent.trim()).toEqual('hello')
        expect(Parent.vm.selected).toEqual(-1)
      })
    })
  })
  