Skip to content

Commit

Permalink
fix: refactor typeaheadselect, add regression test
Browse files Browse the repository at this point in the history
Closes #1156
  • Loading branch information
sagalbot committed Apr 12, 2020
1 parent 142a639 commit e244d4f
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 36 deletions.
11 changes: 10 additions & 1 deletion dev/Dev.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
<template>
<div id="app">
<sandbox hide-help v-slot="config">
<v-select v-bind="config"/>
<v-select
label="name"
:options="[]"
v-model="organization"
taggable
:create-option="org => ({ name: org })"
></v-select>

{{ organization }}
</sandbox>
</div>
</template>
Expand All @@ -14,6 +22,7 @@ import Sandbox from '../docs/.vuepress/components/Sandbox';
export default {
components: {Sandbox, vSelect},
data: () => ({organization: null})
};
</script>

Expand Down
11 changes: 7 additions & 4 deletions src/components/Select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@
*/
onAfterSelect(option) {
if (this.closeOnSelect) {
this.open = !this.open
this.open = !this.open;
this.searchEl.blur()
}
Expand Down Expand Up @@ -1153,10 +1153,13 @@
}
let options = this.search.length ? this.filter(optionList, this.search, this) : optionList;
if (this.taggable && this.search.length && !this.optionExists(this.createOption(this.search))) {
options.unshift(this.search)
if (this.taggable && this.search.length) {
const createdOption = this.createOption(this.search);
if (!this.optionExists(createdOption)) {
options.unshift(createdOption);
}
}
return options
return options;
},
/**
Expand Down
6 changes: 0 additions & 6 deletions src/mixins/typeAheadPointer.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,6 @@ export default {

if (typeAheadOption) {
this.select(typeAheadOption);
} else if (this.taggable && this.search.length) {
this.select(this.createOption(this.search));
}

if (this.clearSearchOnSelect) {
this.search = "";
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@ export const searchSubmit = (Wrapper, searchText = false) => {
Wrapper.find({ ref: "search" }).trigger("keydown.enter")
};

/**
* Focus the input, enter some search text, hit return.
* @param Wrapper {Wrapper<Vue>}
* @param searchText
* @return {Promise<void>}
*/
export const selectTag = async (Wrapper, searchText) => {
Wrapper.vm.$refs.search.focus();
await Wrapper.vm.$nextTick();

Wrapper.vm.search = searchText;
await Wrapper.vm.$nextTick();

Wrapper.find({ ref: "search" }).trigger("keydown.enter");
await Wrapper.vm.$nextTick();
};

