mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-19 09:50:33 +03:00
Merge branch 'master' into customizable-text
This commit is contained in:
+10
-4
@@ -13,10 +13,11 @@ describe("Asynchronous Loading", () => {
|
||||
expect(Select.vm.mutableLoading).toEqual(true);
|
||||
});
|
||||
|
||||
it("should trigger the search event when the search text changes", () => {
|
||||
it("should trigger the search event when the search text changes", async () => {
|
||||
const Select = selectWithProps();
|
||||
|
||||
Select.vm.search = "foo";
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
const events = Select.emitted("search");
|
||||
|
||||
@@ -24,11 +25,13 @@ describe("Asynchronous Loading", () => {
|
||||
expect(events.length).toEqual(1);
|
||||
});
|
||||
|
||||
it("should trigger the search event if the search text is empty", () => {
|
||||
it("should trigger the search event if the search text is empty", async () => {
|
||||
const Select = selectWithProps();
|
||||
|
||||
Select.vm.search = "foo";
|
||||
await Select.vm.$nextTick();
|
||||
Select.vm.search = "";
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
const events = Select.emitted("search");
|
||||
|
||||
@@ -36,7 +39,7 @@ describe("Asynchronous Loading", () => {
|
||||
expect(events.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("can set loading to false from the @search event callback", () => {
|
||||
it("can set loading to false from the @search event callback", async () => {
|
||||
const Select = shallowMount(vSelect, {
|
||||
listeners: {
|
||||
search: (search, loading) => {
|
||||
@@ -47,13 +50,16 @@ describe("Asynchronous Loading", () => {
|
||||
|
||||
Select.vm.mutableLoading = true;
|
||||
Select.vm.search = 'foo';
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.mutableLoading).toEqual(false);
|
||||
});
|
||||
|
||||
it("will sync mutable loading with the loading prop", () => {
|
||||
it('will sync mutable loading with the loading prop', async () => {
|
||||
const Select = selectWithProps({ loading: false });
|
||||
Select.setProps({ loading: true });
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.mutableLoading).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { selectWithProps } from "../helpers";
|
||||
|
||||
describe("Removing values", () => {
|
||||
it("can remove the given tag when its close icon is clicked", () => {
|
||||
it("can remove the given tag when its close icon is clicked", async () => {
|
||||
const Select = selectWithProps({ multiple: true });
|
||||
Select.vm.$data._value = 'one';
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
Select.find(".vs__deselect").trigger("click");
|
||||
expect(Select.emitted().input).toEqual([[[]]]);
|
||||
|
||||
@@ -129,14 +129,17 @@ describe("Toggling Dropdown", () => {
|
||||
expect(Select.vm.stateClasses['vs--open']).toEqual(true);
|
||||
});
|
||||
|
||||
it("should not display the dropdown if noDrop is true", () => {
|
||||
it("should not display the dropdown if noDrop is true", async () => {
|
||||
const Select = selectWithProps({
|
||||
noDrop: true,
|
||||
});
|
||||
|
||||
Select.vm.toggleDropdown({ target: Select.vm.$refs.search });
|
||||
expect(Select.vm.open).toEqual(true);
|
||||
expect(Select.contains('.vs__dropdown-menu')).toBeFalsy();
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.find('.vs__dropdown-menu').element.style['display']).toEqual('none');
|
||||
expect(Select.contains('.vs__dropdown-option')).toBeFalsy();
|
||||
expect(Select.contains('.vs__no-options')).toBeFalsy();
|
||||
expect(Select.vm.stateClasses['vs--open']).toBeFalsy();
|
||||
});
|
||||
|
||||
|
||||
@@ -12,13 +12,15 @@ describe("Labels", () => {
|
||||
expect(Select.find(".vs__selected").text()).toBe("Foo");
|
||||
});
|
||||
|
||||
it("will console.warn when options contain objects without a valid label key", () => {
|
||||
it("will console.warn when options contain objects without a valid label key", async () => {
|
||||
const spy = jest.spyOn(console, "warn").mockImplementation(() => {});
|
||||
const Select = selectWithProps({
|
||||
options: [{}]
|
||||
});
|
||||
|
||||
Select.vm.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
'[vue-select warn]: Label key "option.label" does not exist in options object {}.' +
|
||||
"\nhttps://vue-select.org/api/props.html#getoptionlabel"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import VueSelect from "../../src/components/Select";
|
||||
import { mountDefault } from '../helpers';
|
||||
|
||||
describe("Reset on options change", () => {
|
||||
it("should not reset the selected value by default when the options property changes", () => {
|
||||
@@ -13,7 +14,81 @@ describe("Reset on options change", () => {
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
});
|
||||
|
||||
it("should reset the selected value when the options property changes", () => {
|
||||
describe('resetOnOptionsChange as a function', () => {
|
||||
it('will yell at you if resetOnOptionsChange is not a function or boolean', () => {
|
||||
const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
mountDefault({resetOnOptionsChange: 1});
|
||||
expect(spy.mock.calls[0][0]).toContain('Invalid prop: custom validator check failed for prop "resetOnOptionsChange"')
|
||||
|
||||
mountDefault({resetOnOptionsChange: 'one'});
|
||||
expect(spy.mock.calls[1][0]).toContain('Invalid prop: custom validator check failed for prop "resetOnOptionsChange"')
|
||||
|
||||
mountDefault({resetOnOptionsChange: []});
|
||||
expect(spy.mock.calls[2][0]).toContain('Invalid prop: custom validator check failed for prop "resetOnOptionsChange"')
|
||||
|
||||
mountDefault({resetOnOptionsChange: {}});
|
||||
expect(spy.mock.calls[3][0]).toContain('Invalid prop: custom validator check failed for prop "resetOnOptionsChange"')
|
||||
});
|
||||
|
||||
it('should receive the new options, old options, and current value', async () => {
|
||||
let resetOnOptionsChange = jest.fn(option => option);
|
||||
const Select = mountDefault(
|
||||
{resetOnOptionsChange, options: ['bear'], value: 'selected'},
|
||||
);
|
||||
|
||||
Select.setProps({options: ['lake', 'kite']});
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(resetOnOptionsChange).toHaveBeenCalledTimes(1);
|
||||
expect(resetOnOptionsChange)
|
||||
.toHaveBeenCalledWith(['lake', 'kite'], ['bear'], ['selected']);
|
||||
});
|
||||
|
||||
it('should allow resetOnOptionsChange to be a function that returns true', async () => {
|
||||
let resetOnOptionsChange = () => true;
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {resetOnOptionsChange, options: ['one'], value: 'one'},
|
||||
});
|
||||
const spy = jest.spyOn(Select.vm, 'clearSelection');
|
||||
|
||||
Select.setProps({options: ['one', 'two']});
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should allow resetOnOptionsChange to be a function that returns false', () => {
|
||||
let resetOnOptionsChange = () => false;
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {resetOnOptionsChange, options: ['one'], value: 'one'},
|
||||
});
|
||||
const spy = jest.spyOn(Select.vm, 'clearSelection');
|
||||
|
||||
Select.setProps({options: ['one', 'two']});
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should reset the options if the selectedValue does not exist in the new options', async () => {
|
||||
let resetOnOptionsChange = (options, old, val) => val.some(val => options.includes(val));
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {resetOnOptionsChange, options: ['one'], value: 'one'},
|
||||
});
|
||||
const spy = jest.spyOn(Select.vm, 'clearSelection');
|
||||
|
||||
Select.setProps({options: ['one', 'two']});
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual(['one']);
|
||||
|
||||
Select.setProps({options: ['two']});
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
it("should reset the selected value when the options property changes", async () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: { resetOnOptionsChange: true, options: ["one"] }
|
||||
});
|
||||
@@ -21,15 +96,46 @@ describe("Reset on options change", () => {
|
||||
Select.vm.$data._value = 'one';
|
||||
|
||||
Select.setProps({options: ["four", "five", "six"]});
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
it("should return correct selected value when the options property changes and a new option matches", () => {
|
||||
it("should return correct selected value when the options property changes and a new option matches", async () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: { value: "one", options: [], reduce(option) { return option.value } }
|
||||
});
|
||||
|
||||
Select.setProps({options: [{ label: "oneLabel", value: "one" }]});
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "oneLabel", value: "one" }]);
|
||||
});
|
||||
|
||||
it('clearSearchOnBlur returns false when multiple is true', () => {
|
||||
const Select = mountDefault({});
|
||||
let clearSearchOnBlur = jest.spyOn(Select.vm, 'clearSearchOnBlur');
|
||||
Select.find({ref: 'search'}).trigger('click');
|
||||
Select.setData({search: 'one'});
|
||||
Select.find({ref: 'search'}).trigger('blur');
|
||||
|
||||
expect(clearSearchOnBlur).toHaveBeenCalledTimes(1);
|
||||
expect(clearSearchOnBlur).toHaveBeenCalledWith({
|
||||
clearSearchOnSelect: true,
|
||||
multiple: false,
|
||||
});
|
||||
expect(Select.vm.search).toBe('');
|
||||
});
|
||||
|
||||
it('clearSearchOnBlur accepts a function', () => {
|
||||
let clearSearchOnBlur = jest.fn(() => false);
|
||||
const Select = mountDefault({clearSearchOnBlur});
|
||||
|
||||
Select.find({ref: 'search'}).trigger('click');
|
||||
Select.setData({search: 'one'});
|
||||
Select.find({ref: 'search'}).trigger('blur');
|
||||
|
||||
expect(clearSearchOnBlur).toHaveBeenCalledTimes(1);
|
||||
expect(Select.vm.search).toBe('one');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -211,7 +211,7 @@ describe("When reduce prop is defined", () => {
|
||||
|
||||
});
|
||||
|
||||
it("reacts correctly when value property changes", () => {
|
||||
it("reacts correctly when value property changes", async () => {
|
||||
const optionToChangeTo = { id: 1, label: "Foo" };
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
@@ -222,6 +222,7 @@ describe("When reduce prop is defined", () => {
|
||||
});
|
||||
|
||||
Select.setProps({ value: optionToChangeTo.id });
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual([optionToChangeTo]);
|
||||
});
|
||||
|
||||
@@ -1,27 +1,33 @@
|
||||
import { selectWithProps } from "../helpers";
|
||||
|
||||
describe("Selectable prop", () => {
|
||||
it("should select selectable option if clicked", () => {
|
||||
it("should select selectable option if clicked", async () => {
|
||||
const Select = selectWithProps({
|
||||
options: ["one", "two", "three"],
|
||||
selectable: (option) => option === "one"
|
||||
});
|
||||
|
||||
Select.vm.$data.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
Select.find(".vs__dropdown-menu li:first-child").trigger("mousedown");
|
||||
|
||||
await Select.vm.$nextTick();
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
})
|
||||
|
||||
it("should not select not selectable option if clicked", () => {
|
||||
it("should not select not selectable option if clicked", async () => {
|
||||
const Select = selectWithProps({
|
||||
options: ["one", "two", "three"],
|
||||
selectable: (option) => option === "one"
|
||||
});
|
||||
|
||||
Select.vm.$data.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
Select.find(".vs__dropdown-menu li:last-child").trigger("mousedown");
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
+53
-19
@@ -10,32 +10,66 @@ describe('Scoped Slots', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(Select.find({ ref: 'selectedOptions' }).text()).toEqual('one')
|
||||
expect(Select.find({ref: 'selectedOptions'}).text()).toEqual('one');
|
||||
});
|
||||
|
||||
it('receives an option object to the selected-option slot', () => {
|
||||
const Select = mountDefault(
|
||||
{value: 'one'},
|
||||
{
|
||||
scopedSlots: {
|
||||
'selected-option': `<span slot="selected-option" slot-scope="option">{{ option.label }}</span>`,
|
||||
},
|
||||
});
|
||||
describe('Slot: selected-option', () => {
|
||||
it('receives an option object to the selected-option slot', () => {
|
||||
const Select = mountDefault(
|
||||
{value: 'one'},
|
||||
{
|
||||
scopedSlots: {
|
||||
'selected-option': `<span slot="selected-option" slot-scope="option">{{ option.label }}</span>`,
|
||||
},
|
||||
});
|
||||
|
||||
expect(Select.find('.vs__selected').text()).toEqual('one')
|
||||
expect(Select.find('.vs__selected').text()).toEqual('one');
|
||||
});
|
||||
|
||||
it('opens the dropdown when clicking an option in selected-option slot',
|
||||
() => {
|
||||
const Select = mountDefault(
|
||||
{value: 'one'},
|
||||
{
|
||||
scopedSlots: {
|
||||
'selected-option': `<span class="my-option" slot-scope="option">{{ option.label }}</span>`,
|
||||
},
|
||||
});
|
||||
|
||||
Select.find('.my-option').trigger('mousedown');
|
||||
expect(Select.vm.open).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('receives an option object to the option slot in the dropdown menu', () => {
|
||||
const Select = mountDefault(
|
||||
{value: 'one'},
|
||||
{
|
||||
scopedSlots: {
|
||||
'option': `<span slot="option" slot-scope="option">{{ option.label }}</span>`,
|
||||
},
|
||||
});
|
||||
it('receives an option object to the option slot in the dropdown menu',
|
||||
async () => {
|
||||
const Select = mountDefault(
|
||||
{value: 'one'},
|
||||
{
|
||||
scopedSlots: {
|
||||
'option': `<span slot="option" slot-scope="option">{{ option.label }}</span>`,
|
||||
},
|
||||
});
|
||||
|
||||
Select.vm.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.find({ref: 'dropdownMenu'}).text()).toEqual('onetwothree');
|
||||
});
|
||||
|
||||
it('noOptions slot receives the current search text', async () => {
|
||||
const noOptions = jest.fn();
|
||||
const Select = mountDefault({}, {
|
||||
scopedSlots: {'no-options': noOptions},
|
||||
});
|
||||
|
||||
Select.vm.search = 'something not there';
|
||||
Select.vm.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.find({ref: 'dropdownMenu'}).text()).toEqual('onetwothree')
|
||||
expect(noOptions).toHaveBeenCalledWith({
|
||||
search: 'something not there',
|
||||
searching: true,
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
@@ -80,6 +80,20 @@ describe("When Tagging Is Enabled", () => {
|
||||
expect(Select.vm.optionList).toEqual(["one", "two", "three"]);
|
||||
});
|
||||
|
||||
it("should pushTags even if the consumer has defined a createOption callback", () => {
|
||||
const Select = selectWithProps({
|
||||
pushTags: true,
|
||||
taggable: true,
|
||||
createOption: option => option,
|
||||
options: ["one", "two"]
|
||||
});
|
||||
|
||||
searchSubmit(Select, "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", () => {
|
||||
const Select = selectWithProps({
|
||||
filterable: false,
|
||||
@@ -139,7 +153,7 @@ describe("When Tagging Is Enabled", () => {
|
||||
expect(Select.vm.selectedValue).toEqual([two]);
|
||||
});
|
||||
|
||||
it("should select an existing option if the search string matches an objects label from options", () => {
|
||||
it("should select an existing option if the search string matches an objects label from options", async () => {
|
||||
let two = { label: "two" };
|
||||
const Select = selectWithProps({
|
||||
taggable: true,
|
||||
@@ -147,12 +161,13 @@ describe("When Tagging Is Enabled", () => {
|
||||
});
|
||||
|
||||
Select.vm.search = "two";
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
searchSubmit(Select);
|
||||
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", () => {
|
||||
it("should select an existing option if the search string matches an objects label from options when filter-options is false", async () => {
|
||||
let two = { label: "two" };
|
||||
const Select = selectWithProps({
|
||||
taggable: true,
|
||||
@@ -161,6 +176,7 @@ describe("When Tagging Is Enabled", () => {
|
||||
});
|
||||
|
||||
Select.vm.search = "two";
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
searchSubmit(Select);
|
||||
expect(Select.vm.selectedValue).toEqual([two]);
|
||||
|
||||
@@ -120,11 +120,12 @@ describe("Moving the Typeahead Pointer", () => {
|
||||
});
|
||||
|
||||
describe("Measuring pixel distances", () => {
|
||||
it("should calculate pointerHeight as the offsetHeight of the pointer element if it exists", () => {
|
||||
it("should calculate pointerHeight as the offsetHeight of the pointer element if it exists", async () => {
|
||||
const Select = mountDefault();
|
||||
|
||||
// Drop down must be open for $refs to exist
|
||||
Select.vm.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
/**
|
||||
* Since JSDom doesn't render layouts, set the offsetHeight explicitly
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import uniqueId from '../../../src/utility/uniqueId';
|
||||
|
||||
test('it generates a unique number', () => {
|
||||
expect(uniqueId()).not.toEqual(uniqueId());
|
||||
});
|
||||
Reference in New Issue
Block a user