前言
最近被叫去弄一個新專案,是蠻複雜的 managerial 系統。原本我算 Quasar 教徒,Quasar CLI 專案開起來,順風順水。然而,這個新專案有一個Table需要做 drag sort,Quasar提供的component偏偏沒有這功能。這時,我的小腦殼想出了以下方案:
1. Quasar q-table 搭配 Vue.Draggable: q-table 是一個很完整的component,要讓它完美的和Vue.Draggable一起運作,感覺有點抖
2. Quasar q-table:搭配自己寫 drag sort 功能:應該可以,但就麻煩
3. PrimeVue:改用已經有這個功能的 library,最後找到PrimeVue。不過因為沒用過,可能會有潛在的麻煩,風險也蠻高的
PrimeVue 是一個純粹UX Library,本身沒有樣式
使用 PrimeVue 的第一個問題,是引用的component沒有樣式
後來看到官方文件:「PrimeVue is a design agnostic library so unlike other UI libraries it does not enforce a certain styling such as material or bootstrap. 」所以跟Quasar不同,它本身沒帶SCSS或CSS
當然,PrimeVue也有配套,它提供 Material, Bootstrap, Saga......的UI,還蠻多種的,甚至有個編輯器可以輕鬆制定主題顏色。但這整套要用要錢
覺得上面不會出錢的我,想到的方法是...自己寫SCSS
VueCLI 配 Vue3 自架 SCSS
關於Vue CLI install sass-loader、vue.config.js 怎麼配,很多人講的比我清楚,就不詳述了。在這邊只講我最後的配置,和遇到的問題
最後,我的配置是:sass、sass-loaderstyle-resources-loader、vue-cli-plugin-style-resources-loader。引入一個 main.scss檔案管變數,一個 style.css 來制定UI樣式
vue.config.js的內容為:
module.exports = {
pluginOptions: {
'style-resources-loader': {
preProcessor: 'scss',
patterns: [
'./src/assets/scss/main.scss',
'./src/assets/css/style.css'
]
}
}
}
sass-loader的配置方式 Vue CLI都有教學,但我後來是採用 style-resources-loader 的配置。使用sass-loader的過程可能會出現以下報錯:
Syntax Error: TypeError: this.getOptions is not a function
錯誤的原因是 webpage4 沒辦法運作最新版的 sass-loader。要解決這個問題,在 package.json裡把 sass-loader版號改成 "^10.2.0",重新 npm install,就行了
Global引入PrimeVue component
像 Button 這種常常需要用到的組件,也可以使用全局引入。方法很簡單:
1. 打開 main.js
2. import Button from 'primevue/button'; << 引入 Button 組件
測試-面對Global引入的PrimeVue component
誠如上面示範,有些 components 在這個專案裡是以全局方式引入的。
寫 unit test 時就報了一個這樣的警告:
[Vue warn]: Failed to resolve component: Button
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
這是因為跑測試的時候只創建一個組件的實例,因此全局註冊在測試裡失效了。關於這個問題,我找了兩個解法:1. stubs(存根) 2. golbal component。
1. stubs 解法
最直覺的做法,用stubs通知<Button>的內容
這是 vue3 (Vue Test Utils 2)的寫法,使用Vue2 的話要額外查一下
2. global component 解法
如果是全局註冊沒吃到,就直接在 mout 前註冊吧
測試-需留意Vue Test Unit Next廢棄的部分
PrimeVue 的 components 引入、使用的方式和一般自己寫的components一樣。在Vue CLI 的配置下,不會像使用quasar時,因認不出 <q-input> 之類的標籤而需要做一些設定
不過這個專案是使用Vue3,連帶單元測試也是使用 Vue Test Unit Next,必須留意是不是用到已廢棄的功能
例如,我這邊想測試一個引用了Vuex store的component。
如下圖所見,computed 寫在 setup裡:
要測試的code |
這時參考Vue Unit Test Next 來mock一個store,使用 provide。
使用 provide是,因為被測試的component在setup裡使用store的緣故。若是在 mounted 或以往的computed,那就必須使用 mock 或 plugins,這部分請參考
執行測試的code |
上述模擬 store 的部分,若是在Vue2,就會使用createLocalVue來進行。但因createLocalVue在 Vue Unit Test Next 裡已廢棄,所以想使用它的話,會出現沒有這個 function 的報錯:
測試-快照測試(Snapshot)需注意的問題
這部分雖然和 PrimeVue 無關,但也是我在這個專案裡思考的問題。
這個專案是一個複雜的管理系統,必須顯示很多資料、穿插切換編輯用的UI,編輯內容需要驗證,api 返回的內容也會有訊息通知。我在做 snapshot 的時候就遇到一些問題。
我為一個含 data table 的 component 寫了一個 describe function,分別測試一個會造成畫面更動(會改動 reference data的值)的method 和 snapshot。最後靠先測 snapshot,再測 method 的順序來通過測試,但坦白說我不是很滿意。
比較好的做法是看看能不能把 component 拆小用,做成更小的快照。或用shallowMount 取代 Mount,但這樣 data table 裡一些客製化的內容就測不到了,它們會被存根。
相關資訊可以參考Snapshot Testing for Frontends,他點出了幾個不適合 snapshot 的情況:
1. 快照超過1000行
2. 多語化情境
3. 快照過大的情況下要解決快照衝突, 會是繁瑣的工作
測試-Dropdown 被stub後竟然報錯,那就自己設計stub啊
首先,Dropdown 是 PrimeVue 提供的組件。我們先來看看這個報錯:
[Vue warn]: Failed setting prop "scrollHeight" on <dropdown-stub>: value 200px is invalid. TypeError: Cannot set property scrollHeight of [object Element] which has only a getter
再來看看相關的code:
被測的內容:
<Dropdown測試代碼:
被測的內容雖然一堆 props ,但我沒有傳“scrollHeight”進去。打開PrimeVue 裡Dropdown component 一看,原來有個default value。
default 的 scrollHeight,不是我寫地~ |
Unit Test 基本原則是只測自己寫的東西,所以我們不需要管 Dropdown 真正的內容是什麼。既然問題看起來是無法在<dropdown-stub>上掛“scrollHeight = 200px”,那讓 Dropdown 的 stub 變成一般的div就行了吧。
改寫後的測試代碼:
1. <dropdown-stub> 是 shallowMount 預設的stub方式,所以改成用 mount 來生成實例。
2. 在 stubs 裡寫自己替換 Dropdown 內容的template
結果測試成功。從snapshot也可以看到<dropdown-stub>被換成自己設計的 div 了。
(待續...)
留言
張貼留言