@@ -14,9 +14,8 @@ import {createKeyboardEvent} from '../../testing/private';
14
14
import { QueryList } from '@angular/core' ;
15
15
import { fakeAsync , tick } from '@angular/core/testing' ;
16
16
import { take } from 'rxjs/operators' ;
17
- import { FocusOrigin } from '../focus-monitor/focus-monitor' ;
18
17
import { TreeKeyManager , TreeKeyManagerItem } from './tree-key-manager' ;
19
- import { Observable , of as observableOf } from 'rxjs' ;
18
+ import { Observable , of as observableOf , Subscription } from 'rxjs' ;
20
19
21
20
class FakeBaseTreeKeyManagerItem {
22
21
public _isExpanded = false ;
@@ -69,8 +68,9 @@ interface ItemConstructorTestContext {
69
68
}
70
69
71
70
interface ExpandCollapseKeyEventTestContext {
72
- expandKeyEvent : KeyboardEvent ;
73
- collapseKeyEvent : KeyboardEvent ;
71
+ direction : 'ltr' | 'rtl' ;
72
+ expandKeyEvent : ( ) => KeyboardEvent ;
73
+ collapseKeyEvent : ( ) => KeyboardEvent ;
74
74
}
75
75
76
76
fdescribe ( 'TreeKeyManager' , ( ) => {
@@ -445,6 +445,298 @@ fdescribe('TreeKeyManager', () => {
445
445
expect ( fakeKeyEvents . upArrow . defaultPrevented ) . toBe ( true ) ;
446
446
} ) ;
447
447
} ) ;
448
+
449
+ describe ( 'expand/collapse key events' , ( ) => {
450
+ const parameters : ExpandCollapseKeyEventTestContext [ ] = [
451
+ {
452
+ direction : 'ltr' ,
453
+ expandKeyEvent : ( ) => fakeKeyEvents . rightArrow ,
454
+ collapseKeyEvent : ( ) => fakeKeyEvents . leftArrow ,
455
+ } ,
456
+ {
457
+ direction : 'rtl' ,
458
+ expandKeyEvent : ( ) => fakeKeyEvents . leftArrow ,
459
+ collapseKeyEvent : ( ) => fakeKeyEvents . rightArrow ,
460
+ } ,
461
+ ] ;
462
+
463
+ for ( const param of parameters ) {
464
+ describe ( `in ${ param . direction } mode` , ( ) => {
465
+ beforeEach ( ( ) => {
466
+ keyManager = new TreeKeyManager ( {
467
+ items : itemList ,
468
+ horizontalOrientation : param . direction ,
469
+ } ) ;
470
+ for ( const item of itemList ) {
471
+ item . _isExpanded = false ;
472
+ }
473
+ } ) ;
474
+
475
+ it ( 'with nothing active, expand key does not expand any items' , ( ) => {
476
+ expect ( itemList . toArray ( ) . map ( item => item . isExpanded ( ) ) )
477
+ . withContext ( 'item expansion state, for all items' )
478
+ . toEqual ( itemList . toArray ( ) . map ( _ => false ) ) ;
479
+
480
+ keyManager . onKeydown ( param . expandKeyEvent ( ) ) ;
481
+
482
+ expect ( itemList . toArray ( ) . map ( item => item . isExpanded ( ) ) )
483
+ . withContext ( 'item expansion state, for all items, after expand event' )
484
+ . toEqual ( itemList . toArray ( ) . map ( _ => false ) ) ;
485
+ } ) ;
486
+
487
+ it ( 'with nothing active, collapse key does not collapse any items' , ( ) => {
488
+ for ( const item of itemList ) {
489
+ item . _isExpanded = true ;
490
+ }
491
+ expect ( itemList . toArray ( ) . map ( item => item . isExpanded ( ) ) )
492
+ . withContext ( 'item expansion state, for all items' )
493
+ . toEqual ( itemList . toArray ( ) . map ( _ => true ) ) ;
494
+
495
+ keyManager . onKeydown ( param . collapseKeyEvent ( ) ) ;
496
+
497
+ expect ( itemList . toArray ( ) . map ( item => item . isExpanded ( ) ) )
498
+ . withContext ( 'item expansion state, for all items' )
499
+ . toEqual ( itemList . toArray ( ) . map ( _ => true ) ) ;
500
+ } ) ;
501
+
502
+ it ( 'with nothing active, expand key does not change the active item index' , ( ) => {
503
+ expect ( keyManager . getActiveItemIndex ( ) )
504
+ . withContext ( 'active item index, initial' )
505
+ . toEqual ( - 1 ) ;
506
+
507
+ keyManager . onKeydown ( param . expandKeyEvent ( ) ) ;
508
+
509
+ expect ( keyManager . getActiveItemIndex ( ) )
510
+ . withContext ( 'active item index, after expand event' )
511
+ . toEqual ( - 1 ) ;
512
+ } ) ;
513
+
514
+ it ( 'with nothing active, collapse key does not change the active item index' , ( ) => {
515
+ for ( const item of itemList ) {
516
+ item . _isExpanded = true ;
517
+ }
518
+
519
+ expect ( keyManager . getActiveItemIndex ( ) )
520
+ . withContext ( 'active item index, initial' )
521
+ . toEqual ( - 1 ) ;
522
+
523
+ keyManager . onKeydown ( param . collapseKeyEvent ( ) ) ;
524
+
525
+ expect ( keyManager . getActiveItemIndex ( ) )
526
+ . withContext ( 'active item index, after collapse event' )
527
+ . toEqual ( - 1 ) ;
528
+ } ) ;
529
+
530
+ describe ( 'if the current item is expanded' , ( ) => {
531
+ let spy : jasmine . Spy ;
532
+ let subscription : Subscription ;
533
+
534
+ beforeEach ( ( ) => {
535
+ keyManager . onClick ( parentItem ) ;
536
+ parentItem . _isExpanded = true ;
537
+
538
+ spy = jasmine . createSpy ( 'change spy' ) ;
539
+ subscription = keyManager . change . subscribe ( spy ) ;
540
+ } ) ;
541
+
542
+ afterEach ( ( ) => {
543
+ subscription . unsubscribe ( ) ;
544
+ } ) ;
545
+
546
+ it ( 'when the expand key is pressed, moves to the first child' , ( ) => {
547
+ keyManager . onKeydown ( param . expandKeyEvent ( ) ) ;
548
+
549
+ expect ( keyManager . getActiveItemIndex ( ) )
550
+ . withContext ( 'active item index, after one expand key event.' )
551
+ . toBe ( 1 ) ;
552
+ expect ( spy ) . not . toHaveBeenCalledWith ( parentItem ) ;
553
+ expect ( spy ) . toHaveBeenCalledWith ( childItem ) ;
554
+ } ) ;
555
+
556
+ it (
557
+ 'when the expand key is pressed, and the first child is disabled, ' +
558
+ 'moves to the first non-disabled child' ,
559
+ ( ) => {
560
+ childItem . isDisabled = true ;
561
+
562
+ keyManager . onKeydown ( param . expandKeyEvent ( ) ) ;
563
+
564
+ expect ( keyManager . getActiveItemIndex ( ) )
565
+ . withContext ( 'active item index, after one expand key event.' )
566
+ . toBe ( 3 ) ;
567
+ expect ( spy ) . not . toHaveBeenCalledWith ( parentItem ) ;
568
+ expect ( spy ) . not . toHaveBeenCalledWith ( childItem ) ;
569
+ expect ( spy ) . toHaveBeenCalledWith ( childItemWithNoChildren ) ;
570
+ } ,
571
+ ) ;
572
+
573
+ it (
574
+ 'when the expand key is pressed, and all children are disabled, ' +
575
+ 'does not change the active item' ,
576
+ ( ) => {
577
+ childItem . isDisabled = true ;
578
+ childItemWithNoChildren . isDisabled = true ;
579
+
580
+ keyManager . onKeydown ( param . expandKeyEvent ( ) ) ;
581
+
582
+ expect ( keyManager . getActiveItemIndex ( ) )
583
+ . withContext ( 'active item index, after one expand key event.' )
584
+ . toBe ( 0 ) ;
585
+ expect ( spy ) . not . toHaveBeenCalled ( ) ;
586
+ } ,
587
+ ) ;
588
+
589
+ it ( 'when the collapse key is pressed, collapses the item' , ( ) => {
590
+ expect ( parentItem . isExpanded ( ) )
591
+ . withContext ( 'active item initial expansion state' )
592
+ . toBe ( true ) ;
593
+
594
+ keyManager . onKeydown ( param . collapseKeyEvent ( ) ) ;
595
+
596
+ expect ( parentItem . isExpanded ( ) )
597
+ . withContext ( 'active item expansion state, after collapse key' )
598
+ . toBe ( false ) ;
599
+ } ) ;
600
+
601
+ it ( 'when the collapse key is pressed, does not change the active item' , ( ) => {
602
+ expect ( keyManager . getActiveItemIndex ( ) )
603
+ . withContext ( 'active item index, initial' )
604
+ . toBe ( 0 ) ;
605
+
606
+ keyManager . onKeydown ( param . collapseKeyEvent ( ) ) ;
607
+
608
+ expect ( keyManager . getActiveItemIndex ( ) )
609
+ . withContext ( 'active item index, after one collapse key event.' )
610
+ . toBe ( 0 ) ;
611
+ expect ( spy ) . not . toHaveBeenCalled ( ) ;
612
+ } ) ;
613
+ } ) ;
614
+
615
+ describe ( 'if the current item is expanded, and there are no children' , ( ) => {
616
+ let spy : jasmine . Spy ;
617
+ let subscription : Subscription ;
618
+
619
+ beforeEach ( ( ) => {
620
+ keyManager . onClick ( childItemWithNoChildren ) ;
621
+ childItemWithNoChildren . _isExpanded = true ;
622
+
623
+ spy = jasmine . createSpy ( 'change spy' ) ;
624
+ subscription = keyManager . change . subscribe ( spy ) ;
625
+ } ) ;
626
+
627
+ afterEach ( ( ) => {
628
+ subscription . unsubscribe ( ) ;
629
+ } ) ;
630
+
631
+ it ( 'when the expand key is pressed, does not change the active item' , ( ) => {
632
+ keyManager . onKeydown ( param . expandKeyEvent ( ) ) ;
633
+
634
+ expect ( keyManager . getActiveItemIndex ( ) )
635
+ . withContext ( 'active item index, after one expand key event.' )
636
+ . toBe ( 3 ) ;
637
+ expect ( spy ) . not . toHaveBeenCalled ( ) ;
638
+ } ) ;
639
+ } ) ;
640
+
641
+ describe ( 'if the current item is collapsed, and has a parent item' , ( ) => {
642
+ let spy : jasmine . Spy ;
643
+ let subscription : Subscription ;
644
+
645
+ beforeEach ( ( ) => {
646
+ keyManager . onClick ( childItem ) ;
647
+ childItem . _isExpanded = false ;
648
+
649
+ spy = jasmine . createSpy ( 'change spy' ) ;
650
+ subscription = keyManager . change . subscribe ( spy ) ;
651
+ } ) ;
652
+
653
+ afterEach ( ( ) => {
654
+ subscription . unsubscribe ( ) ;
655
+ } ) ;
656
+
657
+ it ( 'when the expand key is pressed, expands the current item' , ( ) => {
658
+ expect ( childItem . isExpanded ( ) )
659
+ . withContext ( 'active item initial expansion state' )
660
+ . toBe ( false ) ;
661
+
662
+ keyManager . onKeydown ( param . expandKeyEvent ( ) ) ;
663
+
664
+ expect ( childItem . isExpanded ( ) )
665
+ . withContext ( 'active item expansion state, after expand key' )
666
+ . toBe ( true ) ;
667
+ } ) ;
668
+
669
+ it ( 'when the expand key is pressed, does not change active item' , ( ) => {
670
+ expect ( keyManager . getActiveItemIndex ( ) )
671
+ . withContext ( 'active item index, initial' )
672
+ . toBe ( 1 ) ;
673
+
674
+ keyManager . onKeydown ( param . expandKeyEvent ( ) ) ;
675
+
676
+ expect ( keyManager . getActiveItemIndex ( ) )
677
+ . withContext ( 'active item index, after one collapse key event.' )
678
+ . toBe ( 1 ) ;
679
+ expect ( spy ) . not . toHaveBeenCalled ( ) ;
680
+ } ) ;
681
+
682
+ it ( 'when the collapse key is pressed, moves the active item to the parent' , ( ) => {
683
+ expect ( keyManager . getActiveItemIndex ( ) )
684
+ . withContext ( 'active item index, initial' )
685
+ . toBe ( 1 ) ;
686
+
687
+ keyManager . onKeydown ( param . collapseKeyEvent ( ) ) ;
688
+
689
+ expect ( keyManager . getActiveItemIndex ( ) )
690
+ . withContext ( 'active item index, after one collapse key event.' )
691
+ . toBe ( 0 ) ;
692
+ } ) ;
693
+
694
+ it ( 'when the collapse key is pressed, and the parent is disabled, does nothing' , ( ) => {
695
+ expect ( keyManager . getActiveItemIndex ( ) )
696
+ . withContext ( 'active item index, initial' )
697
+ . toBe ( 1 ) ;
698
+
699
+ parentItem . isDisabled = true ;
700
+ keyManager . onKeydown ( param . collapseKeyEvent ( ) ) ;
701
+
702
+ expect ( keyManager . getActiveItemIndex ( ) )
703
+ . withContext ( 'active item index, after one collapse key event.' )
704
+ . toBe ( 1 ) ;
705
+ } ) ;
706
+ } ) ;
707
+
708
+ describe ( 'if the current item is collapsed, and has no parent items' , ( ) => {
709
+ let spy : jasmine . Spy ;
710
+ let subscription : Subscription ;
711
+
712
+ beforeEach ( ( ) => {
713
+ keyManager . onClick ( parentItem ) ;
714
+ parentItem . _isExpanded = false ;
715
+
716
+ spy = jasmine . createSpy ( 'change spy' ) ;
717
+ subscription = keyManager . change . subscribe ( spy ) ;
718
+ } ) ;
719
+
720
+ afterEach ( ( ) => {
721
+ subscription . unsubscribe ( ) ;
722
+ } ) ;
723
+
724
+ it ( 'when the collapse key is pressed, does nothing' , ( ) => {
725
+ expect ( keyManager . getActiveItemIndex ( ) )
726
+ . withContext ( 'active item index, initial' )
727
+ . toBe ( 0 ) ;
728
+
729
+ keyManager . onKeydown ( param . collapseKeyEvent ( ) ) ;
730
+
731
+ expect ( keyManager . getActiveItemIndex ( ) )
732
+ . withContext ( 'active item index, after one collapse key event.' )
733
+ . toBe ( 0 ) ;
734
+ expect ( spy ) . not . toHaveBeenCalledWith ( parentItem ) ;
735
+ } ) ;
736
+ } ) ;
737
+ } ) ;
738
+ }
739
+ } ) ;
448
740
} ) ;
449
741
}
450
742
0 commit comments