1- import { TestBed , async , ComponentFixture } from '@angular/core/testing' ;
1+ import { TestBed , async , fakeAsync , tick , ComponentFixture } from '@angular/core/testing' ;
22import { Component , OnDestroy , QueryList , ViewChild , ViewChildren } from '@angular/core' ;
33import { By } from '@angular/platform-browser' ;
44import { MdAutocompleteModule , MdAutocompleteTrigger } from './index' ;
@@ -518,97 +518,88 @@ describe('MdAutocomplete', () => {
518518 } ) ;
519519 } ) ) ;
520520
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 > ;
525525
526- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
526+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
527+ tick ( ) ;
528+ fixture . detectChanges ( ) ;
527529
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' ) ;
534534
535- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
535+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
536+ tick ( ) ;
537+ fixture . detectChanges ( ) ;
536538
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' ) ;
547544 } ) ) ;
548545
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 > ;
553550
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 ( ) ;
556555
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' ) ;
563560
564- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
561+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
562+ tick ( ) ;
563+ fixture . detectChanges ( ) ;
565564
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' ) ;
576569 } ) ) ;
577570
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 ( ) ;
582575
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 ( ) ;
586580
587- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
581+ const optionEls =
582+ overlayContainerElement . querySelectorAll ( 'md-option' ) as NodeListOf < HTMLElement > ;
588583
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' ) ;
602589 } ) ) ;
603590
604591 it ( 'should fill the text field when an option is selected with ENTER' , async ( ( ) => {
605592 fixture . whenStable ( ) . then ( ( ) => {
606593 fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
607- fixture . componentInstance . trigger . _handleKeydown ( ENTER_EVENT ) ;
608594
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+ } ) ;
612603 } ) ;
613604 } ) ) ;
614605
@@ -619,11 +610,16 @@ describe('MdAutocomplete', () => {
619610
620611 const SPACE_EVENT = new MockKeyboardEvent ( SPACE ) as KeyboardEvent ;
621612 fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
622- fixture . componentInstance . trigger . _handleKeydown ( SPACE_EVENT ) ;
623- fixture . detectChanges ( ) ;
624613
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+ } ) ;
627623 } ) ;
628624 } ) ) ;
629625
@@ -633,51 +629,59 @@ describe('MdAutocomplete', () => {
633629 . toBe ( false , `Expected control to start out pristine.` ) ;
634630
635631 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 ( ) ;
638635
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+ } ) ;
641639 } ) ;
642640 } ) ) ;
643641
644642 it ( 'should open the panel again when typing after making a selection' , async ( ( ) => {
645643 fixture . whenStable ( ) . then ( ( ) => {
646644 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 ( ) ;
649648
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.` ) ;
654653
655- typeInElement ( 'Alabama' , input ) ;
656- fixture . detectChanges ( ) ;
654+ typeInElement ( 'Alabama' , input ) ;
655+ fixture . detectChanges ( ) ;
657656
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+ } ) ;
662662 } ) ;
663663 } ) ) ;
664664
665665 it ( 'should scroll to active options below the fold' , async ( ( ) => {
666666 fixture . whenStable ( ) . then ( ( ) => {
667- const scrollContainer = document . querySelector ( '.cdk-overlay-pane .mat-autocomplete-panel' ) ;
667+ const scrollContainer =
668+ document . querySelector ( '.cdk-overlay-pane .mat-autocomplete-panel' ) ;
668669
669670 fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
670- fixture . detectChanges ( ) ;
671- expect ( scrollContainer . scrollTop ) . toEqual ( 0 , `Expected panel not to scroll.` ) ;
671+ fixture . whenStable ( ) . then ( ( ) => {
672+ fixture . detectChanges ( ) ;
673+ expect ( scrollContainer . scrollTop ) . toEqual ( 0 , `Expected panel not to scroll.` ) ;
672674
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 ( ) ;
675+ // These down arrows will set the 6th option active, below the fold.
676+ [ 1 , 2 , 3 , 4 , 5 ] . forEach ( ( ) => {
677+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
678+ } ) ;
679+ fixture . detectChanges ( ) ;
678680
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+ // 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+ } ) ;
681685 } ) ;
682686
683687 } ) ) ;
@@ -728,18 +732,23 @@ describe('MdAutocomplete', () => {
728732
729733 const DOWN_ARROW_EVENT = new MockKeyboardEvent ( DOWN_ARROW ) as KeyboardEvent ;
730734 fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
731- fixture . detectChanges ( ) ;
732735
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.' ) ;
736+ fixture . whenStable ( ) . then ( ( ) => {
737+ fixture . detectChanges ( ) ;
738+ expect ( input . getAttribute ( 'aria-activedescendant' ) )
739+ . toEqual ( fixture . componentInstance . options . first . id ,
740+ 'Expected aria-activedescendant to match the active item after 1 down arrow.' ) ;
736741
737- fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
738- fixture . detectChanges ( ) ;
742+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
743+ fixture . whenStable ( ) . then ( ( ) => {
744+ fixture . detectChanges ( ) ;
745+
746+ expect ( input . getAttribute ( 'aria-activedescendant' ) )
747+ . toEqual ( fixture . componentInstance . options . toArray ( ) [ 1 ] . id ,
748+ 'Expected aria-activedescendant to match the active item after 2 down arrows.' ) ;
749+ } ) ;
750+ } ) ;
739751
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.' ) ;
743752 } ) ;
744753 } ) ) ;
745754
@@ -879,6 +888,26 @@ describe('MdAutocomplete', () => {
879888 . toContain ( 'Two' , `Expected panel to display when input is focused.` ) ;
880889 } ) ;
881890
891+ it ( 'should filter properly with ngIf after setting the active item' , fakeAsync ( ( ) => {
892+ const fixture = TestBed . createComponent ( NgIfAutocomplete ) ;
893+ fixture . detectChanges ( ) ;
894+
895+ fixture . componentInstance . trigger . openPanel ( ) ;
896+ tick ( ) ;
897+ fixture . detectChanges ( ) ;
898+
899+ const DOWN_ARROW_EVENT = new MockKeyboardEvent ( DOWN_ARROW ) as KeyboardEvent ;
900+ fixture . componentInstance . trigger . _handleKeydown ( DOWN_ARROW_EVENT ) ;
901+ tick ( ) ;
902+ fixture . detectChanges ( ) ;
903+
904+ const input = fixture . debugElement . query ( By . css ( 'input' ) ) . nativeElement ;
905+ typeInElement ( 'o' , input ) ;
906+ fixture . detectChanges ( ) ;
907+
908+ expect ( fixture . componentInstance . mdOptions . length ) . toBe ( 2 ) ;
909+ } ) ) ;
910+
882911 } ) ;
883912} ) ;
884913
@@ -956,9 +985,10 @@ class NgIfAutocomplete {
956985 optionCtrl = new FormControl ( ) ;
957986 filteredOptions : Observable < any > ;
958987 isVisible = true ;
988+ options = [ 'One' , 'Two' , 'Three' ] ;
959989
960990 @ViewChild ( MdAutocompleteTrigger ) trigger : MdAutocompleteTrigger ;
961- options = [ 'One' , 'Two' , 'Three' ] ;
991+ @ ViewChildren ( MdOption ) mdOptions : QueryList < MdOption > ;
962992
963993 constructor ( ) {
964994 this . filteredOptions = this . optionCtrl . valueChanges . startWith ( null ) . map ( ( val ) => {
0 commit comments