mirror of
https://github.com/tenrok/vue-select.git
synced 2026-05-17 02:29:37 +03:00
V3 - Remove mutable class properties plus other misc changes (#781)
* Remove the mutableValue prop in the Select component. * Add back mutable value when Vue Select has to manage its own value. * Remove mutableOptions, valueAsAarray. Update webpack minifer to use Terser. * Fix tabbing * Fix bug with showClearButton * Fix tests. * Call clearSelection when possible * Update dev sandbox to have all three options for setting value. * Update dev sandbox to display current value * Remove unused karma test setup. * Revert onInput name change. * Use coveralls * Change this.internalValue to this.$data._value. * Remove onInput prop and replace with internal method, updateValue. * Update tests. * Rename optionObjectComparator to optionComparator.
This commit is contained in:
+1
-2
@@ -5,5 +5,4 @@ node_js:
|
||||
- node
|
||||
|
||||
script:
|
||||
- yarn test --coverage --coverageReporters=text-lcov
|
||||
- codecov
|
||||
- yarn test --coverage --coverageReporters=text-lcov | coveralls
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const merge = require('webpack-merge');
|
||||
const baseWebpackConfig = require('./webpack.base.conf');
|
||||
|
||||
@@ -9,4 +10,16 @@ module.exports = merge(baseWebpackConfig, {
|
||||
libraryTarget: 'umd',
|
||||
globalObject: 'typeof self !== \'undefined\' ? self : this',
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
sourceMap: true,
|
||||
terserOptions: {
|
||||
compress: {
|
||||
drop_console: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
}
|
||||
});
|
||||
|
||||
+43
@@ -2,7 +2,18 @@
|
||||
<div id="app">
|
||||
<sandbox hide-help>
|
||||
<template slot-scope="config">
|
||||
|
||||
<p>Value managed by `v-model`:</p>
|
||||
<v-select v-model="vModelValue" v-bind="config" />
|
||||
<pre><code>`v-model` value: {{ vModelValueStringified }}</code></pre>
|
||||
<hr />
|
||||
|
||||
<p>Value managed by `:value` and `@input`:</p>
|
||||
<v-select :value="valueProp" @input="changeValueProp" v-bind="config" />
|
||||
<pre><code>value passed to `@input`: {{ valuePropStringified }}</code></pre>
|
||||
<hr />
|
||||
|
||||
<p>Value managed by Vue Select internally:</p>
|
||||
<v-select v-bind="config" />
|
||||
|
||||
</template>
|
||||
@@ -18,6 +29,30 @@ import Sandbox from '../docs/.vuepress/components/Sandbox';
|
||||
|
||||
export default {
|
||||
components: {Sandbox, vSelect},
|
||||
data: () => ({
|
||||
vModelValue: {
|
||||
value: 'CA',
|
||||
label: 'Canada'
|
||||
},
|
||||
valueProp: {
|
||||
value: 'US',
|
||||
label: 'United States'
|
||||
}
|
||||
}),
|
||||
methods: {
|
||||
changeValueProp(value) {
|
||||
this.valueProp = value;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
vModelValueStringified() {
|
||||
return JSON.stringify(this.vModelValue, null, 2);
|
||||
},
|
||||
|
||||
valuePropStringified() {
|
||||
return JSON.stringify(this.valueProp, null, 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -32,4 +67,12 @@ export default {
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-bottom: 1px solid #cacaca;
|
||||
margin-bottom: 1em;
|
||||
padding-top: 1em;
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
|
||||
+1
-16
@@ -189,21 +189,6 @@ getOptionLabel: {
|
||||
},
|
||||
```
|
||||
|
||||
## onChange
|
||||
|
||||
An optional callback function that is called each time the selected
|
||||
value(s) change. When integrating with Vuex, use this callback to trigger
|
||||
an action, rather than using `v-model` to retrieve the selected value.
|
||||
|
||||
```js
|
||||
onChange: {
|
||||
type: Function,
|
||||
default: function(val) {
|
||||
this.$emit("input", val);
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
## onTab
|
||||
|
||||
Select the current value if `selectOnTab` is enabled
|
||||
@@ -311,7 +296,7 @@ User defined function for adding Options
|
||||
createOption: {
|
||||
type: Function,
|
||||
default(newOption) {
|
||||
if (typeof this.mutableOptions[0] === "object") {
|
||||
if (typeof this.optionList[0] === "object") {
|
||||
newOption = { [this.label]: newOption };
|
||||
}
|
||||
this.$emit("option:created", newOption);
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-scss": "^2.0.0",
|
||||
"sass-loader": "^7.1.0",
|
||||
"terser-webpack-plugin": "^1.2.3",
|
||||
"url-loader": "^1.1.2",
|
||||
"vue": "^2.6.4",
|
||||
"vue-html-loader": "^1.2.4",
|
||||
|
||||
+96
-139
@@ -7,7 +7,7 @@
|
||||
<div ref="toggle" @mousedown.prevent="toggleDropdown" class="vs__dropdown-toggle">
|
||||
|
||||
<div class="vs__selected-options" ref="selectedOptions">
|
||||
<slot v-for="option in valueAsArray"
|
||||
<slot v-for="option in selectedValue"
|
||||
name="selected-option-container"
|
||||
:option="(typeof option === 'object')?option:{[label]: option}"
|
||||
:deselect="deselect"
|
||||
@@ -90,9 +90,7 @@
|
||||
* using 'change' event using v-on
|
||||
* @type {Object||String||null}
|
||||
*/
|
||||
value: {
|
||||
default: null
|
||||
},
|
||||
value: {},
|
||||
|
||||
/**
|
||||
* An array of strings or objects to be used as dropdown choices.
|
||||
@@ -191,7 +189,6 @@
|
||||
default: 'label'
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Value of the 'autocomplete' field of the input
|
||||
* element.
|
||||
@@ -246,27 +243,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* An optional callback function that is called each time the selected
|
||||
* value(s) change. When integrating with Vuex, use this callback to trigger
|
||||
* an action, rather than using :value.sync to retreive the selected value.
|
||||
* @type {Function}
|
||||
* @param {Object || String} val
|
||||
*/
|
||||
onChange: {
|
||||
type: Function,
|
||||
default: function (val) {
|
||||
this.$emit('change', val);
|
||||
}
|
||||
},
|
||||
|
||||
onInput: {
|
||||
type: Function,
|
||||
default: function (val) {
|
||||
this.$emit('input', val);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Select the current value if selectOnTab is enabled
|
||||
*/
|
||||
@@ -366,9 +342,10 @@
|
||||
createOption: {
|
||||
type: Function,
|
||||
default(newOption) {
|
||||
if (typeof this.mutableOptions[0] === 'object') {
|
||||
if (typeof this.optionList[0] === 'object') {
|
||||
newOption = {[this.label]: newOption}
|
||||
}
|
||||
|
||||
this.$emit('option:created', newOption)
|
||||
return newOption
|
||||
}
|
||||
@@ -440,65 +417,31 @@
|
||||
return {
|
||||
search: '',
|
||||
open: false,
|
||||
mutableValue: null,
|
||||
mutableOptions: []
|
||||
pushedTags: [],
|
||||
_value: [] // Internal value managed by Vue Select if no `value` prop is passed
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
/**
|
||||
* When the value prop changes, update
|
||||
* the internal mutableValue.
|
||||
* @param {mixed} val
|
||||
* @return {void}
|
||||
*/
|
||||
value(val) {
|
||||
this.mutableValue = val
|
||||
},
|
||||
|
||||
/**
|
||||
* Maybe run the onChange callback.
|
||||
* @param {string|object} val
|
||||
* @param {string|object} old
|
||||
* @return {void}
|
||||
*/
|
||||
mutableValue(val, old) {
|
||||
if (this.multiple) {
|
||||
this.onChange ? this.onChange(val) : null
|
||||
} else {
|
||||
this.onChange && val !== old ? this.onChange(val) : null
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* When options change, update
|
||||
* the internal mutableOptions.
|
||||
* @param {array} val
|
||||
* @return {void}
|
||||
*/
|
||||
options(val) {
|
||||
this.mutableOptions = val
|
||||
},
|
||||
|
||||
/**
|
||||
* Maybe reset the mutableValue
|
||||
* when mutableOptions change.
|
||||
* Maybe reset the value
|
||||
* when options change.
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
mutableOptions() {
|
||||
options(val) {
|
||||
if (!this.taggable && this.resetOnOptionsChange) {
|
||||
this.mutableValue = this.multiple ? [] : null
|
||||
this.clearSelection()
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Always reset the mutableValue when
|
||||
* Always reset the value when
|
||||
* the multiple prop changes.
|
||||
* @param {Boolean} val
|
||||
* @param {Boolean} isMultiple
|
||||
* @return {void}
|
||||
*/
|
||||
multiple(val) {
|
||||
this.mutableValue = val ? [] : null
|
||||
multiple() {
|
||||
this.clearSelection()
|
||||
},
|
||||
},
|
||||
|
||||
@@ -507,8 +450,6 @@
|
||||
* attach any event listeners.
|
||||
*/
|
||||
created() {
|
||||
this.mutableValue = this.value
|
||||
this.mutableOptions = this.options.slice(0)
|
||||
this.mutableLoading = this.loading
|
||||
|
||||
this.$on('option:created', this.maybePushTag)
|
||||
@@ -526,7 +467,8 @@
|
||||
if (this.taggable && !this.optionExists(option)) {
|
||||
option = this.createOption(option)
|
||||
}
|
||||
if(this.index) {
|
||||
|
||||
if (this.index) {
|
||||
if (!option.hasOwnProperty(this.index)) {
|
||||
return console.warn(
|
||||
`[vue-select warn]: Index key "option.${this.index}" does not` +
|
||||
@@ -535,14 +477,11 @@
|
||||
}
|
||||
option = option[this.index]
|
||||
}
|
||||
if (this.multiple && !this.mutableValue) {
|
||||
this.mutableValue = [option]
|
||||
} else if (this.multiple) {
|
||||
this.mutableValue.push(option)
|
||||
} else {
|
||||
this.mutableValue = option
|
||||
|
||||
if (this.multiple) {
|
||||
option = this.selectedValue.concat(option)
|
||||
}
|
||||
this.onInput(this.mutableValue);
|
||||
this.updateValue(option);
|
||||
}
|
||||
|
||||
this.onAfterSelect(option)
|
||||
@@ -554,14 +493,14 @@
|
||||
* @return {void}
|
||||
*/
|
||||
deselect(option) {
|
||||
let value = null
|
||||
|
||||
if (this.multiple) {
|
||||
this.mutableValue = this.mutableValue.filter(val => {
|
||||
return ! (val === option || (this.index && val === option[this.index]) || (typeof val === 'object' && val[this.label] === option[this.label]));
|
||||
value = this.selectedValue.filter(val => {
|
||||
return ! this.optionComparator(val, option)
|
||||
});
|
||||
} else {
|
||||
this.mutableValue = null
|
||||
}
|
||||
this.onInput(this.mutableValue);
|
||||
this.updateValue(value);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -569,8 +508,7 @@
|
||||
* @return {void}
|
||||
*/
|
||||
clearSelection() {
|
||||
this.mutableValue = this.multiple ? [] : null
|
||||
this.onInput(this.mutableValue)
|
||||
this.updateValue(this.multiple ? [] : null)
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -589,6 +527,14 @@
|
||||
}
|
||||
},
|
||||
|
||||
updateValue(value) {
|
||||
if (typeof this.value === 'undefined') {
|
||||
// Vue select has to manage value
|
||||
this.$data._value = value;
|
||||
}
|
||||
this.$emit('input', value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the visibility of the dropdown menu.
|
||||
* @param {Event} e
|
||||
@@ -614,11 +560,8 @@
|
||||
* @return {Boolean} True when selected | False otherwise
|
||||
*/
|
||||
isOptionSelected(option) {
|
||||
return this.valueAsArray.some(value => {
|
||||
if (typeof value === 'object') {
|
||||
return this.optionObjectComparator(value, option)
|
||||
}
|
||||
return value === option || value === option[this.index]
|
||||
return this.selectedValue.some(value => {
|
||||
return this.optionComparator(value, option)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -629,14 +572,26 @@
|
||||
* @param option {Object}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
optionObjectComparator(value, option) {
|
||||
if (this.index && value === option[this.index]) {
|
||||
return true
|
||||
} else if ((value[this.label] === option[this.label]) || (value[this.label] === option)) {
|
||||
return true
|
||||
} else if (this.index && value[this.index] === option[this.index]) {
|
||||
return true
|
||||
optionComparator(value, option) {
|
||||
// This method will need to be cleaned/replaced when the `reducer` API is added
|
||||
if (typeof value !== 'object' && typeof option !== 'object') {
|
||||
// Comparing primitives
|
||||
if (value === option) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
// Comparing objects
|
||||
if (this.index && value === option[this.index]) {
|
||||
return true
|
||||
}
|
||||
if ((value[this.label] === option[this.label]) || (value[this.label] === option)) {
|
||||
return true
|
||||
}
|
||||
if (this.index && value[this.index] === option[this.index]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
@@ -686,7 +641,7 @@
|
||||
return
|
||||
}
|
||||
// Fixed bug where no-options message could not be closed
|
||||
if(this.search.length === 0 && this.options.length === 0){
|
||||
if (this.search.length === 0 && this.options.length === 0){
|
||||
this.closeSearchOptions()
|
||||
return
|
||||
}
|
||||
@@ -718,42 +673,43 @@
|
||||
* @return {this.value}
|
||||
*/
|
||||
maybeDeleteValue() {
|
||||
if (!this.searchEl.value.length && this.mutableValue && this.clearable) {
|
||||
return this.multiple ? this.mutableValue.pop() : this.mutableValue = null
|
||||
if (!this.searchEl.value.length && this.selectedValue && this.clearable) {
|
||||
let value = null;
|
||||
if (this.multiple) {
|
||||
value = [...this.selectedValue.slice(0, this.selectedValue.length - 1)]
|
||||
}
|
||||
this.updateValue(value)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine if an option exists
|
||||
* within this.mutableOptions array.
|
||||
* within this.optionList array.
|
||||
*
|
||||
* @param {Object || String} option
|
||||
* @return {boolean}
|
||||
*/
|
||||
optionExists(option) {
|
||||
let exists = false
|
||||
|
||||
this.mutableOptions.forEach(opt => {
|
||||
return this.optionList.some(opt => {
|
||||
if (typeof opt === 'object' && opt[this.label] === option) {
|
||||
exists = true
|
||||
return true
|
||||
} else if (opt === option) {
|
||||
exists = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return exists
|
||||
},
|
||||
|
||||
/**
|
||||
* If push-tags is true, push the
|
||||
* given option to mutableOptions.
|
||||
* given option to `this.pushedTags`.
|
||||
*
|
||||
* @param {Object || String} option
|
||||
* @return {void}
|
||||
*/
|
||||
maybePushTag(option) {
|
||||
if (this.pushTags) {
|
||||
this.mutableOptions.push(option)
|
||||
this.pushedTags.push(option)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -812,6 +768,25 @@
|
||||
|
||||
computed: {
|
||||
|
||||
selectedValue () {
|
||||
let value = this.value;
|
||||
|
||||
if (typeof this.value === 'undefined') {
|
||||
// Vue select has to manage value internally
|
||||
value = this.$data._value;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
return [].concat(value);
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
|
||||
optionList () {
|
||||
return this.options.concat(this.pushedTags);
|
||||
},
|
||||
|
||||
/**
|
||||
* Find the search input DOM element.
|
||||
* @returns {HTMLInputElement}
|
||||
@@ -848,7 +823,7 @@
|
||||
'keyup': this.onSearchKeyUp,
|
||||
'blur': this.onSearchBlur,
|
||||
'focus': this.onSearchFocus,
|
||||
'input': (e) => this.search = e.target.value,
|
||||
'input': (e) => this.search = e.target.value
|
||||
},
|
||||
},
|
||||
spinner: {
|
||||
@@ -919,10 +894,13 @@
|
||||
* @return {array}
|
||||
*/
|
||||
filteredOptions() {
|
||||
const optionList = [].concat(this.optionList);
|
||||
|
||||
if (!this.filterable && !this.taggable) {
|
||||
return this.mutableOptions.slice()
|
||||
return optionList;
|
||||
}
|
||||
let options = this.search.length ? this.filter(this.mutableOptions, this.search, this) : this.mutableOptions;
|
||||
|
||||
let options = this.search.length ? this.filter(optionList, this.search, this) : optionList;
|
||||
if (this.taggable && this.search.length && !this.optionExists(this.search)) {
|
||||
options.unshift(this.search)
|
||||
}
|
||||
@@ -934,28 +912,7 @@
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isValueEmpty() {
|
||||
if (this.mutableValue) {
|
||||
if (typeof this.mutableValue === 'object') {
|
||||
return ! Object.keys(this.mutableValue).length
|
||||
}
|
||||
return ! this.valueAsArray.length
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the current value in array format.
|
||||
* @return {Array}
|
||||
*/
|
||||
valueAsArray() {
|
||||
if (this.multiple && this.mutableValue) {
|
||||
return this.mutableValue
|
||||
} else if (this.mutableValue) {
|
||||
return [].concat(this.mutableValue)
|
||||
}
|
||||
|
||||
return []
|
||||
return this.selectedValue.length === 0;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -963,7 +920,7 @@
|
||||
* @return {Boolean}
|
||||
*/
|
||||
showClearButton() {
|
||||
return !this.multiple && this.clearable && !this.open && this.mutableValue != null
|
||||
return !this.multiple && this.clearable && !this.open && !this.isValueEmpty
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
var merge = require('webpack-merge')
|
||||
|
||||
var baseWebpackConfig = require('../../build/webpack.base.conf')
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
browsers: ['PhantomJS'],
|
||||
frameworks: ['jasmine'],
|
||||
files: [
|
||||
'../../node_modules/phantomjs-polyfill-object-assign/object-assign-polyfill.js',
|
||||
'**/*.js'
|
||||
],
|
||||
reporters: ['spec', 'coverage'],
|
||||
preprocessors: {
|
||||
'**/*.js': ['webpack', 'sourcemap']
|
||||
},
|
||||
captureConsole: true,
|
||||
browserConsoleLogOptions: {
|
||||
terminal: true,
|
||||
level: ""
|
||||
},
|
||||
|
||||
webpack: merge(baseWebpackConfig, {
|
||||
entry: './dev/dev.js'
|
||||
}),
|
||||
|
||||
webpackMiddleware: {
|
||||
noInfo: true
|
||||
},
|
||||
|
||||
specReporter: {
|
||||
suppressSkipped: true
|
||||
},
|
||||
|
||||
coverageReporter: {
|
||||
instrumenters: { isparta: require('isparta') },
|
||||
instrumenter: {
|
||||
'**/*.js': 'isparta'
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,10 +2,12 @@ import { selectWithProps } from "../helpers";
|
||||
|
||||
describe("Removing values", () => {
|
||||
it("can remove the given tag when its close icon is clicked", () => {
|
||||
const Select = selectWithProps({ multiple: true, value: ["foo"] });
|
||||
const Select = selectWithProps({ multiple: true });
|
||||
Select.vm.$data._value = 'one';
|
||||
|
||||
Select.find(".vs__deselect").trigger("click");
|
||||
expect(Select.vm.mutableValue).toEqual([]);
|
||||
expect(Select.emitted().input).toEqual([[[]]]);
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
it("should not remove tag when close icon is clicked and component is disabled", () => {
|
||||
@@ -17,28 +19,32 @@ describe("Removing values", () => {
|
||||
});
|
||||
|
||||
Select.find(".vs__deselect").trigger("click");
|
||||
expect(Select.vm.mutableValue).toEqual(["one"]);
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
});
|
||||
|
||||
it("should remove the last item in the value array on delete keypress when multiple is true", () => {
|
||||
const Select = selectWithProps({
|
||||
multiple: true,
|
||||
value: ["one", "two"],
|
||||
options: ["one", "two", "three"]
|
||||
});
|
||||
|
||||
Select.vm.maybeDeleteValue();
|
||||
expect(Select.vm.mutableValue).toEqual(["one"]);
|
||||
Select.vm.$data._value = ["one", "two"];
|
||||
|
||||
Select.find('.vs__search').trigger('keydown.backspace')
|
||||
|
||||
expect(Select.emitted().input).toEqual([[['one']]]);
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
});
|
||||
|
||||
it("should set value to null on delete keypress when multiple is false", () => {
|
||||
const Select = selectWithProps({
|
||||
value: "one",
|
||||
options: ["one", "two", "three"]
|
||||
});
|
||||
|
||||
Select.vm.$data._value = 'one';
|
||||
|
||||
Select.vm.maybeDeleteValue();
|
||||
expect(Select.vm.mutableValue).toEqual(null);
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
describe("Clear button", () => {
|
||||
@@ -64,12 +70,14 @@ describe("Removing values", () => {
|
||||
it("should remove selected value when clicked", () => {
|
||||
const Select = selectWithProps({
|
||||
options: ["foo", "bar"],
|
||||
value: "foo"
|
||||
});
|
||||
Select.vm.$data._value = 'foo';
|
||||
|
||||
expect(Select.vm.mutableValue).toEqual("foo");
|
||||
expect(Select.vm.selectedValue).toEqual(["foo"]);
|
||||
Select.find("button.vs__clear").trigger("click");
|
||||
expect(Select.vm.mutableValue).toEqual(null);
|
||||
|
||||
expect(Select.emitted().input).toEqual([[null]]);
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
it("should be disabled when component is disabled", () => {
|
||||
|
||||
@@ -59,11 +59,6 @@ describe("Toggling Dropdown", () => {
|
||||
multiple: true,
|
||||
closeOnSelect: false
|
||||
});
|
||||
// const vm = new Vue({
|
||||
// template:
|
||||
// '<div><v-select ref="select" :options="options" multiple :closeOnSelect="false" :value="value"></v-select></div>',
|
||||
// components: { vSelect },
|
||||
// }).$mount();
|
||||
|
||||
Select.vm.open = true;
|
||||
Select.vm.select("one");
|
||||
@@ -120,7 +115,7 @@ describe("Toggling Dropdown", () => {
|
||||
});
|
||||
|
||||
Select.vm.search = "foo";
|
||||
Select.vm.onEscape();
|
||||
Select.find('.vs__search').trigger('keyup.esc')
|
||||
expect(Select.vm.search).toEqual("");
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,17 @@ import { shallowMount } from "@vue/test-utils";
|
||||
import VueSelect from "../../src/components/Select";
|
||||
|
||||
describe("Filtering Options", () => {
|
||||
it("should update the search value when the input element receives the 'input' event", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: { options: ["foo", "bar", "baz"] }
|
||||
});
|
||||
|
||||
const input = Select.find('.vs__search');
|
||||
input.element.value = 'a'
|
||||
input.trigger('input')
|
||||
expect(Select.vm.search).toEqual('a');
|
||||
});
|
||||
|
||||
it("should filter an array of strings", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: { options: ["foo", "bar", "baz"] }
|
||||
|
||||
@@ -36,7 +36,7 @@ describe("Labels", () => {
|
||||
});
|
||||
|
||||
expect(Select.vm.searchPlaceholder).toEqual("foo");
|
||||
Select.vm.mutableValue = "one";
|
||||
Select.vm.$data._value = "one";
|
||||
expect(Select.vm.searchPlaceholder).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ describe("When index prop is defined", () => {
|
||||
options: [{ label: "This is Foo", value: "foo" }]
|
||||
}
|
||||
});
|
||||
expect(Select.vm.mutableValue).toEqual("foo");
|
||||
expect(Select.vm.selectedValue).toEqual(["foo"]);
|
||||
});
|
||||
|
||||
it("can determine if an object is pre-selected", () => {
|
||||
@@ -66,7 +66,7 @@ describe("When index prop is defined", () => {
|
||||
}
|
||||
});
|
||||
|
||||
expect(Select.vm.mutableValue).toEqual(["foo", "bar"]);
|
||||
expect(Select.vm.selectedValue).toEqual(["foo", "bar"]);
|
||||
});
|
||||
|
||||
it("can deselect a pre-selected object", () => {
|
||||
@@ -74,7 +74,6 @@ describe("When index prop is defined", () => {
|
||||
propsData: {
|
||||
multiple: true,
|
||||
index: "value",
|
||||
value: ["foo", "bar"],
|
||||
options: [
|
||||
{ label: "This is Foo", value: "foo" },
|
||||
{ label: "This is Bar", value: "bar" }
|
||||
@@ -82,16 +81,16 @@ describe("When index prop is defined", () => {
|
||||
}
|
||||
});
|
||||
|
||||
Select.vm.$data._value = ['foo', 'bar'];
|
||||
|
||||
Select.vm.deselect("foo");
|
||||
expect(Select.vm.mutableValue.length).toEqual(1);
|
||||
expect(Select.vm.mutableValue).toEqual(["bar"]);
|
||||
expect(Select.vm.selectedValue).toEqual(["bar"]);
|
||||
});
|
||||
|
||||
it("can deselect an option when multiple is false", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
index: "value",
|
||||
value: "foo",
|
||||
options: [
|
||||
{ label: "This is Foo", value: "foo" },
|
||||
{ label: "This is Bar", value: "bar" }
|
||||
@@ -100,7 +99,7 @@ describe("When index prop is defined", () => {
|
||||
});
|
||||
|
||||
Select.vm.deselect("foo");
|
||||
expect(Select.vm.mutableValue).toEqual(null);
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
it("can use v-model syntax for a two way binding to a parent component", () => {
|
||||
@@ -120,7 +119,7 @@ describe("When index prop is defined", () => {
|
||||
const Select = Parent.vm.$children[0];
|
||||
|
||||
expect(Select.value).toEqual("foo");
|
||||
expect(Select.mutableValue).toEqual("foo");
|
||||
expect(Select.selectedValue).toEqual(["foo"]);
|
||||
|
||||
Select.select({ label: "This is Bar", value: "bar" });
|
||||
expect(Parent.vm.value).toEqual("bar");
|
||||
|
||||
@@ -4,17 +4,23 @@ import VueSelect from "../../src/components/Select";
|
||||
describe("Reset on options change", () => {
|
||||
it("should not reset the selected value by default when the options property changes", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: { value: "one", options: ["one"] }
|
||||
propsData: { options: ["one"] }
|
||||
});
|
||||
Select.vm.mutableOptions = ["four", "five", "six"];
|
||||
expect(Select.vm.mutableValue).toEqual("one");
|
||||
|
||||
Select.vm.$data._value = 'one';
|
||||
|
||||
Select.setProps({options: ["four", "five", "six"]});
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
});
|
||||
|
||||
it("should reset the selected value when the options property changes", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: { resetOnOptionsChange: true, value: "one", options: ["one"] }
|
||||
propsData: { resetOnOptionsChange: true, options: ["one"] }
|
||||
});
|
||||
Select.vm.mutableOptions = ["four", "five", "six"];
|
||||
expect(Select.vm.mutableValue).toEqual(null);
|
||||
|
||||
Select.vm.$data._value = 'one';
|
||||
|
||||
Select.setProps({options: ["four", "five", "six"]});
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,7 +15,7 @@ describe("VS - Selecting Values", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: defaultProps
|
||||
});
|
||||
expect(Select.mutableValue).toEqual(Select.value);
|
||||
expect(Select.selectedValue).toEqual(Select.value);
|
||||
});
|
||||
|
||||
it("can accept an array of objects and pre-selected value (single)", () => {
|
||||
@@ -28,7 +28,7 @@ describe("VS - Selecting Values", () => {
|
||||
]
|
||||
}
|
||||
});
|
||||
expect(Select.mutableValue).toEqual(Select.value);
|
||||
expect(Select.selectedValue).toEqual(Select.value);
|
||||
});
|
||||
|
||||
it("can accept an array of objects and pre-selected values (multiple)", () => {
|
||||
@@ -46,7 +46,7 @@ describe("VS - Selecting Values", () => {
|
||||
multiple: true
|
||||
});
|
||||
|
||||
expect(Select.mutableValue).toEqual(Select.value);
|
||||
expect(Select.selectedValue).toEqual(Select.value);
|
||||
});
|
||||
|
||||
it("can select an option on tab", () => {
|
||||
@@ -67,10 +67,6 @@ describe("VS - Selecting Values", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
multiple: true,
|
||||
value: [
|
||||
{ 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" }
|
||||
@@ -78,36 +74,41 @@ describe("VS - Selecting Values", () => {
|
||||
}
|
||||
});
|
||||
|
||||
Select.vm.$data._value = [
|
||||
{ label: "This is Foo", value: "foo" },
|
||||
{ label: "This is Bar", value: "bar" }
|
||||
];
|
||||
|
||||
Select.vm.deselect({ label: "This is Foo", value: "foo" });
|
||||
expect(Select.vm.mutableValue.length).toEqual(1);
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "This is Bar", value: "bar" }]);
|
||||
});
|
||||
|
||||
it("can deselect a pre-selected string", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
multiple: true,
|
||||
value: ["foo", "bar"],
|
||||
options: ["foo", "bar"]
|
||||
}
|
||||
});
|
||||
|
||||
Select.vm.$data._value = "foo";
|
||||
|
||||
Select.vm.deselect("foo");
|
||||
expect(Select.vm.mutableValue.length).toEqual(1);
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
it("can deselect an option when multiple is false", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
value: "foo"
|
||||
}
|
||||
});
|
||||
const Select = shallowMount(VueSelect);
|
||||
|
||||
Select.vm.$data._value = "foo";
|
||||
|
||||
Select.vm.deselect("foo");
|
||||
expect(Select.vm.mutableValue).toEqual(null);
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
it("can determine if the value prop is empty", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
value: [],
|
||||
options: ["one", "two", "three"]
|
||||
}
|
||||
});
|
||||
@@ -134,19 +135,16 @@ describe("VS - Selecting Values", () => {
|
||||
it("should reset the selected values when the multiple property changes", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
value: ["one"],
|
||||
multiple: true,
|
||||
options: ["one", "two", "three"]
|
||||
}
|
||||
});
|
||||
|
||||
expect(Select.vm.mutableValue).toEqual(["one"]);
|
||||
|
||||
Select.setProps({ multiple: false });
|
||||
expect(Select.vm.mutableValue).toEqual(null);
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
|
||||
Select.setProps({ multiple: true });
|
||||
expect(Select.vm.mutableValue).toEqual([]);
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
it("can retain values present in a new array of options", () => {
|
||||
@@ -158,7 +156,7 @@ describe("VS - Selecting Values", () => {
|
||||
});
|
||||
|
||||
Select.setProps({ options: ["one", "five", "six"] });
|
||||
expect(Select.vm.mutableValue).toEqual(["one"]);
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
});
|
||||
|
||||
it("can determine if an object is already selected", () => {
|
||||
@@ -181,7 +179,7 @@ describe("VS - Selecting Values", () => {
|
||||
const Select = Parent.vm.$children[0];
|
||||
|
||||
expect(Select.value).toEqual("foo");
|
||||
expect(Select.mutableValue).toEqual("foo");
|
||||
expect(Select.selectedValue).toEqual(["foo"]);
|
||||
|
||||
Select.select("bar");
|
||||
expect(Parent.vm.value).toEqual("bar");
|
||||
|
||||
+22
-22
@@ -44,25 +44,24 @@ describe("When Tagging Is Enabled", () => {
|
||||
const Select = selectWithProps({
|
||||
taggable: true,
|
||||
multiple: true,
|
||||
value: ["one"],
|
||||
options: ["one", "two"]
|
||||
});
|
||||
|
||||
searchSubmit(Select, "three");
|
||||
expect(Select.vm.mutableValue).toEqual(["one", "three"]);
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual(["three"]);
|
||||
});
|
||||
|
||||
it("can select the current search text as an object", () => {
|
||||
const Select = selectWithProps({
|
||||
taggable: true,
|
||||
multiple: true,
|
||||
value: [{ label: "one" }],
|
||||
options: [{ label: "one" }]
|
||||
});
|
||||
|
||||
searchSubmit(Select, "two");
|
||||
expect(Select.vm.mutableValue).toEqual([
|
||||
{ label: "one" },
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual([
|
||||
{ label: "two" }
|
||||
]);
|
||||
});
|
||||
@@ -77,7 +76,8 @@ describe("When Tagging Is Enabled", () => {
|
||||
});
|
||||
|
||||
searchSubmit(Select, "three");
|
||||
expect(Select.vm.mutableOptions).toEqual(["one", "two", "three"]);
|
||||
expect(Select.vm.pushedTags).toEqual(["three"]);
|
||||
expect(Select.vm.optionList).toEqual(["one", "two", "three"]);
|
||||
});
|
||||
|
||||
it("should add a freshly created option/tag to the options list when pushTags is true and filterable is false", () => {
|
||||
@@ -91,7 +91,8 @@ describe("When Tagging Is Enabled", () => {
|
||||
});
|
||||
|
||||
searchSubmit(Select, "three");
|
||||
expect(Select.vm.mutableOptions).toEqual(["one", "two", "three"]);
|
||||
expect(Select.vm.pushedTags).toEqual(["three"]);
|
||||
expect(Select.vm.optionList).toEqual(["one", "two", "three"]);
|
||||
expect(Select.vm.filteredOptions).toEqual(["one", "two", "three"]);
|
||||
});
|
||||
|
||||
@@ -105,7 +106,7 @@ describe("When Tagging Is Enabled", () => {
|
||||
});
|
||||
|
||||
searchSubmit(Select, "three");
|
||||
expect(Select.vm.mutableOptions).toEqual(["one", "two"]);
|
||||
expect(Select.vm.optionList).toEqual(["one", "two"]);
|
||||
});
|
||||
|
||||
it("wont add a freshly created option/tag to the options list when pushTags is false and filterable is false", () => {
|
||||
@@ -119,16 +120,15 @@ describe("When Tagging Is Enabled", () => {
|
||||
});
|
||||
|
||||
searchSubmit(Select, "three");
|
||||
expect(Select.vm.mutableOptions).toEqual(["one", "two"]);
|
||||
expect(Select.vm.optionList).toEqual(["one", "two"]);
|
||||
expect(Select.vm.filteredOptions).toEqual(["one", "two"]);
|
||||
});
|
||||
|
||||
it("should select an existing option if the search string matches a string from options", () => {
|
||||
it("should select an existing option if the search string matches a string from options", async () => {
|
||||
let two = "two";
|
||||
const Select = selectWithProps({
|
||||
taggable: true,
|
||||
multiple: true,
|
||||
value: null,
|
||||
options: ["one", two]
|
||||
});
|
||||
|
||||
@@ -136,7 +136,7 @@ describe("When Tagging Is Enabled", () => {
|
||||
|
||||
searchSubmit(Select);
|
||||
|
||||
expect(Select.vm.mutableValue[0]).toBe(two);
|
||||
expect(Select.vm.selectedValue).toEqual([two]);
|
||||
});
|
||||
|
||||
it("should select an existing option if the search string matches an objects label from options", () => {
|
||||
@@ -149,7 +149,7 @@ describe("When Tagging Is Enabled", () => {
|
||||
Select.vm.search = "two";
|
||||
|
||||
searchSubmit(Select);
|
||||
expect(Select.vm.mutableValue.label).toBe(two.label);
|
||||
expect(Select.vm.selectedValue).toEqual([two]);
|
||||
});
|
||||
|
||||
it("should select an existing option if the search string matches an objects label from options when filter-options is false", () => {
|
||||
@@ -163,7 +163,7 @@ describe("When Tagging Is Enabled", () => {
|
||||
Select.vm.search = "two";
|
||||
|
||||
searchSubmit(Select);
|
||||
expect(Select.vm.mutableValue.label).toBe(two.label);
|
||||
expect(Select.vm.selectedValue).toEqual([two]);
|
||||
});
|
||||
|
||||
it("should not reset the selected value when the options property changes", () => {
|
||||
@@ -174,8 +174,8 @@ describe("When Tagging Is Enabled", () => {
|
||||
options: [{ label: "one" }]
|
||||
});
|
||||
|
||||
Select.vm.mutableOptions = [{ label: "two" }];
|
||||
expect(Select.vm.mutableValue).toEqual([{ label: "one" }]);
|
||||
Select.setProps({ options: [{ label: "two" }] });
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
|
||||
});
|
||||
|
||||
it("should not reset the selected value when the options property changes when filterable is false", () => {
|
||||
@@ -187,8 +187,8 @@ describe("When Tagging Is Enabled", () => {
|
||||
options: [{ label: "one" }]
|
||||
});
|
||||
|
||||
Select.vm.mutableOptions = [{ label: "two" }];
|
||||
expect(Select.vm.mutableValue).toEqual([{ label: "one" }]);
|
||||
Select.setProps({ options: [{ label: "two" }] });
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
|
||||
});
|
||||
|
||||
it("should not allow duplicate tags when using string options", () => {
|
||||
@@ -198,11 +198,11 @@ describe("When Tagging Is Enabled", () => {
|
||||
});
|
||||
|
||||
searchSubmit(Select, "one");
|
||||
expect(Select.vm.mutableValue).toEqual(["one"]);
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
expect(Select.vm.search).toEqual("");
|
||||
|
||||
searchSubmit(Select, "one");
|
||||
expect(Select.vm.mutableValue).toEqual(["one"]);
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
expect(Select.vm.search).toEqual("");
|
||||
});
|
||||
|
||||
@@ -214,11 +214,11 @@ describe("When Tagging Is Enabled", () => {
|
||||
});
|
||||
|
||||
searchSubmit(Select, "one");
|
||||
expect(Select.vm.mutableValue).toEqual([{ label: "one" }]);
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
|
||||
expect(Select.vm.search).toEqual("");
|
||||
|
||||
searchSubmit(Select, "one");
|
||||
expect(Select.vm.mutableValue).toEqual([{ label: "one" }]);
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
|
||||
expect(Select.vm.search).toEqual("");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user