1
+ import type { UseDraggableReturn } from '@vueuse/core' ;
1
2
import type { Ref } from 'vue' ;
2
3
import type { UsePointerOptions } from './use-pointer' ;
3
- import { beforeEach , describe , expect , it } from 'vitest' ;
4
- import { computed , ref } from 'vue' ;
4
+ import { useDraggable } from '@vueuse/core' ;
5
+ import { beforeEach , describe , expect , it , vi } from 'vitest' ;
6
+ import { computed , nextTick , ref } from 'vue' ;
5
7
import { usePointer } from './use-pointer' ;
6
8
9
+ vi . mock ( '@vueuse/core' , async ( ) => {
10
+ const actual = await vi . importActual ( '@vueuse/core' ) ;
11
+
12
+ return {
13
+ ...actual ,
14
+ useDraggable : vi . fn ( ) ,
15
+ } ;
16
+ } ) ;
17
+
7
18
describe ( 'usePointer' , ( ) => {
8
19
let collapsed : Ref < boolean > ;
9
20
let sizePercentage : Ref < number > ;
@@ -12,6 +23,10 @@ describe('usePointer', () => {
12
23
let dividerEl : Ref < HTMLElement | null > ;
13
24
let panelEl : Ref < HTMLElement | null > ;
14
25
26
+ let mockDragX : Ref < number > ;
27
+ let mockDragY : Ref < number > ;
28
+ let mockDragDragging : Ref < boolean > ;
29
+
15
30
beforeEach ( ( ) => {
16
31
collapsed = ref ( false ) ;
17
32
sizePercentage = ref ( 50 ) ;
@@ -40,6 +55,12 @@ describe('usePointer', () => {
40
55
minSizePixels : computed ( ( ) => 50 ) ,
41
56
snapPixels : computed ( ( ) => [ 100 , 200 , 300 ] ) ,
42
57
} ;
58
+
59
+ mockDragX = ref ( 75 ) ;
60
+ mockDragY = ref ( 75 ) ;
61
+ mockDragDragging = ref ( false ) ;
62
+
63
+ vi . mocked ( useDraggable ) . mockReturnValue ( { x : mockDragX , y : mockDragY , isDragging : mockDragDragging } as UseDraggableReturn ) ;
43
64
} ) ;
44
65
45
66
it ( 'should return handleDblClick and isDragging' , ( ) => {
@@ -51,51 +72,190 @@ describe('usePointer', () => {
51
72
expect ( typeof result . isDragging . value ) . toBe ( 'boolean' ) ;
52
73
} ) ;
53
74
54
- it ( 'should handle double click to snap to closest point' , ( ) => {
55
- const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
75
+ describe ( 'dbl click' , ( ) => {
76
+ it ( 'should handle double click to snap to closest point' , ( ) => {
77
+ const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
56
78
57
- sizePixels . value = 195 ; // Close to 200
58
- handleDblClick ( ) ;
79
+ sizePixels . value = 195 ; // Close to 200
80
+ handleDblClick ( ) ;
59
81
60
- expect ( sizePixels . value ) . toBe ( 200 ) ;
61
- } ) ;
82
+ expect ( sizePixels . value ) . toBe ( 200 ) ;
83
+ } ) ;
62
84
63
- it ( 'should remain collapsed on handle double click when collapsed' , ( ) => {
64
- collapsed . value = true ;
65
- const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
85
+ it ( 'should remain collapsed on handle double click when collapsed' , ( ) => {
86
+ collapsed . value = true ;
87
+ const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
66
88
67
- handleDblClick ( ) ;
89
+ handleDblClick ( ) ;
68
90
69
- expect ( collapsed . value ) . toBe ( true ) ;
70
- } ) ;
91
+ expect ( collapsed . value ) . toBe ( true ) ;
92
+ } ) ;
71
93
72
- it ( 'should not snap on double click when disabled' , ( ) => {
73
- options . disabled = ref ( true ) ;
74
- const originalSize = sizePixels . value ;
75
- const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
94
+ it ( 'should not snap on double click when disabled' , ( ) => {
95
+ options . disabled = ref ( true ) ;
96
+ const originalSize = sizePixels . value ;
97
+ const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
76
98
77
- handleDblClick ( ) ;
99
+ handleDblClick ( ) ;
78
100
79
- expect ( sizePixels . value ) . toBe ( originalSize ) ;
80
- } ) ;
101
+ expect ( sizePixels . value ) . toBe ( originalSize ) ;
102
+ } ) ;
103
+
104
+ it ( 'should not snap on double click when no snap points exist' , ( ) => {
105
+ options . snapPixels = computed ( ( ) => [ ] ) ;
106
+ const originalSize = sizePixels . value ;
107
+ const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
81
108
82
- it ( 'should not snap on double click when no snap points exist' , ( ) => {
83
- options . snapPixels = computed ( ( ) => [ ] ) ;
84
- const originalSize = sizePixels . value ;
85
- const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
109
+ handleDblClick ( ) ;
86
110
87
- handleDblClick ( ) ;
111
+ expect ( sizePixels . value ) . toBe ( originalSize ) ;
112
+ } ) ;
88
113
89
- expect ( sizePixels . value ) . toBe ( originalSize ) ;
114
+ it ( 'should handle when collapsible is false' , ( ) => {
115
+ options . collapsible = ref ( false ) ;
116
+ collapsed . value = false ;
117
+ const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
118
+
119
+ handleDblClick ( ) ;
120
+
121
+ expect ( collapsed . value ) . toBe ( false ) ; // Should remain visible when not collapsible
122
+ } ) ;
90
123
} ) ;
91
124
92
- it ( 'should handle when collapsible is false' , ( ) => {
93
- options . collapsible = ref ( false ) ;
94
- collapsed . value = false ;
95
- const { handleDblClick } = usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
125
+ describe ( 'dragging' , ( ) => {
126
+ it ( 'should not do anything when disabled' , async ( ) => {
127
+ options . disabled = true ;
128
+
129
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
130
+
131
+ mockDragDragging . value = true ;
132
+ mockDragX . value = 30 ; // below the minsize - threshold
133
+ await nextTick ( ) ;
134
+ expect ( collapsed . value ) . toBe ( false ) ;
135
+ } ) ;
136
+
137
+ it ( 'should update sizePercentage when dragging horizontally' , async ( ) => {
138
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
139
+
140
+ mockDragX . value = 100 ; // Move to 100px
141
+ await nextTick ( ) ;
142
+ expect ( sizePercentage . value ) . toBe ( 25 ) ; // 100/400 * 100 = 25%
143
+ } ) ;
144
+
145
+ it ( 'should update sizePercentage when dragging vertically' , async ( ) => {
146
+ options . orientation = ref ( 'vertical' ) ;
147
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
148
+
149
+ mockDragY . value = 150 ; // Move to 150px
150
+ await nextTick ( ) ;
151
+ expect ( sizePercentage . value ) . toBe ( 37.5 ) ; // 150/400 * 100 = 37.5%
152
+ } ) ;
153
+
154
+ it ( 'should handle primary end positioning' , async ( ) => {
155
+ options . primary = ref ( 'end' ) ;
156
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
157
+
158
+ mockDragX . value = 100 ; // Drag position at 100px
159
+ await nextTick ( ) ;
160
+ // With primary end, actual position = 400 - 100 = 300px
161
+
162
+ expect ( sizePercentage . value ) . toBe ( 75 ) ; // 300/400 * 100 = 75%
163
+ } ) ;
164
+
165
+ it ( 'should collapse when dragging below collapse threshold' , async ( ) => {
166
+ options . minSizePixels = computed ( ( ) => 50 ) ;
167
+ options . collapseThreshold = ref ( 10 ) ;
168
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
169
+
170
+ mockDragX . value = 30 ; // Below minSize (50) - collapseThreshold (10) = 40
171
+ await nextTick ( ) ;
172
+ expect ( collapsed . value ) . toBe ( true ) ;
173
+ } ) ;
174
+
175
+ it ( 'should expand when dragging above expand threshold' , async ( ) => {
176
+ collapsed . value = true ;
177
+ options . collapseThreshold = ref ( 15 ) ;
178
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
179
+
180
+ mockDragX . value = 20 ; // Above collapseThreshold (15)
181
+ await nextTick ( ) ;
182
+ expect ( collapsed . value ) . toBe ( false ) ;
183
+ } ) ;
184
+
185
+ it ( 'should not collapse when collapsible is false' , async ( ) => {
186
+ options . collapsible = ref ( false ) ;
187
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
188
+
189
+ mockDragX . value = 10 ; // Very low position
190
+ await nextTick ( ) ;
191
+ expect ( collapsed . value ) . toBe ( false ) ;
192
+ } ) ;
193
+
194
+ it ( 'should snap to snap points within threshold' , async ( ) => {
195
+ options . snapPixels = computed ( ( ) => [ 100 , 200 , 300 ] ) ;
196
+ options . snapThreshold = ref ( 8 ) ;
197
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
198
+
199
+ mockDragX . value = 195 ; // Within 8px of snap point 200
200
+ await nextTick ( ) ;
201
+ expect ( sizePercentage . value ) . toBe ( 50 ) ; // 200/400 * 100 = 50%
202
+ } ) ;
203
+
204
+ it ( 'should not snap when outside snap threshold' , async ( ) => {
205
+ options . snapPixels = computed ( ( ) => [ 100 , 200 , 300 ] ) ;
206
+ options . snapThreshold = ref ( 5 ) ;
207
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
208
+
209
+ mockDragX . value = 190 ; // Outside 5px threshold of snap point 200
210
+ await nextTick ( ) ;
211
+ expect ( sizePercentage . value ) . toBe ( 47.5 ) ; // 190/400 * 100 = 47.5%
212
+ } ) ;
213
+
214
+ it ( 'should handle RTL direction with horizontal orientation' , async ( ) => {
215
+ options . direction = ref ( 'rtl' ) ;
216
+ options . orientation = ref ( 'horizontal' ) ;
217
+ options . snapPixels = computed ( ( ) => [ 100 ] ) ;
218
+ options . snapThreshold = ref ( 5 ) ;
219
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
220
+
221
+ // With RTL, snap point 100 becomes 400 - 100 = 300
222
+ mockDragX . value = 298 ; // Within threshold of transformed snap point
223
+ await nextTick ( ) ;
224
+ expect ( sizePercentage . value ) . toBe ( 75 ) ; // 300/400 * 100 = 75%
225
+ } ) ;
226
+
227
+ it ( 'should clamp sizePercentage between 0 and 100' , async ( ) => {
228
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
229
+
230
+ mockDragX . value = - 50 ; // Negative position
231
+ await nextTick ( ) ;
232
+ expect ( sizePercentage . value ) . toBe ( 0 ) ;
233
+
234
+ mockDragX . value = 500 ; // Beyond component size
235
+ await nextTick ( ) ;
236
+ expect ( sizePercentage . value ) . toBe ( 100 ) ;
237
+ } ) ;
238
+
239
+ it ( 'should update threshold location when dragging stops' , async ( ) => {
240
+ usePointer ( collapsed , sizePercentage , sizePixels , options ) ;
241
+
242
+ // Start dragging
243
+ mockDragDragging . value = true ;
244
+ await nextTick ( ) ;
245
+
246
+ // Collapse during drag
247
+ mockDragX . value = 30 ;
248
+ await nextTick ( ) ;
249
+ expect ( collapsed . value ) . toBe ( true ) ;
96
250
97
- handleDblClick ( ) ;
251
+ // Stop dragging
252
+ mockDragDragging . value = false ;
253
+ await nextTick ( ) ;
98
254
99
- expect ( collapsed . value ) . toBe ( false ) ; // Should remain visible when not collapsible
255
+ // Should now be in expand mode for next drag
256
+ mockDragX . value = 5 ; // Below expand threshold
257
+ await nextTick ( ) ;
258
+ expect ( collapsed . value ) . toBe ( true ) ; // Should remain collapsed
259
+ } ) ;
100
260
} ) ;
101
261
} ) ;
0 commit comments