1
- import { TestBed , async , ComponentFixture } from '@angular/core/testing' ;
1
+ import { TestBed , async , fakeAsync , tick , ComponentFixture } from '@angular/core/testing' ;
2
2
import { Component , OnDestroy , QueryList , ViewChild , ViewChildren } from '@angular/core' ;
3
3
import { By } from '@angular/platform-browser' ;
4
4
import { MdAutocompleteModule , MdAutocompleteTrigger } from './index' ;
@@ -518,97 +518,88 @@ describe('MdAutocomplete', () => {
518
518
} ) ;
519
519
} ) ) ;
520
520
521
- it ( 'should set the active item to the first option when DOWN key is pressed' , async ( ( ) => {
522
- fixture . whenStable ( ) . then ( ( ) => {
523
- const optionEls =
524
- overlayContainerElement . querySelectorAll ( 'md-option' ) as NodeListOf < HTMLElement > ;
521
+ it ( 'should set the active item to the first option when DOWN key is pressed' , fakeAsync ( ( ) => {
522
+ tick ( ) ;
523
+ const optionEls =
524
+ overlayContainerElement . querySelectorAll ( 'md-option' ) as NodeListOf < HTMLElement > ;
525
525
526
- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
526
+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
527
+ tick ( ) ;
528
+ fixture . detectChanges ( ) ;
527
529
528
- fixture . whenStable ( ) . then ( ( ) => {
529
- fixture . detectChanges ( ) ;
530
- expect ( fixture . componentInstance . trigger . activeOption )
531
- . toBe ( fixture . componentInstance . options . first , 'Expected first option to be active.' ) ;
532
- expect ( optionEls [ 0 ] . classList ) . toContain ( 'mat-active' ) ;
533
- expect ( optionEls [ 1 ] . classList ) . not . toContain ( 'mat-active' ) ;
530
+ expect ( fixture . componentInstance . trigger . activeOption )
531
+ . toBe ( fixture . componentInstance . options . first , 'Expected first option to be active.' ) ;
532
+ expect ( optionEls [ 0 ] . classList ) . toContain ( 'mat-active' ) ;
533
+ expect ( optionEls [ 1 ] . classList ) . not . toContain ( 'mat-active' ) ;
534
534
535
- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
535
+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
536
+ tick ( ) ;
537
+ fixture . detectChanges ( ) ;
536
538
537
- fixture . whenStable ( ) . then ( ( ) => {
538
- fixture . detectChanges ( ) ;
539
- expect ( fixture . componentInstance . trigger . activeOption )
540
- . toBe ( fixture . componentInstance . options . toArray ( ) [ 1 ] ,
541
- 'Expected second option to be active.' ) ;
542
- expect ( optionEls [ 0 ] . classList ) . not . toContain ( 'mat-active' ) ;
543
- expect ( optionEls [ 1 ] . classList ) . toContain ( 'mat-active' ) ;
544
- } ) ;
545
- } ) ;
546
- } ) ;
539
+ expect ( fixture . componentInstance . trigger . activeOption )
540
+ . toBe ( fixture . componentInstance . options . toArray ( ) [ 1 ] ,
541
+ 'Expected second option to be active.' ) ;
542
+ expect ( optionEls [ 0 ] . classList ) . not . toContain ( 'mat-active' ) ;
543
+ expect ( optionEls [ 1 ] . classList ) . toContain ( 'mat-active' ) ;
547
544
} ) ) ;
548
545
549
- it ( 'should set the active item to the last option when UP key is pressed' , async ( ( ) => {
550
- fixture . whenStable ( ) . then ( ( ) => {
551
- const optionEls =
552
- overlayContainerElement . querySelectorAll ( 'md-option' ) as NodeListOf < HTMLElement > ;
546
+ it ( 'should set the active item to the last option when UP key is pressed' , fakeAsync ( ( ) => {
547
+ tick ( ) ;
548
+ const optionEls =
549
+ overlayContainerElement . querySelectorAll ( 'md-option' ) as NodeListOf < HTMLElement > ;
553
550
554
- const UP_ARROW_EVENT = new MockKeyboardEvent ( UP_ARROW ) as KeyboardEvent ;
555
- fixture . componentInstance . trigger . _handleKeydown ( UP_ARROW_EVENT ) ;
551
+ const UP_ARROW_EVENT = new MockKeyboardEvent ( UP_ARROW ) as KeyboardEvent ;
552
+ fixture . componentInstance . trigger . _handleKeydown ( UP_ARROW_EVENT ) ;
553
+ tick ( ) ;
554
+ fixture . detectChanges ( ) ;
556
555
557
- fixture . whenStable ( ) . then ( ( ) => {
558
- fixture . detectChanges ( ) ;
559
- expect ( fixture . componentInstance . trigger . activeOption )
560
- . toBe ( fixture . componentInstance . options . last , 'Expected last option to be active.' ) ;
561
- expect ( optionEls [ 10 ] . classList ) . toContain ( 'mat-active' ) ;
562
- expect ( optionEls [ 0 ] . classList ) . not . toContain ( 'mat-active' ) ;
556
+ expect ( fixture . componentInstance . trigger . activeOption )
557
+ . toBe ( fixture . componentInstance . options . last , 'Expected last option to be active.' ) ;
558
+ expect ( optionEls [ 10 ] . classList ) . toContain ( 'mat-active' ) ;
559
+ expect ( optionEls [ 0 ] . classList ) . not . toContain ( 'mat-active' ) ;
563
560
564
- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
561
+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
562
+ tick ( ) ;
563
+ fixture . detectChanges ( ) ;
565
564
566
- fixture . whenStable ( ) . then ( ( ) => {
567
- fixture . detectChanges ( ) ;
568
- expect ( fixture . componentInstance . trigger . activeOption )
569
- . toBe ( fixture . componentInstance . options . first ,
570
- 'Expected first option to be active.' ) ;
571
- expect ( optionEls [ 0 ] . classList ) . toContain ( 'mat-active' ) ;
572
- expect ( optionEls [ 10 ] . classList ) . not . toContain ( 'mat-active' ) ;
573
- } ) ;
574
- } ) ;
575
- } ) ;
565
+ expect ( fixture . componentInstance . trigger . activeOption )
566
+ . toBe ( fixture . componentInstance . options . first ,
567
+ 'Expected first option to be active.' ) ;
568
+ expect ( optionEls [ 0 ] . classList ) . toContain ( 'mat-active' ) ;
576
569
} ) ) ;
577
570
578
- it ( 'should set the active item properly after filtering' , async ( ( ) => {
579
- fixture . whenStable ( ) . then ( ( ) => {
580
- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
581
- fixture . detectChanges ( ) ;
571
+ it ( 'should set the active item properly after filtering' , fakeAsync ( ( ) => {
572
+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
573
+ tick ( ) ;
574
+ fixture . detectChanges ( ) ;
582
575
583
- fixture . whenStable ( ) . then ( ( ) => {
584
- typeInElement ( 'o' , input ) ;
585
- fixture . detectChanges ( ) ;
576
+ typeInElement ( 'o' , input ) ;
577
+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
578
+ tick ( ) ;
579
+ fixture . detectChanges ( ) ;
586
580
587
- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
581
+ const optionEls =
582
+ overlayContainerElement . querySelectorAll ( 'md-option' ) as NodeListOf < HTMLElement > ;
588
583
589
- fixture . whenStable ( ) . then ( ( ) => {
590
- fixture . detectChanges ( ) ;
591
- const optionEls =
592
- overlayContainerElement . querySelectorAll ( 'md-option' ) as NodeListOf < HTMLElement > ;
593
-
594
- expect ( fixture . componentInstance . trigger . activeOption )
595
- . toBe ( fixture . componentInstance . options . first ,
596
- 'Expected first option to be active.' ) ;
597
- expect ( optionEls [ 0 ] . classList ) . toContain ( 'mat-active' ) ;
598
- expect ( optionEls [ 1 ] . classList ) . not . toContain ( 'mat-active' ) ;
599
- } ) ;
600
- } ) ;
601
- } ) ;
584
+ expect ( fixture . componentInstance . trigger . activeOption )
585
+ . toBe ( fixture . componentInstance . options . first ,
586
+ 'Expected first option to be active.' ) ;
587
+ expect ( optionEls [ 0 ] . classList ) . toContain ( 'mat-active' ) ;
588
+ expect ( optionEls [ 1 ] . classList ) . not . toContain ( 'mat-active' ) ;
602
589
} ) ) ;
603
590
604
591
it ( 'should fill the text field when an option is selected with ENTER' , async ( ( ) => {
605
592
fixture . whenStable ( ) . then ( ( ) => {
606
593
fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
607
- fixture . componentInstance . trigger . _handleKeydown ( ENTER_EVENT ) ;
608
594
609
- fixture . detectChanges ( ) ;
610
- expect ( input . value )
611
- . toContain ( 'Alabama' , `Expected text field to fill with selected value on ENTER.` ) ;
595
+ fixture . whenStable ( ) . then ( ( ) => {
596
+ fixture . detectChanges ( ) ;
597
+
598
+ fixture . componentInstance . trigger . _handleKeydown ( ENTER_EVENT ) ;
599
+ fixture . detectChanges ( ) ;
600
+ expect ( input . value )
601
+ . toContain ( 'Alabama' , `Expected text field to fill with selected value on ENTER.` ) ;
602
+ } ) ;
612
603
} ) ;
613
604
} ) ) ;
614
605
@@ -619,11 +610,16 @@ describe('MdAutocomplete', () => {
619
610
620
611
const SPACE_EVENT = new MockKeyboardEvent ( SPACE ) as KeyboardEvent ;
621
612
fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
622
- fixture . componentInstance . trigger . _handleKeydown ( SPACE_EVENT ) ;
623
- fixture . detectChanges ( ) ;
624
613
625
- expect ( input . value )
626
- . not . toContain ( 'New York' , `Expected option not to be selected on SPACE.` ) ;
614
+ fixture . whenStable ( ) . then ( ( ) => {
615
+ fixture . detectChanges ( ) ;
616
+
617
+ fixture . componentInstance . trigger . _handleKeydown ( SPACE_EVENT ) ;
618
+ fixture . detectChanges ( ) ;
619
+
620
+ expect ( input . value )
621
+ . not . toContain ( 'New York' , `Expected option not to be selected on SPACE.` ) ;
622
+ } ) ;
627
623
} ) ;
628
624
} ) ) ;
629
625
@@ -633,54 +629,74 @@ describe('MdAutocomplete', () => {
633
629
. toBe ( false , `Expected control to start out pristine.` ) ;
634
630
635
631
fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
636
- fixture . componentInstance . trigger . _handleKeydown ( ENTER_EVENT ) ;
637
- fixture . detectChanges ( ) ;
632
+ fixture . whenStable ( ) . then ( ( ) => {
633
+ fixture . componentInstance . trigger . _handleKeydown ( ENTER_EVENT ) ;
634
+ fixture . detectChanges ( ) ;
638
635
639
- expect ( fixture . componentInstance . stateCtrl . dirty )
640
- . toBe ( true , `Expected control to become dirty when option was selected by ENTER.` ) ;
636
+ expect ( fixture . componentInstance . stateCtrl . dirty )
637
+ . toBe ( true , `Expected control to become dirty when option was selected by ENTER.` ) ;
638
+ } ) ;
641
639
} ) ;
642
640
} ) ) ;
643
641
644
642
it ( 'should open the panel again when typing after making a selection' , async ( ( ) => {
645
643
fixture . whenStable ( ) . then ( ( ) => {
646
644
fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
647
- fixture . componentInstance . trigger . _handleKeydown ( ENTER_EVENT ) ;
648
- fixture . detectChanges ( ) ;
645
+ fixture . whenStable ( ) . then ( ( ) => {
646
+ fixture . componentInstance . trigger . _handleKeydown ( ENTER_EVENT ) ;
647
+ fixture . detectChanges ( ) ;
649
648
650
- expect ( fixture . componentInstance . trigger . panelOpen )
651
- . toBe ( false , `Expected panel state to read closed after ENTER key.` ) ;
652
- expect ( overlayContainerElement . textContent )
653
- . toEqual ( '' , `Expected panel to close after ENTER key.` ) ;
649
+ expect ( fixture . componentInstance . trigger . panelOpen )
650
+ . toBe ( false , `Expected panel state to read closed after ENTER key.` ) ;
651
+ expect ( overlayContainerElement . textContent )
652
+ . toEqual ( '' , `Expected panel to close after ENTER key.` ) ;
654
653
655
- typeInElement ( 'Alabama' , input ) ;
656
- fixture . detectChanges ( ) ;
654
+ typeInElement ( 'Alabama' , input ) ;
655
+ fixture . detectChanges ( ) ;
657
656
658
- expect ( fixture . componentInstance . trigger . panelOpen )
659
- . toBe ( true , `Expected panel state to read open when typing in input.` ) ;
660
- expect ( overlayContainerElement . textContent )
661
- . toContain ( 'Alabama' , `Expected panel to display when typing in input.` ) ;
657
+ expect ( fixture . componentInstance . trigger . panelOpen )
658
+ . toBe ( true , `Expected panel state to read open when typing in input.` ) ;
659
+ expect ( overlayContainerElement . textContent )
660
+ . toContain ( 'Alabama' , `Expected panel to display when typing in input.` ) ;
661
+ } ) ;
662
662
} ) ;
663
663
} ) ) ;
664
664
665
- it ( 'should scroll to active options below the fold' , async ( ( ) => {
666
- fixture . whenStable ( ) . then ( ( ) => {
667
- const scrollContainer = document . querySelector ( '.cdk-overlay-pane .mat-autocomplete-panel' ) ;
665
+ it ( 'should scroll to active options below the fold' , fakeAsync ( ( ) => {
666
+ tick ( ) ;
667
+ const scrollContainer =
668
+ document . querySelector ( '.cdk-overlay-pane .mat-autocomplete-panel' ) ;
668
669
670
+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
671
+ tick ( ) ;
672
+ fixture . detectChanges ( ) ;
673
+ expect ( scrollContainer . scrollTop ) . toEqual ( 0 , `Expected panel not to scroll.` ) ;
674
+
675
+ // These down arrows will set the 6th option active, below the fold.
676
+ [ 1 , 2 , 3 , 4 , 5 ] . forEach ( ( ) => {
669
677
fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
670
- fixture . detectChanges ( ) ;
671
- expect ( scrollContainer . scrollTop ) . toEqual ( 0 , `Expected panel not to scroll.` ) ;
678
+ tick ( ) ;
679
+ } ) ;
672
680
673
- // These down arrows will set the 6th option active, below the fold.
674
- [ 1 , 2 , 3 , 4 , 5 ] . forEach ( ( ) => {
675
- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
676
- } ) ;
677
- fixture . detectChanges ( ) ;
681
+ // Expect option bottom minus the panel height (288 - 256 = 32)
682
+ expect ( scrollContainer . scrollTop )
683
+ . toEqual ( 32 , `Expected panel to reveal the sixth option.` ) ;
684
+ } ) ) ;
678
685
679
- // Expect option bottom minus the panel height (288 - 256 = 32)
680
- expect ( scrollContainer . scrollTop ) . toEqual ( 32 , `Expected panel to reveal the sixth option.` ) ;
681
- } ) ;
686
+ it ( 'should scroll to active options on UP arrow' , fakeAsync ( ( ) => {
687
+ tick ( ) ;
688
+ const scrollContainer =
689
+ document . querySelector ( '.cdk-overlay-pane .mat-autocomplete-panel' ) ;
690
+
691
+ const UP_ARROW_EVENT = new MockKeyboardEvent ( UP_ARROW ) as KeyboardEvent ;
692
+ fixture . componentInstance . trigger . _handleKeydown ( UP_ARROW_EVENT ) ;
693
+ tick ( ) ;
694
+ fixture . detectChanges ( ) ;
682
695
696
+ // Expect option bottom minus the panel height (528 - 256 = 272)
697
+ expect ( scrollContainer . scrollTop ) . toEqual ( 272 , `Expected panel to reveal last option.` ) ;
683
698
} ) ) ;
699
+
684
700
} ) ;
685
701
686
702
describe ( 'aria' , ( ) => {
@@ -728,18 +744,23 @@ describe('MdAutocomplete', () => {
728
744
729
745
const DOWN_ARROW_EVENT = new MockKeyboardEvent ( DOWN_ARROW ) as KeyboardEvent ;
730
746
fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
731
- fixture . detectChanges ( ) ;
732
747
733
- expect ( input . getAttribute ( 'aria-activedescendant' ) )
734
- . toEqual ( fixture . componentInstance . options . first . id ,
735
- 'Expected aria-activedescendant to match the active item after 1 down arrow.' ) ;
748
+ fixture . whenStable ( ) . then ( ( ) => {
749
+ fixture . detectChanges ( ) ;
750
+ expect ( input . getAttribute ( 'aria-activedescendant' ) )
751
+ . toEqual ( fixture . componentInstance . options . first . id ,
752
+ 'Expected aria-activedescendant to match the active item after 1 down arrow.' ) ;
736
753
737
- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
738
- fixture . detectChanges ( ) ;
754
+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
755
+ fixture . whenStable ( ) . then ( ( ) => {
756
+ fixture . detectChanges ( ) ;
757
+
758
+ expect ( input . getAttribute ( 'aria-activedescendant' ) )
759
+ . toEqual ( fixture . componentInstance . options . toArray ( ) [ 1 ] . id ,
760
+ 'Expected aria-activedescendant to match the active item after 2 down arrows.' ) ;
761
+ } ) ;
762
+ } ) ;
739
763
740
- expect ( input . getAttribute ( 'aria-activedescendant' ) )
741
- . toEqual ( fixture . componentInstance . options . toArray ( ) [ 1 ] . id ,
742
- 'Expected aria-activedescendant to match the active item after 2 down arrows.' ) ;
743
764
} ) ;
744
765
} ) ) ;
745
766
@@ -879,6 +900,26 @@ describe('MdAutocomplete', () => {
879
900
. toContain ( 'Two' , `Expected panel to display when input is focused.` ) ;
880
901
} ) ;
881
902
903
+ it ( 'should filter properly with ngIf after setting the active item' , fakeAsync ( ( ) => {
904
+ const fixture = TestBed . createComponent ( NgIfAutocomplete ) ;
905
+ fixture . detectChanges ( ) ;
906
+
907
+ fixture . componentInstance . trigger . openPanel ( ) ;
908
+ tick ( ) ;
909
+ fixture . detectChanges ( ) ;
910
+
911
+ const DOWN_ARROW_EVENT = new MockKeyboardEvent ( DOWN_ARROW ) as KeyboardEvent ;
912
+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
913
+ tick ( ) ;
914
+ fixture . detectChanges ( ) ;
915
+
916
+ const input = fixture . debugElement . query ( By . css ( 'input' ) ) . nativeElement ;
917
+ typeInElement ( 'o' , input ) ;
918
+ fixture . detectChanges ( ) ;
919
+
920
+ expect ( fixture . componentInstance . mdOptions . length ) . toBe ( 2 ) ;
921
+ } ) ) ;
922
+
882
923
} ) ;
883
924
} ) ;
884
925
@@ -956,9 +997,10 @@ class NgIfAutocomplete {
956
997
optionCtrl = new FormControl ( ) ;
957
998
filteredOptions : Observable < any > ;
958
999
isVisible = true ;
1000
+ options = [ 'One' , 'Two' , 'Three' ] ;
959
1001
960
1002
@ViewChild ( MdAutocompleteTrigger ) trigger : MdAutocompleteTrigger ;
961
- options = [ 'One' , 'Two' , 'Three' ] ;
1003
+ @ ViewChildren ( MdOption ) mdOptions : QueryList < MdOption > ;
962
1004
963
1005
constructor ( ) {
964
1006
this . filteredOptions = this . optionCtrl . valueChanges . startWith ( null ) . map ( ( val ) => {
0 commit comments