@@ -329,6 +329,200 @@ describe('MatTabHeader', () => {
329
329
} ) ;
330
330
} ) ;
331
331
332
+ describe ( 'scrolling when holding paginator' , ( ) => {
333
+ let nextButton : HTMLElement ;
334
+ let prevButton : HTMLElement ;
335
+ let header : MatTabHeader ;
336
+ let headerElement : HTMLElement ;
337
+
338
+ beforeEach ( ( ) => {
339
+ fixture = TestBed . createComponent ( SimpleTabHeaderApp ) ;
340
+ fixture . componentInstance . disableRipple = true ;
341
+ fixture . detectChanges ( ) ;
342
+
343
+ fixture . componentInstance . addTabsForScrolling ( 50 ) ;
344
+ fixture . detectChanges ( ) ;
345
+
346
+ nextButton = fixture . nativeElement . querySelector ( '.mat-tab-header-pagination-after' ) ;
347
+ prevButton = fixture . nativeElement . querySelector ( '.mat-tab-header-pagination-before' ) ;
348
+ header = fixture . componentInstance . tabHeader ;
349
+ headerElement = fixture . nativeElement . querySelector ( '.mat-tab-header' ) ;
350
+ } ) ;
351
+
352
+ it ( 'should scroll towards the end while holding down the next button using a mouse' ,
353
+ fakeAsync ( ( ) => {
354
+ assertNextButtonScrolling ( 'mousedown' , 'click' ) ;
355
+ } ) ) ;
356
+
357
+ it ( 'should scroll towards the start while holding down the prev button using a mouse' ,
358
+ fakeAsync ( ( ) => {
359
+ assertPrevButtonScrolling ( 'mousedown' , 'click' ) ;
360
+ } ) ) ;
361
+
362
+ it ( 'should scroll towards the end while holding down the next button using touch' ,
363
+ fakeAsync ( ( ) => {
364
+ assertNextButtonScrolling ( 'touchstart' , 'touchend' ) ;
365
+ } ) ) ;
366
+
367
+ it ( 'should scroll towards the start while holding down the prev button using touch' ,
368
+ fakeAsync ( ( ) => {
369
+ assertPrevButtonScrolling ( 'touchstart' , 'touchend' ) ;
370
+ } ) ) ;
371
+
372
+ it ( 'should not scroll if the sequence is interrupted quickly' , fakeAsync ( ( ) => {
373
+ expect ( header . scrollDistance ) . toBe ( 0 , 'Expected to start off not scrolled.' ) ;
374
+
375
+ dispatchFakeEvent ( nextButton , 'mousedown' ) ;
376
+ fixture . detectChanges ( ) ;
377
+
378
+ tick ( 100 ) ;
379
+
380
+ dispatchFakeEvent ( headerElement , 'mouseleave' ) ;
381
+ fixture . detectChanges ( ) ;
382
+
383
+ tick ( 3000 ) ;
384
+
385
+ expect ( header . scrollDistance ) . toBe ( 0 , 'Expected not to have scrolled after a while.' ) ;
386
+ } ) ) ;
387
+
388
+ it ( 'should clear the timeouts on destroy' , fakeAsync ( ( ) => {
389
+ dispatchFakeEvent ( nextButton , 'mousedown' ) ;
390
+ fixture . detectChanges ( ) ;
391
+ fixture . destroy ( ) ;
392
+
393
+ // No need to assert. If fakeAsync doesn't throw, it means that the timers were cleared.
394
+ } ) ) ;
395
+
396
+ it ( 'should clear the timeouts on click' , fakeAsync ( ( ) => {
397
+ dispatchFakeEvent ( nextButton , 'mousedown' ) ;
398
+ fixture . detectChanges ( ) ;
399
+
400
+ dispatchFakeEvent ( nextButton , 'click' ) ;
401
+ fixture . detectChanges ( ) ;
402
+
403
+ // No need to assert. If fakeAsync doesn't throw, it means that the timers were cleared.
404
+ } ) ) ;
405
+
406
+ it ( 'should clear the timeouts on touchend' , fakeAsync ( ( ) => {
407
+ dispatchFakeEvent ( nextButton , 'touchstart' ) ;
408
+ fixture . detectChanges ( ) ;
409
+
410
+ dispatchFakeEvent ( nextButton , 'touchend' ) ;
411
+ fixture . detectChanges ( ) ;
412
+
413
+ // No need to assert. If fakeAsync doesn't throw, it means that the timers were cleared.
414
+ } ) ) ;
415
+
416
+ it ( 'should clear the timeouts when reaching the end' , fakeAsync ( ( ) => {
417
+ dispatchFakeEvent ( nextButton , 'mousedown' ) ;
418
+ fixture . detectChanges ( ) ;
419
+
420
+ // Simulate a very long timeout.
421
+ tick ( 60000 ) ;
422
+
423
+ // No need to assert. If fakeAsync doesn't throw, it means that the timers were cleared.
424
+ } ) ) ;
425
+
426
+ it ( 'should clear the timeouts when reaching the start' , fakeAsync ( ( ) => {
427
+ header . scrollDistance = Infinity ;
428
+ fixture . detectChanges ( ) ;
429
+
430
+ dispatchFakeEvent ( prevButton , 'mousedown' ) ;
431
+ fixture . detectChanges ( ) ;
432
+
433
+ // Simulate a very long timeout.
434
+ tick ( 60000 ) ;
435
+
436
+ // No need to assert. If fakeAsync doesn't throw, it means that the timers were cleared.
437
+ } ) ) ;
438
+
439
+ it ( 'should stop scrolling if the pointer leaves the header' , fakeAsync ( ( ) => {
440
+ expect ( header . scrollDistance ) . toBe ( 0 , 'Expected to start off not scrolled.' ) ;
441
+
442
+ dispatchFakeEvent ( nextButton , 'mousedown' ) ;
443
+ fixture . detectChanges ( ) ;
444
+ tick ( 300 ) ;
445
+
446
+ expect ( header . scrollDistance ) . toBe ( 0 , 'Expected not to scroll after short amount of time.' ) ;
447
+
448
+ tick ( 1000 ) ;
449
+
450
+ expect ( header . scrollDistance ) . toBeGreaterThan ( 0 , 'Expected to scroll after some time.' ) ;
451
+
452
+ let previousDistance = header . scrollDistance ;
453
+
454
+ dispatchFakeEvent ( headerElement , 'mouseleave' ) ;
455
+ fixture . detectChanges ( ) ;
456
+ tick ( 100 ) ;
457
+
458
+ expect ( header . scrollDistance ) . toBe ( previousDistance ) ;
459
+ } ) ) ;
460
+
461
+ /**
462
+ * Asserts that auto scrolling using the next button works.
463
+ * @param startEventName Name of the event that is supposed to start the scrolling.
464
+ * @param endEventName Name of the event that is supposed to end the scrolling.
465
+ */
466
+ function assertNextButtonScrolling ( startEventName : string , endEventName : string ) {
467
+ expect ( header . scrollDistance ) . toBe ( 0 , 'Expected to start off not scrolled.' ) ;
468
+
469
+ dispatchFakeEvent ( nextButton , startEventName ) ;
470
+ fixture . detectChanges ( ) ;
471
+ tick ( 300 ) ;
472
+
473
+ expect ( header . scrollDistance ) . toBe ( 0 , 'Expected not to scroll after short amount of time.' ) ;
474
+
475
+ tick ( 1000 ) ;
476
+
477
+ expect ( header . scrollDistance ) . toBeGreaterThan ( 0 , 'Expected to scroll after some time.' ) ;
478
+
479
+ let previousDistance = header . scrollDistance ;
480
+
481
+ tick ( 100 ) ;
482
+
483
+ expect ( header . scrollDistance )
484
+ . toBeGreaterThan ( previousDistance , 'Expected to scroll again after some more time.' ) ;
485
+
486
+ dispatchFakeEvent ( nextButton , endEventName ) ;
487
+ }
488
+
489
+ /**
490
+ * Asserts that auto scrolling using the previous button works.
491
+ * @param startEventName Name of the event that is supposed to start the scrolling.
492
+ * @param endEventName Name of the event that is supposed to end the scrolling.
493
+ */
494
+ function assertPrevButtonScrolling ( startEventName : string , endEventName : string ) {
495
+ header . scrollDistance = Infinity ;
496
+ fixture . detectChanges ( ) ;
497
+
498
+ let currentScroll = header . scrollDistance ;
499
+
500
+ expect ( currentScroll ) . toBeGreaterThan ( 0 , 'Expected to start off scrolled.' ) ;
501
+
502
+ dispatchFakeEvent ( prevButton , startEventName ) ;
503
+ fixture . detectChanges ( ) ;
504
+ tick ( 300 ) ;
505
+
506
+ expect ( header . scrollDistance )
507
+ . toBe ( currentScroll , 'Expected not to scroll after short amount of time.' ) ;
508
+
509
+ tick ( 1000 ) ;
510
+
511
+ expect ( header . scrollDistance )
512
+ . toBeLessThan ( currentScroll , 'Expected to scroll after some time.' ) ;
513
+
514
+ currentScroll = header . scrollDistance ;
515
+
516
+ tick ( 100 ) ;
517
+
518
+ expect ( header . scrollDistance )
519
+ . toBeLessThan ( currentScroll , 'Expected to scroll again after some more time.' ) ;
520
+
521
+ dispatchFakeEvent ( nextButton , endEventName ) ;
522
+ }
523
+
524
+ } ) ;
525
+
332
526
it ( 'should re-align the ink bar when the direction changes' , fakeAsync ( ( ) => {
333
527
fixture = TestBed . createComponent ( SimpleTabHeaderApp ) ;
334
528
@@ -453,7 +647,9 @@ class SimpleTabHeaderApp {
453
647
this . tabs [ this . disabledTabIndex ] . disabled = true ;
454
648
}
455
649
456
- addTabsForScrolling ( ) {
457
- this . tabs . push ( { label : 'new' } , { label : 'new' } , { label : 'new' } , { label : 'new' } ) ;
650
+ addTabsForScrolling ( amount = 4 ) {
651
+ for ( let i = 0 ; i < amount ; i ++ ) {
652
+ this . tabs . push ( { label : 'new' } ) ;
653
+ }
458
654
}
459
655
}
0 commit comments