mirror of
https://github.com/tenrok/vue-select.git
synced 2026-05-17 02:29:37 +03:00
switch to vue cli for build
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
@@ -0,0 +1,25 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
extends: ["plugin:vue/vue3-essential", "eslint:recommended", "@vue/prettier"],
|
||||
parserOptions: {
|
||||
parser: "babel-eslint"
|
||||
},
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: [
|
||||
"**/__tests__/*.{j,t}s?(x)",
|
||||
"**/tests/unit/**/*.spec.{j,t}s?(x)"
|
||||
],
|
||||
env: {
|
||||
jest: true
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
+7
-11
@@ -1,8 +1,12 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
/tests/e2e/videos/
|
||||
/tests/e2e/screenshots/
|
||||
|
||||
|
||||
# local env files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
@@ -10,6 +14,7 @@ node_modules
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
@@ -18,13 +23,4 @@ yarn-error.log*
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw*
|
||||
|
||||
# Project specific
|
||||
coverage
|
||||
dist
|
||||
test/unit/coverage
|
||||
package-lock.json
|
||||
dev/dist
|
||||
docs/.vuepress/dist
|
||||
.netlify
|
||||
*.sw?
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["@vue/cli-plugin-babel/preset"]
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"pluginsFile": "tests/e2e/plugins/index.js"
|
||||
}
|
||||
+56
-30
@@ -1,39 +1,49 @@
|
||||
{
|
||||
"name": "vue-select",
|
||||
"version": "3.11.2",
|
||||
"description": "Everything you wish the HTML <select> element could do, wrapped up into a lightweight, extensible Vue component.",
|
||||
"author": "Jeff Sagal <sagalbot@gmail.com>",
|
||||
"homepage": "https://vue-select.org",
|
||||
"directories": {
|
||||
"doc": "docs",
|
||||
"test": "tests"
|
||||
},
|
||||
"private": false,
|
||||
"main": "dist/vue-select.js",
|
||||
"license": "MIT",
|
||||
"prepare": "npm run build",
|
||||
"description": "Everything you wish the HTML <select> element could do, wrapped up into a lightweight, accessible and composable Vue component.",
|
||||
"author": {
|
||||
"name": "Jeff Sagal",
|
||||
"email": "sagalbot@gmail.com"
|
||||
},
|
||||
"scripts": {
|
||||
"serve": "webpack-dev-server --config build/webpack.dev.conf.js --hot --progress -d",
|
||||
"serve:docs": "cd docs && yarn serve",
|
||||
"build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.conf.js --progress",
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"test:unit": "vue-cli-service test:unit",
|
||||
"test:e2e": "vue-cli-service test:e2e",
|
||||
"lint": "vue-cli-service lint",
|
||||
"build:docs": "cd docs && yarn build",
|
||||
"build:preview": "cd docs && yarn build",
|
||||
"test": "jest",
|
||||
"commit": "git-cz",
|
||||
"semantic-release": "semantic-release",
|
||||
"commit": "git-cz"
|
||||
"serve:docs": "cd docs && yarn serve",
|
||||
"test": "jest"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sagalbot/vue-select.git"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "2.x"
|
||||
},
|
||||
"resolutions": {
|
||||
"ajv": "6.8.1"
|
||||
"main": "dist/vue-select.js",
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-e2e-cypress": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-unit-jest": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"@vue/test-utils": "^2.0.0-0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-vue": "^7.0.0-0",
|
||||
"prettier": "^1.19.1",
|
||||
"typescript": "~3.9.3",
|
||||
"vue-jest": "^5.0.0-0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "3.x"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
@@ -66,12 +76,11 @@
|
||||
],
|
||||
"coverageReporters": [
|
||||
"text"
|
||||
]
|
||||
],
|
||||
"preset": "@vue/cli-plugin-unit-jest"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
"bugs": {
|
||||
"url": "https://github.com/sagalbot/vue-select/issues"
|
||||
},
|
||||
"bundlewatch": {
|
||||
"files": [
|
||||
@@ -86,5 +95,22 @@
|
||||
"maxSize": "6 KB"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"directories": {
|
||||
"doc": "docs",
|
||||
"test": "tests"
|
||||
},
|
||||
"homepage": "https://vue-select.org",
|
||||
"license": "MIT",
|
||||
"prepare": "npm run build",
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sagalbot/vue-select.git"
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,8 +1,8 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer'),
|
||||
require('cssnano')({
|
||||
preset: 'default',
|
||||
}),
|
||||
],
|
||||
require("autoprefixer"),
|
||||
require("cssnano")({
|
||||
preset: "default"
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<img alt="Vue logo" src="./assets/logo.png" />
|
||||
<HelloWorld msg="Welcome to Your Vue.js App" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HelloWorld from "./components/HelloWorld.vue";
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
HelloWorld
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}
|
||||
</style>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
@@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10">
|
||||
<path d="M6.895455 5l2.842897-2.842898c.348864-.348863.348864-.914488 0-1.263636L9.106534.261648c-.348864-.348864-.914489-.348864-1.263636 0L5 3.104545 2.157102.261648c-.348863-.348864-.914488-.348864-1.263636 0L.261648.893466c-.348864.348864-.348864.914489 0 1.263636L3.104545 5 .261648 7.842898c-.348864.348863-.348864.914488 0 1.263636l.631818.631818c.348864.348864.914773.348864 1.263636 0L5 6.895455l2.842898 2.842897c.348863.348864.914772.348864 1.263636 0l.631818-.631818c.348864-.348864.348864-.914489 0-1.263636L6.895455 5z"/>
|
||||
<path
|
||||
d="M6.895455 5l2.842897-2.842898c.348864-.348863.348864-.914488 0-1.263636L9.106534.261648c-.348864-.348864-.914489-.348864-1.263636 0L5 3.104545 2.157102.261648c-.348863-.348864-.914488-.348864-1.263636 0L.261648.893466c-.348864.348864-.348864.914489 0 1.263636L3.104545 5 .261648 7.842898c-.348864.348863-.348864.914488 0 1.263636l.631818.631818c.348864.348864.914773.348864 1.263636 0L5 6.895455l2.842898 2.842897c.348863.348864.914772.348864 1.263636 0l.631818-.631818c.348864-.348864.348864-.914489 0-1.263636L6.895455 5z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br />
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-cli documentation</a
|
||||
>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>babel</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>eslint</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-jest"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>unit-jest</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-e2e-cypress"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>e2e-cypress</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
|
||||
>Forum</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
|
||||
>Community Chat</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
|
||||
>Twitter</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-router</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-devtools#vue-devtools"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>vue-devtools</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-loader</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/awesome-vue"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>awesome-vue</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "HelloWorld",
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="10">
|
||||
<path d="M9.211364 7.59931l4.48338-4.867229c.407008-.441854.407008-1.158247 0-1.60046l-.73712-.80023c-.407008-.441854-1.066904-.441854-1.474243 0L7 5.198617 2.51662.33139c-.407008-.441853-1.066904-.441853-1.474243 0l-.737121.80023c-.407008.441854-.407008 1.158248 0 1.600461l4.48338 4.867228L7 10l2.211364-2.40069z"/>
|
||||
<path
|
||||
d="M9.211364 7.59931l4.48338-4.867229c.407008-.441854.407008-1.158247 0-1.60046l-.73712-.80023c-.407008-.441854-1.066904-.441854-1.474243 0L7 5.198617 2.51662.33139c-.407008-.441853-1.066904-.441853-1.474243 0l-.737121.80023c-.407008.441854-.407008 1.158248 0 1.600461l4.48338 4.867228L7 10l2.211364-2.40069z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
+1080
-1122
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
import Deselect from './Deselect';
|
||||
import OpenIndicator from './OpenIndicator';
|
||||
import Deselect from "./Deselect";
|
||||
import OpenIndicator from "./OpenIndicator";
|
||||
|
||||
export default {
|
||||
Deselect,
|
||||
OpenIndicator
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,27 +1,32 @@
|
||||
export default {
|
||||
inserted (el, bindings, {context}) {
|
||||
if (context.appendToBody) {
|
||||
const {height, top, left, width} = context.$refs.toggle.getBoundingClientRect();
|
||||
let scrollX = window.scrollX || window.pageXOffset;
|
||||
let scrollY = window.scrollY || window.pageYOffset;
|
||||
el.unbindPosition = context.calculatePosition(el, context, {
|
||||
width: width + 'px',
|
||||
left: (scrollX + left) + 'px',
|
||||
top: (scrollY + top + height) + 'px',
|
||||
});
|
||||
|
||||
document.body.appendChild(el);
|
||||
}
|
||||
},
|
||||
inserted(el, bindings, { context }) {
|
||||
if (context.appendToBody) {
|
||||
const {
|
||||
height,
|
||||
top,
|
||||
left,
|
||||
width
|
||||
} = context.$refs.toggle.getBoundingClientRect();
|
||||
let scrollX = window.scrollX || window.pageXOffset;
|
||||
let scrollY = window.scrollY || window.pageYOffset;
|
||||
el.unbindPosition = context.calculatePosition(el, context, {
|
||||
width: width + "px",
|
||||
left: scrollX + left + "px",
|
||||
top: scrollY + top + height + "px"
|
||||
});
|
||||
|
||||
unbind (el, bindings, {context}) {
|
||||
if (context.appendToBody) {
|
||||
if (el.unbindPosition && typeof el.unbindPosition === 'function') {
|
||||
el.unbindPosition();
|
||||
}
|
||||
if (el.parentNode) {
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
document.body.appendChild(el);
|
||||
}
|
||||
},
|
||||
|
||||
unbind(el, bindings, { context }) {
|
||||
if (context.appendToBody) {
|
||||
if (el.unbindPosition && typeof el.unbindPosition === "function") {
|
||||
el.unbindPosition();
|
||||
}
|
||||
if (el.parentNode) {
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
import VueSelect from './components/Select.vue'
|
||||
import mixins from './mixins/index'
|
||||
import VueSelect from "./components/Select.vue";
|
||||
import mixins from "./mixins/index";
|
||||
|
||||
export default VueSelect
|
||||
export { VueSelect, mixins }
|
||||
export default VueSelect;
|
||||
export { VueSelect, mixins };
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
|
||||
createApp(App).mount("#app");
|
||||
+11
-11
@@ -7,13 +7,13 @@ export default {
|
||||
*/
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
mutableLoading: false,
|
||||
mutableLoading: false
|
||||
};
|
||||
},
|
||||
|
||||
@@ -27,8 +27,8 @@ export default {
|
||||
*
|
||||
* @emits search
|
||||
*/
|
||||
search () {
|
||||
this.$emit('search', this.search, this.toggleLoading);
|
||||
search() {
|
||||
this.$emit("search", this.search, this.toggleLoading);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -36,9 +36,9 @@ export default {
|
||||
* mutable loading value.
|
||||
* @param val
|
||||
*/
|
||||
loading (val) {
|
||||
loading(val) {
|
||||
this.mutableLoading = val;
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -49,11 +49,11 @@ export default {
|
||||
* @param toggle Boolean
|
||||
* @returns {*}
|
||||
*/
|
||||
toggleLoading (toggle = null) {
|
||||
toggleLoading(toggle = null) {
|
||||
if (toggle == null) {
|
||||
return (this.mutableLoading = !this.mutableLoading);
|
||||
}
|
||||
return (this.mutableLoading = toggle);
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
import ajax from './ajax'
|
||||
import pointer from './typeAheadPointer'
|
||||
import pointerScroll from './pointerScroll'
|
||||
import ajax from "./ajax";
|
||||
import pointer from "./typeAheadPointer";
|
||||
import pointerScroll from "./pointerScroll";
|
||||
|
||||
export default { ajax, pointer, pointerScroll }
|
||||
export default { ajax, pointer, pointerScroll };
|
||||
|
||||
@@ -11,7 +11,7 @@ export default {
|
||||
if (this.autoscroll) {
|
||||
this.maybeAdjustScroll();
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
@@ -2,7 +2,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
typeAheadPointer: -1
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
@@ -37,7 +37,11 @@ export default {
|
||||
* @return {void}
|
||||
*/
|
||||
typeAheadDown() {
|
||||
for (let i = this.typeAheadPointer + 1; i < this.filteredOptions.length; i++) {
|
||||
for (
|
||||
let i = this.typeAheadPointer + 1;
|
||||
i < this.filteredOptions.length;
|
||||
i++
|
||||
) {
|
||||
if (this.selectable(this.filteredOptions[i])) {
|
||||
this.typeAheadPointer = i;
|
||||
break;
|
||||
@@ -58,4 +62,4 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
function sortAndStringify(sortable) {
|
||||
const ordered = {};
|
||||
|
||||
Object.keys(sortable).sort().forEach(key => {
|
||||
ordered[key] = sortable[key];
|
||||
});
|
||||
Object.keys(sortable)
|
||||
.sort()
|
||||
.forEach(key => {
|
||||
ordered[key] = sortable[key];
|
||||
});
|
||||
|
||||
return JSON.stringify(ordered);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
plugins: ["cypress"],
|
||||
env: {
|
||||
mocha: true,
|
||||
"cypress/globals": true
|
||||
},
|
||||
rules: {
|
||||
strict: "off"
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
/* eslint-disable arrow-body-style */
|
||||
// https://docs.cypress.io/guides/guides/plugins-guide.html
|
||||
|
||||
// if you need a custom webpack configuration you can uncomment the following import
|
||||
// and then use the `file:preprocessor` event
|
||||
// as explained in the cypress docs
|
||||
// https://docs.cypress.io/api/plugins/preprocessors-api.html#Examples
|
||||
|
||||
// /* eslint-disable import/no-extraneous-dependencies, global-require */
|
||||
// const webpack = require('@cypress/webpack-preprocessor')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// on('file:preprocessor', webpack({
|
||||
// webpackOptions: require('@vue/cli-service/webpack.config'),
|
||||
// watchOptions: {}
|
||||
// }))
|
||||
|
||||
return Object.assign({}, config, {
|
||||
fixturesFolder: "tests/e2e/fixtures",
|
||||
integrationFolder: "tests/e2e/specs",
|
||||
screenshotsFolder: "tests/e2e/screenshots",
|
||||
videosFolder: "tests/e2e/videos",
|
||||
supportFile: "tests/e2e/support/index.js"
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
// https://docs.cypress.io/api/introduction/api.html
|
||||
|
||||
describe("My First Test", () => {
|
||||
it("Visits the app root url", () => {
|
||||
cy.visit("/");
|
||||
cy.contains("h1", "Welcome to Your Vue.js App");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||
@@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import "./commands";
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
+12
-12
@@ -1,6 +1,6 @@
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import VueSelect from "../src/components/Select.vue";
|
||||
import Vue from 'vue';
|
||||
import Vue from "vue";
|
||||
|
||||
/**
|
||||
* Trigger a submit event on the search
|
||||
@@ -13,7 +13,7 @@ export const searchSubmit = (Wrapper, searchText = false) => {
|
||||
if (searchText) {
|
||||
Wrapper.vm.search = searchText;
|
||||
}
|
||||
Wrapper.find({ ref: "search" }).trigger("keydown.enter")
|
||||
Wrapper.find({ ref: "search" }).trigger("keydown.enter");
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -52,14 +52,13 @@ export const selectWithProps = (propsData = {}) => {
|
||||
export const mountDefault = (props = {}, options = {}) => {
|
||||
return shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
options: ['one', 'two', 'three'],
|
||||
...props,
|
||||
options: ["one", "two", "three"],
|
||||
...props
|
||||
},
|
||||
...options,
|
||||
...options
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a v-select component directly.
|
||||
* @param props
|
||||
@@ -68,11 +67,12 @@ export const mountDefault = (props = {}, options = {}) => {
|
||||
*/
|
||||
export const mountWithoutTestUtils = (props = {}, options = {}) => {
|
||||
return new Vue({
|
||||
render: createEl => createEl('vue-select', {
|
||||
ref: 'select',
|
||||
props: {options: ['one', 'two', 'three'], ...props},
|
||||
...options
|
||||
}),
|
||||
components: {VueSelect},
|
||||
render: createEl =>
|
||||
createEl("vue-select", {
|
||||
ref: "select",
|
||||
props: { options: ["one", "two", "three"], ...props },
|
||||
...options
|
||||
}),
|
||||
components: { VueSelect }
|
||||
}).$mount().$refs.select;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,6 @@ module.exports = {
|
||||
jest: true
|
||||
},
|
||||
rules: {
|
||||
'import/no-extraneous-dependencies': 'off'
|
||||
"import/no-extraneous-dependencies": "off"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { selectWithProps } from "../helpers";
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import vSelect from '../../src/components/Select';
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import vSelect from "../../src/components/Select";
|
||||
|
||||
describe("Asynchronous Loading", () => {
|
||||
it("can toggle the loading class", () => {
|
||||
@@ -43,19 +43,19 @@ describe("Asynchronous Loading", () => {
|
||||
const Select = shallowMount(vSelect, {
|
||||
listeners: {
|
||||
search: (search, loading) => {
|
||||
loading(false)
|
||||
},
|
||||
},
|
||||
loading(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Select.vm.mutableLoading = true;
|
||||
Select.vm.search = 'foo';
|
||||
Select.vm.search = "foo";
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.mutableLoading).toEqual(false);
|
||||
});
|
||||
|
||||
it('will sync mutable loading with the loading prop', async () => {
|
||||
it("will sync mutable loading with the loading prop", async () => {
|
||||
const Select = selectWithProps({ loading: false });
|
||||
Select.setProps({ loading: true });
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
import Vue from 'vue';
|
||||
import { selectWithProps } from '../helpers';
|
||||
import Vue from "vue";
|
||||
import { selectWithProps } from "../helpers";
|
||||
|
||||
describe('Components API', () => {
|
||||
|
||||
it('swap the Deselect component', () => {
|
||||
const Deselect = Vue.component('Deselect', {
|
||||
render (createElement) {
|
||||
return createElement('button', 'remove');
|
||||
},
|
||||
describe("Components API", () => {
|
||||
it("swap the Deselect component", () => {
|
||||
const Deselect = Vue.component("Deselect", {
|
||||
render(createElement) {
|
||||
return createElement("button", "remove");
|
||||
}
|
||||
});
|
||||
|
||||
const Select = selectWithProps({components: {Deselect}});
|
||||
const Select = selectWithProps({ components: { Deselect } });
|
||||
|
||||
expect(Select.contains(Deselect)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('swap the OpenIndicator component', () => {
|
||||
const OpenIndicator = Vue.component('OpenIndicator', {
|
||||
render (createElement) {
|
||||
return createElement('i', '^');
|
||||
},
|
||||
it("swap the OpenIndicator component", () => {
|
||||
const OpenIndicator = Vue.component("OpenIndicator", {
|
||||
render(createElement) {
|
||||
return createElement("i", "^");
|
||||
}
|
||||
});
|
||||
|
||||
const Select = selectWithProps({components: {OpenIndicator}});
|
||||
const Select = selectWithProps({ components: { OpenIndicator } });
|
||||
|
||||
expect(Select.contains(OpenIndicator)).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { mountDefault, selectWithProps } from '../helpers';
|
||||
import { mountDefault, selectWithProps } from "../helpers";
|
||||
|
||||
describe("Removing values", () => {
|
||||
it("can remove the given tag when its close icon is clicked", async () => {
|
||||
const Select = selectWithProps({ multiple: true });
|
||||
Select.vm.$data._value = 'one';
|
||||
Select.vm.$data._value = "one";
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
Select.find(".vs__deselect").trigger("click");
|
||||
@@ -31,9 +31,9 @@ describe("Removing values", () => {
|
||||
|
||||
Select.vm.$data._value = ["one", "two"];
|
||||
|
||||
Select.find('.vs__search').trigger('keydown.backspace')
|
||||
Select.find(".vs__search").trigger("keydown.backspace");
|
||||
|
||||
expect(Select.emitted().input).toEqual([[['one']]]);
|
||||
expect(Select.emitted().input).toEqual([[["one"]]]);
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
});
|
||||
|
||||
@@ -42,20 +42,20 @@ describe("Removing values", () => {
|
||||
options: ["one", "two", "three"]
|
||||
});
|
||||
|
||||
Select.vm.$data._value = 'one';
|
||||
Select.vm.$data._value = "one";
|
||||
|
||||
Select.vm.maybeDeleteValue();
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
});
|
||||
|
||||
it('will not emit input event if value has not changed with backspace', () => {
|
||||
it("will not emit input event if value has not changed with backspace", () => {
|
||||
const Select = mountDefault();
|
||||
Select.vm.$data._value = 'one';
|
||||
Select.find({ ref: 'search' }).trigger('keydown.backspace');
|
||||
Select.vm.$data._value = "one";
|
||||
Select.find({ ref: "search" }).trigger("keydown.backspace");
|
||||
expect(Select.emitted().input.length).toBe(1);
|
||||
|
||||
Select.find({ ref: 'search' }).trigger('keydown.backspace');
|
||||
Select.find({ ref: 'search' }).trigger('keydown.backspace');
|
||||
Select.find({ ref: "search" }).trigger("keydown.backspace");
|
||||
Select.find({ ref: "search" }).trigger("keydown.backspace");
|
||||
expect(Select.emitted().input.length).toBe(1);
|
||||
});
|
||||
|
||||
@@ -81,9 +81,9 @@ describe("Removing values", () => {
|
||||
|
||||
it("should remove selected value when clicked", () => {
|
||||
const Select = selectWithProps({
|
||||
options: ["foo", "bar"],
|
||||
options: ["foo", "bar"]
|
||||
});
|
||||
Select.vm.$data._value = 'foo';
|
||||
Select.vm.$data._value = "foo";
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual(["foo"]);
|
||||
Select.find("button.vs__clear").trigger("click");
|
||||
|
||||
+18
-19
@@ -1,10 +1,10 @@
|
||||
import { selectWithProps } from "../helpers";
|
||||
import OpenIndicator from "../../src/components/OpenIndicator";
|
||||
|
||||
const preventDefault = jest.fn()
|
||||
const preventDefault = jest.fn();
|
||||
|
||||
function clickEvent (currentTarget) {
|
||||
return { currentTarget, preventDefault }
|
||||
function clickEvent(currentTarget) {
|
||||
return { currentTarget, preventDefault };
|
||||
}
|
||||
|
||||
describe("Toggling Dropdown", () => {
|
||||
@@ -34,7 +34,7 @@ describe("Toggling Dropdown", () => {
|
||||
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search));
|
||||
expect(Select.vm.open).toEqual(true);
|
||||
Select.vm.toggleDropdown(clickEvent(Select.vm.$el));
|
||||
expect(Select.vm.open).toEqual(false)
|
||||
expect(Select.vm.open).toEqual(false);
|
||||
});
|
||||
|
||||
it("should open the dropdown when the selected tag is clicked", () => {
|
||||
@@ -135,22 +135,22 @@ describe("Toggling Dropdown", () => {
|
||||
});
|
||||
|
||||
Select.vm.search = "foo";
|
||||
Select.find('.vs__search').trigger('keydown.esc')
|
||||
Select.find(".vs__search").trigger("keydown.esc");
|
||||
expect(Select.vm.search).toEqual("");
|
||||
});
|
||||
|
||||
it("should have an open class when dropdown is active", () => {
|
||||
const Select = selectWithProps();
|
||||
|
||||
expect(Select.vm.stateClasses['vs--open']).toEqual(false);
|
||||
expect(Select.vm.stateClasses["vs--open"]).toEqual(false);
|
||||
|
||||
Select.vm.open = true;
|
||||
expect(Select.vm.stateClasses['vs--open']).toEqual(true);
|
||||
expect(Select.vm.stateClasses["vs--open"]).toEqual(true);
|
||||
});
|
||||
|
||||
it("should not display the dropdown if noDrop is true", async () => {
|
||||
const Select = selectWithProps({
|
||||
noDrop: true,
|
||||
noDrop: true
|
||||
});
|
||||
|
||||
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search));
|
||||
@@ -158,34 +158,33 @@ describe("Toggling Dropdown", () => {
|
||||
expect(Select.vm.open).toEqual(true);
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.contains('.vs__dropdown-menu')).toBeFalsy();
|
||||
expect(Select.contains('.vs__dropdown-option')).toBeFalsy();
|
||||
expect(Select.contains('.vs__no-options')).toBeFalsy();
|
||||
expect(Select.vm.stateClasses['vs--open']).toBeFalsy();
|
||||
expect(Select.contains(".vs__dropdown-menu")).toBeFalsy();
|
||||
expect(Select.contains(".vs__dropdown-option")).toBeFalsy();
|
||||
expect(Select.contains(".vs__no-options")).toBeFalsy();
|
||||
expect(Select.vm.stateClasses["vs--open"]).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should hide the open indicator if noDrop is true", () => {
|
||||
const Select = selectWithProps({
|
||||
noDrop: true,
|
||||
noDrop: true
|
||||
});
|
||||
expect(Select.contains(OpenIndicator)).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should not add the searchable state class when noDrop is true", () => {
|
||||
const Select = selectWithProps({
|
||||
noDrop: true,
|
||||
noDrop: true
|
||||
});
|
||||
expect(Select.classes('vs--searchable')).toBeFalsy();
|
||||
expect(Select.classes("vs--searchable")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should not add the searching state class when noDrop is true", () => {
|
||||
const Select = selectWithProps({
|
||||
noDrop: true,
|
||||
noDrop: true
|
||||
});
|
||||
|
||||
Select.vm.search = 'Canada';
|
||||
Select.vm.search = "Canada";
|
||||
|
||||
expect(Select.classes('vs--searching')).toBeFalsy();
|
||||
expect(Select.classes("vs--searching")).toBeFalsy();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -6,11 +6,11 @@ describe("Filtering Options", () => {
|
||||
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');
|
||||
|
||||
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", () => {
|
||||
|
||||
+27
-31
@@ -1,74 +1,70 @@
|
||||
import { mountDefault } from '../helpers';
|
||||
import { mountDefault } from "../helpers";
|
||||
|
||||
describe('Custom Keydown Handlers', () => {
|
||||
|
||||
it('can use the map-keydown prop to trigger custom behaviour', () => {
|
||||
describe("Custom Keydown Handlers", () => {
|
||||
it("can use the map-keydown prop to trigger custom behaviour", () => {
|
||||
const onKeyDown = jest.fn();
|
||||
const Select = mountDefault({
|
||||
mapKeydown: (defaults, vm) => ({ ...defaults, 32: onKeyDown }),
|
||||
mapKeydown: (defaults, vm) => ({ ...defaults, 32: onKeyDown })
|
||||
});
|
||||
|
||||
Select.find({ ref: 'search' }).trigger('keydown.space');
|
||||
Select.find({ ref: "search" }).trigger("keydown.space");
|
||||
|
||||
expect(onKeyDown.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('selectOnKeyCodes should trigger a selection for custom keycodes', () => {
|
||||
it("selectOnKeyCodes should trigger a selection for custom keycodes", () => {
|
||||
const Select = mountDefault({
|
||||
selectOnKeyCodes: [32],
|
||||
selectOnKeyCodes: [32]
|
||||
});
|
||||
|
||||
const spy = jest.spyOn(Select.vm, 'typeAheadSelect');
|
||||
const spy = jest.spyOn(Select.vm, "typeAheadSelect");
|
||||
|
||||
Select.find({ ref: 'search' }).trigger('keydown.space');
|
||||
Select.find({ ref: "search" }).trigger("keydown.space");
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('even works when combining selectOnKeyCodes with map-keydown', () => {
|
||||
it("even works when combining selectOnKeyCodes with map-keydown", () => {
|
||||
const onKeyDown = jest.fn();
|
||||
const Select = mountDefault({
|
||||
mapKeydown: (defaults, vm) => ({ ...defaults, 32: onKeyDown }),
|
||||
selectOnKeyCodes: [9],
|
||||
selectOnKeyCodes: [9]
|
||||
});
|
||||
|
||||
const spy = jest.spyOn(Select.vm, 'typeAheadSelect');
|
||||
const spy = jest.spyOn(Select.vm, "typeAheadSelect");
|
||||
|
||||
Select.find({ ref: 'search' }).trigger('keydown.space');
|
||||
Select.find({ ref: "search" }).trigger("keydown.space");
|
||||
expect(onKeyDown.mock.calls.length).toBe(1);
|
||||
|
||||
Select.find({ ref: 'search' }).trigger('keydown.tab');
|
||||
Select.find({ ref: "search" }).trigger("keydown.tab");
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
describe('CompositionEvent support', () => {
|
||||
|
||||
it('will not select a value with enter if the user is composing', () => {
|
||||
describe("CompositionEvent support", () => {
|
||||
it("will not select a value with enter if the user is composing", () => {
|
||||
const Select = mountDefault();
|
||||
const spy = jest.spyOn(Select.vm, 'typeAheadSelect');
|
||||
const spy = jest.spyOn(Select.vm, "typeAheadSelect");
|
||||
|
||||
Select.find({ ref: 'search' }).trigger('compositionstart');
|
||||
Select.find({ ref: 'search' }).trigger('keydown.enter');
|
||||
Select.find({ ref: "search" }).trigger("compositionstart");
|
||||
Select.find({ ref: "search" }).trigger("keydown.enter");
|
||||
expect(spy).toHaveBeenCalledTimes(0);
|
||||
|
||||
Select.find({ ref: 'search' }).trigger('compositionend');
|
||||
Select.find({ ref: 'search' }).trigger('keydown.enter');
|
||||
Select.find({ ref: "search" }).trigger("compositionend");
|
||||
Select.find({ ref: "search" }).trigger("keydown.enter");
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('will not select a value with tab if the user is composing', () => {
|
||||
it("will not select a value with tab if the user is composing", () => {
|
||||
const Select = mountDefault({ selectOnTab: true });
|
||||
const spy = jest.spyOn(Select.vm, 'typeAheadSelect');
|
||||
const spy = jest.spyOn(Select.vm, "typeAheadSelect");
|
||||
|
||||
Select.find({ ref: 'search' }).trigger('compositionstart');
|
||||
Select.find({ ref: 'search' }).trigger('keydown.tab');
|
||||
Select.find({ ref: "search" }).trigger("compositionstart");
|
||||
Select.find({ ref: "search" }).trigger("keydown.tab");
|
||||
expect(spy).toHaveBeenCalledTimes(0);
|
||||
|
||||
Select.find({ ref: 'search' }).trigger('compositionend');
|
||||
Select.find({ ref: 'search' }).trigger('keydown.tab');
|
||||
Select.find({ ref: "search" }).trigger("compositionend");
|
||||
Select.find({ ref: "search" }).trigger("keydown.tab");
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
+20
-16
@@ -42,15 +42,19 @@ describe("Labels", () => {
|
||||
expect(Select.vm.searchPlaceholder).not.toBeDefined();
|
||||
});
|
||||
|
||||
describe('getOptionLabel', () => {
|
||||
it('will return undefined if the option lacks the label key', () => {
|
||||
const getOptionLabel = VueSelect.props.getOptionLabel.default.bind({ label: 'label' });
|
||||
expect(getOptionLabel({name: 'vue'})).toEqual(undefined);
|
||||
describe("getOptionLabel", () => {
|
||||
it("will return undefined if the option lacks the label key", () => {
|
||||
const getOptionLabel = VueSelect.props.getOptionLabel.default.bind({
|
||||
label: "label"
|
||||
});
|
||||
expect(getOptionLabel({ name: "vue" })).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('will return a string value for a valid key', () => {
|
||||
const getOptionLabel = VueSelect.props.getOptionLabel.default.bind({ label: 'label' });
|
||||
expect(getOptionLabel({label: 'vue'})).toEqual('vue');
|
||||
it("will return a string value for a valid key", () => {
|
||||
const getOptionLabel = VueSelect.props.getOptionLabel.default.bind({
|
||||
label: "label"
|
||||
});
|
||||
expect(getOptionLabel({ label: "vue" })).toEqual("vue");
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -59,23 +63,23 @@ describe("Labels", () => {
|
||||
* @see https://github.com/vuejs/vue/issues/10224
|
||||
* @see https://github.com/vuejs/vue/pull/10229
|
||||
*/
|
||||
xit('will not call getOptionLabel if both scoped option slots are used and a filter is provided', () => {
|
||||
const spy = spyOn(VueSelect.props.getOptionLabel, 'default');
|
||||
xit("will not call getOptionLabel if both scoped option slots are used and a filter is provided", () => {
|
||||
const spy = spyOn(VueSelect.props.getOptionLabel, "default");
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
options: [{name: 'one'}],
|
||||
filter: () => {},
|
||||
options: [{ name: "one" }],
|
||||
filter: () => {}
|
||||
},
|
||||
scopedSlots: {
|
||||
'option': '<span class="option">{{ props.name }}</span>',
|
||||
'selected-option': '<span class="selected">{{ props.name }}</span>',
|
||||
},
|
||||
option: '<span class="option">{{ props.name }}</span>',
|
||||
"selected-option": '<span class="selected">{{ props.name }}</span>'
|
||||
}
|
||||
});
|
||||
|
||||
Select.vm.select({name: 'one'});
|
||||
Select.vm.select({ name: "one" });
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(0);
|
||||
expect(Select.find('.selected').exists()).toBeTruthy();
|
||||
expect(Select.find(".selected").exists()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
import Select from '../../src/components/Select';
|
||||
|
||||
describe('Comparing Options', () => {
|
||||
import Select from "../../src/components/Select";
|
||||
|
||||
describe("Comparing Options", () => {
|
||||
const comparator = Select.methods.optionComparator.bind({
|
||||
getOptionKey: Select.props.getOptionKey.default,
|
||||
getOptionKey: Select.props.getOptionKey.default
|
||||
});
|
||||
|
||||
it('can compare numbers', () => {
|
||||
it("can compare numbers", () => {
|
||||
expect(comparator(1, 2)).toBeFalsy();
|
||||
expect(comparator(1, 1)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('can compare strings', () => {
|
||||
expect(comparator('one', 'one')).toBeTruthy();
|
||||
expect(comparator('one', 'two')).toBeFalsy();
|
||||
it("can compare strings", () => {
|
||||
expect(comparator("one", "one")).toBeTruthy();
|
||||
expect(comparator("one", "two")).toBeFalsy();
|
||||
});
|
||||
|
||||
it('can compare objects', () => {
|
||||
it("can compare objects", () => {
|
||||
// compare ID keys
|
||||
expect(comparator({label: 'halo', id: 1}, {label: 'halo', id: 2}))
|
||||
.toBeFalsy();
|
||||
expect(
|
||||
comparator({ label: "halo", id: 1 }, { label: "halo", id: 2 })
|
||||
).toBeFalsy();
|
||||
// compare objects
|
||||
expect(comparator({label: 'halo', value: 1}, {label: 'halo', value: 1}))
|
||||
.toBeTruthy();
|
||||
expect(
|
||||
comparator({ label: "halo", value: 1 }, { label: "halo", value: 1 })
|
||||
).toBeTruthy();
|
||||
// compare objects with different orders
|
||||
expect(comparator({value: 1, label: 'halo'}, {label: 'halo', value: 1}))
|
||||
.toBeTruthy();
|
||||
expect(
|
||||
comparator({ value: 1, label: "halo" }, { label: "halo", value: 1 })
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import Select from '../../src/components/Select.vue';
|
||||
|
||||
describe('Serializing Option Keys', () => {
|
||||
import Select from "../../src/components/Select.vue";
|
||||
|
||||
describe("Serializing Option Keys", () => {
|
||||
const getOptionKey = Select.props.getOptionKey.default;
|
||||
|
||||
it('can serialize strings to a key', () => {
|
||||
expect(getOptionKey('vue')).toBe('vue');
|
||||
it("can serialize strings to a key", () => {
|
||||
expect(getOptionKey("vue")).toBe("vue");
|
||||
});
|
||||
|
||||
it('can serialize integers to a key', () => {
|
||||
it("can serialize integers to a key", () => {
|
||||
expect(getOptionKey(1)).toBe(1);
|
||||
});
|
||||
|
||||
it('can serialize objects to a key', () => {
|
||||
expect(getOptionKey({label: 'vue'})).toBe('{"label":"vue"}');
|
||||
it("can serialize objects to a key", () => {
|
||||
expect(getOptionKey({ label: "vue" })).toBe('{"label":"vue"}');
|
||||
});
|
||||
|
||||
it('will use an ID property if the object contains one', () => {
|
||||
expect(getOptionKey({id: 1})).toBe(1);
|
||||
expect(getOptionKey({id: 'one'})).toBe('one');
|
||||
expect(getOptionKey({id: {im: 'a nested object'}}))
|
||||
.toEqual({im: 'a nested object'});
|
||||
it("will use an ID property if the object contains one", () => {
|
||||
expect(getOptionKey({ id: 1 })).toBe(1);
|
||||
expect(getOptionKey({ id: "one" })).toBe("one");
|
||||
expect(getOptionKey({ id: { im: "a nested object" } })).toEqual({
|
||||
im: "a nested object"
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import { mount, shallowMount } from "@vue/test-utils";
|
||||
import VueSelect from "../../src/components/Select";
|
||||
import { mountDefault } from '../helpers';
|
||||
import { mountDefault } from "../helpers";
|
||||
|
||||
describe("Reset on options change", () => {
|
||||
it("should not reset the selected value by default when the options property changes", () => {
|
||||
@@ -8,80 +8,94 @@ describe("Reset on options change", () => {
|
||||
propsData: { options: ["one"] }
|
||||
});
|
||||
|
||||
Select.vm.$data._value = 'one';
|
||||
Select.vm.$data._value = "one";
|
||||
|
||||
Select.setProps({options: ["four", "five", "six"]});
|
||||
Select.setProps({ options: ["four", "five", "six"] });
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
});
|
||||
|
||||
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(() => {});
|
||||
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'},
|
||||
mountDefault({ resetOnOptionsChange: 1 });
|
||||
expect(spy.mock.calls[0][0]).toContain(
|
||||
'Invalid prop: custom validator check failed for prop "resetOnOptionsChange"'
|
||||
);
|
||||
|
||||
Select.setProps({options: ['lake', 'kite']});
|
||||
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']);
|
||||
expect(resetOnOptionsChange).toHaveBeenCalledWith(
|
||||
["lake", "kite"],
|
||||
["bear"],
|
||||
["selected"]
|
||||
);
|
||||
});
|
||||
|
||||
it('should allow resetOnOptionsChange to be a function that returns true', async () => {
|
||||
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'},
|
||||
propsData: { resetOnOptionsChange, options: ["one"], value: "one" }
|
||||
});
|
||||
const spy = jest.spyOn(Select.vm, 'clearSelection');
|
||||
const spy = jest.spyOn(Select.vm, "clearSelection");
|
||||
|
||||
Select.setProps({options: ['one', 'two']});
|
||||
Select.setProps({ options: ["one", "two"] });
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should allow resetOnOptionsChange to be a function that returns false', () => {
|
||||
it("should allow resetOnOptionsChange to be a function that returns false", () => {
|
||||
let resetOnOptionsChange = () => false;
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {resetOnOptionsChange, options: ['one'], value: 'one'},
|
||||
propsData: { resetOnOptionsChange, options: ["one"], value: "one" }
|
||||
});
|
||||
const spy = jest.spyOn(Select.vm, 'clearSelection');
|
||||
const spy = jest.spyOn(Select.vm, "clearSelection");
|
||||
|
||||
Select.setProps({options: ['one', 'two']});
|
||||
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));
|
||||
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'},
|
||||
propsData: { resetOnOptionsChange, options: ["one"], value: "one" }
|
||||
});
|
||||
const spy = jest.spyOn(Select.vm, 'clearSelection');
|
||||
const spy = jest.spyOn(Select.vm, "clearSelection");
|
||||
|
||||
Select.setProps({options: ['one', 'two']});
|
||||
Select.setProps({ options: ["one", "two"] });
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual(['one']);
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
|
||||
Select.setProps({options: ['two']});
|
||||
Select.setProps({ options: ["two"] });
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
@@ -93,9 +107,9 @@ describe("Reset on options change", () => {
|
||||
propsData: { resetOnOptionsChange: true, options: ["one"] }
|
||||
});
|
||||
|
||||
Select.vm.$data._value = 'one';
|
||||
Select.vm.$data._value = "one";
|
||||
|
||||
Select.setProps({options: ["four", "five", "six"]});
|
||||
Select.setProps({ options: ["four", "five", "six"] });
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual([]);
|
||||
@@ -103,39 +117,47 @@ describe("Reset on options change", () => {
|
||||
|
||||
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 } }
|
||||
propsData: {
|
||||
value: "one",
|
||||
options: [],
|
||||
reduce(option) {
|
||||
return option.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Select.setProps({options: [{ label: "oneLabel", value: "one" }]});
|
||||
Select.setProps({ options: [{ label: "oneLabel", value: "one" }] });
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "oneLabel", value: "one" }]);
|
||||
expect(Select.vm.selectedValue).toEqual([
|
||||
{ label: "oneLabel", value: "one" }
|
||||
]);
|
||||
});
|
||||
|
||||
it('clearSearchOnBlur returns false when multiple is true', () => {
|
||||
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');
|
||||
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,
|
||||
multiple: false
|
||||
});
|
||||
expect(Select.vm.search).toBe('');
|
||||
expect(Select.vm.search).toBe("");
|
||||
});
|
||||
|
||||
it('clearSearchOnBlur accepts a function', () => {
|
||||
it("clearSearchOnBlur accepts a function", () => {
|
||||
let clearSearchOnBlur = jest.fn(() => false);
|
||||
const Select = mountDefault({clearSearchOnBlur});
|
||||
const Select = mountDefault({ clearSearchOnBlur });
|
||||
|
||||
Select.find({ref: 'search'}).trigger('click');
|
||||
Select.setData({search: 'one'});
|
||||
Select.find({ref: 'search'}).trigger('blur');
|
||||
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');
|
||||
expect(Select.vm.search).toBe("one");
|
||||
});
|
||||
});
|
||||
|
||||
+55
-41
@@ -10,7 +10,9 @@ describe("When reduce prop is defined", () => {
|
||||
options: [{ label: "This is Foo", value: "foo" }]
|
||||
}
|
||||
});
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "This is Foo", value: "foo" }]);
|
||||
expect(Select.vm.selectedValue).toEqual([
|
||||
{ label: "This is Foo", value: "foo" }
|
||||
]);
|
||||
});
|
||||
|
||||
it("can determine if an object is pre-selected", () => {
|
||||
@@ -35,22 +37,24 @@ describe("When reduce prop is defined", () => {
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
it('can determine if an object is selected after its been chosen', () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
reduce: option => option.id,
|
||||
options: [{id: 'foo', label: 'FooBar'}],
|
||||
},
|
||||
});
|
||||
|
||||
Select.vm.select({id: 'foo', label: 'FooBar'});
|
||||
|
||||
expect(Select.vm.isOptionSelected({
|
||||
id: 'foo',
|
||||
label: 'This is FooBar',
|
||||
})).toEqual(true);
|
||||
it("can determine if an object is selected after its been chosen", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
reduce: option => option.id,
|
||||
options: [{ id: "foo", label: "FooBar" }]
|
||||
}
|
||||
});
|
||||
|
||||
Select.vm.select({ id: "foo", label: "FooBar" });
|
||||
|
||||
expect(
|
||||
Select.vm.isOptionSelected({
|
||||
id: "foo",
|
||||
label: "This is FooBar"
|
||||
})
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
it("can accept an array of objects and pre-selected values (multiple)", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
@@ -64,7 +68,9 @@ describe("When reduce prop is defined", () => {
|
||||
}
|
||||
});
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "This is Foo", value: "foo" }]);
|
||||
expect(Select.vm.selectedValue).toEqual([
|
||||
{ label: "This is Foo", value: "foo" }
|
||||
]);
|
||||
});
|
||||
|
||||
it("can deselect a pre-selected object", () => {
|
||||
@@ -79,7 +85,7 @@ describe("When reduce prop is defined", () => {
|
||||
}
|
||||
});
|
||||
|
||||
Select.vm.$data._value = ['foo', 'bar'];
|
||||
Select.vm.$data._value = ["foo", "bar"];
|
||||
|
||||
Select.vm.deselect("foo");
|
||||
expect(Select.vm.selectedValue).toEqual(["bar"]);
|
||||
@@ -118,7 +124,7 @@ describe("When reduce prop is defined", () => {
|
||||
return this.current;
|
||||
},
|
||||
set(value) {
|
||||
if (value == 'baz') return;
|
||||
if (value == "baz") return;
|
||||
this.current = value;
|
||||
}
|
||||
}
|
||||
@@ -134,18 +140,24 @@ describe("When reduce prop is defined", () => {
|
||||
const Select = Parent.vm.$children[0];
|
||||
|
||||
expect(Select.value).toEqual("foo");
|
||||
expect(Select.selectedValue).toEqual([{ label: "This is Foo", value: "foo" }]);
|
||||
expect(Select.selectedValue).toEqual([
|
||||
{ label: "This is Foo", value: "foo" }
|
||||
]);
|
||||
|
||||
Select.select({ label: "This is Bar", value: "bar" });
|
||||
await Select.$nextTick();
|
||||
expect(Parent.vm.value).toEqual("bar");
|
||||
expect(Select.selectedValue).toEqual([{ label: "This is Bar", value: "bar" }]);
|
||||
expect(Select.selectedValue).toEqual([
|
||||
{ label: "This is Bar", value: "bar" }
|
||||
]);
|
||||
|
||||
// Parent denies to set baz
|
||||
Select.select({ label: "This is Baz", value: "baz" });
|
||||
await Select.$nextTick();
|
||||
expect(Select.selectedValue).toEqual([{ label: "This is Bar", value: "bar" }]);
|
||||
expect(Parent.vm.value).toEqual('bar');
|
||||
expect(Select.selectedValue).toEqual([
|
||||
{ label: "This is Bar", value: "bar" }
|
||||
]);
|
||||
expect(Parent.vm.value).toEqual("bar");
|
||||
});
|
||||
|
||||
it("can generate labels using a custom label key", () => {
|
||||
@@ -155,7 +167,10 @@ describe("When reduce prop is defined", () => {
|
||||
reduce: option => option.value,
|
||||
value: ["CA"],
|
||||
label: "name",
|
||||
options: [{ value: "CA", name: "Canada" }, { value: "US", name: "United States" }]
|
||||
options: [
|
||||
{ value: "CA", name: "Canada" },
|
||||
{ value: "US", name: "United States" }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
@@ -177,28 +192,28 @@ describe("When reduce prop is defined", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('can work with falsey values', () => {
|
||||
const option = {value: 0, label: 'No'};
|
||||
it("can work with falsey values", () => {
|
||||
const option = { value: 0, label: "No" };
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
reduce: option => option.value,
|
||||
options: [option, {value: 1, label: 'Yes'}],
|
||||
value: 0,
|
||||
},
|
||||
options: [option, { value: 1, label: "Yes" }],
|
||||
value: 0
|
||||
}
|
||||
});
|
||||
|
||||
expect(Select.vm.findOptionFromReducedValue(option)).toEqual(option);
|
||||
expect(Select.vm.selectedValue).toEqual([option]);
|
||||
});
|
||||
|
||||
it('works with null values', () => {
|
||||
const option = {value: null, label: 'No'};
|
||||
it("works with null values", () => {
|
||||
const option = { value: null, label: "No" };
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: {
|
||||
reduce: option => option.value,
|
||||
options: [option, {value: 1, label: 'Yes'}],
|
||||
value: null,
|
||||
},
|
||||
options: [option, { value: 1, label: "Yes" }],
|
||||
value: null
|
||||
}
|
||||
});
|
||||
|
||||
expect(Select.vm.findOptionFromReducedValue(option)).toEqual(option);
|
||||
@@ -233,7 +248,6 @@ describe("When reduce prop is defined", () => {
|
||||
Select.vm.select(nestedOption);
|
||||
expect(Select.vm.isOptionSelected(nestedOption)).toEqual(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("reacts correctly when value property changes", async () => {
|
||||
@@ -252,10 +266,10 @@ describe("When reduce prop is defined", () => {
|
||||
expect(Select.vm.selectedValue).toEqual([optionToChangeTo]);
|
||||
});
|
||||
|
||||
describe('Reducing Tags', () => {
|
||||
it('tracks values that have been created by the user', async () => {
|
||||
describe("Reducing Tags", () => {
|
||||
it("tracks values that have been created by the user", async () => {
|
||||
const Parent = mount({
|
||||
data: () => ({selected: null, options: []}),
|
||||
data: () => ({ selected: null, options: [] }),
|
||||
template: `
|
||||
<v-select
|
||||
v-model="selected"
|
||||
@@ -265,7 +279,7 @@ describe("When reduce prop is defined", () => {
|
||||
:create-option="label => ({ label, value: -1 })"
|
||||
/>
|
||||
`,
|
||||
components: {'v-select': VueSelect},
|
||||
components: { "v-select": VueSelect }
|
||||
});
|
||||
const Select = Parent.vm.$children[0];
|
||||
|
||||
@@ -273,15 +287,15 @@ describe("When reduce prop is defined", () => {
|
||||
Select.$refs.search.focus();
|
||||
await Select.$nextTick();
|
||||
|
||||
Select.search = 'hello';
|
||||
Select.search = "hello";
|
||||
await Select.$nextTick();
|
||||
|
||||
Select.typeAheadSelect();
|
||||
await Select.$nextTick();
|
||||
|
||||
// Then
|
||||
expect(Select.selectedValue).toEqual([{label: 'hello', value: -1}]);
|
||||
expect(Select.$refs.selectedOptions.textContent.trim()).toEqual('hello');
|
||||
expect(Select.selectedValue).toEqual([{ label: "hello", value: -1 }]);
|
||||
expect(Select.$refs.selectedOptions.textContent.trim()).toEqual("hello");
|
||||
expect(Parent.vm.selected).toEqual(-1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ describe("Selectable prop", () => {
|
||||
it("should select selectable option if clicked", async () => {
|
||||
const Select = selectWithProps({
|
||||
options: ["one", "two", "three"],
|
||||
selectable: (option) => option === "one"
|
||||
selectable: option => option === "one"
|
||||
});
|
||||
|
||||
Select.vm.$data.open = true;
|
||||
@@ -14,12 +14,12 @@ describe("Selectable prop", () => {
|
||||
|
||||
await Select.vm.$nextTick();
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
})
|
||||
});
|
||||
|
||||
it("should not select not selectable option if clicked", async () => {
|
||||
const Select = selectWithProps({
|
||||
options: ["one", "two", "three"],
|
||||
selectable: (option) => option === "one"
|
||||
selectable: option => option === "one"
|
||||
});
|
||||
|
||||
Select.vm.$data.open = true;
|
||||
@@ -34,7 +34,7 @@ describe("Selectable prop", () => {
|
||||
it("should skip non-selectable option on down arrow keyDown", () => {
|
||||
const Select = selectWithProps({
|
||||
options: ["one", "two", "three"],
|
||||
selectable: (option) => option !== "two"
|
||||
selectable: option => option !== "two"
|
||||
});
|
||||
|
||||
Select.vm.typeAheadPointer = 1;
|
||||
@@ -42,12 +42,12 @@ describe("Selectable prop", () => {
|
||||
Select.find({ ref: "search" }).trigger("keydown.down");
|
||||
|
||||
expect(Select.vm.typeAheadPointer).toEqual(2);
|
||||
})
|
||||
});
|
||||
|
||||
it("should skip non-selectable option on up arrow keyDown", () => {
|
||||
const Select = selectWithProps({
|
||||
options: ["one", "two", "three"],
|
||||
selectable: (option) => option !== "two"
|
||||
selectable: option => option !== "two"
|
||||
});
|
||||
|
||||
Select.vm.typeAheadPointer = 2;
|
||||
@@ -55,5 +55,5 @@ describe("Selectable prop", () => {
|
||||
Select.find({ ref: "search" }).trigger("keydown.up");
|
||||
|
||||
expect(Select.vm.typeAheadPointer).toEqual(0);
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { mount, shallowMount } from "@vue/test-utils";
|
||||
import VueSelect from "../../src/components/Select.vue";
|
||||
import { mountDefault } from '../helpers';
|
||||
import { mountDefault } from "../helpers";
|
||||
|
||||
describe("VS - Selecting Values", () => {
|
||||
let defaultProps;
|
||||
@@ -81,7 +81,9 @@ describe("VS - Selecting Values", () => {
|
||||
];
|
||||
|
||||
Select.vm.deselect({ label: "This is Foo", value: "foo" });
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "This is Bar", value: "bar" }]);
|
||||
expect(Select.vm.selectedValue).toEqual([
|
||||
{ label: "This is Bar", value: "bar" }
|
||||
]);
|
||||
});
|
||||
|
||||
it("can deselect a pre-selected string", () => {
|
||||
@@ -193,15 +195,20 @@ describe("VS - Selecting Values", () => {
|
||||
value: [{ label: "foo", value: "bar" }]
|
||||
}
|
||||
});
|
||||
expect(Select.vm.isOptionSelected({ label: "foo", value: "bar" })).toEqual(true);
|
||||
expect(Select.vm.isOptionSelected({ label: "foo", value: "bar" })).toEqual(
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('can select two options with the same label', () => {
|
||||
const options = [{label: 'one', id: 1}, {label: 'one', id: 2}];
|
||||
const Select = mountDefault({options, multiple: true});
|
||||
it("can select two options with the same label", () => {
|
||||
const options = [
|
||||
{ label: "one", id: 1 },
|
||||
{ label: "one", id: 2 }
|
||||
];
|
||||
const Select = mountDefault({ options, multiple: true });
|
||||
|
||||
Select.vm.select({label: 'one', id: 1});
|
||||
Select.vm.select({label: 'one', id: 2});
|
||||
Select.vm.select({ label: "one", id: 1 });
|
||||
Select.vm.select({ label: "one", id: 2 });
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual(options);
|
||||
});
|
||||
@@ -223,7 +230,11 @@ describe("VS - Selecting Values", () => {
|
||||
|
||||
it("will not trigger the input event when multiple is true and selection is repeated", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: { multiple: true, value: ["foo ", "bar"], options: ["foo", "bar", "baz"] }
|
||||
propsData: {
|
||||
multiple: true,
|
||||
value: ["foo ", "bar"],
|
||||
options: ["foo", "bar", "baz"]
|
||||
}
|
||||
});
|
||||
|
||||
Select.vm.select("bar");
|
||||
@@ -257,7 +268,11 @@ describe("VS - Selecting Values", () => {
|
||||
|
||||
it("will trigger the option:selecting event regardless of current value when multiple is true", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: { multiple: true, value: ["foo", "bar"], options: ["foo", "bar"] }
|
||||
propsData: {
|
||||
multiple: true,
|
||||
value: ["foo", "bar"],
|
||||
options: ["foo", "bar"]
|
||||
}
|
||||
});
|
||||
Select.vm.select("bar");
|
||||
Select.vm.select("bar");
|
||||
@@ -293,7 +308,11 @@ describe("VS - Selecting Values", () => {
|
||||
|
||||
it("will trigger the option:selected event regardless of current value when multiple is true", () => {
|
||||
const Select = shallowMount(VueSelect, {
|
||||
propsData: { multiple: true, value: ["foo", "bar"], options: ["foo", "bar"] }
|
||||
propsData: {
|
||||
multiple: true,
|
||||
value: ["foo", "bar"],
|
||||
options: ["foo", "bar"]
|
||||
}
|
||||
});
|
||||
Select.vm.deselect("bar");
|
||||
Select.vm.deselect("bar");
|
||||
|
||||
+99
-68
@@ -1,122 +1,153 @@
|
||||
import { mountDefault } from '../helpers';
|
||||
import { mountDefault } from "../helpers";
|
||||
|
||||
describe('Scoped Slots', () => {
|
||||
it('receives an option object to the selected-option-container slot', () => {
|
||||
describe("Scoped Slots", () => {
|
||||
it("receives an option object to the selected-option-container slot", () => {
|
||||
const Select = mountDefault(
|
||||
{value: 'one'},
|
||||
{ value: "one" },
|
||||
{
|
||||
scopedSlots: {
|
||||
'selected-option-container': `<span slot="selected-option-container" slot-scope="{option}">{{ option.label }}</span>`,
|
||||
},
|
||||
});
|
||||
"selected-option-container": `<span slot="selected-option-container" slot-scope="{option}">{{ option.label }}</span>`
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
expect(Select.find({ref: 'selectedOptions'}).text()).toEqual('one');
|
||||
expect(Select.find({ ref: "selectedOptions" }).text()).toEqual("one");
|
||||
});
|
||||
|
||||
describe('Slot: selected-option', () => {
|
||||
it('receives an option object to the selected-option slot', () => {
|
||||
describe("Slot: selected-option", () => {
|
||||
it("receives an option object to the selected-option slot", () => {
|
||||
const Select = mountDefault(
|
||||
{value: 'one'},
|
||||
{ value: "one" },
|
||||
{
|
||||
scopedSlots: {
|
||||
'selected-option': `<span slot="selected-option" slot-scope="option">{{ option.label }}</span>`,
|
||||
},
|
||||
});
|
||||
"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>`,
|
||||
},
|
||||
});
|
||||
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);
|
||||
});
|
||||
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',
|
||||
async () => {
|
||||
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();
|
||||
Select.vm.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(Select.find({ref: 'dropdownMenu'}).text()).toEqual('onetwothree');
|
||||
});
|
||||
expect(Select.find({ ref: "dropdownMenu" }).text()).toEqual("onetwothree");
|
||||
});
|
||||
|
||||
it('noOptions slot receives the current search text', async () => {
|
||||
it("noOptions slot receives the current search text", async () => {
|
||||
const noOptions = jest.fn();
|
||||
const Select = mountDefault({}, {
|
||||
scopedSlots: {'no-options': noOptions},
|
||||
});
|
||||
const Select = mountDefault(
|
||||
{},
|
||||
{
|
||||
scopedSlots: { "no-options": noOptions }
|
||||
}
|
||||
);
|
||||
|
||||
Select.vm.search = 'something not there';
|
||||
Select.vm.search = "something not there";
|
||||
Select.vm.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
|
||||
expect(noOptions).toHaveBeenCalledWith({
|
||||
loading: false,
|
||||
search: 'something not there',
|
||||
searching: true,
|
||||
})
|
||||
search: "something not there",
|
||||
searching: true
|
||||
});
|
||||
});
|
||||
|
||||
test('header slot props', async () => {
|
||||
test("header slot props", async () => {
|
||||
const header = jest.fn();
|
||||
const Select = mountDefault({}, {
|
||||
scopedSlots: {header: header},
|
||||
});
|
||||
const Select = mountDefault(
|
||||
{},
|
||||
{
|
||||
scopedSlots: { header: header }
|
||||
}
|
||||
);
|
||||
await Select.vm.$nextTick();
|
||||
expect(Object.keys(header.mock.calls[0][0])).toEqual([
|
||||
'search', 'loading', 'searching', 'filteredOptions', 'deselect',
|
||||
"search",
|
||||
"loading",
|
||||
"searching",
|
||||
"filteredOptions",
|
||||
"deselect"
|
||||
]);
|
||||
});
|
||||
|
||||
test('footer slot props', async () => {
|
||||
test("footer slot props", async () => {
|
||||
const footer = jest.fn();
|
||||
const Select = mountDefault({}, {
|
||||
scopedSlots: {footer: footer},
|
||||
});
|
||||
const Select = mountDefault(
|
||||
{},
|
||||
{
|
||||
scopedSlots: { footer: footer }
|
||||
}
|
||||
);
|
||||
await Select.vm.$nextTick();
|
||||
expect(Object.keys(footer.mock.calls[0][0])).toEqual([
|
||||
'search', 'loading', 'searching', 'filteredOptions', 'deselect',
|
||||
"search",
|
||||
"loading",
|
||||
"searching",
|
||||
"filteredOptions",
|
||||
"deselect"
|
||||
]);
|
||||
});
|
||||
|
||||
test('list-header slot props', async () => {
|
||||
test("list-header slot props", async () => {
|
||||
const header = jest.fn();
|
||||
const Select = mountDefault({}, {
|
||||
scopedSlots: {'list-header': header},
|
||||
});
|
||||
const Select = mountDefault(
|
||||
{},
|
||||
{
|
||||
scopedSlots: { "list-header": header }
|
||||
}
|
||||
);
|
||||
Select.vm.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
expect(Object.keys(header.mock.calls[0][0])).toEqual([
|
||||
'search', 'loading', 'searching', 'filteredOptions',
|
||||
"search",
|
||||
"loading",
|
||||
"searching",
|
||||
"filteredOptions"
|
||||
]);
|
||||
});
|
||||
|
||||
test('list-footer slot props', async () => {
|
||||
test("list-footer slot props", async () => {
|
||||
const footer = jest.fn();
|
||||
const Select = mountDefault({}, {
|
||||
scopedSlots: {'list-footer': footer},
|
||||
});
|
||||
const Select = mountDefault(
|
||||
{},
|
||||
{
|
||||
scopedSlots: { "list-footer": footer }
|
||||
}
|
||||
);
|
||||
Select.vm.open = true;
|
||||
await Select.vm.$nextTick();
|
||||
expect(Object.keys(footer.mock.calls[0][0])).toEqual([
|
||||
'search', 'loading', 'searching', 'filteredOptions',
|
||||
"search",
|
||||
"loading",
|
||||
"searching",
|
||||
"filteredOptions"
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
+11
-14
@@ -2,12 +2,11 @@ import {
|
||||
mountDefault,
|
||||
searchSubmit,
|
||||
selectTag,
|
||||
selectWithProps,
|
||||
} from '../helpers';
|
||||
import Select from '../../src/components/Select';
|
||||
selectWithProps
|
||||
} from "../helpers";
|
||||
import Select from "../../src/components/Select";
|
||||
|
||||
describe("When Tagging Is Enabled", () => {
|
||||
|
||||
it("can determine if a given option string already exists", () => {
|
||||
const Select = selectWithProps({ taggable: true, options: ["one", "two"] });
|
||||
expect(Select.vm.optionExists("one")).toEqual(true);
|
||||
@@ -20,8 +19,8 @@ describe("When Tagging Is Enabled", () => {
|
||||
options: [{ label: "one" }, { label: "two" }]
|
||||
});
|
||||
|
||||
expect(Select.vm.optionExists({label: "one"})).toEqual(true);
|
||||
expect(Select.vm.optionExists({label: "three"})).toEqual(false);
|
||||
expect(Select.vm.optionExists({ label: "one" })).toEqual(true);
|
||||
expect(Select.vm.optionExists({ label: "three" })).toEqual(false);
|
||||
});
|
||||
|
||||
it("can determine if a given option object already exists when using custom labels", () => {
|
||||
@@ -31,7 +30,7 @@ describe("When Tagging Is Enabled", () => {
|
||||
label: "foo"
|
||||
});
|
||||
|
||||
const createOption = (text) => Select.vm.createOption(text);
|
||||
const createOption = text => Select.vm.createOption(text);
|
||||
|
||||
expect(Select.vm.optionExists(createOption("one"))).toEqual(true);
|
||||
expect(Select.vm.optionExists(createOption("three"))).toEqual(false);
|
||||
@@ -71,9 +70,7 @@ describe("When Tagging Is Enabled", () => {
|
||||
|
||||
await selectTag(Select, "two");
|
||||
|
||||
expect(Select.vm.selectedValue).toEqual([
|
||||
{ label: "two" }
|
||||
]);
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "two" }]);
|
||||
});
|
||||
|
||||
it("should add a freshly created option/tag to the options list when pushTags is true", async () => {
|
||||
@@ -236,11 +233,11 @@ describe("When Tagging Is Enabled", () => {
|
||||
multiple: true,
|
||||
options: [{ label: "two" }]
|
||||
});
|
||||
const spy = jest.spyOn(Select.vm, 'select');
|
||||
const spy = jest.spyOn(Select.vm, "select");
|
||||
|
||||
await selectTag(Select, "one");
|
||||
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
|
||||
expect(spy).lastCalledWith({label: 'one'});
|
||||
expect(spy).lastCalledWith({ label: "one" });
|
||||
expect(Select.vm.search).toEqual("");
|
||||
|
||||
await selectTag(Select, "one");
|
||||
@@ -258,6 +255,6 @@ describe("When Tagging Is Enabled", () => {
|
||||
Select.find({ ref: "search" }).trigger("keydown.tab");
|
||||
|
||||
await Select.vm.$nextTick();
|
||||
expect(Select.vm.selectedValue).toEqual(['one']);
|
||||
})
|
||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import HelloWorld from "@/components/HelloWorld.vue";
|
||||
|
||||
describe("HelloWorld.vue", () => {
|
||||
it("renders props.msg when passed", () => {
|
||||
const msg = "new message";
|
||||
const wrapper = shallowMount(HelloWorld, {
|
||||
props: { msg }
|
||||
});
|
||||
expect(wrapper.text()).toMatch(msg);
|
||||
});
|
||||
});
|
||||
@@ -1,14 +1,15 @@
|
||||
import sortAndStringify from '../../../src/utility/sortAndStringify';
|
||||
import sortAndStringify from "../../../src/utility/sortAndStringify";
|
||||
|
||||
test('it will stringify an object', () => {
|
||||
expect(sortAndStringify({hello: 'world'})).toEqual('{"hello":"world"}');
|
||||
test("it will stringify an object", () => {
|
||||
expect(sortAndStringify({ hello: "world" })).toEqual('{"hello":"world"}');
|
||||
});
|
||||
|
||||
test('it will sort attributes alphabetically', () => {
|
||||
expect(sortAndStringify({b: 'b', a: 'a'})).toEqual('{"a":"a","b":"b"}');
|
||||
test("it will sort attributes alphabetically", () => {
|
||||
expect(sortAndStringify({ b: "b", a: "a" })).toEqual('{"a":"a","b":"b"}');
|
||||
});
|
||||
|
||||
test('comparing two objects with unsorted keys', () => {
|
||||
expect(sortAndStringify({b: 'b', a: 'a'}))
|
||||
.toEqual(sortAndStringify({a: 'a', b: 'b'}))
|
||||
test("comparing two objects with unsorted keys", () => {
|
||||
expect(sortAndStringify({ b: "b", a: "a" })).toEqual(
|
||||
sortAndStringify({ a: "a", b: "b" })
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import uniqueId from '../../../src/utility/uniqueId';
|
||||
import uniqueId from "../../../src/utility/uniqueId";
|
||||
|
||||
test('it generates a unique number', () => {
|
||||
test("it generates a unique number", () => {
|
||||
expect(uniqueId()).not.toEqual(uniqueId());
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user