@@ -39,6 +39,21 @@ describe('CdkDrag', () => {
3939 expect ( dragElement . style . transform ) . toBe ( 'translate3d(50px, 100px, 0px)' ) ;
4040 } ) ) ;
4141
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+
4257 it ( 'should continue dragging the element from where it was left off' , fakeAsync ( ( ) => {
4358 const fixture = createComponent ( StandaloneDraggable ) ;
4459 fixture . detectChanges ( ) ;
@@ -52,6 +67,26 @@ describe('CdkDrag', () => {
5267 dragElementViaMouse ( fixture , dragElement , 100 , 200 ) ;
5368 expect ( dragElement . style . transform ) . toBe ( 'translate3d(150px, 300px, 0px)' ) ;
5469 } ) ) ;
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+ } ) ) ;
5590 } ) ;
5691
5792 describe ( 'touch dragging' , ( ) => {
@@ -65,6 +100,21 @@ describe('CdkDrag', () => {
65100 expect ( dragElement . style . transform ) . toBe ( 'translate3d(50px, 100px, 0px)' ) ;
66101 } ) ) ;
67102
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+
68118 it ( 'should continue dragging the element from where it was left off' , fakeAsync ( ( ) => {
69119 const fixture = createComponent ( StandaloneDraggable ) ;
70120 fixture . detectChanges ( ) ;
@@ -79,6 +129,26 @@ describe('CdkDrag', () => {
79129 expect ( dragElement . style . transform ) . toBe ( 'translate3d(150px, 300px, 0px)' ) ;
80130 } ) ) ;
81131
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+
82152 it ( 'should prevent the default `touchmove` action on the page while dragging' ,
83153 fakeAsync ( ( ) => {
84154 const fixture = createComponent ( StandaloneDraggable ) ;
@@ -257,58 +327,36 @@ describe('CdkDrag', () => {
257327 it ( 'should move the placeholder as an item is being sorted down' , fakeAsync ( ( ) => {
258328 const fixture = createComponent ( DraggableInDropZone ) ;
259329 fixture . detectChanges ( ) ;
330+ assertDownwardSorting ( fixture ) ;
331+ } ) ) ;
260332
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 ) ;
276336 fixture . detectChanges ( ) ;
277- expect ( getElementIndex ( placeholder ) ) . toBe ( i ) ;
278- }
337+ const cleanup = makePageScrollable ( ) ;
279338
280- dispatchMouseEvent ( document , 'mouseup' ) ;
281- fixture . detectChanges ( ) ;
282- flush ( ) ;
283- } ) ) ;
339+ scrollTo ( 0 , 500 ) ;
340+ assertDownwardSorting ( fixture ) ;
341+ cleanup ( ) ;
342+ } ) ) ;
284343
285344 it ( 'should move the placeholder as an item is being sorted up' , fakeAsync ( ( ) => {
286345 const fixture = createComponent ( DraggableInDropZone ) ;
287346 fixture . detectChanges ( ) ;
347+ assertUpwardSorting ( fixture ) ;
348+ } ) ) ;
288349
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 ) ;
304353 fixture . detectChanges ( ) ;
305- expect ( getElementIndex ( placeholder ) ) . toBe ( Math . min ( i + 1 , items . length - 1 ) ) ;
306- }
354+ const cleanup = makePageScrollable ( ) ;
307355
308- dispatchMouseEvent ( document , 'mouseup' ) ;
309- fixture . detectChanges ( ) ;
310- flush ( ) ;
311- } ) ) ;
356+ scrollTo ( 0 , 500 ) ;
357+ assertUpwardSorting ( fixture ) ;
358+ cleanup ( ) ;
359+ } ) ) ;
312360
313361 it ( 'should clean up the preview element if the item is destroyed mid-drag' , fakeAsync ( ( ) => {
314362 const fixture = createComponent ( DraggableInDropZone ) ;
@@ -580,3 +628,77 @@ function dragElementViaTouch(fixture: ComponentFixture<any>,
580628function getElementIndex ( element : HTMLElement ) {
581629 return element . parentElement ? Array . from ( element . parentElement . children ) . indexOf ( element ) : - 1 ;
582630}
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