w-flow-vue 1.0.21 → 1.0.23
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 +61 -6
- package/docs/components_ui_Controls.vue.html +1 -1
- 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 +1 -1
- package/docs/index.html +1 -1
- package/docs/js_defaults.mjs.html +1 -1
- package/docs/js_edgePath.mjs.html +1 -1
- package/docs/js_fixSvgNs.mjs.html +1 -1
- package/docs/js_geometry.mjs.html +1 -1
- package/docs/js_graph.mjs.html +1 -1
- package/docs/js_stepRouting.mjs.html +1 -1
- package/docs/module-WFlowVue.html +1 -1
- package/package.json +1 -1
- package/src/components/WFlowVue.vue +60 -5
- package/src/components/nodes/NodeRenderer.vue +1 -0
- package/src/components/nodes/NodeWrapper.vue +81 -19
- package/test/pics/flow-E2E-011-node-settings-form.png +0 -0
- package/test/pics/flow-E2E-012-popup-exclusive.png +0 -0
- package/test/unit-WFlowVue-features.test.mjs +10 -8
- package/test/unit-WFlowVue.test.mjs +432 -421
- package/test/unit-components-canvas.test.mjs +104 -102
- package/test/unit-components-edge.test.mjs +157 -147
- package/test/unit-components-node.test.mjs +27 -5
- package/test/unit-geometry.test.mjs +248 -236
- package/test/unit-graph.test.mjs +72 -72
- package/test/unit-node-drag-gesture.test.mjs +254 -0
package/test/unit-graph.test.mjs
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
{ id: 'e1-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{ id: '
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
test('generates unique ids', () => {
|
|
63
|
-
const id1 = generateId()
|
|
64
|
-
const id2 = generateId()
|
|
65
|
-
expect(id1).not.toBe(id2)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
test('returns string', () => {
|
|
69
|
-
expect(typeof generateId()).toBe('string')
|
|
70
|
-
})
|
|
71
|
-
})
|
|
72
|
-
})
|
|
1
|
+
//resetIdCounter 已自 graph.mjs 移除; generateId 以 Date.now()+內部counter+random 組成,
|
|
2
|
+
//唯一性不依賴 counter 歸零, 故原斷言仍有效, 僅移除該前置
|
|
3
|
+
import { isValidConnection, generateId } from '../src/js/graph'
|
|
4
|
+
|
|
5
|
+
describe('graph', () => {
|
|
6
|
+
const conns = [
|
|
7
|
+
{ id: 'e1-2', from: '1', to: '2' },
|
|
8
|
+
{ id: 'e2-3', from: '2', to: '3' },
|
|
9
|
+
{ id: 'e1-3', from: '1', to: '3' },
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
const nodes = [
|
|
13
|
+
{ id: '1', position: { x: 0, y: 0 } },
|
|
14
|
+
{ id: '2', position: { x: 100, y: 0 } },
|
|
15
|
+
{ id: '3', position: { x: 200, y: 0 } },
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
describe('isValidConnection', () => {
|
|
19
|
+
test('valid connection returns true', () => {
|
|
20
|
+
const connection = { from: '1', to: '2' }
|
|
21
|
+
expect(isValidConnection(connection, nodes, [], null)).toBe(true)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('self-connection returns false', () => {
|
|
25
|
+
const connection = { from: '1', to: '1' }
|
|
26
|
+
expect(isValidConnection(connection, nodes, [], null)).toBe(false)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('duplicate connection returns false', () => {
|
|
30
|
+
const connection = { from: '1', to: '2' }
|
|
31
|
+
expect(isValidConnection(connection, nodes, conns, null)).toBe(false)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('missing from returns false', () => {
|
|
35
|
+
expect(isValidConnection({ to: '1' }, nodes, [], null)).toBe(false)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('missing to returns false', () => {
|
|
39
|
+
expect(isValidConnection({ from: '1' }, nodes, [], null)).toBe(false)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('custom validator rejection', () => {
|
|
43
|
+
const connection = { from: '1', to: '3' }
|
|
44
|
+
const validator = () => false
|
|
45
|
+
expect(isValidConnection(connection, nodes, [], validator)).toBe(false)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('custom validator approval', () => {
|
|
49
|
+
const connection = { from: '1', to: '3' }
|
|
50
|
+
const validator = () => true
|
|
51
|
+
expect(isValidConnection(connection, nodes, [], validator)).toBe(true)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('same from-to pair is always duplicate', () => {
|
|
55
|
+
const existing = [{ id: 'e1-2', from: '1', to: '2' }]
|
|
56
|
+
const connection = { from: '1', to: '2' }
|
|
57
|
+
expect(isValidConnection(connection, nodes, existing, null)).toBe(false)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
describe('generateId', () => {
|
|
62
|
+
test('generates unique ids', () => {
|
|
63
|
+
const id1 = generateId()
|
|
64
|
+
const id2 = generateId()
|
|
65
|
+
expect(id1).not.toBe(id2)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('returns string', () => {
|
|
69
|
+
expect(typeof generateId()).toBe('string')
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
})
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 節點 mousedown 拖曳武裝之修正驗收(缺陷 C)。
|
|
3
|
+
*
|
|
4
|
+
* 修正前:mousedown 當下即 emit drag-start,不分按鍵、無位移門檻,
|
|
5
|
+
* 故純點擊也會走完 endDrag → 回寫座標 → emit update:nodes,
|
|
6
|
+
* 宿主收到未變更之全量節點而誤判有未儲存變更。
|
|
7
|
+
*/
|
|
8
|
+
import { mount } from '@vue/test-utils'
|
|
9
|
+
import WFlowVue from '../src/components/WFlowVue.vue'
|
|
10
|
+
|
|
11
|
+
const sampleNodes = [
|
|
12
|
+
{ id: '1', type: 'input', name: 'Node 1', position: { x: 50, y: 50 }, width: 100, height: 40 },
|
|
13
|
+
{ id: '2', type: 'output', name: 'Node 2', position: { x: 300, y: 300 }, width: 100, height: 40 },
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
function createWrapper(optOverrides = {}) {
|
|
17
|
+
return mount(WFlowVue, {
|
|
18
|
+
propsData: {
|
|
19
|
+
opt: {
|
|
20
|
+
nodes: JSON.parse(JSON.stringify(sampleNodes)),
|
|
21
|
+
conns: [],
|
|
22
|
+
...optOverrides,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
attachTo: document.body,
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const nodeEl = (w, id) => w.find(`.vue-flow__node[data-id="${id}"]`)
|
|
30
|
+
|
|
31
|
+
//以真實 DOM 事件驅動:mousedown/mouseup 打在節點元素上, mousemove 打在 document(與實作註冊位置一致)
|
|
32
|
+
function mouseDownOn(el, { x = 0, y = 0, button = 0 } = {}) {
|
|
33
|
+
el.element.dispatchEvent(new MouseEvent('mousedown', {
|
|
34
|
+
bubbles: true, clientX: x, clientY: y, button, buttons: button === 0 ? 1 : 2,
|
|
35
|
+
}))
|
|
36
|
+
}
|
|
37
|
+
function mouseMoveDoc({ x = 0, y = 0, buttons = 1 } = {}) {
|
|
38
|
+
document.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, clientX: x, clientY: y, buttons }))
|
|
39
|
+
}
|
|
40
|
+
function mouseUpOn(el, { x = 0, y = 0 } = {}) {
|
|
41
|
+
//節點元素上放開:先觸發元素層之 onMouseUp, 冒泡後才到 document 之 onDocMouseUp
|
|
42
|
+
el.element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: x, clientY: y, buttons: 0 }))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe('純點擊不得走拖曳生命週期', () => {
|
|
46
|
+
test('點擊節點無位移: 不發 node-drag-start / node-drag-stop / update:nodes', async () => {
|
|
47
|
+
const w = createWrapper()
|
|
48
|
+
const n = nodeEl(w, '1')
|
|
49
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
50
|
+
mouseUpOn(n, { x: 100, y: 100 })
|
|
51
|
+
await w.vm.$nextTick()
|
|
52
|
+
expect(w.emitted('node-drag-start')).toBeFalsy()
|
|
53
|
+
expect(w.emitted('node-drag-stop')).toBeFalsy()
|
|
54
|
+
expect(w.emitted('update:nodes')).toBeFalsy()
|
|
55
|
+
expect(w.emitted('node-click')).toBeTruthy()
|
|
56
|
+
w.destroy()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('位移 2px(未跨門檻)後放開: 仍視為點擊', async () => {
|
|
60
|
+
const w = createWrapper()
|
|
61
|
+
const n = nodeEl(w, '1')
|
|
62
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
63
|
+
mouseMoveDoc({ x: 102, y: 100 })
|
|
64
|
+
mouseUpOn(n, { x: 102, y: 100 })
|
|
65
|
+
await w.vm.$nextTick()
|
|
66
|
+
expect(w.emitted('node-drag-start')).toBeFalsy()
|
|
67
|
+
expect(w.emitted('update:nodes')).toBeFalsy()
|
|
68
|
+
expect(w.emitted('node-click')).toBeTruthy()
|
|
69
|
+
w.destroy()
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
describe('跨越位移門檻才啟動拖曳', () => {
|
|
74
|
+
test('位移超過 2px: node-drag-start 恰發一次', async () => {
|
|
75
|
+
const w = createWrapper()
|
|
76
|
+
const n = nodeEl(w, '1')
|
|
77
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
78
|
+
mouseMoveDoc({ x: 110, y: 100 })
|
|
79
|
+
mouseMoveDoc({ x: 120, y: 100 })
|
|
80
|
+
mouseMoveDoc({ x: 130, y: 100 })
|
|
81
|
+
await w.vm.$nextTick()
|
|
82
|
+
expect(w.emitted('node-drag-start')).toHaveLength(1)
|
|
83
|
+
w.destroy()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('跨門檻後立即放開: 節點仍套用該次位移(不得原地不動)', async () => {
|
|
87
|
+
const w = createWrapper()
|
|
88
|
+
const n = nodeEl(w, '1')
|
|
89
|
+
const x0 = w.vm.opt.nodes[0].position.x
|
|
90
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
91
|
+
mouseMoveDoc({ x: 140, y: 100 })
|
|
92
|
+
mouseUpOn(n, { x: 140, y: 100 })
|
|
93
|
+
await w.vm.$nextTick()
|
|
94
|
+
expect(w.vm.opt.nodes[0].position.x).not.toBe(x0)
|
|
95
|
+
w.destroy()
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test('跨門檻拖出後又移回原點放開: 不得再發 node-click', async () => {
|
|
99
|
+
const w = createWrapper()
|
|
100
|
+
const n = nodeEl(w, '1')
|
|
101
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
102
|
+
mouseMoveDoc({ x: 140, y: 100 })
|
|
103
|
+
mouseMoveDoc({ x: 100, y: 100 })
|
|
104
|
+
mouseUpOn(n, { x: 100, y: 100 })
|
|
105
|
+
await w.vm.$nextTick()
|
|
106
|
+
expect(w.emitted('node-drag-start')).toHaveLength(1)
|
|
107
|
+
expect(w.emitted('node-click')).toBeFalsy()
|
|
108
|
+
w.destroy()
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
describe('非主鍵不啟動拖曳', () => {
|
|
113
|
+
test('右鍵按於節點: 不發 drag-start 與 node-click', async () => {
|
|
114
|
+
const w = createWrapper()
|
|
115
|
+
const n = nodeEl(w, '1')
|
|
116
|
+
mouseDownOn(n, { x: 100, y: 100, button: 2 })
|
|
117
|
+
mouseMoveDoc({ x: 140, y: 100, buttons: 2 })
|
|
118
|
+
mouseUpOn(n, { x: 140, y: 100 })
|
|
119
|
+
await w.vm.$nextTick()
|
|
120
|
+
expect(w.emitted('node-drag-start')).toBeFalsy()
|
|
121
|
+
expect(w.emitted('node-click')).toBeFalsy()
|
|
122
|
+
w.destroy()
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('中鍵按於節點: 不發 drag-start', async () => {
|
|
126
|
+
const w = createWrapper()
|
|
127
|
+
const n = nodeEl(w, '1')
|
|
128
|
+
mouseDownOn(n, { x: 100, y: 100, button: 1 })
|
|
129
|
+
mouseMoveDoc({ x: 140, y: 100, buttons: 4 })
|
|
130
|
+
await w.vm.$nextTick()
|
|
131
|
+
expect(w.emitted('node-drag-start')).toBeFalsy()
|
|
132
|
+
w.destroy()
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
describe('mouseup 遺失後不得幽靈拖曳', () => {
|
|
137
|
+
test('主鍵已放開(buttons=0)之 mousemove 不得跨門檻啟動拖曳', async () => {
|
|
138
|
+
const w = createWrapper()
|
|
139
|
+
const n = nodeEl(w, '1')
|
|
140
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
141
|
+
//模擬使用者在視窗外放開:document 收不到 mouseup, 回到視窗後移動時 buttons 已為 0
|
|
142
|
+
mouseMoveDoc({ x: 300, y: 300, buttons: 0 })
|
|
143
|
+
mouseMoveDoc({ x: 400, y: 400, buttons: 0 })
|
|
144
|
+
await w.vm.$nextTick()
|
|
145
|
+
expect(w.emitted('node-drag-start')).toBeFalsy()
|
|
146
|
+
expect(w.vm.isDraggingNode).toBe(false)
|
|
147
|
+
w.destroy()
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
describe('不可拖節點之點擊判準不受影響', () => {
|
|
152
|
+
test('nodesDraggable=false 時移動 4px 放開: 不得發 node-click(距離判準仍在)', async () => {
|
|
153
|
+
const w = createWrapper({ nodesDraggable: false })
|
|
154
|
+
const n = nodeEl(w, '1')
|
|
155
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
156
|
+
mouseMoveDoc({ x: 104, y: 100 })
|
|
157
|
+
mouseUpOn(n, { x: 104, y: 100 })
|
|
158
|
+
await w.vm.$nextTick()
|
|
159
|
+
expect(w.emitted('node-drag-start')).toBeFalsy()
|
|
160
|
+
expect(w.emitted('node-click')).toBeFalsy()
|
|
161
|
+
w.destroy()
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
test('nodesDraggable=false 時原地點擊: node-click 照常發出', async () => {
|
|
165
|
+
const w = createWrapper({ nodesDraggable: false })
|
|
166
|
+
const n = nodeEl(w, '1')
|
|
167
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
168
|
+
mouseUpOn(n, { x: 100, y: 100 })
|
|
169
|
+
await w.vm.$nextTick()
|
|
170
|
+
expect(w.emitted('node-click')).toBeTruthy()
|
|
171
|
+
w.destroy()
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
describe('選取時機不因拖曳延後而改變', () => {
|
|
176
|
+
test('selectNodesOnDrag=true: mousedown 當下即選取(不必等 mouseup)', async () => {
|
|
177
|
+
const w = createWrapper()
|
|
178
|
+
const n = nodeEl(w, '2')
|
|
179
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
180
|
+
await w.vm.$nextTick()
|
|
181
|
+
expect(w.vm.selectedNodes).toContain('2')
|
|
182
|
+
w.destroy()
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
test('locked=true: mousedown 不選取亦不啟動拖曳', async () => {
|
|
186
|
+
const w = createWrapper({ locked: true })
|
|
187
|
+
const n = nodeEl(w, '2')
|
|
188
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
189
|
+
mouseMoveDoc({ x: 140, y: 100 })
|
|
190
|
+
await w.vm.$nextTick()
|
|
191
|
+
expect(w.emitted('node-drag-start')).toBeFalsy()
|
|
192
|
+
expect(w.vm.selectedNodes).not.toContain('2')
|
|
193
|
+
w.destroy()
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
describe('元件銷毀時清理 document 監聽器', () => {
|
|
198
|
+
test('拖曳進行中銷毀: 後續 mousemove 不得再觸發任何 emit', async () => {
|
|
199
|
+
const w = createWrapper()
|
|
200
|
+
const n = nodeEl(w, '1')
|
|
201
|
+
mouseDownOn(n, { x: 100, y: 100 })
|
|
202
|
+
const addSpy = jest.spyOn(document, 'removeEventListener')
|
|
203
|
+
w.destroy()
|
|
204
|
+
const removed = addSpy.mock.calls.filter(c => c[0] === 'mousemove' || c[0] === 'mouseup')
|
|
205
|
+
expect(removed.length).toBeGreaterThan(0)
|
|
206
|
+
addSpy.mockRestore()
|
|
207
|
+
})
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
describe('resize 手勢收尾: 全域游標樣式不得殘留', () => {
|
|
211
|
+
//why: onResizeStart 會往 document.head 插入 `* { cursor: X !important; }`,
|
|
212
|
+
// 原本只在自身之 document mouseup 移除; 若元件於 resize 中被銷毀或視窗失焦後於視窗外放開,
|
|
213
|
+
// 該樣式會永久殘留, 使整頁每個元素卡在 resize 游標直到重新整理
|
|
214
|
+
const cursorStyles = () => Array.from(document.head.querySelectorAll('style'))
|
|
215
|
+
.filter(s => /\*\s*\{\s*cursor:/.test(s.textContent || ''))
|
|
216
|
+
|
|
217
|
+
const startResize = (w) => {
|
|
218
|
+
const nw = w.findComponent({ name: 'NodeWrapper' })
|
|
219
|
+
nw.vm.onResizeStart({ clientX: 0, clientY: 0, preventDefault() {}, stopPropagation() {} }, 'bottom-right')
|
|
220
|
+
return nw
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
test('resize 進行中銷毀元件: 全域游標樣式須被移除', () => {
|
|
224
|
+
const w = createWrapper()
|
|
225
|
+
const n0 = cursorStyles().length
|
|
226
|
+
startResize(w)
|
|
227
|
+
expect(cursorStyles()).toHaveLength(n0 + 1)
|
|
228
|
+
w.destroy()
|
|
229
|
+
expect(cursorStyles()).toHaveLength(n0)
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
test('resize 進行中視窗失焦: 全域游標樣式須被移除', () => {
|
|
233
|
+
const w = createWrapper()
|
|
234
|
+
const n0 = cursorStyles().length
|
|
235
|
+
startResize(w)
|
|
236
|
+
expect(cursorStyles()).toHaveLength(n0 + 1)
|
|
237
|
+
window.dispatchEvent(new Event('blur'))
|
|
238
|
+
expect(cursorStyles()).toHaveLength(n0)
|
|
239
|
+
w.destroy()
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
test('正常 mouseup 收尾: 樣式移除且發出 node-resize-end 恰一次', () => {
|
|
243
|
+
const w = createWrapper()
|
|
244
|
+
const n0 = cursorStyles().length
|
|
245
|
+
const nw = startResize(w)
|
|
246
|
+
document.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, buttons: 0 }))
|
|
247
|
+
expect(cursorStyles()).toHaveLength(n0)
|
|
248
|
+
expect(nw.emitted('node-resize-end')).toHaveLength(1)
|
|
249
|
+
//收尾後再來一次 mouseup 不得重複發出
|
|
250
|
+
document.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, buttons: 0 }))
|
|
251
|
+
expect(nw.emitted('node-resize-end')).toHaveLength(1)
|
|
252
|
+
w.destroy()
|
|
253
|
+
})
|
|
254
|
+
})
|