浏览代码

chore: update test deps and conf (#14735)

* test: run in headless chrome

* chore: update travis node version

* chore: upgrade test deps

* test: fix tests

* test: support async await

* test: fix tree test case

* test: fix tree test cases

* test: fix popper test case
Jiewei Qian 6 年之前
父节点
当前提交
9c7fcf30f2

+ 1 - 6
.eslintrc

@@ -1,11 +1,6 @@
 {
 {
-  "env": {
-    "mocha": true
-  },
   "globals": {
   "globals": {
-    "ga": true,
-    "expect": true,
-    "sinon": true
+    "ga": true
   },
   },
   "plugins": ["html", "json"],
   "plugins": ["html", "json"],
   "extends": "elemefe",
   "extends": "elemefe",

+ 3 - 4
.travis.yml

@@ -1,10 +1,9 @@
 sudo: false
 sudo: false
 language: node_js
 language: node_js
-node_js: 8
+node_js: 10
+addons:
+  chrome: stable
 before_install:
 before_install:
-- export CHROME_BIN=chromium-browser
-- export DISPLAY=:99.0
-- sh -e /etc/init.d/xvfb start
 - export TRAVIS_COMMIT_MSG="[deploy] $(git log --format='%h - %B' --no-merges -n 1)"
 - export TRAVIS_COMMIT_MSG="[deploy] $(git log --format='%h - %B' --no-merges -n 1)"
 - export TRAVIS_COMMIT_USER="$(git log --no-merges -n 1 --format=%an)"
 - export TRAVIS_COMMIT_USER="$(git log --no-merges -n 1 --format=%an)"
 - export TRAVIS_COMMIT_EMAIL="$(git log --no-merges -n 1 --format=%ae)"
 - export TRAVIS_COMMIT_EMAIL="$(git log --no-merges -n 1 --format=%ae)"

+ 12 - 11
package.json

@@ -81,10 +81,11 @@
     "babel-plugin-transform-vue-jsx": "^3.7.0",
     "babel-plugin-transform-vue-jsx": "^3.7.0",
     "babel-preset-env": "^1.7.0",
     "babel-preset-env": "^1.7.0",
     "babel-preset-stage-2": "^6.24.1",
     "babel-preset-stage-2": "^6.24.1",
-    "chai": "^3.5.0",
+    "babel-regenerator-runtime": "^6.5.0",
+    "chai": "^4.2.0",
     "chokidar": "^1.7.0",
     "chokidar": "^1.7.0",
     "copy-webpack-plugin": "^5.0.0",
     "copy-webpack-plugin": "^5.0.0",
-    "coveralls": "^2.11.14",
+    "coveralls": "^3.0.3",
     "cp-cli": "^1.0.2",
     "cp-cli": "^1.0.2",
     "cross-env": "^3.1.3",
     "cross-env": "^3.1.3",
     "css-loader": "^2.1.0",
     "css-loader": "^2.1.0",
@@ -104,20 +105,20 @@
     "html-webpack-plugin": "^3.2.0",
     "html-webpack-plugin": "^3.2.0",
     "json-loader": "^0.5.7",
     "json-loader": "^0.5.7",
     "json-templater": "^1.0.4",
     "json-templater": "^1.0.4",
-    "karma": "^1.3.0",
+    "karma": "^4.0.1",
     "karma-chrome-launcher": "^2.2.0",
     "karma-chrome-launcher": "^2.2.0",
-    "karma-coverage": "^1.1.1",
-    "karma-mocha": "^1.2.0",
-    "karma-sinon-chai": "^1.2.4",
+    "karma-coverage": "^1.1.2",
+    "karma-mocha": "^1.3.0",
+    "karma-sinon-chai": "^2.0.2",
     "karma-sourcemap-loader": "^0.3.7",
     "karma-sourcemap-loader": "^0.3.7",
-    "karma-spec-reporter": "0.0.26",
-    "karma-webpack": "^3.0.0",
+    "karma-spec-reporter": "^0.0.32",
+    "karma-webpack": "^3.0.5",
     "markdown-it": "^8.4.1",
     "markdown-it": "^8.4.1",
     "markdown-it-anchor": "^5.0.2",
     "markdown-it-anchor": "^5.0.2",
     "markdown-it-chain": "^1.3.0",
     "markdown-it-chain": "^1.3.0",
     "markdown-it-container": "^2.0.0",
     "markdown-it-container": "^2.0.0",
     "mini-css-extract-plugin": "^0.4.1",
     "mini-css-extract-plugin": "^0.4.1",
-    "mocha": "^3.1.1",
+    "mocha": "^6.0.2",
     "node-sass": "^4.11.0",
     "node-sass": "^4.11.0",
     "optimize-css-assets-webpack-plugin": "^5.0.1",
     "optimize-css-assets-webpack-plugin": "^5.0.1",
     "perspective.js": "^1.0.0",
     "perspective.js": "^1.0.0",
@@ -126,8 +127,8 @@
     "rimraf": "^2.5.4",
     "rimraf": "^2.5.4",
     "sass-loader": "^7.1.0",
     "sass-loader": "^7.1.0",
     "select-version-cli": "^0.0.2",
     "select-version-cli": "^0.0.2",
-    "sinon": "^1.17.6",
-    "sinon-chai": "^2.8.0",
+    "sinon": "^7.2.7",
+    "sinon-chai": "^3.3.0",
     "style-loader": "^0.23.1",
     "style-loader": "^0.23.1",
     "transliteration": "^1.1.11",
     "transliteration": "^1.1.11",
     "uglifyjs-webpack-plugin": "^2.1.1",
     "uglifyjs-webpack-plugin": "^2.1.1",

+ 13 - 0
test/.eslintrc

@@ -0,0 +1,13 @@
+{
+  "env": {
+    "mocha": true,
+    "es6": true
+  },
+  "globals": {
+    "expect": true,
+    "sinon": true
+  },
+  "parserOptions": {
+    "ecmaVersion": 2017
+  }
+}

+ 1 - 3
test/unit/index.js

@@ -1,6 +1,4 @@
-// Polyfill fn.bind() for PhantomJS
-/* eslint-disable no-extend-native */
-Function.prototype.bind = require('function-bind');
+require('babel-regenerator-runtime'); // add regenerator support for async await
 require('packages/theme-chalk/lib/index.css');
 require('packages/theme-chalk/lib/index.css');
 
 
 // require all test files (files that ends with .spec.js)
 // require all test files (files that ends with .spec.js)

+ 1 - 11
test/unit/karma.conf.js

@@ -2,13 +2,7 @@ const webpackConfig = require('../../build/webpack.test');
 
 
 module.exports = function(config) {
 module.exports = function(config) {
   const configuration = {
   const configuration = {
-    browsers: ['Chrome'],
-    customLaunchers: {
-      Chrome_travis_ci: {
-        base: 'Chrome',
-        flags: ['--no-sandbox']
-      }
-    },
+    browsers: ['ChromeHeadless'],
     frameworks: ['mocha', 'sinon-chai'],
     frameworks: ['mocha', 'sinon-chai'],
     reporters: ['spec', 'coverage'],
     reporters: ['spec', 'coverage'],
     files: ['./index.js'],
     files: ['./index.js'],
@@ -33,9 +27,5 @@ module.exports = function(config) {
     }
     }
   };
   };
 
 
-  if (process.env.TRAVIS) {
-    configuration.browsers = ['Chrome_travis_ci'];
-  }
-
   config.set(configuration);
   config.set(configuration);
 };
 };

+ 174 - 118
test/unit/specs/date-picker.spec.js

@@ -2,7 +2,8 @@ import {
   createTest,
   createTest,
   createVue,
   createVue,
   destroyVM,
   destroyVM,
-  triggerEvent
+  triggerEvent,
+  wait
 } from '../util';
 } from '../util';
 import DatePicker from 'packages/date-picker';
 import DatePicker from 'packages/date-picker';
 
 
@@ -21,16 +22,14 @@ const keyDown = (el, keyCode) => {
 
 
 describe('DatePicker', () => {
 describe('DatePicker', () => {
   let vm;
   let vm;
-  afterEach(() => {
-    destroyVM(vm);
-  });
+  afterEach(() => { destroyVM(vm); });
 
 
   it('create', () => {
   it('create', () => {
     vm = createTest(DatePicker, {
     vm = createTest(DatePicker, {
       readonly: true,
       readonly: true,
       placeholder: '23333',
       placeholder: '23333',
       format: 'HH-mm-ss'
       format: 'HH-mm-ss'
-    });
+    }, true);
     const input = vm.$el.querySelector('input');
     const input = vm.$el.querySelector('input');
 
 
     expect(input.getAttribute('placeholder')).to.equal('23333');
     expect(input.getAttribute('placeholder')).to.equal('23333');
@@ -319,9 +318,7 @@ describe('DatePicker', () => {
   describe('input event', () => {
   describe('input event', () => {
     // mimic standard <select>'s behavior
     // mimic standard <select>'s behavior
     // emit input if and only if value changes
     // emit input if and only if value changes
-    afterEach(() => {
-      destroyVM(vm);
-    });
+    afterEach(() => { destroyVM(vm); });
 
 
     it('works for type=date', done => {
     it('works for type=date', done => {
       let emitted = false;
       let emitted = false;
@@ -455,6 +452,8 @@ describe('DatePicker', () => {
   });
   });
 
 
   describe('value-format', () => {
   describe('value-format', () => {
+    afterEach(() => { destroyVM(vm); });
+
     it('emits', done => {
     it('emits', done => {
       vm = createVue({
       vm = createVue({
         template: `
         template: `
@@ -655,7 +654,9 @@ describe('DatePicker', () => {
     });
     });
   });
   });
 
 
-  describe('default value', done => {
+  describe('default value', () => {
+    afterEach(() => { destroyVM(vm); });
+
     it('it works', done => {
     it('it works', done => {
       let defaultValue = '2000-01-01';
       let defaultValue = '2000-01-01';
       let expectValue = new Date(2000, 0, 1);
       let expectValue = new Date(2000, 0, 1);
@@ -799,6 +800,8 @@ describe('DatePicker', () => {
   });
   });
 
 
   describe('can be cleared using keyboard', () => {
   describe('can be cleared using keyboard', () => {
+    afterEach(() => { destroyVM(vm); });
+
     it('works for type=date, when blur', done => {
     it('works for type=date, when blur', done => {
       vm = createVue({
       vm = createVue({
         template: `
         template: `
@@ -858,15 +861,17 @@ describe('DatePicker', () => {
     // TODO: implement the same feature for range panels
     // TODO: implement the same feature for range panels
   });
   });
 
 
-  describe('nagivation', _ => {
-    const click = (el, cbk = () => {}) => {
+  describe('nagivation', () => {
+    afterEach(() => { destroyVM(vm); });
+
+    const clickAndWait = (el) => {
       el.click();
       el.click();
-      setTimeout(cbk, DELAY);
+      return wait();
     };
     };
 
 
     let prevMonth, prevYear, nextMonth, nextYear, getYearLabel, getMonthLabel;
     let prevMonth, prevYear, nextMonth, nextYear, getYearLabel, getMonthLabel;
 
 
-    const navigationTest = (value, cbk) => {
+    const initNavigationTest = async(value) => {
       vm = createVue({
       vm = createVue({
         template: '<el-date-picker v-model="value" ref="compo" />',
         template: '<el-date-picker v-model="value" ref="compo" />',
         data() {
         data() {
@@ -876,80 +881,63 @@ describe('DatePicker', () => {
         }
         }
       }, true);
       }, true);
       vm.$refs.compo.$el.querySelector('input').focus();
       vm.$refs.compo.$el.querySelector('input').focus();
-      setTimeout(_ => {
-        const $el = vm.$refs.compo.picker.$el;
-        prevMonth = $el.querySelector('button.el-icon-arrow-left');
-        prevYear = $el.querySelector('button.el-icon-d-arrow-left');
-        nextMonth = $el.querySelector('button.el-icon-arrow-right');
-        nextYear = $el.querySelector('button.el-icon-d-arrow-right');
-        getYearLabel = () => $el.querySelectorAll('.el-date-picker__header-label')[0].textContent;
-        getMonthLabel = () => $el.querySelectorAll('.el-date-picker__header-label')[1].textContent;
-        cbk();
-      }, DELAY);
+      await wait();
+      const $el = vm.$refs.compo.picker.$el;
+      prevMonth = $el.querySelector('button.el-icon-arrow-left');
+      prevYear = $el.querySelector('button.el-icon-d-arrow-left');
+      nextMonth = $el.querySelector('button.el-icon-arrow-right');
+      nextYear = $el.querySelector('button.el-icon-d-arrow-right');
+      getYearLabel = () => $el.querySelectorAll('.el-date-picker__header-label')[0].textContent;
+      getMonthLabel = () => $el.querySelectorAll('.el-date-picker__header-label')[1].textContent;
     };
     };
 
 
-    it('month, year', done => {
-      navigationTest(new Date(2000, 0, 1), _ => {
-        expect(getYearLabel()).to.include('2000');
-        expect(getMonthLabel()).to.include('1');
-        click(prevMonth, _ => {
-          expect(getYearLabel()).to.include('1999');
-          expect(getMonthLabel()).to.include('12');
-          click(prevYear, _ => {
-            expect(getYearLabel()).to.include('1998');
-            expect(getMonthLabel()).to.include('12');
-            click(nextMonth, _ => {
-              expect(getYearLabel()).to.include('1999');
-              expect(getMonthLabel()).to.include('1');
-              click(nextYear, _ => {
-                expect(getYearLabel()).to.include('2000');
-                expect(getMonthLabel()).to.include('1');
-                done();
-              });
-            });
-          });
-        });
-      });
+    it('month, year', async() => {
+      await initNavigationTest(new Date(2000, 0, 1));
+      expect(getYearLabel()).to.include('2000');
+      expect(getMonthLabel()).to.include('1');
+
+      await clickAndWait(prevMonth);
+      expect(getYearLabel()).to.include('1999');
+      expect(getMonthLabel()).to.include('12');
+
+      await clickAndWait(prevYear);
+      expect(getYearLabel()).to.include('1998');
+      expect(getMonthLabel()).to.include('12');
+
+      await clickAndWait(nextMonth);
+      expect(getYearLabel()).to.include('1999');
+      expect(getMonthLabel()).to.include('1');
+
+      await clickAndWait(nextYear);
+      expect(getYearLabel()).to.include('2000');
+      expect(getMonthLabel()).to.include('1');
     });
     });
 
 
-    it('month with fewer dates', done => {
+    it('month with fewer dates', async() => {
       // July has 31 days, June has 30
       // July has 31 days, June has 30
-      navigationTest(new Date(2000, 6, 31), _ => {
-        click(prevMonth, _ => {
-          expect(getYearLabel()).to.include('2000');
-          expect(getMonthLabel()).to.include('6');
-          done();
-        });
-      });
+      await initNavigationTest(new Date(2000, 6, 31));
+      await clickAndWait(prevMonth);
+      expect(getYearLabel()).to.include('2000');
+      expect(getMonthLabel()).to.include('6');
     });
     });
 
 
-    it('year with fewer Feburary dates', done => {
+    it('year with fewer Feburary dates', async() => {
       // Feburary 2008 has 29 days, Feburary 2007 has 28
       // Feburary 2008 has 29 days, Feburary 2007 has 28
-      navigationTest(new Date(2008, 1, 29), _ => {
-        click(prevYear, _ => {
-          expect(getYearLabel()).to.include('2007');
-          expect(getMonthLabel()).to.include('2');
-          done();
-        });
-      });
+      await initNavigationTest(new Date(2008, 1, 29));
+      await clickAndWait(prevYear);
+      expect(getYearLabel()).to.include('2007');
+      expect(getMonthLabel()).to.include('2');
     });
     });
 
 
-    it('month label with fewer dates', done => {
-      navigationTest(new Date(2000, 6, 31), _ => {
-        const $el = vm.$refs.compo.picker.$el;
-        const monthLabel = $el.querySelectorAll('.el-date-picker__header-label')[1];
-        click(monthLabel, _ => {
-          setTimeout(_ => {
-            const juneLabel = $el.querySelectorAll('.el-month-table td a')[5];
-            juneLabel.click();
-            setTimeout(_ => {
-              expect(getYearLabel()).to.include('2000');
-              expect(getMonthLabel()).to.include('6');
-              done();
-            }, DELAY);
-          }, DELAY);
-        });
-      });
+    it('month label with fewer dates', async() => {
+      await initNavigationTest(new Date(2000, 6, 31));
+      const $el = vm.$refs.compo.picker.$el;
+      const monthLabel = $el.querySelectorAll('.el-date-picker__header-label')[1];
+      await clickAndWait(monthLabel);
+      const juneLabel = $el.querySelectorAll('.el-month-table td a')[5];
+      await clickAndWait(juneLabel);
+      expect(getYearLabel()).to.include('2000');
+      expect(getMonthLabel()).to.include('6');
     });
     });
   });
   });
 
 
@@ -1004,22 +992,27 @@ describe('DatePicker', () => {
 
 
   describe('type:datetime', () => {
   describe('type:datetime', () => {
     let vm;
     let vm;
-    beforeEach(done => {
-      vm = createTest(DatePicker, {
-        type: 'datetime'
+
+    afterEach(() => destroyVM(vm));
+
+    it('create', done => {
+      vm = createVue({
+        template: '<el-date-picker type="datetime" v-model="value" ref="compo" />',
+        data() {
+          return {
+            value: ''
+          };
+        }
       }, true);
       }, true);
-      const input = vm.$el.querySelector('input');
+      const input = vm.$refs.compo.$el.querySelector('input');
 
 
       input.blur();
       input.blur();
       input.focus();
       input.focus();
 
 
-      setTimeout(done, DELAY);
-    });
-
-    afterEach(() => destroyVM(vm));
-
-    it('create', () => {
-      expect(vm.picker.$el.querySelector('.el-time-panel')).to.ok;
+      setTimeout(_ => {
+        expect(vm.$refs.compo.picker.$el.querySelector('.el-time-panel')).to.ok;
+        done();
+      }, DELAY);
     });
     });
 
 
     it('both picker show correct formated value (extract date-format and time-format from format property)', done => {
     it('both picker show correct formated value (extract date-format and time-format from format property)', done => {
@@ -1053,7 +1046,7 @@ describe('DatePicker', () => {
             expect(dateInput.value).to.equal('5-3-18');
             expect(dateInput.value).to.equal('5-3-18');
             expect(timeInput.value).to.equal('10 am');
             expect(timeInput.value).to.equal('10 am');
 
 
-            // change not documented pickerOptions.format mustn't change picker format
+            // change undocumented pickerOptions.format won't change picker format
             vm.pickerOptions = { format: 'yyyy-MM-dd HH:mm:ss'};
             vm.pickerOptions = { format: 'yyyy-MM-dd HH:mm:ss'};
             setTimeout(_ => {
             setTimeout(_ => {
               expect(dateInput.value).to.equal('5-3-18');
               expect(dateInput.value).to.equal('5-3-18');
@@ -1111,69 +1104,122 @@ describe('DatePicker', () => {
     });
     });
 
 
     it('click now button', done => {
     it('click now button', done => {
-      const date = new Date(1999, 10, 10, 10, 10);
+      vm = createTest(DatePicker, {
+        type: 'datetime'
+      }, true);
+      const input = vm.$el.querySelector('input');
+
+      input.blur();
+      input.focus();
 
 
-      vm.picker.$el.querySelector('.el-picker-panel__link-btn').click();
       setTimeout(_ => {
       setTimeout(_ => {
-        expect(vm.picker.date > date).to.true;
-        done();
+        const date = new Date(1999, 10, 10, 10, 10);
+
+        vm.picker.$el.querySelector('.el-picker-panel__link-btn').click();
+        setTimeout(_ => {
+          expect(vm.picker.date > date).to.true;
+          done();
+        }, DELAY);
       }, DELAY);
       }, DELAY);
     });
     });
 
 
     it('click timepicker', done => {
     it('click timepicker', done => {
-      const input = vm.picker.$el.querySelectorAll('.el-date-picker__editor-wrap input')[1];
-      triggerEvent(input, 'focus');
+      vm = createTest(DatePicker, {
+        type: 'datetime'
+      }, true);
+      const input = vm.$el.querySelector('input');
+
+      input.blur();
+      input.focus();
 
 
       setTimeout(_ => {
       setTimeout(_ => {
-        expect(vm.picker.$el.querySelector('.el-time-panel')).to.have.deep.property('style.display').to.equal('');
-        done();
+        const input = vm.picker.$el.querySelectorAll('.el-date-picker__editor-wrap input')[1];
+        triggerEvent(input, 'focus');
+
+        setTimeout(_ => {
+          const timePanel = vm.picker.$el.querySelector('.el-time-panel');
+          expect(window.getComputedStyle(timePanel)).to.not.equal('none');
+          done();
+        }, DELAY);
       }, DELAY);
       }, DELAY);
     });
     });
 
 
     it('input timepicker', done => {
     it('input timepicker', done => {
-      const input = vm.picker.$el.querySelectorAll('.el-date-picker__editor-wrap input')[1];
+      vm = createTest(DatePicker, {
+        type: 'datetime'
+      }, true);
+      const input = vm.$el.querySelector('input');
+
+      input.blur();
+      input.focus();
 
 
-      input.value = '20:30:33';
-      triggerEvent(input, 'change', true);
       setTimeout(_ => {
       setTimeout(_ => {
-        expect(vm.picker.date.getHours()).to.equal(20);
-        expect(vm.picker.date.getMinutes()).to.equal(30);
-        expect(vm.picker.date.getSeconds()).to.equal(33);
-        done();
+        const input = vm.picker.$el.querySelectorAll('.el-date-picker__editor-wrap input')[1];
+
+        input.value = '20:30:33';
+        triggerEvent(input, 'change', true);
+        setTimeout(_ => {
+          expect(vm.picker.date.getHours()).to.equal(20);
+          expect(vm.picker.date.getMinutes()).to.equal(30);
+          expect(vm.picker.date.getSeconds()).to.equal(33);
+          done();
+        }, DELAY);
       }, DELAY);
       }, DELAY);
     });
     });
 
 
     it('input date', done => {
     it('input date', done => {
-      const input = vm.picker.$el.querySelector('.el-date-picker__editor-wrap input');
+      vm = createTest(DatePicker, {
+        type: 'datetime'
+      }, true);
+      const input = vm.$el.querySelector('input');
+
+      input.blur();
+      input.focus();
 
 
-      input.value = '2017-2-2';
-      triggerEvent(input, 'change', true);
       setTimeout(_ => {
       setTimeout(_ => {
-        expect(vm.picker.date.getFullYear()).to.equal(2017);
-        expect(vm.picker.date.getMonth()).to.equal(1);
-        expect(vm.picker.date.getDate()).to.equal(2);
-        done();
+        const input = vm.picker.$el.querySelector('.el-date-picker__editor-wrap input');
+
+        input.value = '2017-2-2';
+        triggerEvent(input, 'change', true);
+        setTimeout(_ => {
+          expect(vm.picker.date.getFullYear()).to.equal(2017);
+          expect(vm.picker.date.getMonth()).to.equal(1);
+          expect(vm.picker.date.getDate()).to.equal(2);
+          done();
+        }, DELAY);
       }, DELAY);
       }, DELAY);
     });
     });
 
 
     it('select time', done => {
     it('select time', done => {
-      const input = vm.picker.$el.querySelectorAll('.el-date-picker__editor-wrap input')[1];
+      vm = createTest(DatePicker, {
+        type: 'datetime'
+      }, true);
+      const input = vm.$el.querySelector('input');
+
       input.blur();
       input.blur();
       input.focus();
       input.focus();
-      input.blur();
 
 
       setTimeout(_ => {
       setTimeout(_ => {
-        const button = vm.picker.$el.querySelector('.el-time-panel .confirm');
-        button.click();
+        const input = vm.picker.$el.querySelectorAll('.el-date-picker__editor-wrap input')[1];
+        input.blur();
+        input.focus();
+        input.blur();
 
 
         setTimeout(_ => {
         setTimeout(_ => {
-          expect(input.value).to.exist;
-          done();
+          const button = vm.picker.$el.querySelector('.el-time-panel .confirm');
+          button.click();
+
+          setTimeout(_ => {
+            expect(input.value).to.exist;
+            done();
+          }, DELAY);
         }, DELAY);
         }, DELAY);
       }, DELAY);
       }, DELAY);
     });
     });
 
 
     describe('change event', () => {
     describe('change event', () => {
+      afterEach(() => destroyVM(vm));
+
       it('pick date, emits on confirm', done => {
       it('pick date, emits on confirm', done => {
         vm = createVue({
         vm = createVue({
           template: '<el-date-picker type="datetime" v-model="value" ref="compo" />',
           template: '<el-date-picker type="datetime" v-model="value" ref="compo" />',
@@ -1242,6 +1288,8 @@ describe('DatePicker', () => {
     });
     });
 
 
     describe('cancel time', () => {
     describe('cancel time', () => {
+      afterEach(() => destroyVM(vm));
+
       it('cancel to empty', done => {
       it('cancel to empty', done => {
         vm = createVue({
         vm = createVue({
           template: '<el-date-picker type="datetime" v-model="value" ref="compo" />',
           template: '<el-date-picker type="datetime" v-model="value" ref="compo" />',
@@ -1539,6 +1587,8 @@ describe('DatePicker', () => {
   });
   });
 
 
   describe('type:daterange', () => {
   describe('type:daterange', () => {
+    afterEach(() => destroyVM(vm));
+
     it('works', done => {
     it('works', done => {
       vm = createVue({
       vm = createVue({
         template: '<el-date-picker type="daterange" v-model="value" ref="compo" />',
         template: '<el-date-picker type="daterange" v-model="value" ref="compo" />',
@@ -2194,6 +2244,8 @@ describe('DatePicker', () => {
     });
     });
 
 
     it('confirm honors disabledDate', done => {
     it('confirm honors disabledDate', done => {
+      destroyVM(vm); // nuke beforeEach's vm before creating our own
+
       vm = createVue({
       vm = createVue({
         template: '<el-date-picker type="datetimerange" value-format="yyyy-MM-dd HH:mm:ss" v-model="value" :picker-options="pickerOptions" ref="compo" />',
         template: '<el-date-picker type="datetimerange" value-format="yyyy-MM-dd HH:mm:ss" v-model="value" :picker-options="pickerOptions" ref="compo" />',
         data() {
         data() {
@@ -2232,6 +2284,8 @@ describe('DatePicker', () => {
   });
   });
 
 
   describe('type:monthrange', () => {
   describe('type:monthrange', () => {
+    afterEach(() => destroyVM(vm));
+
     it('works', done => {
     it('works', done => {
       vm = createVue({
       vm = createVue({
         template: '<el-date-picker type="monthrange" v-model="value" ref="compo" />',
         template: '<el-date-picker type="monthrange" v-model="value" ref="compo" />',
@@ -2472,6 +2526,8 @@ describe('DatePicker', () => {
     });
     });
 
 
     describe('default value', () => {
     describe('default value', () => {
+      afterEach(() => destroyVM(vm));
+
       it('single', done => {
       it('single', done => {
         let defaultValue = '2000-10';
         let defaultValue = '2000-10';
         let expectValue = [new Date(2000, 9), new Date(2000, 10)];
         let expectValue = [new Date(2000, 9), new Date(2000, 10)];
@@ -2671,7 +2727,7 @@ describe('DatePicker', () => {
     });
     });
   });
   });
 
 
-  describe('picker-options:firstDayOfWeek especial', () => {
+  describe('picker-options:firstDayOfWeek issue-14523', () => {
     let vm;
     let vm;
     beforeEach(done => {
     beforeEach(done => {
       vm = createTest(DatePicker, {
       vm = createTest(DatePicker, {

+ 4 - 4
test/unit/specs/dialog.spec.js

@@ -100,14 +100,14 @@ describe('Dialog', () => {
         };
         };
       }
       }
     }, true);
     }, true);
-    const dialog = vm.$children[0];
-    expect(dialog.$el.style.display).to.equal('none');
+    const dialogEl = vm.$children[0].$el;
+    expect(getComputedStyle(dialogEl).display).to.equal('none');
     vm.visible = true;
     vm.visible = true;
     setTimeout(() => {
     setTimeout(() => {
-      expect(dialog.$el.style.display).to.not.equal('none');
+      expect(getComputedStyle(dialogEl).display).to.not.equal('none');
       vm.visible = false;
       vm.visible = false;
       setTimeout(() => {
       setTimeout(() => {
-        expect(dialog.$el.style.display).to.equal('none');
+        expect(getComputedStyle(dialogEl).display).to.equal('none');
         done();
         done();
       }, 400);
       }, 400);
     }, 50);
     }, 50);

+ 24 - 33
test/unit/specs/input.spec.js

@@ -1,4 +1,4 @@
-import { createVue, destroyVM } from '../util';
+import { createVue, destroyVM, wait, waitImmediate } from '../util';
 
 
 describe('Input', () => {
 describe('Input', () => {
   let vm;
   let vm;
@@ -100,7 +100,7 @@ describe('Input', () => {
   });
   });
 
 
   // Github issue #2836
   // Github issue #2836
-  it('resize', done => {
+  it('resize', async() => {
     vm = createVue({
     vm = createVue({
       template: `
       template: `
         <div>
         <div>
@@ -111,17 +111,14 @@ describe('Input', () => {
         resize: 'none'
         resize: 'none'
       }
       }
     }, true);
     }, true);
-    vm.$nextTick(() => {
-      expect(vm.$el.querySelector('.el-textarea__inner').style.resize).to.be.equal(vm.resize);
-      vm.resize = 'horizontal';
-      vm.$nextTick(() => {
-        expect(vm.$el.querySelector('.el-textarea__inner').style.resize).to.be.equal(vm.resize);
-        done();
-      });
-    });
+    await waitImmediate();
+    expect(vm.$el.querySelector('.el-textarea__inner').style.resize).to.be.equal(vm.resize);
+    vm.resize = 'horizontal';
+    await waitImmediate();
+    expect(vm.$el.querySelector('.el-textarea__inner').style.resize).to.be.equal(vm.resize);
   });
   });
 
 
-  it('autosize', done => {
+  it('autosize', async() => {
     vm = createVue({
     vm = createVue({
       template: `
       template: `
         <div>
         <div>
@@ -154,14 +151,13 @@ describe('Input', () => {
     expect(limitlessSizeInput.textareaStyle.height).to.be.equal('201px');
     expect(limitlessSizeInput.textareaStyle.height).to.be.equal('201px');
 
 
     vm.textareaValue = '';
     vm.textareaValue = '';
-    setTimeout(_ => {
-      expect(limitSizeInput.textareaStyle.height).to.be.equal('75px');
-      expect(limitlessSizeInput.textareaStyle.height).to.be.equal('33px');
-      done();
-    }, 200);
+
+    await wait();
+    expect(limitSizeInput.textareaStyle.height).to.be.equal('75px');
+    expect(limitlessSizeInput.textareaStyle.height).to.be.equal('33px');
   });
   });
 
 
-  it('focus', done => {
+  it('focus', async() => {
     vm = createVue({
     vm = createVue({
       template: `
       template: `
         <el-input ref="input">
         <el-input ref="input">
@@ -174,13 +170,11 @@ describe('Input', () => {
     vm.$refs.input.$on('focus', spy);
     vm.$refs.input.$on('focus', spy);
     vm.$refs.input.focus();
     vm.$refs.input.focus();
 
 
-    vm.$nextTick(_ => {
-      expect(spy.calledOnce).to.be.true;
-      done();
-    });
+    await waitImmediate();
+    expect(spy.calledOnce).to.be.true;
   });
   });
 
 
-  it('Input contains Select and append slot', (done) => {
+  it('Input contains Select and append slot', async() => {
     vm = createVue({
     vm = createVue({
       template: `
       template: `
       <el-input v-model="value" clearable class="input-with-select" ref="input">
       <el-input v-model="value" clearable class="input-with-select" ref="input">
@@ -200,15 +194,14 @@ describe('Input', () => {
       }
       }
     }, true);
     }, true);
     vm.$refs.input.hovering = true;
     vm.$refs.input.hovering = true;
-    setTimeout(() => {
-      const suffixEl = document.querySelector('.input-with-select > .el-input__suffix');
-      expect(suffixEl).to.not.be.null;
-      expect(suffixEl.style.transform).to.not.be.empty;
-      done();
-    }, 20);
+
+    await wait();
+    const suffixEl = document.querySelector('.input-with-select > .el-input__suffix');
+    expect(suffixEl).to.not.be.null;
+    expect(suffixEl.style.transform).to.not.be.empty;
   });
   });
 
 
-  it('validateEvent', done => {
+  it('validateEvent', async() => {
     const spy = sinon.spy();
     const spy = sinon.spy();
     vm = createVue({
     vm = createVue({
       template: `
       template: `
@@ -238,10 +231,8 @@ describe('Input', () => {
     }, true);
     }, true);
 
 
     vm.model.input = '123';
     vm.model.input = '123';
-    vm.$nextTick(() => {
-      expect(spy.called).to.be.false;
-      done();
-    });
+    await waitImmediate();
+    expect(spy.called).to.be.false;
   });
   });
 
 
   describe('Input Events', () => {
   describe('Input Events', () => {

+ 2 - 2
test/unit/specs/loading.spec.js

@@ -257,8 +257,8 @@ describe('Loading', () => {
             expect(masks.length).to.equal(0);
             expect(masks.length).to.equal(0);
             done();
             done();
           }, 350);
           }, 350);
-        }, 10);
-      }, 10);
+        }, 50);
+      }, 50);
     });
     });
 
 
     it('lock', () => {
     it('lock', () => {

+ 4 - 2
test/unit/specs/popover.spec.js

@@ -162,7 +162,8 @@ describe('Popover', () => {
       vm.$el.querySelector('button').click();
       vm.$el.querySelector('button').click();
       expect(compo.popperElm).to.not.exist;
       expect(compo.popperElm).to.not.exist;
       vm.$nextTick(_ => {
       vm.$nextTick(_ => {
-        expect(compo).to.have.deep.property('popperElm.style.display').not.equal('none');
+        const popperElm = compo.popperElm;
+        expect(getComputedStyle(popperElm).display).to.not.equal('none');
         done();
         done();
       });
       });
     });
     });
@@ -194,7 +195,8 @@ describe('Popover', () => {
       vm.$el.querySelector('button').click();
       vm.$el.querySelector('button').click();
       expect(compo.popperElm).to.not.exist;
       expect(compo.popperElm).to.not.exist;
       vm.$nextTick(_ => {
       vm.$nextTick(_ => {
-        expect(compo).to.have.deep.property('popperElm.style.display').not.equal('none');
+        const popperElm = compo.popperElm;
+        expect(getComputedStyle(popperElm).display).to.not.equal('none');
         done();
         done();
       });
       });
     });
     });

+ 6 - 8
test/unit/specs/slider.spec.js

@@ -1,4 +1,4 @@
-import { createTest, createVue, triggerEvent, destroyVM } from '../util';
+import { createTest, createVue, triggerEvent, destroyVM, waitImmediate } from '../util';
 import Slider from 'packages/slider';
 import Slider from 'packages/slider';
 
 
 describe('Slider', () => {
 describe('Slider', () => {
@@ -81,11 +81,11 @@ describe('Slider', () => {
     expect(slider.$refs.tooltip.disabled).to.true;
     expect(slider.$refs.tooltip.disabled).to.true;
   });
   });
 
 
-  it('format tooltip', () => {
+  it('format tooltip', async() => {
     vm = createVue({
     vm = createVue({
       template: `
       template: `
         <div>
         <div>
-          <el-slider v-model="value" :format-tooltip="formatTooltip">
+          <el-slider ref="slider" v-model="value" :format-tooltip="formatTooltip">
           </el-slider>
           </el-slider>
         </div>
         </div>
       `,
       `,
@@ -101,11 +101,9 @@ describe('Slider', () => {
         }
         }
       }
       }
     }, true);
     }, true);
-    const slider = vm.$children[0].$children[0];
-    expect(slider.formatTooltip).to.function;
-    vm.$nextTick(() => {
-      expect(slider.formatValue).to.equal('$0');
-    });
+    const sliderButton = vm.$refs.slider.$children[0];
+    await waitImmediate();
+    expect(sliderButton.formatValue).to.equal('$0');
   });
   });
 
 
   it('drag', done => {
   it('drag', done => {

+ 14 - 16
test/unit/specs/steps.spec.js

@@ -1,5 +1,4 @@
-import { createVue, destroyVM } from '../util';
-import Vue from 'vue';
+import { createVue, destroyVM, waitImmediate } from '../util';
 
 
 describe('Steps', () => {
 describe('Steps', () => {
   let vm;
   let vm;
@@ -19,14 +18,14 @@ describe('Steps', () => {
     expect(vm.$el.querySelectorAll('.el-step')).to.length(3);
     expect(vm.$el.querySelectorAll('.el-step')).to.length(3);
   });
   });
 
 
-  it('space', done => {
+  it('space', async() => {
     vm = createVue(`
     vm = createVue(`
       <el-steps>
       <el-steps>
         <el-step title="step1"></el-step>
         <el-step title="step1"></el-step>
         <el-step title="step2"></el-step>
         <el-step title="step2"></el-step>
         <el-step title="step3"></el-step>
         <el-step title="step3"></el-step>
       </el-steps>
       </el-steps>
-    `);
+    `, true);
 
 
     const vm2 = createVue(`
     const vm2 = createVue(`
       <el-steps :space="100">
       <el-steps :space="100">
@@ -35,13 +34,13 @@ describe('Steps', () => {
         <el-step title="step3"></el-step>
         <el-step title="step3"></el-step>
         <el-step title="step4"></el-step>
         <el-step title="step4"></el-step>
       </el-steps>
       </el-steps>
-    `);
+    `, true);
 
 
-    Vue.nextTick(_ => {
-      expect(vm.$el.querySelector('.el-step')).have.deep.property('style.webkitFlexBasis').equal('50%');
-      expect(vm2.$el.querySelector('.el-step')).have.deep.property('style.webkitFlexBasis').equal('100px');
-      done();
-    });
+    await waitImmediate();
+    const stepElm = vm.$el.querySelector('.el-step');
+    const stepElm2 = vm2.$el.querySelector('.el-step');
+    expect(getComputedStyle(stepElm).flexBasis).to.equal('50%');
+    expect(getComputedStyle(stepElm2).flexBasis).to.equal('100px');
   });
   });
 
 
   it('processStatus', done => {
   it('processStatus', done => {
@@ -131,18 +130,17 @@ describe('Steps', () => {
     expect(vm.$el.querySelector('.is-vertical')).to.exist;
     expect(vm.$el.querySelector('.is-vertical')).to.exist;
   });
   });
 
 
-  it('vertical:height', done => {
+  it('vertical:height', async() => {
     vm = createVue(`
     vm = createVue(`
       <el-steps direction="vertical" :space="200">
       <el-steps direction="vertical" :space="200">
         <el-step title="aaa"></el-step>
         <el-step title="aaa"></el-step>
         <el-step title="bbb"></el-step>
         <el-step title="bbb"></el-step>
       </el-steps>
       </el-steps>
-    `);
+    `, true);
 
 
-    vm.$nextTick(_ => {
-      expect(vm.$el.querySelector('.el-step')).have.deep.property('style.webkitFlexBasis').equal('200px');
-      done();
-    });
+    await waitImmediate();
+    const stepElm = vm.$el.querySelector('.el-step');
+    expect(getComputedStyle(stepElm).flexBasis).to.equal('200px');
   });
   });
 
 
   it('step:status=error', done => {
   it('step:status=error', done => {

+ 32 - 35
test/unit/specs/tree.spec.js

@@ -1,4 +1,4 @@
-import { createVue, destroyVM } from '../util';
+import { createVue, destroyVM, waitImmediate } from '../util';
 
 
 const DELAY = 10;
 const DELAY = 10;
 
 
@@ -353,12 +353,10 @@ describe('Tree', () => {
   });
   });
 
 
   it('check', done => {
   it('check', done => {
+    const spy = sinon.spy();
     vm = getTreeVm(':props="defaultProps" show-checkbox @check="handleCheck"', {
     vm = getTreeVm(':props="defaultProps" show-checkbox @check="handleCheck"', {
       methods: {
       methods: {
-        handleCheck(data, args) {
-          this.data = data;
-          this.args = args;
-        }
+        handleCheck: spy
       }
       }
     });
     });
     const secondNode = document.querySelectorAll('.el-tree-node__content')[1];
     const secondNode = document.querySelectorAll('.el-tree-node__content')[1];
@@ -366,8 +364,10 @@ describe('Tree', () => {
     expect(nodeCheckbox).to.be.exist;
     expect(nodeCheckbox).to.be.exist;
     nodeCheckbox.click();
     nodeCheckbox.click();
     setTimeout(() => {
     setTimeout(() => {
-      expect(vm.args.checkedNodes.length).to.equal(3);
-      expect(vm.data.id).to.equal(2);
+      expect(spy.calledOnce).to.be.true;
+      const [data, args] = spy.args[0];
+      expect(data.id).to.equal(2);
+      expect(args.checkedNodes.length).to.equal(3);
       done();
       done();
     }, 10);
     }, 10);
   });
   });
@@ -389,31 +389,31 @@ describe('Tree', () => {
     }, 10);
     }, 10);
   });
   });
 
 
-  it('setCheckedKeys', () => {
+  it('setCheckedKeys', async() => {
     vm = getTreeVm(':props="defaultProps" show-checkbox node-key="id"');
     vm = getTreeVm(':props="defaultProps" show-checkbox node-key="id"');
     const tree = vm.$children[0];
     const tree = vm.$children[0];
     tree.setCheckedKeys([111]);
     tree.setCheckedKeys([111]);
+    await waitImmediate();
     expect(tree.getCheckedNodes().length).to.equal(3);
     expect(tree.getCheckedNodes().length).to.equal(3);
     expect(tree.getCheckedKeys().length).to.equal(3);
     expect(tree.getCheckedKeys().length).to.equal(3);
 
 
     tree.setCheckedKeys([1]);
     tree.setCheckedKeys([1]);
-    setTimeout(function() {
-      expect(tree.getCheckedNodes().length).to.equal(3);
-      expect(tree.getCheckedKeys().length).to.equal(3);
-    }, 0);
+    await waitImmediate();
+    expect(tree.getCheckedNodes().length).to.equal(3);
+    expect(tree.getCheckedKeys().length).to.equal(3);
 
 
     tree.setCheckedKeys([2]);
     tree.setCheckedKeys([2]);
-    setTimeout(function() {
-      expect(tree.getCheckedNodes().length).to.equal(3);
-      expect(tree.getCheckedKeys().length).to.equal(3);
-    }, 0);
+    await waitImmediate();
+    expect(tree.getCheckedNodes().length).to.equal(3);
+    expect(tree.getCheckedKeys().length).to.equal(3);
 
 
     tree.setCheckedKeys([21]);
     tree.setCheckedKeys([21]);
+    await waitImmediate();
     expect(tree.getCheckedNodes().length).to.equal(1);
     expect(tree.getCheckedNodes().length).to.equal(1);
     expect(tree.getCheckedKeys().length).to.equal(1);
     expect(tree.getCheckedKeys().length).to.equal(1);
   });
   });
 
 
-  it('setCheckedKeys with checkStrictly', () => {
+  it('setCheckedKeys with checkStrictly', async() => {
     vm = getTreeVm(':props="defaultProps" checkStrictly show-checkbox node-key="id"');
     vm = getTreeVm(':props="defaultProps" checkStrictly show-checkbox node-key="id"');
     const tree = vm.$children[0];
     const tree = vm.$children[0];
     tree.setCheckedKeys([111]);
     tree.setCheckedKeys([111]);
@@ -421,18 +421,17 @@ describe('Tree', () => {
     expect(tree.getCheckedKeys().length).to.equal(1);
     expect(tree.getCheckedKeys().length).to.equal(1);
 
 
     tree.setCheckedKeys([1]);
     tree.setCheckedKeys([1]);
-    setTimeout(function() {
-      expect(tree.getCheckedNodes().length).to.equal(1);
-      expect(tree.getCheckedKeys().length).to.equal(1);
-    }, 0);
+    await waitImmediate();
+    expect(tree.getCheckedNodes().length).to.equal(1);
+    expect(tree.getCheckedKeys().length).to.equal(1);
 
 
     tree.setCheckedKeys([2]);
     tree.setCheckedKeys([2]);
-    setTimeout(function() {
-      expect(tree.getCheckedNodes().length).to.equal(1);
-      expect(tree.getCheckedKeys().length).to.equal(1);
-    }, 0);
+    await waitImmediate();
+    expect(tree.getCheckedNodes().length).to.equal(1);
+    expect(tree.getCheckedKeys().length).to.equal(1);
 
 
     tree.setCheckedKeys([21, 22]);
     tree.setCheckedKeys([21, 22]);
+    await waitImmediate();
     expect(tree.getCheckedNodes().length).to.equal(2);
     expect(tree.getCheckedNodes().length).to.equal(2);
     expect(tree.getCheckedKeys().length).to.equal(2);
     expect(tree.getCheckedKeys().length).to.equal(2);
   });
   });
@@ -449,24 +448,22 @@ describe('Tree', () => {
     expect(tree.getCheckedKeys().length).to.equal(0);
     expect(tree.getCheckedKeys().length).to.equal(0);
   });
   });
 
 
-  it('setCheckedKeys with leafOnly=false', () => {
+  it('setCheckedKeys with leafOnly=false', async() => {
     vm = getTreeVm(':props="defaultProps" show-checkbox node-key="id"');
     vm = getTreeVm(':props="defaultProps" show-checkbox node-key="id"');
     const tree = vm.$children[0];
     const tree = vm.$children[0];
     tree.setCheckedKeys([1, 11, 111, 2], false);
     tree.setCheckedKeys([1, 11, 111, 2], false);
-    setTimeout(function() {
-      expect(tree.getCheckedNodes().length).to.equal(6);
-      expect(tree.getCheckedKeys().length).to.equal(6);
-    }, 0);
+    await waitImmediate();
+    expect(tree.getCheckedNodes().length).to.equal(6);
+    expect(tree.getCheckedKeys().length).to.equal(6);
   });
   });
 
 
-  it('setCheckedKeys with leafOnly=true', () => {
+  it('setCheckedKeys with leafOnly=true', async() => {
     vm = getTreeVm(':props="defaultProps" show-checkbox node-key="id"');
     vm = getTreeVm(':props="defaultProps" show-checkbox node-key="id"');
     const tree = vm.$children[0];
     const tree = vm.$children[0];
     tree.setCheckedKeys([2], true);
     tree.setCheckedKeys([2], true);
-    setTimeout(function() {
-      expect(tree.getCheckedNodes().length).to.equal(2);
-      expect(tree.getCheckedKeys().length).to.equal(2);
-    }, 0);
+    await waitImmediate();
+    expect(tree.getCheckedNodes().length).to.equal(2);
+    expect(tree.getCheckedKeys().length).to.equal(2);
   });
   });
 
 
   it('setCurrentKey', (done) => {
   it('setCurrentKey', (done) => {

+ 1 - 0
test/unit/specs/upload.spec.js

@@ -4,6 +4,7 @@ const noop = () => {
 };
 };
 const option = {
 const option = {
   onSuccess: noop,
   onSuccess: noop,
+  onProgress: noop,
   data: { a: 'abc', b: 'bcd' },
   data: { a: 'abc', b: 'bcd' },
   filename: 'file.png',
   filename: 'file.png',
   file: 'foo',
   file: 'foo',

+ 2 - 2
test/unit/specs/util.vue-popper.spec.js

@@ -139,7 +139,7 @@ describe('Utils:VuePopper', () => {
     const vm = createTest(Popper, {
     const vm = createTest(Popper, {
       visibleArrow: true
       visibleArrow: true
     });
     });
-    expect(vm.appended).to.empty;
+    expect(vm.appended).to.be.undefined;
     vm.createPopper();
     vm.createPopper();
     expect(vm.appended).to.true;
     expect(vm.appended).to.true;
     vm.appendArrow();
     vm.appendArrow();
@@ -155,7 +155,7 @@ describe('Utils:VuePopper', () => {
       visibleArrow: true,
       visibleArrow: true,
       popper
       popper
     });
     });
-    expect(vm.appended).to.empty;
+    expect(vm.appended).to.be.undefined;
     vm.createPopper();
     vm.createPopper();
     expect(vm.popperJS._popper.querySelector('[x-arrow][_v-110]')).to.exist;
     expect(vm.popperJS._popper.querySelector('[x-arrow][_v-110]')).to.exist;
   });
   });

+ 13 - 0
test/unit/util.js

@@ -106,3 +106,16 @@ export const triggerKeyDown = function(el, keyCode) {
   evt.keyCode = keyCode;
   evt.keyCode = keyCode;
   el.dispatchEvent(evt);
   el.dispatchEvent(evt);
 };
 };
+
+/**
+ * 等待 ms 毫秒,返回 Promise
+ * @param {Number} ms
+ */
+export const wait = function(ms = 50) {
+  return new Promise(resolve => setTimeout(() => resolve(), ms));
+};
+
+/**
+ * 等待一个 Tick,代替 Vue.nextTick,返回 Promise
+ */
+export const waitImmediate = () => wait(0);

文件差异内容过多而无法显示
+ 231 - 321
yarn.lock


部分文件因为文件数量过多而无法显示