/**
* Create a new VueSelect instance with
* a provided set of props.
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/CreateOption.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { searchSubmit, selectTag, selectWithProps } from "../helpers";

describe("CreateOption When Tagging Is Enabled", () => {
it("can select the current search text as a string", async () => {
const Select = selectWithProps({
taggable: true,
multiple: true,
options: ["one", "two"],
createOption: option => "four"
});

await selectTag(Select, "three");
expect(Select.vm.selectedValue).toEqual(["four"]);
});

it("can select the current search text as an object", async () => {
const Select = selectWithProps({
taggable: true,
multiple: false,
value: null,
options: [],
label: "name",
createOption: title => ({ name: title })
});

await selectTag(Select, "two");

expect(Select.emitted("input")[0]).toEqual([{ name: "two" }]);
});
});
5 changes: 5 additions & 0 deletions tests/unit/Reduce.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,12 @@ describe("When reduce prop is defined", () => {
const Select = Parent.vm.$children[0];

// When
Select.$refs.search.focus();
await Select.$nextTick();

Select.search = 'hello';
await Select.$nextTick();

Select.typeAheadSelect();
await Select.$nextTick();

Expand Down
54 changes: 29 additions & 25 deletions tests/unit/Tagging.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { mountDefault, searchSubmit, selectWithProps } from '../helpers';
import {
mountDefault,
searchSubmit,
selectTag,
selectWithProps,
} from '../helpers';
import Select from '../../src/components/Select';

describe("When Tagging Is Enabled", () => {
Expand Down Expand Up @@ -32,7 +37,7 @@ describe("When Tagging Is Enabled", () => {
expect(Select.vm.optionExists(createOption("three"))).toEqual(false);
});

it("can add the current search text as the first item in the options list", () => {
it("can add the current search text as the first item in the options list", async () => {
const Select = selectWithProps({
taggable: true,
multiple: true,
Expand All @@ -41,36 +46,37 @@ describe("When Tagging Is Enabled", () => {
});

Select.vm.search = "three";
await Select.vm.$nextTick();
expect(Select.vm.filteredOptions).toEqual(["three"]);
});

it("can select the current search text as a string", () => {
it("can select the current search text as a string", async () => {
const Select = selectWithProps({
taggable: true,
multiple: true,
options: ["one", "two"]
});

searchSubmit(Select, "three");
await selectTag(Select, "three");

expect(Select.vm.selectedValue).toEqual(["three"]);
});

it("can select the current search text as an object", () => {
it("can select the current search text as an object", async () => {
const Select = selectWithProps({
taggable: true,
multiple: true,
options: [{ label: "one" }]
});

searchSubmit(Select, "two");
await selectTag(Select, "two");

expect(Select.vm.selectedValue).toEqual([
{ label: "two" }
]);
});

it("should add a freshly created option/tag to the options list when pushTags is true", () => {
it("should add a freshly created option/tag to the options list when pushTags is true", async () => {
const Select = selectWithProps({
pushTags: true,
taggable: true,
Expand All @@ -79,26 +85,26 @@ describe("When Tagging Is Enabled", () => {
options: ["one", "two"]
});

searchSubmit(Select, "three");
await selectTag(Select, "three");
expect(Select.vm.pushedTags).toEqual(["three"]);
expect(Select.vm.optionList).toEqual(["one", "two", "three"]);
});

it("should pushTags even if the consumer has defined a createOption callback", () => {
it("should pushTags even if the consumer has defined a createOption callback", async () => {
const Select = selectWithProps({
pushTags: true,
taggable: true,
createOption: option => option,
options: ["one", "two"]
});

searchSubmit(Select, "three");
await selectTag(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", () => {
it("should add a freshly created option/tag to the options list when pushTags is true and filterable is false", async () => {
const Select = selectWithProps({
filterable: false,
pushTags: true,
Expand All @@ -108,13 +114,13 @@ describe("When Tagging Is Enabled", () => {
options: ["one", "two"]
});

searchSubmit(Select, "three");
await selectTag(Select, "three");
expect(Select.vm.pushedTags).toEqual(["three"]);
expect(Select.vm.optionList).toEqual(["one", "two", "three"]);
expect(Select.vm.filteredOptions).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", async () => {
const Select = selectWithProps({
pushTags: false,
taggable: true,
Expand All @@ -123,11 +129,11 @@ describe("When Tagging Is Enabled", () => {
options: ["one", "two"]
});

searchSubmit(Select, "three");
await selectTag(Select, "three");
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", () => {
it("wont add a freshly created option/tag to the options list when pushTags is false and filterable is false", async () => {
const Select = selectWithProps({
filterable: false,
pushTags: false,
Expand All @@ -137,7 +143,7 @@ describe("When Tagging Is Enabled", () => {
options: ["one", "two"]
});

searchSubmit(Select, "three");
await selectTag(Select, "three");
expect(Select.vm.optionList).toEqual(["one", "two"]);
expect(Select.vm.filteredOptions).toEqual(["one", "two"]);
});
Expand All @@ -150,9 +156,7 @@ describe("When Tagging Is Enabled", () => {
options: ["one", two]
});

Select.vm.search = "two";

searchSubmit(Select);
await selectTag(Select, "two");

expect(Select.vm.selectedValue).toEqual([two]);
});
Expand Down Expand Up @@ -211,35 +215,35 @@ describe("When Tagging Is Enabled", () => {
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
});

it("should not allow duplicate tags when using string options", () => {
it("should not allow duplicate tags when using string options", async () => {
const Select = selectWithProps({
taggable: true,
multiple: true
});

searchSubmit(Select, "one");
await selectTag(Select, "one");
expect(Select.vm.selectedValue).toEqual(["one"]);
expect(Select.vm.search).toEqual("");

searchSubmit(Select, "one");
await selectTag(Select, "one");
expect(Select.vm.selectedValue).toEqual(["one"]);
expect(Select.vm.search).toEqual("");
});

it("should not allow duplicate tags when using object options", () => {
it("should not allow duplicate tags when using object options", async () => {
const Select = selectWithProps({
taggable: true,
multiple: true,
options: [{ label: "two" }]
});
const spy = jest.spyOn(Select.vm, 'select');

searchSubmit(Select, "one");
await selectTag(Select, "one");
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
expect(spy).lastCalledWith({label: 'one'});
expect(Select.vm.search).toEqual("");

searchSubmit(Select, "one");
await selectTag(Select, "one");
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
expect(Select.vm.search).toEqual("");
});
Expand Down

0 comments on commit e244d4f

Please sign in to comment.