Skip to content

Commit

Permalink
allow array for multiselect .setValue() method (#1554)
Browse files Browse the repository at this point in the history
* feat(wrapper.setvalue): allow array for multiselect .setValue() method

enables Wrapper.setValue() method to accept array value for select elements (requires select to have
an attribute 'multiple' or 'multiple="true"')

fix #1505

* fix "missing property" error

* Update test/specs/wrapper/setValue.spec.js

Co-authored-by: Adrià Fontcuberta <afontcu@gmail.com>

* Update test/specs/wrapper/setValue.spec.js

Co-authored-by: Adrià Fontcuberta <afontcu@gmail.com>

Co-authored-by: Adrià Fontcuberta <afontcu@gmail.com>
  • Loading branch information
bugy and afontcu committed May 22, 2020
1 parent e5b0f00 commit 4d4a5f3
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 15 deletions.
4 changes: 4 additions & 0 deletions docs/api/wrapper/setValue.md
Expand Up @@ -19,6 +19,10 @@ textInput.setValue('some value')

const select = wrapper.find('select')
select.setValue('option value')

// requires <select multiple>
const multiselect = wrapper.find('select')
multiselect.setValue(['value1', 'value3'])
```

- **Note:**
Expand Down
4 changes: 4 additions & 0 deletions docs/ja/api/wrapper/setValue.md
Expand Up @@ -19,6 +19,10 @@ textInput.setValue('some value')

const select = wrapper.find('select')
select.setValue('option value')

// requires <select multiple>
const multiselect = wrapper.find('select')
multiselect.setValue(['value1', 'value3'])
```

- **注:**
Expand Down
4 changes: 4 additions & 0 deletions docs/ru/api/wrapper/setValue.md
Expand Up @@ -19,6 +19,10 @@ textInput.setValue('some value')

const select = wrapper.find('select')
select.setValue('option value')

// требует <select multiple>
const multiselect = wrapper.find('select')
multiselect.setValue(['value1', 'value3'])
```

- **Примечание:**
Expand Down
4 changes: 4 additions & 0 deletions docs/zh/api/wrapper/setValue.md
Expand Up @@ -19,6 +19,10 @@ textInput.setValue('some value')

const select = wrapper.find('select')
select.setValue('option value')

// requires <select multiple>
const multiselect = wrapper.find('select')
multiselect.setValue(['value1', 'value3'])
```

- **注意:**
Expand Down
33 changes: 18 additions & 15 deletions packages/test-utils/src/wrapper.js
Expand Up @@ -744,27 +744,30 @@ export default class Wrapper implements BaseWrapper {
`wrapper.setValue() cannot be called on a <input type="radio" /> ` +
`element. Use wrapper.setChecked() instead`
)
} else if (
tagName === 'INPUT' ||
tagName === 'TEXTAREA' ||
tagName === 'SELECT'
) {
} else if (tagName === 'SELECT') {
if (Array.isArray(value)) {
// $FlowIgnore
const options = this.element.options
for (let i = 0; i < options.length; i++) {
const option = options[i]
option.selected = value.indexOf(option.value) >= 0
}
} else {
// $FlowIgnore
this.element.value = value
}

this.trigger('change')
return nextTick()
} else if (tagName === 'INPUT' || tagName === 'TEXTAREA') {
// $FlowIgnore
this.element.value = value

if (tagName === 'SELECT') {
this.trigger('change')
} else {
this.trigger('input')
}
this.trigger('input')

// for v-model.lazy, we need to trigger a change event, too.
// $FlowIgnore
if (
(tagName === 'INPUT' || tagName === 'TEXTAREA') &&
this.element._vModifiers &&
this.element._vModifiers.lazy
) {
if (this.element._vModifiers && this.element._vModifiers.lazy) {
this.trigger('change')
}
return nextTick()
Expand Down
7 changes: 7 additions & 0 deletions test/resources/components/component-with-input.vue
Expand Up @@ -20,6 +20,11 @@
<option value="selectB"></option>
<option value="selectC"></option>
</select>
<select v-model="multiselectVal" class="multiselect" multiple>
<option value="selectA"></option>
<option value="selectB"></option>
<option value="selectC"></option>
</select>
<select v-model="selectVal" class="with-optgroups">
<optgroup label="Group1">
<option value="selectA"></option>
Expand All @@ -35,6 +40,7 @@
<span class="counter">{{ counter }}</span>
{{ textVal }}
{{ selectVal }}
{{ JSON.stringify(multiselectVal) }}
{{ radioVal }}
<input id="lazy" type="text" v-model.lazy="lazy" />
{{ lazy }}
Expand All @@ -52,6 +58,7 @@ export default {
textareaVal: undefined,
radioVal: undefined,
selectVal: undefined,
multiselectVal: [],
counter: 0
}
},
Expand Down
31 changes: 31 additions & 0 deletions test/specs/wrapper/setValue.spec.js
Expand Up @@ -65,6 +65,37 @@ describeWithShallowAndMount('setValue', mountingMethod => {
expect(wrapper.text()).to.contain('selectB')
})

it('sets element of multiselect value', () => {
const wrapper = mountingMethod(ComponentWithInput)
const select = wrapper.find('select.multiselect')
select.setValue(['selectA', 'selectC'])

const selectedOptions = Array.from(select.element.selectedOptions).map(
o => o.value
)
expect(selectedOptions).to.deep.equal(['selectA', 'selectC'])
})

it('overrides elements of multiselect', () => {
const wrapper = mountingMethod(ComponentWithInput)
const select = wrapper.find('select.multiselect')
select.setValue(['selectA', 'selectC'])
select.setValue(['selectB'])

const selectedOptions = Array.from(select.element.selectedOptions).map(
o => o.value
)
expect(selectedOptions).to.deep.equal(['selectB'])
})

it('updates dom with multiselect v-model when array', async () => {
const wrapper = mountingMethod(ComponentWithInput)
const select = wrapper.find('select.multiselect')
await select.setValue(['selectA', 'selectC'])

expect(wrapper.text()).to.contain('["selectA","selectC"]')
})

it('throws error if element is option', () => {
const message =
'wrapper.setValue() cannot be called on an <option> element. Use wrapper.setSelected() instead'
Expand Down

0 comments on commit 4d4a5f3

Please sign in to comment.