w-flow-vue 1.0.20 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/w-flow-vue.umd.js +3 -3
- package/dist/w-flow-vue.umd.js.map +1 -1
- package/docs/components_WFlowVue.vue.html +1392 -1307
- package/docs/components_ui_Controls.vue.html +278 -0
- package/docs/examples/app.html +1 -1
- package/docs/examples/app.umd.js +4 -4
- package/docs/examples/app.umd.js.map +1 -1
- package/docs/examples/ex-AppBasic.html +1 -1
- package/docs/examples/ex-AppConnectivity.html +1 -1
- package/docs/global.html +87 -2
- package/docs/index.html +2 -2
- package/docs/js_defaults.mjs.html +2 -2
- package/docs/js_edgePath.mjs.html +2 -2
- package/docs/js_fixSvgNs.mjs.html +2 -2
- package/docs/js_geometry.mjs.html +2 -2
- package/docs/js_graph.mjs.html +2 -2
- package/docs/js_stepRouting.mjs.html +2 -2
- package/docs/module-WFlowVue.html +1236 -17
- package/package.json +1 -1
- package/src/components/WFlowVue.vue +1390 -1305
- package/src/components/ui/Controls.vue +206 -119
- package/test/unit-components-ui.test.mjs +248 -69
|
@@ -1,119 +1,206 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<!-- 垂直選單: 改用w-threejs-vue同款組件WGroupIconCheck(:dir='vertical'), 最頂為設定鈕, 收合時僅顯示設定鈕, 展開才顯示其餘按鈕 -->
|
|
3
|
-
<div
|
|
4
|
-
|
|
5
|
-
:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<!--
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
:
|
|
12
|
-
:
|
|
13
|
-
:
|
|
14
|
-
:
|
|
15
|
-
:
|
|
16
|
-
:
|
|
17
|
-
:
|
|
18
|
-
:
|
|
19
|
-
:
|
|
20
|
-
:seplineColor="
|
|
21
|
-
:shadow="
|
|
22
|
-
:
|
|
23
|
-
:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 垂直選單: 改用w-threejs-vue同款組件WGroupIconCheck(:dir='vertical'), 最頂為設定鈕, 收合時僅顯示設定鈕, 展開才顯示其餘按鈕 -->
|
|
3
|
+
<div
|
|
4
|
+
v-if="cfg.useMenu"
|
|
5
|
+
:class="['vue-flow__panel', `vue-flow__panel--${cfg.menuPosition}`]"
|
|
6
|
+
:style="panelStyle"
|
|
7
|
+
>
|
|
8
|
+
<!-- 淺色系配色(w-flow-vue圖台為白底, 沿用原Controls之#fefefe白底/深灰icon風格; iconSize預設22, 按鈕寬=22+左右padding8=30px與w-threejs-vue選單一致) -->
|
|
9
|
+
<!-- 全數為一般動作鈕(不用active態): 鎖頭點擊即切換上鎖/解鎖並換icon(比照fitView等), 不留固定灰底; value恆空故無任一鈕呈active, 故不開放*ColorActive類選項 -->
|
|
10
|
+
<WGroupIconCheck
|
|
11
|
+
:items="useItems"
|
|
12
|
+
:dir="'vertical'"
|
|
13
|
+
:iconColor="cfg.menuIconColor"
|
|
14
|
+
:iconColorHover="cfg.menuIconColorHover"
|
|
15
|
+
:iconColorFocus="cfg.menuIconColorFocus"
|
|
16
|
+
:iconSize="cfg.menuIconSize"
|
|
17
|
+
:backgroundColor="cfg.menuBackgroundColor"
|
|
18
|
+
:backgroundColorHover="cfg.menuBackgroundColorHover"
|
|
19
|
+
:backgroundColorFocus="cfg.menuBackgroundColorFocus"
|
|
20
|
+
:seplineColor="cfg.menuSeparatorColor"
|
|
21
|
+
:shadow="cfg.menuShadow"
|
|
22
|
+
:tooltipTextColor="cfg.menuTooltipTextColor"
|
|
23
|
+
:tooltipTextFontSize="cfg.menuTooltipTextFontSize"
|
|
24
|
+
:tooltipBackgroundColor="cfg.menuTooltipBackgroundColor"
|
|
25
|
+
:value="[]"
|
|
26
|
+
@click="onClickItem"
|
|
27
|
+
></WGroupIconCheck>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script>
|
|
32
|
+
import WGroupIconCheck from 'w-component-vue/src/components/WGroupIconCheck.vue'
|
|
33
|
+
import { mdiCogOutline, mdiMagnifyPlusOutline, mdiMagnifyMinusOutline, mdiFitToPageOutline, mdiLockOutline, mdiLockOpenVariantOutline } from '@mdi/js/mdi.js'
|
|
34
|
+
|
|
35
|
+
//menuDef, 選單各項之預設值, 未被opt覆寫者沿用之
|
|
36
|
+
//注意: menuIconSize, menuTooltipTextColor, menuTooltipBackgroundColor原為WGroupIconCheck之預設值,
|
|
37
|
+
//因w-component-vue為浮動相依(^2.5.2), 子套件改預設會靜默改變本套件外觀, 故於此明寫鎖住現值
|
|
38
|
+
let menuDef = {
|
|
39
|
+
|
|
40
|
+
//整體
|
|
41
|
+
useMenu: true,
|
|
42
|
+
menuPosition: 'top-left',
|
|
43
|
+
menuYShift: 0,
|
|
44
|
+
useSetting: true,
|
|
45
|
+
|
|
46
|
+
//設定鈕(收合/展開)
|
|
47
|
+
menuSettingIcon: mdiCogOutline,
|
|
48
|
+
menuSettingTooltip: 'Settings',
|
|
49
|
+
|
|
50
|
+
//放大
|
|
51
|
+
useMenuItemZoomIn: true,
|
|
52
|
+
menuZoomInIcon: mdiMagnifyPlusOutline,
|
|
53
|
+
menuZoomInTooltip: 'Zoom In',
|
|
54
|
+
|
|
55
|
+
//縮小
|
|
56
|
+
useMenuItemZoomOut: true,
|
|
57
|
+
menuZoomOutIcon: mdiMagnifyMinusOutline,
|
|
58
|
+
menuZoomOutTooltip: 'Zoom Out',
|
|
59
|
+
|
|
60
|
+
//全圖
|
|
61
|
+
useMenuItemFitView: true,
|
|
62
|
+
menuFitViewIcon: mdiFitToPageOutline,
|
|
63
|
+
menuFitViewTooltip: 'Fit View',
|
|
64
|
+
|
|
65
|
+
//鎖定(雙態: 無後綴為未鎖態, Locked後綴為已鎖態)
|
|
66
|
+
useMenuItemLock: true,
|
|
67
|
+
menuLockIcon: mdiLockOpenVariantOutline,
|
|
68
|
+
menuLockTooltip: 'Lock',
|
|
69
|
+
menuLockIconLocked: mdiLockOutline,
|
|
70
|
+
menuLockTooltipLocked: 'Unlock',
|
|
71
|
+
|
|
72
|
+
//樣式
|
|
73
|
+
menuIconColor: '#555',
|
|
74
|
+
menuIconColorHover: '#222',
|
|
75
|
+
menuIconColorFocus: '#222',
|
|
76
|
+
menuIconSize: 22,
|
|
77
|
+
menuBackgroundColor: '#fefefe',
|
|
78
|
+
menuBackgroundColorHover: '#f0f0f0',
|
|
79
|
+
menuBackgroundColorFocus: '#f0f0f0',
|
|
80
|
+
menuSeparatorColor: '#e6e6e6',
|
|
81
|
+
menuShadow: true,
|
|
82
|
+
menuTooltipTextColor: 'white',
|
|
83
|
+
menuTooltipTextFontSize: '0.7rem',
|
|
84
|
+
menuTooltipBackgroundColor: 'rgba(60,60,60,0.75)',
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
//menuPositions, menuPosition之允許值, 不在其中者回退預設
|
|
89
|
+
let menuPositions = ['top-left', 'top-right', 'bottom-left', 'bottom-right']
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 取單項設定值, 型別與menuDef同型且有效才採用, 否則回退menuDef
|
|
93
|
+
*/
|
|
94
|
+
function pickMenuValue(k, v) {
|
|
95
|
+
let d = menuDef[k]
|
|
96
|
+
if (typeof d === 'string') {
|
|
97
|
+
return (typeof v === 'string' && v !== '') ? v : d
|
|
98
|
+
}
|
|
99
|
+
if (typeof d === 'boolean') {
|
|
100
|
+
return (typeof v === 'boolean') ? v : d
|
|
101
|
+
}
|
|
102
|
+
if (typeof d === 'number') {
|
|
103
|
+
return (typeof v === 'number' && isFinite(v)) ? v : d
|
|
104
|
+
}
|
|
105
|
+
return d
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export default {
|
|
109
|
+
name: 'FlowControls',
|
|
110
|
+
components: { WGroupIconCheck },
|
|
111
|
+
props: {
|
|
112
|
+
//選單設定物件, 鍵值同menuDef, 由WFlowVue自opt原樣取出後傳入; 各鍵未給或型別不符即回退menuDef
|
|
113
|
+
menu: { type: Object, default: () => ({}) },
|
|
114
|
+
locked: { type: Boolean, default: false },
|
|
115
|
+
},
|
|
116
|
+
data() {
|
|
117
|
+
return {
|
|
118
|
+
//設定鈕展開狀態(收合時僅顯示設定鈕, 展開才顯示其餘按鈕), 比照w-threejs-vue; 初值取menu.useSetting
|
|
119
|
+
useSetting: pickMenuValue('useSetting', (this.menu || {}).useSetting),
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
computed: {
|
|
123
|
+
cfg() {
|
|
124
|
+
let m = this.menu || {}
|
|
125
|
+
let r = {}
|
|
126
|
+
for (let k in menuDef) {
|
|
127
|
+
r[k] = pickMenuValue(k, m[k])
|
|
128
|
+
}
|
|
129
|
+
//menuPosition另檢核列舉值
|
|
130
|
+
if (menuPositions.indexOf(r.menuPosition) < 0) {
|
|
131
|
+
r.menuPosition = menuDef.menuPosition
|
|
132
|
+
}
|
|
133
|
+
return r
|
|
134
|
+
},
|
|
135
|
+
allItems() {
|
|
136
|
+
let c = this.cfg
|
|
137
|
+
let rs = [
|
|
138
|
+
{ id: 'setting', icon: c.menuSettingIcon, tooltip: c.menuSettingTooltip },
|
|
139
|
+
]
|
|
140
|
+
if (c.useMenuItemZoomIn) {
|
|
141
|
+
rs.push({ id: 'zoomIn', icon: c.menuZoomInIcon, tooltip: c.menuZoomInTooltip })
|
|
142
|
+
}
|
|
143
|
+
if (c.useMenuItemZoomOut) {
|
|
144
|
+
rs.push({ id: 'zoomOut', icon: c.menuZoomOutIcon, tooltip: c.menuZoomOutTooltip })
|
|
145
|
+
}
|
|
146
|
+
if (c.useMenuItemFitView) {
|
|
147
|
+
rs.push({ id: 'fitView', icon: c.menuFitViewIcon, tooltip: c.menuFitViewTooltip })
|
|
148
|
+
}
|
|
149
|
+
if (c.useMenuItemLock) {
|
|
150
|
+
rs.push({ id: 'interactive', icon: this.locked ? c.menuLockIconLocked : c.menuLockIcon, tooltip: this.locked ? c.menuLockTooltipLocked : c.menuLockTooltip })
|
|
151
|
+
}
|
|
152
|
+
return rs
|
|
153
|
+
},
|
|
154
|
+
useItems() {
|
|
155
|
+
//設定鈕恆在最頂; 收合時僅顯示設定鈕
|
|
156
|
+
if (this.useSetting) {
|
|
157
|
+
return this.allItems
|
|
158
|
+
}
|
|
159
|
+
return [this.allItems[0]]
|
|
160
|
+
},
|
|
161
|
+
panelStyle() {
|
|
162
|
+
//向下偏移: top-*位置加margin-top, bottom-*位置加margin-bottom(margin於絕對定位元素上等同再位移該側)
|
|
163
|
+
//故menuYShift之語義為[正值使選單遠離其錨定邊]: top-*向下, bottom-*向上
|
|
164
|
+
let s = 'z-index:5;'
|
|
165
|
+
if (this.cfg.menuPosition.indexOf('bottom') >= 0) {
|
|
166
|
+
s += `margin-bottom:${this.cfg.menuYShift}px;`
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
s += `margin-top:${this.cfg.menuYShift}px;`
|
|
170
|
+
}
|
|
171
|
+
return s
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
methods: {
|
|
175
|
+
onClickItem(item) {
|
|
176
|
+
let id = (item && item.id) || ''
|
|
177
|
+
if (id === 'setting') {
|
|
178
|
+
this.useSetting = !this.useSetting
|
|
179
|
+
}
|
|
180
|
+
else if (id === 'zoomIn') {
|
|
181
|
+
this.$emit('zoom-in')
|
|
182
|
+
}
|
|
183
|
+
else if (id === 'zoomOut') {
|
|
184
|
+
this.$emit('zoom-out')
|
|
185
|
+
}
|
|
186
|
+
else if (id === 'fitView') {
|
|
187
|
+
this.$emit('fit-view')
|
|
188
|
+
}
|
|
189
|
+
else if (id === 'interactive') {
|
|
190
|
+
this.$emit('toggle-interactive')
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
</script>
|
|
196
|
+
|
|
197
|
+
<style scoped>
|
|
198
|
+
.vue-flow__panel {
|
|
199
|
+
position: absolute;
|
|
200
|
+
z-index: 5;
|
|
201
|
+
}
|
|
202
|
+
.vue-flow__panel--top-left { top: 10px; left: 10px; }
|
|
203
|
+
.vue-flow__panel--top-right { top: 10px; right: 10px; }
|
|
204
|
+
.vue-flow__panel--bottom-left { bottom: 10px; left: 10px; }
|
|
205
|
+
.vue-flow__panel--bottom-right { bottom: 10px; right: 10px; }
|
|
206
|
+
</style>
|
|
@@ -1,69 +1,248 @@
|
|
|
1
|
-
import { mount } from '@vue/test-utils'
|
|
2
|
-
import Controls from '../src/components/ui/Controls.vue'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
test('
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
test('
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
})
|
|
68
|
-
})
|
|
69
|
-
|
|
1
|
+
import { mount } from '@vue/test-utils'
|
|
2
|
+
import Controls from '../src/components/ui/Controls.vue'
|
|
3
|
+
import WGroupIconCheck from 'w-component-vue/src/components/WGroupIconCheck.vue'
|
|
4
|
+
|
|
5
|
+
//Controls以WGroupIconCheck渲染, 單顆按鈕為[role="button"]之元素(非原生<button>)
|
|
6
|
+
const btns = (w) => w.findAll('[role="button"]')
|
|
7
|
+
|
|
8
|
+
//WGroupIconCheck之toggleState於$nextTick內才emit, 故點擊後需多刷幾輪microtask才看得到結果
|
|
9
|
+
const flush = async (w) => {
|
|
10
|
+
for (let i = 0; i < 3; i++) {
|
|
11
|
+
await w.vm.$nextTick()
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//WButtonCircle之role="button"在最外層div, 但@click掛在內層之可點擊面(帶cursor:pointer)上,
|
|
15
|
+
//jsdom之trigger不會往下傳, 故點擊須打在該內層元素
|
|
16
|
+
const clickItem = async (w, i) => {
|
|
17
|
+
await btns(w).at(i).find('[style*="cursor: pointer"]').trigger('click')
|
|
18
|
+
await flush(w)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe('Controls 預設(不給任何menu選項)', () => {
|
|
22
|
+
test('顯示5顆鈕: setting/zoomIn/zoomOut/fitView/lock', () => {
|
|
23
|
+
const w = mount(Controls)
|
|
24
|
+
expect(w.vm.allItems.map((v) => v.id)).toEqual(['setting', 'zoomIn', 'zoomOut', 'fitView', 'interactive'])
|
|
25
|
+
expect(btns(w)).toHaveLength(5)
|
|
26
|
+
w.destroy()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('tooltip與icon為現行英文預設', () => {
|
|
30
|
+
const w = mount(Controls)
|
|
31
|
+
expect(w.vm.allItems.map((v) => v.tooltip)).toEqual(['Settings', 'Zoom In', 'Zoom Out', 'Fit View', 'Lock'])
|
|
32
|
+
w.destroy()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('套用top-left位置class', () => {
|
|
36
|
+
const w = mount(Controls)
|
|
37
|
+
expect(w.classes()).toContain('vue-flow__panel--top-left')
|
|
38
|
+
w.destroy()
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
describe('Controls 事件', () => {
|
|
43
|
+
test('各鈕點擊送出對應事件', async () => {
|
|
44
|
+
const w = mount(Controls)
|
|
45
|
+
await clickItem(w, 1)
|
|
46
|
+
expect(w.emitted('zoom-in')).toBeTruthy()
|
|
47
|
+
await clickItem(w, 2)
|
|
48
|
+
expect(w.emitted('zoom-out')).toBeTruthy()
|
|
49
|
+
await clickItem(w, 3)
|
|
50
|
+
expect(w.emitted('fit-view')).toBeTruthy()
|
|
51
|
+
await clickItem(w, 4)
|
|
52
|
+
expect(w.emitted('toggle-interactive')).toBeTruthy()
|
|
53
|
+
w.destroy()
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('設定鈕點擊為收合/展開, 不送出事件', async () => {
|
|
57
|
+
const w = mount(Controls)
|
|
58
|
+
expect(w.vm.useItems).toHaveLength(5)
|
|
59
|
+
await clickItem(w, 0)
|
|
60
|
+
expect(w.vm.useItems).toHaveLength(1)
|
|
61
|
+
expect(w.vm.useItems[0].id).toBe('setting')
|
|
62
|
+
await clickItem(w, 0)
|
|
63
|
+
expect(w.vm.useItems).toHaveLength(5)
|
|
64
|
+
expect(w.emitted('zoom-in')).toBeFalsy()
|
|
65
|
+
expect(w.emitted('toggle-interactive')).toBeFalsy()
|
|
66
|
+
w.destroy()
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
describe('Controls 可見性(useMenu/useMenuItem*)', () => {
|
|
71
|
+
test('useMenu=false整列不渲染', () => {
|
|
72
|
+
const w = mount(Controls, { propsData: { menu: { useMenu: false } } })
|
|
73
|
+
expect(w.find('.vue-flow__panel').exists()).toBe(false)
|
|
74
|
+
w.destroy()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('useMenuItemZoomIn=false僅隱藏放大鈕, 縮小鈕仍在', () => {
|
|
78
|
+
const w = mount(Controls, { propsData: { menu: { useMenuItemZoomIn: false } } })
|
|
79
|
+
expect(w.vm.allItems.map((v) => v.id)).toEqual(['setting', 'zoomOut', 'fitView', 'interactive'])
|
|
80
|
+
w.destroy()
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('useMenuItemZoomOut=false僅隱藏縮小鈕, 放大鈕仍在', () => {
|
|
84
|
+
const w = mount(Controls, { propsData: { menu: { useMenuItemZoomOut: false } } })
|
|
85
|
+
expect(w.vm.allItems.map((v) => v.id)).toEqual(['setting', 'zoomIn', 'fitView', 'interactive'])
|
|
86
|
+
w.destroy()
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('useMenuItemFitView=false隱藏全圖鈕', () => {
|
|
90
|
+
const w = mount(Controls, { propsData: { menu: { useMenuItemFitView: false } } })
|
|
91
|
+
expect(w.vm.allItems.map((v) => v.id)).toEqual(['setting', 'zoomIn', 'zoomOut', 'interactive'])
|
|
92
|
+
w.destroy()
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('useMenuItemLock=false隱藏鎖頭鈕', () => {
|
|
96
|
+
const w = mount(Controls, { propsData: { menu: { useMenuItemLock: false } } })
|
|
97
|
+
expect(w.vm.allItems.map((v) => v.id)).toEqual(['setting', 'zoomIn', 'zoomOut', 'fitView'])
|
|
98
|
+
w.destroy()
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('useSetting=false初始即收合', () => {
|
|
102
|
+
const w = mount(Controls, { propsData: { menu: { useSetting: false } } })
|
|
103
|
+
expect(w.vm.useItems).toHaveLength(1)
|
|
104
|
+
expect(w.vm.useItems[0].id).toBe('setting')
|
|
105
|
+
w.destroy()
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
describe('Controls 文字與icon覆寫', () => {
|
|
110
|
+
test('逐項覆寫tooltip', () => {
|
|
111
|
+
const w = mount(Controls, {
|
|
112
|
+
propsData: {
|
|
113
|
+
menu: {
|
|
114
|
+
menuSettingTooltip: '收合工具列',
|
|
115
|
+
menuZoomInTooltip: '放大',
|
|
116
|
+
menuZoomOutTooltip: '縮小',
|
|
117
|
+
menuFitViewTooltip: '全圖顯示',
|
|
118
|
+
menuLockTooltip: '鎖定',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
})
|
|
122
|
+
expect(w.vm.allItems.map((v) => v.tooltip)).toEqual(['收合工具列', '放大', '縮小', '全圖顯示', '鎖定'])
|
|
123
|
+
w.destroy()
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('部分覆寫時未給者維持英文預設', () => {
|
|
127
|
+
const w = mount(Controls, { propsData: { menu: { menuZoomInTooltip: '放大' } } })
|
|
128
|
+
expect(w.vm.allItems.map((v) => v.tooltip)).toEqual(['Settings', '放大', 'Zoom Out', 'Fit View', 'Lock'])
|
|
129
|
+
w.destroy()
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('空字串回退預設, 不出現空白tooltip', () => {
|
|
133
|
+
const w = mount(Controls, { propsData: { menu: { menuZoomInTooltip: '' } } })
|
|
134
|
+
expect(w.vm.cfg.menuZoomInTooltip).toBe('Zoom In')
|
|
135
|
+
w.destroy()
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
test('型別不符回退預設', () => {
|
|
139
|
+
const w = mount(Controls, {
|
|
140
|
+
propsData: {
|
|
141
|
+
menu: {
|
|
142
|
+
menuZoomInTooltip: 123,
|
|
143
|
+
useMenuItemFitView: 'yes',
|
|
144
|
+
menuIconSize: 'big',
|
|
145
|
+
menuYShift: NaN,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
})
|
|
149
|
+
expect(w.vm.cfg.menuZoomInTooltip).toBe('Zoom In')
|
|
150
|
+
expect(w.vm.cfg.useMenuItemFitView).toBe(true)
|
|
151
|
+
expect(w.vm.cfg.menuIconSize).toBe(22)
|
|
152
|
+
expect(w.vm.cfg.menuYShift).toBe(0)
|
|
153
|
+
w.destroy()
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('覆寫icon', () => {
|
|
157
|
+
const w = mount(Controls, { propsData: { menu: { menuZoomInIcon: 'M0 0 L1 1' } } })
|
|
158
|
+
expect(w.vm.allItems[1].icon).toBe('M0 0 L1 1')
|
|
159
|
+
w.destroy()
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
describe('Controls 鎖頭雙態', () => {
|
|
164
|
+
test('未鎖態取無後綴之icon與tooltip', () => {
|
|
165
|
+
const w = mount(Controls, { propsData: { locked: false, menu: { menuLockTooltip: '鎖定', menuLockTooltipLocked: '解除鎖定' } } })
|
|
166
|
+
expect(w.vm.allItems[4].tooltip).toBe('鎖定')
|
|
167
|
+
w.destroy()
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
test('已鎖態取Locked後綴之icon與tooltip', () => {
|
|
171
|
+
const w = mount(Controls, { propsData: { locked: true, menu: { menuLockTooltip: '鎖定', menuLockTooltipLocked: '解除鎖定' } } })
|
|
172
|
+
expect(w.vm.allItems[4].tooltip).toBe('解除鎖定')
|
|
173
|
+
w.destroy()
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
test('未給覆寫時雙態為Lock/Unlock且icon不同', () => {
|
|
177
|
+
const w0 = mount(Controls, { propsData: { locked: false } })
|
|
178
|
+
const w1 = mount(Controls, { propsData: { locked: true } })
|
|
179
|
+
expect(w0.vm.allItems[4].tooltip).toBe('Lock')
|
|
180
|
+
expect(w1.vm.allItems[4].tooltip).toBe('Unlock')
|
|
181
|
+
expect(w0.vm.allItems[4].icon).not.toBe(w1.vm.allItems[4].icon)
|
|
182
|
+
w0.destroy()
|
|
183
|
+
w1.destroy()
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
describe('Controls 位置與位移', () => {
|
|
188
|
+
test('四個menuPosition各自套用對應class', () => {
|
|
189
|
+
const poss = ['top-left', 'top-right', 'bottom-left', 'bottom-right']
|
|
190
|
+
poss.forEach((p) => {
|
|
191
|
+
const w = mount(Controls, { propsData: { menu: { menuPosition: p } } })
|
|
192
|
+
expect(w.classes()).toContain(`vue-flow__panel--${p}`)
|
|
193
|
+
w.destroy()
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
test('menuPosition非允許值回退top-left', () => {
|
|
198
|
+
const w = mount(Controls, { propsData: { menu: { menuPosition: 'middle' } } })
|
|
199
|
+
expect(w.classes()).toContain('vue-flow__panel--top-left')
|
|
200
|
+
w.destroy()
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
test('menuYShift於top-*加margin-top, 於bottom-*加margin-bottom', () => {
|
|
204
|
+
const wt = mount(Controls, { propsData: { menu: { menuPosition: 'top-left', menuYShift: 40 } } })
|
|
205
|
+
expect(wt.vm.panelStyle).toContain('margin-top:40px;')
|
|
206
|
+
const wb = mount(Controls, { propsData: { menu: { menuPosition: 'bottom-left', menuYShift: 40 } } })
|
|
207
|
+
expect(wb.vm.panelStyle).toContain('margin-bottom:40px;')
|
|
208
|
+
wt.destroy()
|
|
209
|
+
wb.destroy()
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
describe('Controls 樣式選項', () => {
|
|
214
|
+
test('未給樣式選項時鎖住現行值(不隨w-component-vue預設浮動)', () => {
|
|
215
|
+
const c = mount(Controls).vm.cfg
|
|
216
|
+
expect(c.menuIconColor).toBe('#555')
|
|
217
|
+
expect(c.menuIconColorHover).toBe('#222')
|
|
218
|
+
expect(c.menuIconColorFocus).toBe('#222')
|
|
219
|
+
expect(c.menuIconSize).toBe(22)
|
|
220
|
+
expect(c.menuBackgroundColor).toBe('#fefefe')
|
|
221
|
+
expect(c.menuBackgroundColorHover).toBe('#f0f0f0')
|
|
222
|
+
expect(c.menuBackgroundColorFocus).toBe('#f0f0f0')
|
|
223
|
+
expect(c.menuSeparatorColor).toBe('#e6e6e6')
|
|
224
|
+
expect(c.menuShadow).toBe(true)
|
|
225
|
+
expect(c.menuTooltipTextColor).toBe('white')
|
|
226
|
+
expect(c.menuTooltipTextFontSize).toBe('0.7rem')
|
|
227
|
+
expect(c.menuTooltipBackgroundColor).toBe('rgba(60,60,60,0.75)')
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
test('樣式選項可覆寫並下傳至WGroupIconCheck', () => {
|
|
231
|
+
const w = mount(Controls, {
|
|
232
|
+
propsData: {
|
|
233
|
+
menu: {
|
|
234
|
+
menuIconColor: '#111',
|
|
235
|
+
menuSeparatorColor: '#abcabc',
|
|
236
|
+
menuShadow: false,
|
|
237
|
+
menuTooltipTextFontSize: '1rem',
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
})
|
|
241
|
+
const g = w.findComponent(WGroupIconCheck)
|
|
242
|
+
expect(g.props('iconColor')).toBe('#111')
|
|
243
|
+
expect(g.props('seplineColor')).toBe('#abcabc')
|
|
244
|
+
expect(g.props('shadow')).toBe(false)
|
|
245
|
+
expect(g.props('tooltipTextFontSize')).toBe('1rem')
|
|
246
|
+
w.destroy()
|
|
247
|
+
})
|
|
248
|
+
})
|