Commit 99246a895497d26e552bf5633ae6c07c07335726
Committed by
GitHub
Merge pull request #340 from huixisheng/2.0
Support Breadcrumb and add test unit and optimize webpack config
Showing
56 changed files
with
362 additions
and
143 deletions
Show diff stats
.gitignore
README.md
... | ... | @@ -53,7 +53,7 @@ |
53 | 53 | - [x] Tabs |
54 | 54 | - [x] Dropdown |
55 | 55 | - [ ] Page |
56 | -- [ ] Breadcrumb | |
56 | +- [x] Breadcrumb | |
57 | 57 | - [x] Steps |
58 | 58 | - [ ] LoadingBar |
59 | 59 | - [x] Circle |
... | ... | @@ -76,7 +76,7 @@ |
76 | 76 | |
77 | 77 | ## Install |
78 | 78 | |
79 | -### Install vue-webpack project in the first place | |
79 | +### Install vue-webpack project in the first place | |
80 | 80 | |
81 | 81 | Use [iview-project](https://github.com/iview/iview-project)(Recommended) Or [vue-cli](https://github.com/vuejs/vue-cli) |
82 | 82 | ... | ... |
1 | +/** | |
2 | + * 公共配置 | |
3 | + */ | |
4 | +var webpack = require('webpack'); | |
5 | +var path = require('path'); | |
6 | +function resolve (dir) { | |
7 | + return path.join(__dirname, '..', dir) | |
8 | +} | |
9 | + | |
10 | +module.exports = { | |
11 | + // 加载器 | |
12 | + module: { | |
13 | + // https://doc.webpack-china.org/guides/migrating/#module-loaders-module-rules | |
14 | + rules: [ | |
15 | + { | |
16 | + // https://vue-loader.vuejs.org/en/configurations/extract-css.html | |
17 | + test: /\.vue$/, | |
18 | + loader: 'vue-loader', | |
19 | + options: { | |
20 | + loaders: { | |
21 | + css: 'vue-style-loader!css-loader', | |
22 | + less: 'vue-style-loader!css-loader!less-loader' | |
23 | + }, | |
24 | + postLoaders: { | |
25 | + html: 'babel-loader' | |
26 | + } | |
27 | + } | |
28 | + }, | |
29 | + { | |
30 | + test: /\.js$/, | |
31 | + loader: 'babel-loader', exclude: /node_modules/ | |
32 | + }, | |
33 | + { | |
34 | + test: /\.css$/, | |
35 | + use: [ | |
36 | + 'style-loader', | |
37 | + 'css-loader', | |
38 | + 'autoprefixer-loader' | |
39 | + ] | |
40 | + }, | |
41 | + { | |
42 | + test: /\.less$/, | |
43 | + use: [ | |
44 | + 'style-loader', | |
45 | + 'css-loader', | |
46 | + 'less-loader' | |
47 | + ] | |
48 | + }, | |
49 | + { | |
50 | + test: /\.scss$/, | |
51 | + use: [ | |
52 | + 'style-loader', | |
53 | + 'css-loader', | |
54 | + 'sass-loader?sourceMap' | |
55 | + ] | |
56 | + }, | |
57 | + { test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/, loader: 'url-loader?limit=8192'}, | |
58 | + { test: /\.(html|tpl)$/, loader: 'html-loader' } | |
59 | + ] | |
60 | + }, | |
61 | + resolve: { | |
62 | + extensions: ['.js', '.vue'], | |
63 | + alias: { | |
64 | + 'vue': 'vue/dist/vue.esm.js', | |
65 | + '@': resolve('src'), | |
66 | + } | |
67 | + } | |
68 | +}; | ... | ... |
build/webpack.dev.config.js
... | ... | @@ -6,109 +6,37 @@ var path = require('path'); |
6 | 6 | var webpack = require('webpack'); |
7 | 7 | // var ExtractTextPlugin = require('extract-text-webpack-plugin'); |
8 | 8 | var HtmlWebpackPlugin = require('html-webpack-plugin'); |
9 | +var merge = require('webpack-merge') | |
10 | +var webpackBaseConfig = require('./webpack.base.config.js'); | |
11 | +var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') | |
9 | 12 | |
10 | -module.exports = { | |
13 | + | |
14 | +module.exports = merge(webpackBaseConfig, { | |
11 | 15 | // 入口 |
12 | 16 | entry: { |
13 | - main: './test/main', | |
17 | + main: './examples/main', | |
14 | 18 | vendors: ['vue', 'vue-router'] |
15 | 19 | }, |
16 | 20 | // 输出 |
17 | 21 | output: { |
18 | - path: path.join(__dirname, '../test/dist'), | |
22 | + path: path.join(__dirname, '../examples/dist'), | |
19 | 23 | publicPath: '', |
20 | 24 | filename: '[name].js', |
21 | 25 | chunkFilename: '[name].chunk.js' |
22 | 26 | }, |
23 | - // 加载器 | |
24 | - module: { | |
25 | - // https://doc.webpack-china.org/guides/migrating/#module-loaders-module-rules | |
26 | - rules: [ | |
27 | - { | |
28 | - // https://vue-loader.vuejs.org/en/configurations/extract-css.html | |
29 | - test: /\.vue$/, | |
30 | - loader: 'vue-loader', | |
31 | - options: { | |
32 | - loaders: { | |
33 | - css: 'vue-style-loader!css-loader', | |
34 | - less: 'vue-style-loader!css-loader!less-loader' | |
35 | - }, | |
36 | - postLoaders: { | |
37 | - html: 'babel-loader' | |
38 | - } | |
39 | - } | |
40 | - }, | |
41 | - // { test: /\.vue$/, loader: 'vue' }, | |
42 | - // Module build failed: Error: The node API for `babel` has been moved to `babel-core`. | |
43 | - // https://github.com/babel/babel-loader/blob/master/README.md#the-node-api-for-babel-has-been-moved-to-babel-core | |
44 | - { | |
45 | - test: /\.js$/, | |
46 | - loader: 'babel-loader', exclude: /node_modules/ | |
47 | - }, | |
48 | - { | |
49 | - test: /\.css$/, | |
50 | - use: [ | |
51 | - 'style-loader', | |
52 | - 'css-loader', | |
53 | - 'autoprefixer-loader' | |
54 | - ] | |
55 | - }, | |
56 | - { | |
57 | - test: /\.less$/, | |
58 | - use: [ | |
59 | - 'style-loader', | |
60 | - 'css-loader', | |
61 | - 'less-loader' | |
62 | - ] | |
63 | - // loader: 'style!css!less' | |
64 | - }, | |
65 | - { | |
66 | - test: /\.scss$/, | |
67 | - use: [ | |
68 | - 'style-loader', | |
69 | - 'css-loader', | |
70 | - 'sass-loader?sourceMap' | |
71 | - ] | |
72 | - // loader: 'style!css!sass?sourceMap' | |
73 | - }, | |
74 | - { test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/, loader: 'url-loader?limit=8192'}, | |
75 | - { test: /\.(html|tpl)$/, loader: 'html-loader' } | |
76 | - ] | |
77 | - }, | |
78 | - // vue: { | |
79 | - // loaders: { | |
80 | - // css: ExtractTextPlugin.extract( | |
81 | - // "style-loader", | |
82 | - // "css-loader?sourceMap", | |
83 | - // { | |
84 | - // publicPath: "/test/dist/" | |
85 | - // } | |
86 | - // ), | |
87 | - // less: ExtractTextPlugin.extract( | |
88 | - // 'vue-style-loader', | |
89 | - // 'css-loader!less-loader' | |
90 | - // ), | |
91 | - // js: 'babel' | |
92 | - // } | |
93 | - // }, | |
94 | 27 | resolve: { |
95 | - // require时省略的扩展名,如:require('module') 不需要module.js | |
96 | - extensions: ['.js', '.vue'], | |
97 | 28 | alias: { |
98 | 29 | iview: '../../src/index', |
99 | 30 | vue: 'vue/dist/vue.js' |
100 | 31 | } |
101 | 32 | }, |
102 | 33 | plugins: [ |
103 | - // new ExtractTextPlugin({ filename: '[name].css', disable: false, allChunks: true }), | |
104 | - // new ExtractTextPlugin("[name].css",{ allChunks : true,resolve : ['modules'] }), // 提取CSS | |
105 | - // https://doc.webpack-china.org/plugins/commons-chunk-plugin/ | |
106 | 34 | new webpack.optimize.CommonsChunkPlugin({ name: 'vendors', filename: 'vendor.bundle.js' }), |
107 | 35 | new HtmlWebpackPlugin({ |
108 | 36 | inject: true, |
109 | - filename: path.join(__dirname, '../test/dist/index.html'), | |
110 | - template: path.join(__dirname, '../test/index.html') // 模版文件 | |
111 | - }) | |
112 | - // new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'), // 提取第三方库 | |
37 | + filename: path.join(__dirname, '../examples/dist/index.html'), | |
38 | + template: path.join(__dirname, '../examples/index.html') | |
39 | + }), | |
40 | + new FriendlyErrorsPlugin() | |
113 | 41 | ] |
114 | -}; | |
42 | +}); | ... | ... |
build/webpack.dist.dev.config.js
1 | 1 | var path = require('path'); |
2 | 2 | var webpack = require('webpack'); |
3 | +var merge = require('webpack-merge') | |
4 | +var webpackBaseConfig = require('./webpack.base.config.js'); | |
3 | 5 | |
4 | -module.exports = { | |
6 | +module.exports = merge(webpackBaseConfig, { | |
5 | 7 | entry: { |
6 | 8 | main: './src/index.js' |
7 | 9 | }, |
... | ... | @@ -21,26 +23,6 @@ module.exports = { |
21 | 23 | amd: 'vue' |
22 | 24 | } |
23 | 25 | }, |
24 | - resolve: { | |
25 | - extensions: ['.js', '.vue'] | |
26 | - }, | |
27 | - module: { | |
28 | - rules: [ | |
29 | - { | |
30 | - test: /\.vue$/, | |
31 | - loader: 'vue-loader', | |
32 | - options: { | |
33 | - postLoaders: { | |
34 | - html: 'babel-loader' | |
35 | - } | |
36 | - } | |
37 | - }, | |
38 | - { | |
39 | - test: /\.js$/, | |
40 | - loader: 'babel-loader', exclude: /node_modules/ | |
41 | - } | |
42 | - ] | |
43 | - }, | |
44 | 26 | plugins: [ |
45 | 27 | new webpack.DefinePlugin({ |
46 | 28 | 'process.env': { |
... | ... | @@ -48,4 +30,4 @@ module.exports = { |
48 | 30 | } |
49 | 31 | }) |
50 | 32 | ] |
51 | -} | |
33 | +}); | ... | ... |
build/webpack.dist.prod.config.js
1 | 1 | var path = require('path'); |
2 | 2 | var webpack = require('webpack'); |
3 | +var merge = require('webpack-merge') | |
4 | +var webpackBaseConfig = require('./webpack.base.config.js'); | |
3 | 5 | |
4 | -module.exports = { | |
6 | + | |
7 | + | |
8 | +module.exports = merge(webpackBaseConfig, { | |
5 | 9 | entry: { |
6 | 10 | main: './src/index.js' |
7 | 11 | }, |
... | ... | @@ -21,26 +25,6 @@ module.exports = { |
21 | 25 | amd: 'vue' |
22 | 26 | } |
23 | 27 | }, |
24 | - resolve: { | |
25 | - extensions: ['.js', '.vue'] | |
26 | - }, | |
27 | - module: { | |
28 | - rules: [ | |
29 | - { | |
30 | - test: /\.vue$/, | |
31 | - loader: 'vue-loader', | |
32 | - options: { | |
33 | - postLoaders: { | |
34 | - html: 'babel-loader' | |
35 | - } | |
36 | - } | |
37 | - }, | |
38 | - { | |
39 | - test: /\.js$/, | |
40 | - loader: 'babel-loader', exclude: /node_modules/ | |
41 | - } | |
42 | - ] | |
43 | - }, | |
44 | 28 | plugins: [ |
45 | 29 | new webpack.DefinePlugin({ |
46 | 30 | 'process.env': { |
... | ... | @@ -53,4 +37,4 @@ module.exports = { |
53 | 37 | } |
54 | 38 | }) |
55 | 39 | ] |
56 | -} | |
40 | +}); | ... | ... |
1 | +/** | |
2 | + * 用于单元测试 | |
3 | + */ | |
4 | + | |
5 | +var webpack = require('webpack') | |
6 | +var merge = require('webpack-merge') | |
7 | +var webpackBaseConfig = require('./webpack.base.config.js'); | |
8 | + | |
9 | + | |
10 | +var webpackConfig = merge(webpackBaseConfig, { | |
11 | + // use inline sourcemap for karma-sourcemap-loader | |
12 | + devtool: '#inline-source-map', | |
13 | + plugins: [ | |
14 | + new webpack.DefinePlugin({ | |
15 | + 'process.env': { | |
16 | + NODE_ENV: '"testing"' | |
17 | + } | |
18 | + }) | |
19 | + ] | |
20 | +}) | |
21 | + | |
22 | +// no need for app entry during tests | |
23 | +delete webpackConfig.entry | |
24 | + | |
25 | +module.exports = webpackConfig | ... | ... |
test/app.vue renamed to examples/app.vue
... | ... | @@ -39,6 +39,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; } |
39 | 39 | <li><router-link to="/poptip">Poptip</router-link></li> |
40 | 40 | <li><router-link to="/slider">Slider</router-link></li> |
41 | 41 | <li><router-link to="/dropdown">Dropdown</router-link></li> |
42 | + <li><router-link to="/breadcrumb">Breadcrumb</router-link></li> | |
42 | 43 | </ul> |
43 | 44 | </nav> |
44 | 45 | <router-view></router-view> | ... | ... |
test/index.html renamed to examples/index.html
test/main.js renamed to examples/main.js
test/routers/affix.vue renamed to examples/routers/affix.vue
test/routers/alert.vue renamed to examples/routers/alert.vue
test/routers/badge.vue renamed to examples/routers/badge.vue
1 | +<style> | |
2 | + .demo-breadcrumb-separator{ | |
3 | + color: #ff5500; | |
4 | + padding: 0 5px; | |
5 | + } | |
6 | +</style> | |
7 | +<template> | |
8 | +<div> | |
9 | + <Breadcrumb separator="<b class='demo-breadcrumb-separator'>=></b>"> | |
10 | + <Breadcrumb-item href="/">Home4</Breadcrumb-item> | |
11 | + <Breadcrumb-item href="/components/breadcrumb">Components</Breadcrumb-item> | |
12 | + <Breadcrumb-item>Breadcrumb</Breadcrumb-item> | |
13 | + </Breadcrumb> | |
14 | + <Breadcrumb separator=""> | |
15 | + <Breadcrumb-item href="/"> | |
16 | + <template>Home</template> | |
17 | + <template slot="separator"> | |
18 | + <b style="color: #ff5500;">-></b> | |
19 | + </template> | |
20 | + </Breadcrumb-item> | |
21 | + <Breadcrumb-item href="/components/breadcrumb"> | |
22 | + <template>Breadcrumb</template> | |
23 | + <template slot="separator"> | |
24 | + <b style="color: #ff5500;">-></b> | |
25 | + </template> | |
26 | + </Breadcrumb-item> | |
27 | + <Breadcrumb-item>Breadcrumb</Breadcrumb-item> | |
28 | + </Breadcrumb> | |
29 | +</div> | |
30 | +</template> | |
31 | +<script> | |
32 | + export default { | |
33 | + | |
34 | + } | |
35 | +</script> | |
0 | 36 | \ No newline at end of file | ... | ... |
test/routers/button.vue renamed to examples/routers/button.vue
test/routers/card.vue renamed to examples/routers/card.vue
test/routers/carousel.vue renamed to examples/routers/carousel.vue
test/routers/cascader.vue renamed to examples/routers/cascader.vue
test/routers/checkbox.vue renamed to examples/routers/checkbox.vue
test/routers/circle.vue renamed to examples/routers/circle.vue
test/routers/collapse.vue renamed to examples/routers/collapse.vue
test/routers/date.vue renamed to examples/routers/date.vue
test/routers/dropdown.vue renamed to examples/routers/dropdown.vue
test/routers/form.vue renamed to examples/routers/form.vue
test/routers/grid.vue renamed to examples/routers/grid.vue
test/routers/input-number.vue renamed to examples/routers/input-number.vue
test/routers/input.vue renamed to examples/routers/input.vue
test/routers/menu.vue renamed to examples/routers/menu.vue
test/routers/message.vue renamed to examples/routers/message.vue
test/routers/more.vue renamed to examples/routers/more.vue
test/routers/notice.vue renamed to examples/routers/notice.vue
test/routers/page.vue renamed to examples/routers/page.vue
test/routers/poptip.vue renamed to examples/routers/poptip.vue
test/routers/progress.vue renamed to examples/routers/progress.vue
test/routers/radio.vue renamed to examples/routers/radio.vue
test/routers/rate.vue renamed to examples/routers/rate.vue
test/routers/select.vue renamed to examples/routers/select.vue
test/routers/slider.vue renamed to examples/routers/slider.vue
test/routers/steps.vue renamed to examples/routers/steps.vue
test/routers/switch.vue renamed to examples/routers/switch.vue
test/routers/table.vue renamed to examples/routers/table.vue
test/routers/tabs.vue renamed to examples/routers/tabs.vue
test/routers/tag.vue renamed to examples/routers/tag.vue
test/routers/timeline.vue renamed to examples/routers/timeline.vue
test/routers/tooltip.vue renamed to examples/routers/tooltip.vue
test/routers/transfer.vue renamed to examples/routers/transfer.vue
test/routers/tree.vue renamed to examples/routers/tree.vue
test/routers/upload.vue renamed to examples/routers/upload.vue
package.json
... | ... | @@ -25,7 +25,8 @@ |
25 | 25 | "dist:prod": "webpack --config build/webpack.dist.prod.config.js", |
26 | 26 | "dist": "npm run dist:style && npm run dist:dev && npm run dist:prod", |
27 | 27 | "lint": "eslint --fix --ext .js,.vue src", |
28 | - "test": "npm run dist && npm run lint", | |
28 | + "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", | |
29 | + "test": "npm run lint && npm run unit", | |
29 | 30 | "prepublish": "npm run dist" |
30 | 31 | }, |
31 | 32 | "repository": { |
... | ... | @@ -54,11 +55,15 @@ |
54 | 55 | "babel-plugin-transform-runtime": "^6.12.0", |
55 | 56 | "babel-preset-es2015": "^6.9.0", |
56 | 57 | "babel-runtime": "^6.11.6", |
58 | + "chai": "^3.5.0", | |
59 | + "cross-env": "^3.1.4", | |
57 | 60 | "css-loader": "^0.23.1", |
58 | 61 | "eslint": "^3.12.2", |
59 | 62 | "eslint-plugin-html": "^1.7.0", |
60 | 63 | "extract-text-webpack-plugin": "^2.0.0", |
61 | 64 | "file-loader": "^0.8.5", |
65 | + "friendly-errors-webpack-plugin": "^1.6.1", | |
66 | + "function-bind": "^1.1.0", | |
62 | 67 | "gulp": "^3.9.1", |
63 | 68 | "gulp-autoprefixer": "^3.1.1", |
64 | 69 | "gulp-clean-css": "^2.0.13", |
... | ... | @@ -66,8 +71,21 @@ |
66 | 71 | "gulp-rename": "^1.2.2", |
67 | 72 | "html-loader": "^0.3.0", |
68 | 73 | "html-webpack-plugin": "^2.28.0", |
74 | + "karma": "^1.4.1", | |
75 | + "karma-coverage": "^1.1.1", | |
76 | + "karma-mocha": "^1.3.0", | |
77 | + "karma-phantomjs-launcher": "^1.0.2", | |
78 | + "karma-sinon-chai": "^1.2.4", | |
79 | + "karma-sourcemap-loader": "^0.3.7", | |
80 | + "karma-spec-reporter": "0.0.26", | |
81 | + "karma-webpack": "^2.0.2", | |
69 | 82 | "less": "^2.7.1", |
70 | 83 | "less-loader": "^2.2.3", |
84 | + "lolex": "^1.5.2", | |
85 | + "mocha": "^3.2.0", | |
86 | + "phantomjs-prebuilt": "^2.1.13", | |
87 | + "sinon": "^1.17.7", | |
88 | + "sinon-chai": "^2.8.0", | |
71 | 89 | "style-loader": "^0.13.1", |
72 | 90 | "url-loader": "^0.5.7", |
73 | 91 | "vue": "^2.2.1", |
... | ... | @@ -78,6 +96,11 @@ |
78 | 96 | "vue-style-loader": "^1.0.0", |
79 | 97 | "vue-template-compiler": "^2.2.1", |
80 | 98 | "webpack": "^2.2.1", |
81 | - "webpack-dev-server": "^2.4.1" | |
99 | + "webpack-dev-server": "^2.4.1", | |
100 | + "webpack-merge": "^3.0.0" | |
101 | + }, | |
102 | + "engines": { | |
103 | + "node": ">= 4.0.0", | |
104 | + "npm": ">= 3.0.0" | |
82 | 105 | } |
83 | 106 | } | ... | ... |
src/components/breadcrumb/breadcrumb-item.vue
... | ... | @@ -6,8 +6,10 @@ |
6 | 6 | <span v-else :class="linkClasses"> |
7 | 7 | <slot></slot> |
8 | 8 | </span> |
9 | - <span :class="separatorClasses"> | |
10 | - <slot name="separator">{{{ separator }}}</slot> | |
9 | + <span :class="separatorClasses" v-html="separator" v-if="!showSeparator"> | |
10 | + </span> | |
11 | + <span :class="separatorClasses" v-else> | |
12 | + <slot name="separator"></slot> | |
11 | 13 | </span> |
12 | 14 | </span> |
13 | 15 | </template> |
... | ... | @@ -18,12 +20,17 @@ |
18 | 20 | props: { |
19 | 21 | href: { |
20 | 22 | type: String |
21 | - }, | |
22 | - separator: { | |
23 | - type: String, | |
24 | - default: '/' | |
25 | 23 | } |
26 | 24 | }, |
25 | + data () { | |
26 | + return { | |
27 | + separator: '', | |
28 | + showSeparator: false | |
29 | + }; | |
30 | + }, | |
31 | + mounted () { | |
32 | + this.showSeparator = this.$slots.separator !== undefined; | |
33 | + }, | |
27 | 34 | computed: { |
28 | 35 | linkClasses () { |
29 | 36 | return `${prefixCls}-link`; | ... | ... |
src/components/breadcrumb/breadcrumb.vue
src/index.js
... | ... | @@ -5,7 +5,7 @@ import Affix from './components/affix'; |
5 | 5 | import Alert from './components/alert'; |
6 | 6 | // import BackTop from './components/back-top'; |
7 | 7 | import Badge from './components/badge'; |
8 | -// import Breadcrumb from './components/breadcrumb'; | |
8 | +import Breadcrumb from './components/breadcrumb'; | |
9 | 9 | import Button from './components/button'; |
10 | 10 | import Card from './components/card'; |
11 | 11 | import Carousel from './components/carousel'; |
... | ... | @@ -51,8 +51,8 @@ const iview = { |
51 | 51 | Alert, |
52 | 52 | // BackTop, |
53 | 53 | Badge, |
54 | - // Breadcrumb, | |
55 | - // BreadcrumbItem: Breadcrumb.Item, | |
54 | + Breadcrumb, | |
55 | + BreadcrumbItem: Breadcrumb.Item, | |
56 | 56 | // iButton: Button, |
57 | 57 | Button, |
58 | 58 | ButtonGroup: Button.Group, | ... | ... |
1 | +import Vue from 'vue'; | |
2 | +Vue.config.productionTip = false; | |
3 | + | |
4 | +// Polyfill fn.bind() for PhantomJS | |
5 | +/* eslint-disable no-extend-native */ | |
6 | +Function.prototype.bind = require('function-bind'); | |
7 | + | |
8 | +// require all test files (files that ends with .spec.js) | |
9 | +const testsContext = require.context('./specs', true, /\.spec$/); | |
10 | +testsContext.keys().forEach(testsContext); | |
11 | + | |
12 | +// require all src files except main.js for coverage. | |
13 | +// you can also change this to match only the subset of files that | |
14 | +// you want coverage for. | |
15 | +// const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/); | |
16 | +// @todo | |
17 | +const srcContext = require.context('../../src/components/breadcrumb', true, /^\.\/(?!styles.*?(\.less)?$)/); | |
18 | +srcContext.keys().forEach(srcContext); | ... | ... |
1 | +// This is a karma config file. For more details see | |
2 | +// http://karma-runner.github.io/0.13/config/configuration-file.html | |
3 | +// we are also using it with karma-webpack | |
4 | +// https://github.com/webpack/karma-webpack | |
5 | + | |
6 | +var webpackConfig = require('../../build/webpack.test.config.js'); | |
7 | + | |
8 | +module.exports = function (config) { | |
9 | + config.set({ | |
10 | + // to run in additional browsers: | |
11 | + // 1. install corresponding karma launcher | |
12 | + // http://karma-runner.github.io/0.13/config/browsers.html | |
13 | + // 2. add it to the `browsers` array below. | |
14 | + browsers: ['PhantomJS'], | |
15 | + frameworks: ['mocha', 'sinon-chai'], | |
16 | + reporters: ['spec', 'coverage'], | |
17 | + files: ['./index.js'], | |
18 | + preprocessors: { | |
19 | + './index.js': ['webpack', 'sourcemap'] | |
20 | + }, | |
21 | + webpack: webpackConfig, | |
22 | + webpackMiddleware: { | |
23 | + noInfo: true, | |
24 | + }, | |
25 | + coverageReporter: { | |
26 | + dir: './coverage', | |
27 | + reporters: [ | |
28 | + { type: 'lcov', subdir: '.' }, | |
29 | + { type: 'text-summary' }, | |
30 | + ] | |
31 | + }, | |
32 | + }); | |
33 | +}; | ... | ... |
1 | +import { createVue, destroyVM } from '../util'; | |
2 | + | |
3 | +describe('Breadcrumb.vue', () => { | |
4 | + let vm; | |
5 | + afterEach(() => { | |
6 | + destroyVM(vm); | |
7 | + }); | |
8 | + it('create', done => { | |
9 | + vm = createVue(` | |
10 | + <Breadcrumb separator="<b class='demo-breadcrumb-separator'>=></b>"> | |
11 | + <Breadcrumb-item href="/">Home4</Breadcrumb-item> | |
12 | + <Breadcrumb-item href="/components/breadcrumb">Components</Breadcrumb-item> | |
13 | + <Breadcrumb-item>Breadcrumb</Breadcrumb-item> | |
14 | + </Breadcrumb> | |
15 | + `); | |
16 | + expect(vm.$el.querySelectorAll('.ivu-breadcrumb-item-link').length).to.equal(3); | |
17 | + | |
18 | + vm.$nextTick(_ => { | |
19 | + // console.log(vm.$el.querySelector('.ivu-breadcrumb-item-separator').innerHTML); | |
20 | + expect(vm.$el.querySelector('.ivu-breadcrumb-item-separator').innerHTML).to.equal('<b class="demo-breadcrumb-separator">=></b>'); | |
21 | + done(); | |
22 | + }); | |
23 | + }); | |
24 | +}); | |
0 | 25 | \ No newline at end of file | ... | ... |
1 | +import Vue from 'vue'; | |
2 | +import iView from '../../src/index'; | |
3 | + | |
4 | +Vue.use(iView); | |
5 | + | |
6 | +let id = 0; | |
7 | + | |
8 | +const createElm = function() { | |
9 | + const elm = document.createElement('div'); | |
10 | + | |
11 | + elm.id = 'app' + ++id; | |
12 | + document.body.appendChild(elm); | |
13 | + | |
14 | + return elm; | |
15 | +}; | |
16 | + | |
17 | +/** | |
18 | + * 回收 vm | |
19 | + * @param {Object} vm | |
20 | + */ | |
21 | +exports.destroyVM = function(vm) { | |
22 | + vm.$el && | |
23 | + vm.$el.parentNode && | |
24 | + vm.$el.parentNode.removeChild(vm.$el); | |
25 | +}; | |
26 | + | |
27 | +/** | |
28 | + * 创建一个 Vue 的实例对象 | |
29 | + * @param {Object|String} Compo 组件配置,可直接传 template | |
30 | + * @param {Boolean=false} mounted 是否添加到 DOM 上 | |
31 | + * @return {Object} vm | |
32 | + */ | |
33 | +exports.createVue = function(Compo, mounted = false) { | |
34 | + const elm = createElm(); | |
35 | + | |
36 | + if (Object.prototype.toString.call(Compo) === '[object String]') { | |
37 | + Compo = { template: Compo }; | |
38 | + } | |
39 | + return new Vue(Compo).$mount(mounted === false ? null : elm); | |
40 | +}; | |
41 | + | |
42 | +/** | |
43 | + * 创建一个测试组件实例 | |
44 | + * @link http://vuejs.org/guide/unit-testing.html#Writing-Testable-Components | |
45 | + * @param {Object} Compo - 组件对象 | |
46 | + * @param {Object} propsData - props 数据 | |
47 | + * @param {Boolean=false} mounted - 是否添加到 DOM 上 | |
48 | + * @return {Object} vm | |
49 | + */ | |
50 | +exports.createTest = function(Compo, propsData = {}, mounted = false) { | |
51 | + if (propsData === true || propsData === false) { | |
52 | + mounted = propsData; | |
53 | + propsData = {}; | |
54 | + } | |
55 | + const elm = createElm(); | |
56 | + const Ctor = Vue.extend(Compo); | |
57 | + return new Ctor({ propsData }).$mount(mounted === false ? null : elm); | |
58 | +}; | |
59 | + | |
60 | +/** | |
61 | + * 触发一个事件 | |
62 | + * mouseenter, mouseleave, mouseover, keyup, change, click 等 | |
63 | + * @param {Element} elm | |
64 | + * @param {String} name | |
65 | + * @param {*} opts | |
66 | + */ | |
67 | +exports.triggerEvent = function(elm, name, ...opts) { | |
68 | + let eventName; | |
69 | + | |
70 | + if (/^mouse|click/.test(name)) { | |
71 | + eventName = 'MouseEvents'; | |
72 | + } else if (/^key/.test(name)) { | |
73 | + eventName = 'KeyboardEvent'; | |
74 | + } else { | |
75 | + eventName = 'HTMLEvents'; | |
76 | + } | |
77 | + const evt = document.createEvent(eventName); | |
78 | + | |
79 | + evt.initEvent(name, ...opts); | |
80 | + elm.dispatchEvent | |
81 | + ? elm.dispatchEvent(evt) | |
82 | + : elm.fireEvent('on' + name, evt); | |
83 | + | |
84 | + return elm; | |
85 | +}; | ... | ... |