From 8d4df42ae7cb01c49fc518298e4b91aed7a66931 Mon Sep 17 00:00:00 2001 From: yshepilov Date: Thu, 21 May 2020 20:27:44 +0200 Subject: [PATCH 1/4] 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 --- docs/api/wrapper/setValue.md | 4 +++ docs/ja/api/wrapper/setValue.md | 4 +++ docs/ru/api/wrapper/setValue.md | 4 +++ docs/zh/api/wrapper/setValue.md | 4 +++ packages/test-utils/src/wrapper.js | 32 ++++++++++--------- .../components/component-with-input.vue | 7 ++++ test/specs/wrapper/setValue.spec.js | 31 ++++++++++++++++++ 7 files changed, 71 insertions(+), 15 deletions(-) diff --git a/docs/api/wrapper/setValue.md b/docs/api/wrapper/setValue.md index 3822d0bf0..f74e0c3dd 100644 --- a/docs/api/wrapper/setValue.md +++ b/docs/api/wrapper/setValue.md @@ -19,6 +19,10 @@ textInput.setValue('some value') const select = wrapper.find('select') select.setValue('option value') + +// requires +const multiselect = wrapper.find('select') +multiselect.setValue(['value1', 'value3']) ``` - **注:** diff --git a/docs/ru/api/wrapper/setValue.md b/docs/ru/api/wrapper/setValue.md index 5c3b0521b..6971ff9ae 100644 --- a/docs/ru/api/wrapper/setValue.md +++ b/docs/ru/api/wrapper/setValue.md @@ -19,6 +19,10 @@ textInput.setValue('some value') const select = wrapper.find('select') select.setValue('option value') + +// требует +const multiselect = wrapper.find('select') +multiselect.setValue(['value1', 'value3']) ``` - **注意:** diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 8ca08a7e0..4272c9043 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -744,27 +744,29 @@ export default class Wrapper implements BaseWrapper { `wrapper.setValue() cannot be called on a ` + `element. Use wrapper.setChecked() instead` ) - } else if ( - tagName === 'INPUT' || - tagName === 'TEXTAREA' || - tagName === 'SELECT' - ) { + } else if (tagName === 'SELECT') { + if (Array.isArray(value)) { + // $FlowIgnore + for (let i = 0; i < this.element.options.length; i++) { + const option = this.element.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() diff --git a/test/resources/components/component-with-input.vue b/test/resources/components/component-with-input.vue index c161ee8c0..bd1f04236 100644 --- a/test/resources/components/component-with-input.vue +++ b/test/resources/components/component-with-input.vue @@ -20,6 +20,11 @@ + {{ lazy }} @@ -52,6 +58,7 @@ export default { textareaVal: undefined, radioVal: undefined, selectVal: undefined, + multiselectVal: [], counter: 0 } }, diff --git a/test/specs/wrapper/setValue.spec.js b/test/specs/wrapper/setValue.spec.js index 1b4cd8234..7fe987555 100644 --- a/test/specs/wrapper/setValue.spec.js +++ b/test/specs/wrapper/setValue.spec.js @@ -65,6 +65,37 @@ describeWithShallowAndMount('setValue', mountingMethod => { expect(wrapper.text()).to.contain('selectB') }) + it('sets element of multiselect value when array', () => { + 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('sets element of multiselect value when array overrides', () => { + 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