2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-19 09:50:33 +03:00
- change currentSelection to mutableValue
- change currentOptions to mutableOptions
- change showLoading to mutableLoading
- add default onChange function that emits an input event
	- allows the use of v-model syntax on the component
- since spies on props throw warnings because they are now immutable, refactor tests so spies aren't required

todo:
- update docs
- 1 failing test from inject-loader issue
This commit is contained in:
Jeff Sagal
2016-12-20 10:53:49 -08:00
parent 4a7614e368
commit f5e3e25dc0
7 changed files with 199 additions and 143 deletions
+2 -1
View File
@@ -3,4 +3,5 @@ node_modules
npm-debug.log npm-debug.log
.idea .idea
test/unit/coverage test/unit/coverage
.coveralls.yml .coveralls.yml
.flowconfig
+2 -2
View File
@@ -19,8 +19,8 @@ module.exports = {
'src': path.resolve(__dirname, '../src'), 'src': path.resolve(__dirname, '../src'),
'assets': path.resolve(__dirname, '../docs/assets'), 'assets': path.resolve(__dirname, '../docs/assets'),
'mixins': path.resolve(__dirname, '../src/mixins'), 'mixins': path.resolve(__dirname, '../src/mixins'),
'components': path.resolve(__dirname, '../docs/components'), 'components': path.resolve(__dirname, '../src/components'),
'vue$': 'vue/dist/vue.js' 'vue$': 'vue/dist/vue.common.js',
} }
}, },
resolveLoader: { resolveLoader: {
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "vue-select", "name": "vue-select",
"version": "1.3.3", "version": "2.0.0-alpha",
"description": "A native Vue.js component that provides similar functionality to Select2 without the overhead of jQuery.", "description": "A native Vue.js component that provides similar functionality to Select2 without the overhead of jQuery.",
"author": "Jeff Sagal <sagalbot@gmail.com>", "author": "Jeff Sagal <sagalbot@gmail.com>",
"private": false, "private": false,
@@ -62,7 +62,7 @@
"vue": "^2.0.3", "vue": "^2.0.3",
"vue-hot-reload-api": "^1.2.0", "vue-hot-reload-api": "^1.2.0",
"vue-html-loader": "^1.2.3", "vue-html-loader": "^1.2.3",
"vue-loader": "^9.6.0", "vue-loader": "^9.9.5",
"vue-resource": "^1.0.3", "vue-resource": "^1.0.3",
"vue-style-loader": "^1.0.0", "vue-style-loader": "^1.0.0",
"vuex": "^0.6.3", "vuex": "^0.6.3",
+96 -57
View File
@@ -202,7 +202,7 @@
<i ref="openIndicator" role="presentation" class="open-indicator"></i> <i ref="openIndicator" role="presentation" class="open-indicator"></i>
<slot name="spinner"> <slot name="spinner">
<div class="spinner" v-show="showLoading">Loading...</div> <div class="spinner" v-show="mutableLoading">Loading...</div>
</slot> </slot>
</div> </div>
@@ -237,7 +237,7 @@
/** /**
* Contains the currently selected value. Very similar to a * Contains the currently selected value. Very similar to a
* `value` attribute on an <input>. You can listen for changes * `value` attribute on an <input>. You can listen for changes
* using 'change' event using v-on * using 'change' event using v-on
* @type {Object||String||null} * @type {Object||String||null}
*/ */
value: { value: {
@@ -349,8 +349,12 @@
* @type {Function} * @type {Function}
* @default {null} * @default {null}
*/ */
onChange: Function, onChange: {
type: Function,
default: function(val) {
this.$emit('input', val)
}
},
/** /**
* Enable/disable creating options from searchInput. * Enable/disable creating options from searchInput.
@@ -378,7 +382,7 @@
createOption: { createOption: {
type: Function, type: Function,
default: function (newOption) { default: function (newOption) {
if (typeof this.currentOptions[0] === 'object') { if (typeof this.mutableOptions[0] === 'object') {
return {[this.label]: newOption} return {[this.label]: newOption}
} }
return newOption return newOption
@@ -399,45 +403,80 @@
return { return {
search: '', search: '',
open: false, open: false,
currentSelection: null, mutableValue: null,
currentOptions: [], mutableOptions: [],
showLoading: false mutableLoading: false
} }
}, },
watch: { watch: {
value(val, old) { /**
this.currentSelection = val * When the value prop changes, update
* the internal mutableValue.
* @param {mixed} val
* @return {void}
*/
value(val) {
this.mutableValue = val
}, },
currentSelection(val, old) {
/**
* Maybe run the onChange callback.
* @param {string|object} val
* @param {string|object} old
* @return {void}
*/
mutableValue(val, old) {
if (this.multiple) { if (this.multiple) {
this.onChange ? this.onChange(val) : null this.onChange ? this.onChange(val) : null
this.$emit('change', val)
} else { } else {
if(val !== old) { this.onChange && val !== old ? this.onChange(val) : null
this.onChange? this.onChange(val) : null
this.$emit('change', val)
}
} }
}, },
/**
* When options change, update
* the internal mutableOptions.
* @param {array} val
* @return {void}
*/
options(val) { options(val) {
this.currentOptions = val this.mutableOptions = val
}, },
currentOptions() {
/**
* Maybe reset the mutableValue
* when mutableOptions change.
* @return {[type]} [description]
*/
mutableOptions() {
if (!this.taggable && this.resetOnOptionsChange) { if (!this.taggable && this.resetOnOptionsChange) {
this.currentSelection = this.multiple ? [] : null this.mutableValue = this.multiple ? [] : null
} }
}, },
multiple(val) {
this.currentSelection = val ? [] : null /**
* Always reset the mutableValue when
* the multiple prop changes.
* @param {Boolean} val
* @return {void}
*/
multiple(val) {
this.mutableValue = val ? [] : null
} }
}, },
created() {
this.mutableValue = this.value
this.mutableOptions = this.options.slice(0)
this.mutableLoading = this.loading
},
methods: { methods: {
/** /**
* Select a given option. * Select a given option.
* @param {Object||String} option * @param {Object|String} option
* @return {void} * @return {void}
*/ */
select(option) { select(option) {
@@ -448,19 +487,18 @@
option = this.createOption(option) option = this.createOption(option)
if (this.pushTags) { if (this.pushTags) {
console.log("adding " + option +" to "+ this.currentOptions) this.mutableOptions.push(option)
this.currentOptions.push(option)
} }
} }
if (this.multiple) { if (this.multiple) {
if (!this.currentSelection) { if (!this.mutableValue) {
this.currentSelection = [option] this.mutableValue = [option]
} else { } else {
this.currentSelection.push(option) this.mutableValue.push(option)
} }
} else { } else {
this.currentSelection = option this.mutableValue = option
} }
} }
@@ -469,27 +507,27 @@
/** /**
* De-select a given option. * De-select a given option.
* @param {Object||String} option * @param {Object|String} option
* @return {void} * @return {void}
*/ */
deselect(option) { deselect(option) {
if (this.multiple) { if (this.multiple) {
let ref = -1 let ref = -1
this.currentSelection.forEach((val) => { this.mutableValue.forEach((val) => {
if (val === option || typeof val === 'object' && val[this.label] === option[this.label]) { if (val === option || typeof val === 'object' && val[this.label] === option[this.label]) {
ref = val ref = val
} }
}) })
var index = this.currentSelection.indexOf(ref) var index = this.mutableValue.indexOf(ref)
this.currentSelection.splice(index, 1) this.mutableValue.splice(index, 1)
} else { } else {
this.currentSelection = null this.mutableValue = null
} }
}, },
/** /**
* Called from this.select after each selection. * Called from this.select after each selection.
* @param {Object||String} option * @param {Object|String} option
* @return {void} * @return {void}
*/ */
onAfterSelect(option) { onAfterSelect(option) {
@@ -521,13 +559,13 @@
/** /**
* Check if the given option is currently selected. * Check if the given option is currently selected.
* @param {Object||String} option * @param {Object|String} option
* @return {Boolean} True when selected || False otherwise * @return {Boolean} True when selected | False otherwise
*/ */
isOptionSelected(option) { isOptionSelected(option) {
if (this.multiple && this.currentSelection) { if (this.multiple && this.mutableValue) {
let selected = false let selected = false
this.currentSelection.forEach(opt => { this.mutableValue.forEach(opt => {
if (typeof opt === 'object' && opt[this.label] === option[this.label]) { if (typeof opt === 'object' && opt[this.label] === option[this.label]) {
selected = true selected = true
} else if (opt === option) { } else if (opt === option) {
@@ -537,7 +575,7 @@
return selected return selected
} }
return this.currentSelection === option return this.mutableValue === option
}, },
/** /**
@@ -559,14 +597,14 @@
* @return {this.value} * @return {this.value}
*/ */
maybeDeleteValue() { maybeDeleteValue() {
if (!this.$refs.search.value.length && this.currentSelection) { if (!this.$refs.search.value.length && this.mutableValue) {
return this.multiple ? this.currentSelection.pop() : this.currentSelection = null return this.multiple ? this.mutableValue.pop() : this.mutableValue = null
} }
}, },
/** /**
* Determine if an option exists * Determine if an option exists
* within this.currentOptions array. * within this.mutableOptions array.
* *
* @param {Object || String} option * @param {Object || String} option
* @return {boolean} * @return {boolean}
@@ -574,7 +612,7 @@
optionExists(option) { optionExists(option) {
let exists = false let exists = false
this.currentOptions.forEach(opt => { this.mutableOptions.forEach(opt => {
if (typeof opt === 'object' && opt[this.label] === option) { if (typeof opt === 'object' && opt[this.label] === option) {
exists = true exists = true
} else if (opt === option) { } else if (opt === option) {
@@ -596,7 +634,7 @@
return { return {
open: this.open, open: this.open,
searchable: this.searchable, searchable: this.searchable,
loading: this.showLoading loading: this.mutableLoading
} }
}, },
@@ -620,7 +658,13 @@
* @return {array} * @return {array}
*/ */
filteredOptions() { filteredOptions() {
let options = this.$options.filters.filterBy?this.$options.filters.filterBy(this.currentOptions, this.search):this.currentOptions
let options = this.mutableOptions.filter((option) => {
if( typeof option === 'object' ) {
return option[this.label].indexOf(this.search) > -1
}
return option.indexOf(this.search) > -1
})
if (this.taggable && this.search.length && !this.optionExists(this.search)) { if (this.taggable && this.search.length && !this.optionExists(this.search)) {
options.unshift(this.search) options.unshift(this.search)
} }
@@ -632,11 +676,11 @@
* @return {Boolean} * @return {Boolean}
*/ */
isValueEmpty() { isValueEmpty() {
if (this.currentSelection) { if (this.mutableValue) {
if (typeof this.currentSelection === 'object') { if (typeof this.mutableValue === 'object') {
return !Object.keys(this.currentSelection).length return !Object.keys(this.mutableValue).length
} }
return !this.currentSelection.length return !this.mutableValue.length
} }
return true; return true;
@@ -648,19 +692,14 @@
*/ */
valueAsArray() { valueAsArray() {
if (this.multiple) { if (this.multiple) {
return this.currentSelection return this.mutableValue
} else if (this.currentSelection) { } else if (this.mutableValue) {
return [this.currentSelection] return [this.mutableValue]
} }
return [] return []
} }
}, },
created: function() {
this.currentSelection = this.value
this.currentOptions = this.options.slice(0)
this.showLoading = this.loading
}
} }
</script> </script>
+8 -2
View File
@@ -1,5 +1,6 @@
import Vue from 'vue' import Vue from 'vue'
import vSelect from '../src/components/Select.vue' import vSelect from './components/Select.vue'
import countries from '../old_docs/data/advanced.js'
Vue.component('v-select', vSelect) Vue.component('v-select', vSelect)
@@ -7,5 +8,10 @@ Vue.config.devtools = true
/* eslint-disable no-new */ /* eslint-disable no-new */
new Vue({ new Vue({
el: 'body' el: '#app',
data: {
placeholder: "placeholder",
value: null,
options: countries
}
}) })
+1 -1
View File
@@ -64,4 +64,4 @@ module.exports = {
return this.showLoading = toggle return this.showLoading = toggle
} }
} }
} }
+88 -78
View File
@@ -64,11 +64,11 @@ describe('Select.vue', () => {
template: '<div><v-select :options="options" :value="value"></v-select></div>', template: '<div><v-select :options="options" :value="value"></v-select></div>',
components: {vSelect}, components: {vSelect},
data: { data: {
value: ['one'], value: 'one',
options: ['one', 'two', 'three'] options: ['one', 'two', 'three']
} }
}).$mount() }).$mount()
expect(vm.$children[0].currentSelection).toEqual(vm.value) expect(vm.$children[0].mutableValue).toEqual(vm.value)
}) })
it('can accept an array of objects and pre-selected value (single)', () => { it('can accept an array of objects and pre-selected value (single)', () => {
@@ -80,7 +80,7 @@ describe('Select.vue', () => {
options: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}] options: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}]
} }
}).$mount() }).$mount()
expect(vm.$children[0].currentSelection).toEqual(vm.value) expect(vm.$children[0].mutableValue).toEqual(vm.value)
}) })
it('can accept an array of objects and pre-selected values (multiple)', () => { it('can accept an array of objects and pre-selected values (multiple)', () => {
@@ -92,7 +92,7 @@ describe('Select.vue', () => {
options: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}] options: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}]
} }
}).$mount() }).$mount()
expect(vm.$children[0].currentSelection).toEqual(vm.value) expect(vm.$children[0].mutableValue).toEqual(vm.value)
}) })
it('can deselect a pre-selected object', () => { it('can deselect a pre-selected object', () => {
@@ -104,7 +104,7 @@ describe('Select.vue', () => {
} }
}).$mount() }).$mount()
vm.$children[0].select({label: 'This is Foo', value: 'foo'}) vm.$children[0].select({label: 'This is Foo', value: 'foo'})
expect(vm.$children[0].currentSelection.length).toEqual(1) expect(vm.$children[0].mutableValue.length).toEqual(1)
}) })
it('can deselect a pre-selected string', () => { it('can deselect a pre-selected string', () => {
@@ -116,7 +116,7 @@ describe('Select.vue', () => {
} }
}).$mount() }).$mount()
vm.$children[0].select('foo') vm.$children[0].select('foo')
expect(vm.$children[0].currentSelection.length).toEqual(1) expect(vm.$children[0].mutableValue.length).toEqual(1)
}) })
it('can determine if the value prop is empty', () => { it('can determine if the value prop is empty', () => {
@@ -164,10 +164,10 @@ describe('Select.vue', () => {
vm.multiple = false vm.multiple = false
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual(null) expect(vm.$children[0].mutableValue).toEqual(null)
vm.multiple = true vm.multiple = true
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual([]) expect(vm.$children[0].mutableValue).toEqual([])
done() done()
}) })
}) })
@@ -175,20 +175,20 @@ describe('Select.vue', () => {
it('can retain values present in a new array of options', () => { it('can retain values present in a new array of options', () => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select :options="options" :value.sync="value"></v-select></div>', template: '<div><v-select :options="options" v-model="value"></v-select></div>',
components: {vSelect}, components: {vSelect},
data: { data: {
value: ['one'], value: ['one'],
options: ['one', 'two', 'three'] options: ['one', 'two', 'three']
} }
}).$mount() }).$mount()
vm.$children[0].options = ['one', 'five', 'six'] vm.options = ['one', 'five', 'six']
expect(vm.$children[0].currentSelection).toEqual(['one']) expect(vm.$children[0].mutableValue).toEqual(['one'])
}) })
it('can determine if an object is already selected', () => { it('can determine if an object is already selected', () => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select :options="options" multiple :value.sync="value"></v-select></div>', template: '<div><v-select :options="options" multiple v-model="value"></v-select></div>',
components: {vSelect}, components: {vSelect},
data: { data: {
value: [{label: 'one'}], value: [{label: 'one'}],
@@ -199,54 +199,57 @@ describe('Select.vue', () => {
expect(vm.$children[0].isOptionSelected({label: 'one'})).toEqual(true) expect(vm.$children[0].isOptionSelected({label: 'one'})).toEqual(true)
}) })
it('can use v-model syntax for a two way binding to a parent component', (done) => {
const vm = new Vue({
template: '<div><v-select :options="options" v-model="value"></v-select></div>',
components: {vSelect},
data: {
value: 'foo',
options: ['foo','bar','baz']
}
}).$mount()
expect(vm.$children[0].value).toEqual('foo')
expect(vm.$children[0].mutableValue).toEqual('foo')
vm.$children[0].mutableValue = 'bar'
Vue.nextTick(() => {
expect(vm.value).toEqual('bar')
done()
})
})
describe('change Event', () => { describe('change Event', () => {
it('can run a callback when the selection changes', (done) => { it('will trigger the input event when the selection changes', (done) => {
const vm = new Vue({ const vm = new Vue({
template: `<div><v-select :value="['foo']" :options="['foo','bar','baz']" v-on:change="cb"></v-select></div>`, template: `<div><v-select ref="select" :value="['foo']" :options="['foo','bar','baz']" v-on:input="foo = arguments[0]"></v-select></div>`,
components: {vSelect}, data: {
methods: { foo: ''
cb(val) {
console.log("Value Changed to "+val)
}
} }
}).$mount() }).$mount()
spyOn(vm, 'cb') vm.$refs.select.select('bar')
vm.$children[0].select('bar')
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.cb).toHaveBeenCalledWith('bar') expect(vm.foo).toEqual('bar')
vm.$children[0].select('baz') done()
Vue.nextTick(() => {
expect(vm.cb).toHaveBeenCalledWith('baz')
done()
})
}) })
}) })
it('should run change when multiple is true and the value changes', (done) => { it('should run change when multiple is true and the value changes', (done) => {
const vm = new Vue({ const vm = new Vue({
template: `<div><v-select ref="select" :value="['foo']" :options="['foo','bar','baz']" multiple v-on:change="cb"></v-select></div>`, template: `<div><v-select ref="select" :value="['foo']" :options="['foo','bar','baz']" multiple v-on:input="foo = arguments[0]"></v-select></div>`,
methods: { data: {
cb(val) { foo: ''
}
} }
}).$mount() }).$mount()
spyOn(vm, 'cb') vm.$refs.select.select('bar')
vm.$children[0].select('bar')
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.cb).toHaveBeenCalledWith(['foo','bar']) expect(vm.foo).toEqual(['foo','bar'])
vm.$children[0].select('baz') done()
Vue.nextTick(() => {
expect(vm.cb).toHaveBeenCalledWith(['foo','bar','baz'])
done()
})
}) })
}) })
@@ -487,12 +490,14 @@ describe('Select.vue', () => {
return {top: 0, bottom: 1} return {top: 0, bottom: 1}
} }
}) })
let mock = Mock({
'../mixins/pointerScroll': {methods}
})
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select :options="[\'one\', \'two\', \'three\']"></v-select></div>', template: `<div><v-select :options="['one', 'two', 'three']"></v-select></div>`,
components: { components: {
'v-select': Mock({ 'v-select': mock
'../mixins/pointerScroll': {methods}
})
}, },
}).$mount() }).$mount()
@@ -525,7 +530,7 @@ describe('Select.vue', () => {
describe('Removing values', () => { describe('Removing values', () => {
it('can remove the given tag when its close icon is clicked', (done) => { it('can remove the given tag when its close icon is clicked', (done) => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select :options="options" :value.sync="value" :multiple="true"></v-select></div>', template: '<div><v-select :options="options" v-model="value" :multiple="true"></v-select></div>',
components: {vSelect}, components: {vSelect},
data: { data: {
value: ['one'], value: ['one'],
@@ -534,7 +539,7 @@ describe('Select.vue', () => {
}).$mount() }).$mount()
vm.$children[0].$refs.toggle.querySelector('.close').click() vm.$children[0].$refs.toggle.querySelector('.close').click()
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual([]) expect(vm.$children[0].mutableValue).toEqual([])
done() done()
}) })
}) })
@@ -542,7 +547,7 @@ describe('Select.vue', () => {
it('should remove the last item in the value array on delete keypress when multiple is true', () => { it('should remove the last item in the value array on delete keypress when multiple is true', () => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select :options="options" :value.sync="value" :multiple="true"></v-select></div>', template: '<div><v-select :options="options" v-model="value" :multiple="true"></v-select></div>',
components: {vSelect}, components: {vSelect},
data: { data: {
value: ['one', 'two'], value: ['one', 'two'],
@@ -551,13 +556,13 @@ describe('Select.vue', () => {
}).$mount() }).$mount()
vm.$children[0].maybeDeleteValue() vm.$children[0].maybeDeleteValue()
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual(['one']) expect(vm.$children[0].mutableValue).toEqual(['one'])
}) })
}) })
it('should set value to null on delete keypress when multiple is false', () => { it('should set value to null on delete keypress when multiple is false', () => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select :options="options" :value.sync="value"></v-select></div>', template: '<div><v-select :options="options" v-model="value"></v-select></div>',
components: {vSelect}, components: {vSelect},
data: { data: {
value: 'one', value: 'one',
@@ -566,7 +571,7 @@ describe('Select.vue', () => {
}).$mount() }).$mount()
vm.$children[0].maybeDeleteValue() vm.$children[0].maybeDeleteValue()
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual(null) expect(vm.$children[0].mutableValue).toEqual(null)
}) })
}) })
}) })
@@ -574,7 +579,7 @@ describe('Select.vue', () => {
describe('Labels', () => { describe('Labels', () => {
it('can generate labels using a custom label key', () => { it('can generate labels using a custom label key', () => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select label="name" :options="options" :value.sync="value" :multiple="true"></v-select></div>', template: '<div><v-select label="name" :options="options" v-model="value" :multiple="true"></v-select></div>',
components: {vSelect}, components: {vSelect},
data: { data: {
value: [{name: 'Baz'}], value: [{name: 'Baz'}],
@@ -594,13 +599,11 @@ describe('Select.vue', () => {
}).$mount() }).$mount()
expect(vm.$children[0].searchPlaceholder).toEqual('foo') expect(vm.$children[0].searchPlaceholder).toEqual('foo')
vm.$children[0].currentSelection = {label: 'one'} vm.$children[0].mutableValue = {label: 'one'}
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].searchPlaceholder).not.toBeDefined() expect(vm.$children[0].searchPlaceholder).not.toBeDefined()
done() done()
}) })
// expect(vm.$children[0].searchPlaceholder()).toEqual('foo')
}) })
}) })
@@ -670,7 +673,7 @@ describe('Select.vue', () => {
searchSubmit(vm, 'three') searchSubmit(vm, 'three')
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual(['one', 'three']) expect(vm.$children[0].mutableValue).toEqual(['one', 'three'])
done() done()
}) })
}) })
@@ -687,7 +690,7 @@ describe('Select.vue', () => {
searchSubmit(vm, 'two') searchSubmit(vm, 'two')
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual([{label: 'one'}, {label: 'two'}]) expect(vm.$children[0].mutableValue).toEqual([{label: 'one'}, {label: 'two'}])
done() done()
}) })
}) })
@@ -703,7 +706,7 @@ describe('Select.vue', () => {
}).$mount() }).$mount()
searchSubmit(vm, 'three') searchSubmit(vm, 'three')
expect(vm.$children[0].currentOptions).toEqual(['one', 'two', 'three']) expect(vm.$children[0].mutableOptions).toEqual(['one', 'two', 'three'])
}) })
it('wont add a freshly created option/tag to the options list when pushTags is false', () => { it('wont add a freshly created option/tag to the options list when pushTags is false', () => {
@@ -717,7 +720,7 @@ describe('Select.vue', () => {
}).$mount() }).$mount()
searchSubmit(vm, 'three') searchSubmit(vm, 'three')
expect(vm.$children[0].currentOptions).toEqual(['one', 'two']) expect(vm.$children[0].mutableOptions).toEqual(['one', 'two'])
}) })
it('should select an existing option if the search string matches a string from options', (done) => { it('should select an existing option if the search string matches a string from options', (done) => {
@@ -735,7 +738,7 @@ describe('Select.vue', () => {
searchSubmit(vm) searchSubmit(vm)
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection[0]).toBe(two) expect(vm.$children[0].mutableValue[0]).toBe(two)
done() done()
}) })
}) })
@@ -757,7 +760,7 @@ describe('Select.vue', () => {
// This needs to be wrapped in nextTick() twice so that filteredOptions can // This needs to be wrapped in nextTick() twice so that filteredOptions can
// calculate after setting the search text, and move the typeAheadPointer index to 0. // calculate after setting the search text, and move the typeAheadPointer index to 0.
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection.label).toBe(two.label) expect(vm.$children[0].mutableValue.label).toBe(two.label)
done() done()
}) })
}) })
@@ -771,9 +774,9 @@ describe('Select.vue', () => {
options: [{label: 'one'}] options: [{label: 'one'}]
} }
}).$mount() }).$mount()
vm.$children[0].options = [{label: 'two'}] vm.$children[0].mutableOptions = [{label: 'two'}]
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual([{label: 'one'}]) expect(vm.$children[0].mutableValue).toEqual([{label: 'one'}])
done() done()
}) })
}) })
@@ -795,17 +798,20 @@ describe('Select.vue', () => {
it('should trigger the onSearch callback when the search text changes', (done) => { it('should trigger the onSearch callback when the search text changes', (done) => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select ref="select" :on-search="foo"></v-select></div>', template: '<div><v-select ref="select" :on-search="foo"></v-select></div>',
data: {
called: false
},
methods: { methods: {
foo() { foo(val) {
this.called = val
} }
} }
}).$mount() }).$mount()
spyOn(vm.$refs.select, 'onSearch')
vm.$refs.select.search = 'foo' vm.$refs.select.search = 'foo'
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$refs.select.onSearch).toHaveBeenCalledWith('foo', vm.$refs.select.toggleLoading) expect(vm.called).toEqual('foo')
done() done()
}) })
}) })
@@ -813,18 +819,22 @@ describe('Select.vue', () => {
it('should not trigger the onSearch callback if the search text is empty', (done) => { it('should not trigger the onSearch callback if the search text is empty', (done) => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select ref="select" search="foo" :on-search="foo"></v-select></div>', template: '<div><v-select ref="select" search="foo" :on-search="foo"></v-select></div>',
data: { called: false },
methods: { methods: {
foo() { foo(val) {
this.called = ! this.called
} }
} }
}).$mount() }).$mount()
spyOn(vm.$refs.select, 'onSearch') vm.$refs.select.search = 'foo'
vm.$refs.select.search = ''
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$refs.select.onSearch).not.toHaveBeenCalled() expect(vm.called).toBe(true)
done() vm.$refs.select.search = ''
Vue.nextTick(() => {
expect(vm.called).toBe(true)
done()
})
}) })
}) })
@@ -874,9 +884,9 @@ describe('Select.vue', () => {
options: ['one', 'two', 'three'] options: ['one', 'two', 'three']
} }
}).$mount() }).$mount()
vm.$children[0].options = ['four', 'five', 'six'] vm.$children[0].mutableOptions = ['four', 'five', 'six']
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual('one') expect(vm.$children[0].mutableValue).toEqual('one')
done() done()
}) })
}) })
@@ -890,9 +900,9 @@ describe('Select.vue', () => {
options: ['one', 'two', 'three'] options: ['one', 'two', 'three']
} }
}).$mount() }).$mount()
vm.$children[0].options = ['four', 'five', 'six'] vm.$children[0].mutableOptions = ['four', 'five', 'six']
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$children[0].currentSelection).toEqual(null) expect(vm.$children[0].mutableValue).toEqual(null)
done() done()
}) })
}) })