@@ -34,6 +34,8 @@ import {CdkMenuItemRadio} from './menu-item-radio';
34
34
import { CdkMenu } from './menu' ;
35
35
import { CdkMenuItem } from './menu-item' ;
36
36
import { CdkMenuItemCheckbox } from './menu-item-checkbox' ;
37
+ import { CdkMenuItemTrigger } from './menu-item-trigger' ;
38
+ import { CdkMenuGroup } from './menu-group' ;
37
39
38
40
describe ( 'MenuBar' , ( ) => {
39
41
describe ( 'as radio group' , ( ) => {
@@ -735,6 +737,108 @@ describe('MenuBar', () => {
735
737
) ;
736
738
} ) ;
737
739
} ) ;
740
+
741
+ describe ( 'background click closeout' , ( ) => {
742
+ let fixture : ComponentFixture < MenuBarWithMenus > ;
743
+
744
+ let menus : CdkMenu [ ] ;
745
+ let triggers : CdkMenuItemTrigger [ ] ;
746
+
747
+ /** open the attached menu. */
748
+ const openMenu = ( ) => {
749
+ triggers [ 0 ] . toggle ( ) ;
750
+ detectChanges ( ) ;
751
+ } ;
752
+
753
+ /** set the menus and triggers arrays. */
754
+ const grabElementsForTesting = ( ) => {
755
+ menus = fixture . componentInstance . menus . toArray ( ) ;
756
+ triggers = fixture . componentInstance . triggers . toArray ( ) ;
757
+ } ;
758
+
759
+ /** run change detection and, extract and set the rendered elements. */
760
+ const detectChanges = ( ) => {
761
+ fixture . detectChanges ( ) ;
762
+ grabElementsForTesting ( ) ;
763
+ } ;
764
+
765
+ beforeEach ( async ( ( ) => {
766
+ TestBed . configureTestingModule ( {
767
+ imports : [ CdkMenuModule ] ,
768
+ declarations : [ MenuBarWithMenus ] ,
769
+ } ) . compileComponents ( ) ;
770
+ } ) ) ;
771
+
772
+ beforeEach ( ( ) => {
773
+ fixture = TestBed . createComponent ( MenuBarWithMenus ) ;
774
+ detectChanges ( ) ;
775
+ } ) ;
776
+
777
+ it ( 'should close out all open menus when clicked outside the menu tree' , ( ) => {
778
+ openMenu ( ) ;
779
+ expect ( menus . length ) . toBe ( 1 ) ;
780
+
781
+ fixture . debugElement . query ( By . css ( '#container' ) ) . nativeElement . click ( ) ;
782
+ detectChanges ( ) ;
783
+
784
+ expect ( menus . length ) . toBe ( 0 ) ;
785
+ } ) ;
786
+
787
+ it ( 'should not close open menus when clicking on a menu group' , ( ) => {
788
+ openMenu ( ) ;
789
+ expect ( menus . length ) . toBe ( 1 ) ;
790
+
791
+ const menuGroups = fixture . debugElement . queryAll ( By . directive ( CdkMenuGroup ) ) ;
792
+ menuGroups [ 0 ] . nativeElement . click ( ) ;
793
+ menuGroups [ 1 ] . nativeElement . click ( ) ;
794
+ menuGroups [ 2 ] . nativeElement . click ( ) ;
795
+ detectChanges ( ) ;
796
+
797
+ expect ( menus . length ) . toBe ( 1 ) ;
798
+ } ) ;
799
+
800
+ it ( 'should not close open menus when clicking on a menu' , ( ) => {
801
+ openMenu ( ) ;
802
+ expect ( menus . length ) . toBe ( 1 ) ;
803
+
804
+ fixture . debugElement . query ( By . directive ( CdkMenu ) ) . nativeElement . click ( ) ;
805
+ detectChanges ( ) ;
806
+
807
+ expect ( menus . length ) . toBe ( 1 ) ;
808
+ } ) ;
809
+
810
+ it ( 'should not close open menus when clicking on a menu bar' , ( ) => {
811
+ openMenu ( ) ;
812
+ expect ( menus . length ) . toBe ( 1 ) ;
813
+
814
+ fixture . debugElement . query ( By . directive ( CdkMenuBar ) ) . nativeElement . click ( ) ;
815
+ detectChanges ( ) ;
816
+
817
+ expect ( menus . length ) . toBe ( 1 ) ;
818
+ } ) ;
819
+
820
+ it ( 'should not close when clicking on a CdkMenuItemCheckbox element' , ( ) => {
821
+ openMenu ( ) ;
822
+ expect ( menus . length ) . toBe ( 1 ) ;
823
+
824
+ fixture . debugElement . query ( By . directive ( CdkMenuItemCheckbox ) ) . nativeElement . click ( ) ;
825
+ fixture . detectChanges ( ) ;
826
+
827
+ expect ( menus . length ) . toBe ( 1 ) ;
828
+ } ) ;
829
+
830
+ it ( 'should not close when clicking on a non-menu element inside menu' , ( ) => {
831
+ openMenu ( ) ;
832
+ expect ( menus . length ) . toBe ( 1 ) ;
833
+
834
+ fixture . debugElement . query ( By . css ( '#inner-element' ) ) . nativeElement . click ( ) ;
835
+ detectChanges ( ) ;
836
+
837
+ expect ( menus . length )
838
+ . withContext ( 'menu should stay open if clicking on an inner span element' )
839
+ . toBe ( 1 ) ;
840
+ } ) ;
841
+ } ) ;
738
842
} ) ;
739
843
740
844
@Component ( {
@@ -847,3 +951,27 @@ class MenuWithRadioButtons {
847
951
848
952
@ViewChildren ( CdkMenuItemRadio ) radioItems : QueryList < CdkMenuItemRadio > ;
849
953
}
954
+
955
+ @Component ( {
956
+ template : `
957
+ <div id="container">
958
+ <div cdkMenuBar>
959
+ <button cdkMenuItem [cdkMenuTriggerFor]="sub1">Trigger</button>
960
+ </div>
961
+
962
+ <ng-template cdkMenuPanel #sub1="cdkMenuPanel">
963
+ <div cdkMenu [cdkMenuPanel]="sub1">
964
+ <div cdkMenuGroup>
965
+ <button cdkMenuItemCheckbox>Trigger</button>
966
+ <span id="inner-element">A nested non-menuitem element</span>
967
+ </div>
968
+ </div>
969
+ </ng-template>
970
+ </div>
971
+ ` ,
972
+ } )
973
+ class MenuBarWithMenus {
974
+ @ViewChildren ( CdkMenu ) menus : QueryList < CdkMenu > ;
975
+
976
+ @ViewChildren ( CdkMenuItemTrigger ) triggers : QueryList < CdkMenuItemTrigger > ;
977
+ }
0 commit comments