@@ -39,6 +39,21 @@ describe('CdkDrag', () => {
39
39
expect ( dragElement . style . transform ) . toBe ( 'translate3d(50px, 100px, 0px)' ) ;
40
40
} ) ) ;
41
41
42
+ it ( 'should drag an element freely to a particular position when the page is scrolled' ,
43
+ fakeAsync ( ( ) => {
44
+ const fixture = createComponent ( StandaloneDraggable ) ;
45
+ fixture . detectChanges ( ) ;
46
+
47
+ const cleanup = makePageScrollable ( ) ;
48
+ const dragElement = fixture . componentInstance . dragElement . nativeElement ;
49
+
50
+ scrollTo ( 0 , 500 ) ;
51
+ expect ( dragElement . style . transform ) . toBeFalsy ( ) ;
52
+ dragElementViaMouse ( fixture , dragElement , 50 , 100 ) ;
53
+ expect ( dragElement . style . transform ) . toBe ( 'translate3d(50px, 100px, 0px)' ) ;
54
+ cleanup ( ) ;
55
+ } ) ) ;
56
+
42
57
it ( 'should continue dragging the element from where it was left off' , fakeAsync ( ( ) => {
43
58
const fixture = createComponent ( StandaloneDraggable ) ;
44
59
fixture . detectChanges ( ) ;
@@ -52,6 +67,26 @@ describe('CdkDrag', () => {
52
67
dragElementViaMouse ( fixture , dragElement , 100 , 200 ) ;
53
68
expect ( dragElement . style . transform ) . toBe ( 'translate3d(150px, 300px, 0px)' ) ;
54
69
} ) ) ;
70
+
71
+ it ( 'should continue dragging from where it was left off when the page is scrolled' ,
72
+ fakeAsync ( ( ) => {
73
+ const fixture = createComponent ( StandaloneDraggable ) ;
74
+ fixture . detectChanges ( ) ;
75
+
76
+ const dragElement = fixture . componentInstance . dragElement . nativeElement ;
77
+ const cleanup = makePageScrollable ( ) ;
78
+
79
+ scrollTo ( 0 , 500 ) ;
80
+ expect ( dragElement . style . transform ) . toBeFalsy ( ) ;
81
+
82
+ dragElementViaMouse ( fixture , dragElement , 50 , 100 ) ;
83
+ expect ( dragElement . style . transform ) . toBe ( 'translate3d(50px, 100px, 0px)' ) ;
84
+
85
+ dragElementViaMouse ( fixture , dragElement , 100 , 200 ) ;
86
+ expect ( dragElement . style . transform ) . toBe ( 'translate3d(150px, 300px, 0px)' ) ;
87
+
88
+ cleanup ( ) ;
89
+ } ) ) ;
55
90
} ) ;
56
91
57
92
describe ( 'touch dragging' , ( ) => {
@@ -65,6 +100,21 @@ describe('CdkDrag', () => {
65
100
expect ( dragElement . style . transform ) . toBe ( 'translate3d(50px, 100px, 0px)' ) ;
66
101
} ) ) ;
67
102
103
+ it ( 'should drag an element freely to a particular position when the page is scrolled' ,
104
+ fakeAsync ( ( ) => {
105
+ const fixture = createComponent ( StandaloneDraggable ) ;
106
+ fixture . detectChanges ( ) ;
107
+
108
+ const dragElement = fixture . componentInstance . dragElement . nativeElement ;
109
+ const cleanup = makePageScrollable ( ) ;
110
+
111
+ scrollTo ( 0 , 500 ) ;
112
+ expect ( dragElement . style . transform ) . toBeFalsy ( ) ;
113
+ dragElementViaTouch ( fixture , dragElement , 50 , 100 ) ;
114
+ expect ( dragElement . style . transform ) . toBe ( 'translate3d(50px, 100px, 0px)' ) ;
115
+ cleanup ( ) ;
116
+ } ) ) ;
117
+
68
118
it ( 'should continue dragging the element from where it was left off' , fakeAsync ( ( ) => {
69
119
const fixture = createComponent ( StandaloneDraggable ) ;
70
120
fixture . detectChanges ( ) ;
@@ -79,6 +129,26 @@ describe('CdkDrag', () => {
79
129
expect ( dragElement . style . transform ) . toBe ( 'translate3d(150px, 300px, 0px)' ) ;
80
130
} ) ) ;
81
131
132
+ it ( 'should continue dragging from where it was left off when the page is scrolled' ,
133
+ fakeAsync ( ( ) => {
134
+ const fixture = createComponent ( StandaloneDraggable ) ;
135
+ fixture . detectChanges ( ) ;
136
+
137
+ const dragElement = fixture . componentInstance . dragElement . nativeElement ;
138
+ const cleanup = makePageScrollable ( ) ;
139
+
140
+ scrollTo ( 0 , 500 ) ;
141
+ expect ( dragElement . style . transform ) . toBeFalsy ( ) ;
142
+
143
+ dragElementViaTouch ( fixture , dragElement , 50 , 100 ) ;
144
+ expect ( dragElement . style . transform ) . toBe ( 'translate3d(50px, 100px, 0px)' ) ;
145
+
146
+ dragElementViaTouch ( fixture , dragElement , 100 , 200 ) ;
147
+ expect ( dragElement . style . transform ) . toBe ( 'translate3d(150px, 300px, 0px)' ) ;
148
+
149
+ cleanup ( ) ;
150
+ } ) ) ;
151
+
82
152
it ( 'should prevent the default `touchmove` action on the page while dragging' ,
83
153
fakeAsync ( ( ) => {
84
154
const fixture = createComponent ( StandaloneDraggable ) ;
@@ -257,58 +327,36 @@ describe('CdkDrag', () => {
257
327
it ( 'should move the placeholder as an item is being sorted down' , fakeAsync ( ( ) => {
258
328
const fixture = createComponent ( DraggableInDropZone ) ;
259
329
fixture . detectChanges ( ) ;
330
+ assertDownwardSorting ( fixture ) ;
331
+ } ) ) ;
260
332
261
- const items = fixture . componentInstance . dragItems . toArray ( ) ;
262
- const draggedItem = items [ 0 ] . element . nativeElement ;
263
- const { top, left} = draggedItem . getBoundingClientRect ( ) ;
264
-
265
- dispatchMouseEvent ( draggedItem , 'mousedown' , left , top ) ;
266
- fixture . detectChanges ( ) ;
267
-
268
- const placeholder = document . querySelector ( '.cdk-drag-placeholder' ) ! as HTMLElement ;
269
-
270
- // Drag over each item one-by-one going downwards.
271
- for ( let i = 0 ; i < items . length ; i ++ ) {
272
- const elementRect = items [ i ] . element . nativeElement . getBoundingClientRect ( ) ;
273
-
274
- // Add a few pixels to the top offset so we get some overlap.
275
- dispatchMouseEvent ( document , 'mousemove' , elementRect . left , elementRect . top + 5 ) ;
333
+ it ( 'should move the placeholder as an item is being sorted down on a scrolled page' ,
334
+ fakeAsync ( ( ) => {
335
+ const fixture = createComponent ( DraggableInDropZone ) ;
276
336
fixture . detectChanges ( ) ;
277
- expect ( getElementIndex ( placeholder ) ) . toBe ( i ) ;
278
- }
337
+ const cleanup = makePageScrollable ( ) ;
279
338
280
- dispatchMouseEvent ( document , 'mouseup' ) ;
281
- fixture . detectChanges ( ) ;
282
- flush ( ) ;
283
- } ) ) ;
339
+ scrollTo ( 0 , 500 ) ;
340
+ assertDownwardSorting ( fixture ) ;
341
+ cleanup ( ) ;
342
+ } ) ) ;
284
343
285
344
it ( 'should move the placeholder as an item is being sorted up' , fakeAsync ( ( ) => {
286
345
const fixture = createComponent ( DraggableInDropZone ) ;
287
346
fixture . detectChanges ( ) ;
347
+ assertUpwardSorting ( fixture ) ;
348
+ } ) ) ;
288
349
289
- const items = fixture . componentInstance . dragItems . toArray ( ) ;
290
- const draggedItem = items [ items . length - 1 ] . element . nativeElement ;
291
- const { top, left} = draggedItem . getBoundingClientRect ( ) ;
292
-
293
- dispatchMouseEvent ( draggedItem , 'mousedown' , left , top ) ;
294
- fixture . detectChanges ( ) ;
295
-
296
- const placeholder = document . querySelector ( '.cdk-drag-placeholder' ) ! as HTMLElement ;
297
-
298
- // Drag over each item one-by-one going upwards.
299
- for ( let i = items . length - 1 ; i > - 1 ; i -- ) {
300
- const elementRect = items [ i ] . element . nativeElement . getBoundingClientRect ( ) ;
301
-
302
- // Remove a few pixels from the bottom offset so we get some overlap.
303
- dispatchMouseEvent ( document , 'mousemove' , elementRect . left , elementRect . bottom - 5 ) ;
350
+ it ( 'should move the placeholder as an item is being sorted up on a scrolled page' ,
351
+ fakeAsync ( ( ) => {
352
+ const fixture = createComponent ( DraggableInDropZone ) ;
304
353
fixture . detectChanges ( ) ;
305
- expect ( getElementIndex ( placeholder ) ) . toBe ( Math . min ( i + 1 , items . length - 1 ) ) ;
306
- }
354
+ const cleanup = makePageScrollable ( ) ;
307
355
308
- dispatchMouseEvent ( document , 'mouseup' ) ;
309
- fixture . detectChanges ( ) ;
310
- flush ( ) ;
311
- } ) ) ;
356
+ scrollTo ( 0 , 500 ) ;
357
+ assertUpwardSorting ( fixture ) ;
358
+ cleanup ( ) ;
359
+ } ) ) ;
312
360
313
361
it ( 'should clean up the preview element if the item is destroyed mid-drag' , fakeAsync ( ( ) => {
314
362
const fixture = createComponent ( DraggableInDropZone ) ;
@@ -580,3 +628,77 @@ function dragElementViaTouch(fixture: ComponentFixture<any>,
580
628
function getElementIndex ( element : HTMLElement ) {
581
629
return element . parentElement ? Array . from ( element . parentElement . children ) . indexOf ( element ) : - 1 ;
582
630
}
631
+
632
+ /**
633
+ * Adds a large element to the page in order to make it scrollable.
634
+ * @returns Function that should be used to clean up after the test is done.
635
+ */
636
+ function makePageScrollable ( ) {
637
+ const veryTallElement = document . createElement ( 'div' ) ;
638
+ veryTallElement . style . width = '100%' ;
639
+ veryTallElement . style . height = '2000px' ;
640
+ document . body . appendChild ( veryTallElement ) ;
641
+
642
+ return ( ) => {
643
+ scrollTo ( 0 , 0 ) ;
644
+ veryTallElement . parentNode ! . removeChild ( veryTallElement ) ;
645
+ } ;
646
+ }
647
+
648
+ /**
649
+ * Asserts that sorting an element down works correctly.
650
+ * @param fixture Fixture against which to run the assertions.
651
+ */
652
+ function assertDownwardSorting ( fixture : ComponentFixture < DraggableInDropZone > ) {
653
+ const items = fixture . componentInstance . dragItems . toArray ( ) ;
654
+ const draggedItem = items [ 0 ] . element . nativeElement ;
655
+ const { top, left} = draggedItem . getBoundingClientRect ( ) ;
656
+
657
+ dispatchMouseEvent ( draggedItem , 'mousedown' , left , top ) ;
658
+ fixture . detectChanges ( ) ;
659
+
660
+ const placeholder = document . querySelector ( '.cdk-drag-placeholder' ) ! as HTMLElement ;
661
+
662
+ // Drag over each item one-by-one going downwards.
663
+ for ( let i = 0 ; i < items . length ; i ++ ) {
664
+ const elementRect = items [ i ] . element . nativeElement . getBoundingClientRect ( ) ;
665
+
666
+ // Add a few pixels to the top offset so we get some overlap.
667
+ dispatchMouseEvent ( document , 'mousemove' , elementRect . left , elementRect . top + 5 ) ;
668
+ fixture . detectChanges ( ) ;
669
+ expect ( getElementIndex ( placeholder ) ) . toBe ( i ) ;
670
+ }
671
+
672
+ dispatchMouseEvent ( document , 'mouseup' ) ;
673
+ fixture . detectChanges ( ) ;
674
+ flush ( ) ;
675
+ }
676
+
677
+ /**
678
+ * Asserts that sorting an element up works correctly.
679
+ * @param fixture Fixture against which to run the assertions.
680
+ */
681
+ function assertUpwardSorting ( fixture : ComponentFixture < DraggableInDropZone > ) {
682
+ const items = fixture . componentInstance . dragItems . toArray ( ) ;
683
+ const draggedItem = items [ items . length - 1 ] . element . nativeElement ;
684
+ const { top, left} = draggedItem . getBoundingClientRect ( ) ;
685
+
686
+ dispatchMouseEvent ( draggedItem , 'mousedown' , left , top ) ;
687
+ fixture . detectChanges ( ) ;
688
+
689
+ const placeholder = document . querySelector ( '.cdk-drag-placeholder' ) ! as HTMLElement ;
690
+
691
+ // Drag over each item one-by-one going upwards.
692
+ for ( let i = items . length - 1 ; i > - 1 ; i -- ) {
693
+ const elementRect = items [ i ] . element . nativeElement . getBoundingClientRect ( ) ;
694
+
695
+ // Remove a few pixels from the bottom offset so we get some overlap.
696
+ dispatchMouseEvent ( document , 'mousemove' , elementRect . left , elementRect . bottom - 5 ) ;
697
+ fixture . detectChanges ( ) ;
698
+ expect ( getElementIndex ( placeholder ) ) . toBe ( Math . min ( i + 1 , items . length - 1 ) ) ;
699
+ }
700
+
701
+ dispatchMouseEvent ( document , 'mouseup' ) ;
702
+ fixture . detectChanges ( ) ;
703
+ flush ( ) ;
704
+ }
0 commit comments