@@ -74,9 +74,10 @@ context('v-drag', () => {
7474 cy . get ( '[data-testid="box1"]' )
7575 . trigger ( 'pointerdown' , { button : 0 , pointerId : 1 , buttons : 1 , force : true } )
7676
77- // Move pointer (events go to document after pointerdown)
78- cy . document ( ) . trigger ( 'pointermove' , { clientX : 400 , clientY : 400 , buttons : 1 } )
79- cy . document ( ) . trigger ( 'pointerup' )
77+ // Move pointer (events go to document after pointerdown). `pointerId` MUST match
78+ // the pointerdown's — the body-drag handler ignores moves with a different id.
79+ cy . document ( ) . trigger ( 'pointermove' , { clientX : 400 , clientY : 400 , buttons : 1 , pointerId : 1 } )
80+ cy . document ( ) . trigger ( 'pointerup' , { pointerId : 1 } )
8081
8182 cy . wait ( 200 )
8283
@@ -91,59 +92,65 @@ context('v-drag', () => {
9192 } )
9293 } )
9394
94- describe ( 'z-order' , ( ) => {
95+ describe ( 'z-order (keyboard) ' , ( ) => {
9596 beforeEach ( ( ) => {
9697 goPage ( 15 ) // v-drag Z-Order Tests page
9798 } )
9899
99- it ( 'z-order buttons are visible when element is selected' , ( ) => {
100- // Click to select stack-a
101- cy . get ( '[data-testid="stack-a"]' ) . click ( )
102- cy . wait ( 200 )
103-
104- // Z-order buttons should be visible
105- cy . get ( '#drag-control-container button[title*="forward"]' ) . should ( 'exist' )
106- cy . get ( '#drag-control-container button[title*="backward"]' ) . should ( 'exist' )
107- } )
100+ // Z-order has no on-canvas buttons — it's driven by Cmd/Ctrl+Arrow shortcuts,
101+ // handled by DragControl's window-level capture-phase `onZOrderKeyDown` listener
102+ // (Cmd+Up = forward, Cmd+Down = backward, add Shift for to-front/to-back). Dispatch
103+ // straight to `window` so the capture listener fires.
104+ function pressZOrder ( key : 'ArrowUp' | 'ArrowDown' , shift = false ) {
105+ cy . window ( ) . then ( ( win ) => {
106+ win . dispatchEvent ( new win . KeyboardEvent ( 'keydown' , {
107+ key,
108+ metaKey : true ,
109+ shiftKey : shift ,
110+ bubbles : true ,
111+ cancelable : true ,
112+ } ) )
113+ } )
114+ }
108115
109- it ( 'bring forward increases z-index' , ( ) => {
110- // Click to select stack-a (initial z-index: 100)
111- cy . get ( '[data-testid="stack-a"]' ) . click ( )
116+ it ( 'cmd+ArrowUp brings the selected element forward (raises z-index)' , ( ) => {
117+ cy . get ( '[data-testid="stack-a"]' ) . click ( ) // z:100, below b(101) and c(102)
112118 cy . wait ( 200 )
113-
114- // Get initial z-index
115119 cy . get ( '[data-testid="stack-a"]' ) . then ( ( $el ) => {
116120 const initialZIndex = Number . parseInt ( $el . css ( 'z-index' ) )
117-
118- // Click bring forward button
119- cy . get ( '#drag-control-container button[title*="forward"]' ) . first ( ) . click ( )
121+ pressZOrder ( 'ArrowUp' )
120122 cy . wait ( 200 )
121-
122- // z-index should have increased
123123 cy . get ( '[data-testid="stack-a"]' ) . should ( ( $el2 ) => {
124- const newZIndex = Number . parseInt ( $el2 . css ( 'z-index' ) )
125- expect ( newZIndex ) . to . be . greaterThan ( initialZIndex )
124+ expect ( Number . parseInt ( $el2 . css ( 'z-index' ) ) ) . to . be . greaterThan ( initialZIndex )
126125 } )
127126 } )
128127 } )
129128
130- it ( 'send backward decreases z-index' , ( ) => {
131- // Click to select stack-c (initial z-index: 102)
132- cy . get ( '[data-testid="stack-c"]' ) . click ( )
129+ it ( 'cmd+ArrowDown sends the selected element backward (lowers z-index)' , ( ) => {
130+ cy . get ( '[data-testid="stack-c"]' ) . click ( ) // z:102, above a(100) and b(101)
133131 cy . wait ( 200 )
134-
135- // Get initial z-index
136132 cy . get ( '[data-testid="stack-c"]' ) . then ( ( $el ) => {
137133 const initialZIndex = Number . parseInt ( $el . css ( 'z-index' ) )
138-
139- // Click send backward button
140- cy . get ( '#drag-control-container button[title*="backward"]' ) . first ( ) . click ( )
134+ pressZOrder ( 'ArrowDown' )
141135 cy . wait ( 200 )
142-
143- // z-index should have decreased
144136 cy . get ( '[data-testid="stack-c"]' ) . should ( ( $el2 ) => {
145- const newZIndex = Number . parseInt ( $el2 . css ( 'z-index' ) )
146- expect ( newZIndex ) . to . be . lessThan ( initialZIndex )
137+ expect ( Number . parseInt ( $el2 . css ( 'z-index' ) ) ) . to . be . lessThan ( initialZIndex )
138+ } )
139+ } )
140+ } )
141+
142+ it ( 'cmd+Shift+ArrowUp brings the element above all its siblings' , ( ) => {
143+ cy . get ( '[data-testid="stack-a"]' ) . click ( ) // starts lowest at z:100
144+ cy . wait ( 200 )
145+ pressZOrder ( 'ArrowUp' , true )
146+ cy . wait ( 200 )
147+ cy . get ( '[data-testid="stack-a"]' ) . then ( ( $a ) => {
148+ const za = Number . parseInt ( $a . css ( 'z-index' ) )
149+ cy . get ( '[data-testid="stack-b"]' ) . should ( ( $b ) => {
150+ expect ( za ) . to . be . greaterThan ( Number . parseInt ( $b . css ( 'z-index' ) ) )
151+ } )
152+ cy . get ( '[data-testid="stack-c"]' ) . should ( ( $c ) => {
153+ expect ( za ) . to . be . greaterThan ( Number . parseInt ( $c . css ( 'z-index' ) ) )
147154 } )
148155 } )
149156 } )
@@ -193,13 +200,38 @@ context('v-drag', () => {
193200 cy . get ( '#drag-control-container div[style*="cursor"]' ) . should ( 'have.length.at.least' , 4 )
194201 } )
195202
196- it ( 'reset aspect ratio button is visible' , ( ) => {
197- // Click on box1 to select it
203+ it ( 'reset aspect ratio button appears only after a free corner resize' , ( ) => {
198204 cy . get ( '[data-testid="box1"]' ) . click ( )
199205 cy . wait ( 200 )
200206
201- // Reset aspect ratio button should be visible
207+ // Fresh selection: AR unchanged, so the reset-AR button is absent (it's `v-if`d on
208+ // `hasAspectRatioChanged`).
209+ cy . get ( '#drag-control-container button[title="Reset aspect ratio"]' ) . should ( 'not.exist' )
210+
211+ // Free-drag a corner handle to skew the aspect ratio. The corner handlers live on the
212+ // handle element (which re-renders as the box resizes), need `buttons: 1` on the
213+ // pointerdown to arm `currentDrag`, and a matching `pointerId`. Re-query the handle for
214+ // each event so a re-render between events can't leave us dispatching to a stale node,
215+ // and send two moves with different x/y ratios to guarantee the AR actually changes.
216+ const handle = '#drag-control-container div[style*="nwse-resize"]'
217+ cy . get ( handle ) . first ( ) . then ( ( $h ) => {
218+ const r = $h [ 0 ] . getBoundingClientRect ( )
219+ const cx = r . left + r . width / 2
220+ const cy2 = r . top + r . height / 2
221+ cy . get ( handle ) . first ( ) . trigger ( 'pointerdown' , { button : 0 , buttons : 1 , pointerId : 1 , clientX : cx , clientY : cy2 , force : true } )
222+ cy . get ( handle ) . first ( ) . trigger ( 'pointermove' , { button : 0 , buttons : 1 , pointerId : 1 , clientX : cx + 120 , clientY : cy2 + 120 , force : true } )
223+ cy . get ( handle ) . first ( ) . trigger ( 'pointermove' , { button : 0 , buttons : 1 , pointerId : 1 , clientX : cx + 160 , clientY : cy2 + 30 , force : true } )
224+ cy . get ( handle ) . first ( ) . trigger ( 'pointerup' , { pointerId : 1 , force : true } )
225+ } )
226+ cy . wait ( 200 )
227+
228+ // AR now differs from the original → the reset button is shown.
202229 cy . get ( '#drag-control-container button[title="Reset aspect ratio"]' ) . should ( 'exist' )
230+
231+ // Clicking it restores the original AR, so the button hides again.
232+ cy . get ( '#drag-control-container button[title="Reset aspect ratio"]' ) . click ( )
233+ cy . wait ( 200 )
234+ cy . get ( '#drag-control-container button[title="Reset aspect ratio"]' ) . should ( 'not.exist' )
203235 } )
204236 } )
205237
@@ -251,17 +283,18 @@ context('v-drag', () => {
251283 cy . get ( '[data-testid="snap-mover"]' )
252284 . trigger ( 'pointerdown' , { button : 0 , pointerId : 1 , buttons : 1 , force : true } )
253285
254- // Move near the target - should trigger snap guides
286+ // Move near the target - should trigger snap guides. `pointerId` must match the
287+ // pointerdown or the body-drag handler drops the move.
255288 cy . document ( )
256- . trigger ( 'pointermove' , { clientX : nearTargetX , clientY : nearTargetY , buttons : 1 } )
289+ . trigger ( 'pointermove' , { clientX : nearTargetX , clientY : nearTargetY , buttons : 1 , pointerId : 1 } )
257290
258291 cy . wait ( 100 )
259292
260293 // Snap guide lines should appear
261294 cy . get ( '.snap-guide' ) . should ( 'have.length.at.least' , 1 )
262295 cy . screenshot ( 'snap-guides-visible' )
263296
264- cy . document ( ) . trigger ( 'pointerup' )
297+ cy . document ( ) . trigger ( 'pointerup' , { pointerId : 1 } )
265298 cy . wait ( 100 )
266299
267300 // Snap guides should disappear after drag ends
@@ -278,12 +311,15 @@ context('v-drag', () => {
278311 cy . get ( '[data-testid="snap-mover"]' )
279312 . trigger ( 'pointerdown' , { button : 0 , pointerId : 1 , buttons : 1 , force : true } )
280313
281- // Move near target with Meta key held - should NOT snap
314+ // Move near target with Meta key held - should NOT snap (Meta disables snapping).
315+ // `pointerId` must match the pointerdown so the move actually drives the drag —
316+ // otherwise this would pass vacuously (no drag at all → no guides).
282317 cy . document ( )
283318 . trigger ( 'pointermove' , {
284319 clientX : nearTargetX ,
285320 clientY : nearTargetY ,
286321 buttons : 1 ,
322+ pointerId : 1 ,
287323 metaKey : true ,
288324 } )
289325
@@ -293,7 +329,7 @@ context('v-drag', () => {
293329 cy . get ( '.snap-guide' ) . should ( 'not.exist' )
294330 cy . screenshot ( 'snap-meta-no-guides' )
295331
296- cy . document ( ) . trigger ( 'pointerup' )
332+ cy . document ( ) . trigger ( 'pointerup' , { pointerId : 1 } )
297333 } )
298334 } )
299335
@@ -309,13 +345,13 @@ context('v-drag', () => {
309345 . trigger ( 'pointerdown' , { button : 0 , pointerId : 1 , buttons : 1 , force : true } )
310346
311347 cy . document ( )
312- . trigger ( 'pointermove' , { clientX : centerX , clientY : centerY , buttons : 1 } )
348+ . trigger ( 'pointermove' , { clientX : centerX , clientY : centerY , buttons : 1 , pointerId : 1 } )
313349
314350 cy . wait ( 100 )
315351 cy . get ( '.snap-guide' ) . should ( 'have.length.at.least' , 1 )
316352 cy . screenshot ( 'snap-to-slide-center' )
317353
318- cy . document ( ) . trigger ( 'pointerup' )
354+ cy . document ( ) . trigger ( 'pointerup' , { pointerId : 1 } )
319355 } )
320356 } )
321357 } )
0 commit comments