Commit 9b6ff1ce28f5b85b86a886986ee8d5de7bb87fd9
1 parent
c9c5e751
add test and update webpack config
[new] add test config [new] add breadcrumb test [change] update package.json [new] util.js copied from element [unresolved] see test/unit/index.js @todo
Showing
10 changed files
with
222 additions
and
4 deletions
Show diff stats
.gitignore
build/webpack.base.config.js
... | ... | @@ -2,6 +2,10 @@ |
2 | 2 | * 公共配置 |
3 | 3 | */ |
4 | 4 | var webpack = require('webpack'); |
5 | +var path = require('path'); | |
6 | +function resolve (dir) { | |
7 | + return path.join(__dirname, '..', dir) | |
8 | +} | |
5 | 9 | |
6 | 10 | module.exports = { |
7 | 11 | // 加载器 |
... | ... | @@ -55,6 +59,10 @@ module.exports = { |
55 | 59 | ] |
56 | 60 | }, |
57 | 61 | resolve: { |
58 | - extensions: ['.js', '.vue'] | |
62 | + extensions: ['.js', '.vue'], | |
63 | + alias: { | |
64 | + 'vue': 'vue/dist/vue.esm.js', | |
65 | + '@': resolve('src'), | |
66 | + } | |
59 | 67 | } |
60 | 68 | }; | ... | ... |
build/webpack.dev.config.js
... | ... | @@ -8,6 +8,7 @@ var webpack = require('webpack'); |
8 | 8 | var HtmlWebpackPlugin = require('html-webpack-plugin'); |
9 | 9 | var merge = require('webpack-merge') |
10 | 10 | var webpackBaseConfig = require('./webpack.base.config.js'); |
11 | +var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') | |
11 | 12 | |
12 | 13 | |
13 | 14 | module.exports = merge(webpackBaseConfig, { |
... | ... | @@ -35,6 +36,7 @@ module.exports = merge(webpackBaseConfig, { |
35 | 36 | inject: true, |
36 | 37 | filename: path.join(__dirname, '../examples/dist/index.html'), |
37 | 38 | template: path.join(__dirname, '../examples/index.html') |
38 | - }) | |
39 | + }), | |
40 | + new FriendlyErrorsPlugin() | |
39 | 41 | ] |
40 | 42 | }); | ... | ... |
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 | ... | ... |
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 unit", | |
29 | 30 | "prepublish": "npm run dist" |
30 | 31 | }, |
31 | 32 | "repository": { |
... | ... | @@ -54,11 +55,14 @@ |
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", | |
62 | 66 | "gulp": "^3.9.1", |
63 | 67 | "gulp-autoprefixer": "^3.1.1", |
64 | 68 | "gulp-clean-css": "^2.0.13", |
... | ... | @@ -66,8 +70,21 @@ |
66 | 70 | "gulp-rename": "^1.2.2", |
67 | 71 | "html-loader": "^0.3.0", |
68 | 72 | "html-webpack-plugin": "^2.28.0", |
73 | + "karma": "^1.4.1", | |
74 | + "karma-coverage": "^1.1.1", | |
75 | + "karma-mocha": "^1.3.0", | |
76 | + "karma-phantomjs-launcher": "^1.0.2", | |
77 | + "karma-sinon-chai": "^1.2.4", | |
78 | + "karma-sourcemap-loader": "^0.3.7", | |
79 | + "karma-spec-reporter": "0.0.26", | |
80 | + "karma-webpack": "^2.0.2", | |
69 | 81 | "less": "^2.7.1", |
70 | 82 | "less-loader": "^2.2.3", |
83 | + "lolex": "^1.5.2", | |
84 | + "mocha": "^3.2.0", | |
85 | + "phantomjs-prebuilt": "^2.1.13", | |
86 | + "sinon": "^1.17.7", | |
87 | + "sinon-chai": "^2.8.0", | |
71 | 88 | "style-loader": "^0.13.1", |
72 | 89 | "url-loader": "^0.5.7", |
73 | 90 | "vue": "^2.2.1", |
... | ... | @@ -80,5 +97,9 @@ |
80 | 97 | "webpack": "^2.2.1", |
81 | 98 | "webpack-dev-server": "^2.4.1", |
82 | 99 | "webpack-merge": "^3.0.0" |
100 | + }, | |
101 | + "engines": { | |
102 | + "node": ">= 4.0.0", | |
103 | + "npm": ">= 3.0.0" | |
83 | 104 | } |
84 | 105 | } | ... | ... |
test deleted
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 | +}; | ... | ... |