@@ -8,10 +8,10 @@ import {
88 dispatchEvent ,
99} from '../../testing/private' ;
1010import { DOCUMENT } from '@angular/common' ;
11- import { Component , NgZone } from '@angular/core' ;
11+ import { Component , NgZone , ViewChild } from '@angular/core' ;
1212import { ComponentFixture , fakeAsync , flush , inject , TestBed , tick } from '@angular/core/testing' ;
1313import { By } from '@angular/platform-browser' ;
14- import { A11yModule } from '../index' ;
14+ import { A11yModule , CdkMonitorFocus } from '../index' ;
1515import { TOUCH_BUFFER_MS } from '../input-modality/input-modality-detector' ;
1616import {
1717 FocusMonitor ,
@@ -515,6 +515,7 @@ describe('cdkMonitorFocus', () => {
515515 ComplexComponentWithMonitorSubtreeFocus ,
516516 ComplexComponentWithMonitorSubtreeFocusAndMonitorElementFocus ,
517517 FocusMonitorOnCommentNode ,
518+ ExportedFocusMonitor ,
518519 ] ,
519520 } ) . compileComponents ( ) ;
520521 } ) ;
@@ -737,6 +738,77 @@ describe('cdkMonitorFocus', () => {
737738 } ) ) ;
738739 } ) ;
739740
741+ describe ( 'button with exported cdkMonitorElementFocus' , ( ) => {
742+ let fixture : ComponentFixture < ExportedFocusMonitor > ;
743+ let buttonElement : HTMLElement ;
744+
745+ beforeEach ( ( ) => {
746+ fixture = TestBed . createComponent ( ExportedFocusMonitor ) ;
747+ fixture . detectChanges ( ) ;
748+
749+ buttonElement = fixture . debugElement . query ( By . css ( 'button' ) ) ! . nativeElement ;
750+ patchElementFocus ( buttonElement ) ;
751+ } ) ;
752+
753+ it ( 'should initially not be focused' , ( ) => {
754+ expect ( fixture . componentInstance . exportedDirRef . focusOrigin )
755+ . withContext ( 'initial focus origin should be null' )
756+ . toBeNull ( ) ;
757+ } ) ;
758+
759+ it ( 'should detect focus via keyboard' , fakeAsync ( ( ) => {
760+ // Simulate focus via keyboard.
761+ dispatchKeyboardEvent ( document , 'keydown' , TAB ) ;
762+ buttonElement . focus ( ) ;
763+ fixture . detectChanges ( ) ;
764+ flush ( ) ;
765+
766+ expect ( fixture . componentInstance . exportedDirRef . focusOrigin ) . toEqual ( 'keyboard' ) ;
767+ } ) ) ;
768+
769+ it ( 'should detect focus via mouse' , fakeAsync ( ( ) => {
770+ // Simulate focus via mouse.
771+ dispatchMouseEvent ( buttonElement , 'mousedown' ) ;
772+ buttonElement . focus ( ) ;
773+ fixture . detectChanges ( ) ;
774+ flush ( ) ;
775+
776+ expect ( fixture . componentInstance . exportedDirRef . focusOrigin ) . toEqual ( 'mouse' ) ;
777+ } ) ) ;
778+
779+ it ( 'should detect focus via touch' , fakeAsync ( ( ) => {
780+ // Simulate focus via touch.
781+ dispatchFakeEvent ( buttonElement , 'touchstart' ) ;
782+ buttonElement . focus ( ) ;
783+ fixture . detectChanges ( ) ;
784+ tick ( TOUCH_BUFFER_MS ) ;
785+
786+ expect ( fixture . componentInstance . exportedDirRef . focusOrigin ) . toEqual ( 'touch' ) ;
787+ } ) ) ;
788+
789+ it ( 'should detect programmatic focus' , fakeAsync ( ( ) => {
790+ // Programmatically focus.
791+ buttonElement . focus ( ) ;
792+ fixture . detectChanges ( ) ;
793+ tick ( ) ;
794+
795+ expect ( fixture . componentInstance . exportedDirRef . focusOrigin ) . toEqual ( 'program' ) ;
796+ } ) ) ;
797+
798+ it ( 'should remove focus classes on blur' , fakeAsync ( ( ) => {
799+ buttonElement . focus ( ) ;
800+ fixture . detectChanges ( ) ;
801+ tick ( ) ;
802+
803+ expect ( fixture . componentInstance . exportedDirRef . focusOrigin ) . toEqual ( 'program' ) ;
804+
805+ buttonElement . blur ( ) ;
806+ fixture . detectChanges ( ) ;
807+
808+ expect ( fixture . componentInstance . exportedDirRef . focusOrigin ) . toEqual ( null ) ;
809+ } ) ) ;
810+ } ) ;
811+
740812 it ( 'should not throw when trying to monitor focus on a non-element node' , ( ) => {
741813 expect ( ( ) => {
742814 const fixture = TestBed . createComponent ( FocusMonitorOnCommentNode ) ;
@@ -862,3 +934,10 @@ class FocusMonitorOnCommentNode {}
862934 ` ,
863935} )
864936class CheckboxWithLabel { }
937+
938+ @Component ( {
939+ template : `<button cdkMonitorElementFocus #exportedDir="cdkMonitorFocus"></button>` ,
940+ } )
941+ class ExportedFocusMonitor {
942+ @ViewChild ( 'exportedDir' ) exportedDirRef : CdkMonitorFocus ;
943+ }
0 commit comments