對vue-cli(增加/進行)單元測試,所遇到的問題及解決方法。 dom節點為null等
阿新 • • 發佈:2018-12-17
1、用vue-cli生成一個新的專案,把單元測試需要的檔案直接複製到你現有的專案中
2.增加啟動入口
"unit": "karma start test/unit/karma.conf.js --single-run"
3.安裝單元測試需要的外掛
npm i -D karma karma-webpack phantomjs-prebuilt karma-phantomjs-launcher karma-phantomjs-shim karma-chrome-launcher karma-sourcemap-loader mocha karma-mocha sinon chai sinon-chai karma-sinon-chai karma-spec-reporter karma-coverage
4.複製vue-cli生成helloWorld.vue檔案到現有專案
執行 npm run unit
這是測試通過的截圖。
採坑1、 網上找到解決方法
採坑2、執行各種出錯!汗...
在karma.conf.js檔案裡把 PhantomJS 換為 Chrome
採坑2、點選事件及事件封裝方法。
未封裝前:
封裝後:
封裝的util.js採用elementUI專案的原始碼並稍微改動,如createTest函式
util.js貼在本頁最底下。
採坑3、vm.$el.querySelector('xxx') 為 null 等情況.
vm.$el為本元件的dom節點,只能獲取元件內的dom
全域性彈窗等在元件外生成dom,需要從document/html下獲取對應dom
如有引入element等第三方外掛,需要引入
最後建議:github上下載elementUI專案的原始碼進行參考。
util.js:
import Vue from 'vue'; import ElementUI from 'element-ui'; Vue.use(ElementUI); let id = 0; const createElm = function() { const elm = document.createElement('div'); elm.id = 'app' + ++id; document.body.appendChild(elm); return elm; }; /** * 回收 vm * @param {Object} vm vm */ const destroyVM = function(vm) { vm.$destroy && vm.$destroy(); vm.$el && vm.$el.parentNode && vm.$el.parentNode.removeChild(vm.$el); }; /** * 建立一個 Vue 的例項物件 * @param {Object|String} Compo 元件配置,可直接傳 template * @param {Boolean=false} mounted 是否新增到 DOM 上 * @return {Object} vm */ const createVue = function(Compo, mounted = false) { if (Object.prototype.toString.call(Compo) === '[object String]') { Compo = { template: Compo }; } return new Vue(Compo).$mount(mounted === false ? null : createElm()); }; /** * 建立一個測試元件例項 * @link http://vuejs.org/guide/unit-testing.html#Writing-Testable-Components * @param {Object} Compo - 元件物件 * @param {Object} propsData - props 資料 * @param {Boolean=false} mounted - 是否新增到 DOM 上 * @return {Object} vm */ const createTest = function(Compo, propsData = {}, mounted = false) { if (propsData === true || propsData === false) { mounted = propsData; propsData = {}; } const elm = createElm(); const Ctor = Vue.extend(Compo); return new Ctor({ propsData }).$mount(mounted === false ? null : elm); }; /** * 觸發一個事件 * mouseenter, mouseleave, mouseover, keyup, change, click 等 * @param {Element} elm * @param {String} name * @param {*} opts */ const triggerEvent = function(elm, name, ...opts) { let eventName; if (/^mouse|click/.test(name)) { eventName = 'MouseEvents'; } else if (/^key/.test(name)) { eventName = 'KeyboardEvent'; } else { eventName = 'HTMLEvents'; } const evt = document.createEvent(eventName); evt.initEvent(name, ...opts); elm.dispatchEvent ? elm.dispatchEvent(evt) : elm.fireEvent('on' + name, evt); return elm; }; /** * 觸發 “mouseup” 和 “mousedown” 事件 * @param {Element} elm * @param {*} opts */ const triggerClick = function(elm, ...opts) { exports.triggerEvent(elm, 'mousedown', ...opts); exports.triggerEvent(elm, 'mouseup', ...opts); return elm; }; /** * 觸發 keydown 事件 * @param {Element} elm * @param {keyCode} int */ const triggerKeyDown = function(el, keyCode) { const evt = document.createEvent('Events'); evt.initEvent('keydown', true, true); evt.keyCode = keyCode; el.dispatchEvent(evt); }; export { destroyVM, createVue, createTest, triggerEvent, triggerClick, triggerKeyDown };