11import { QueryList } from '@angular/core' ;
2- import { FocusKeyManager } from './focus-key-manager' ;
2+ import { fakeAsync , tick } from '@angular/core/testing' ;
3+ import { FocusKeyManager , FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL } from './focus-key-manager' ;
34import { DOWN_ARROW , UP_ARROW , TAB , HOME , END } from '../keyboard/keycodes' ;
45import { ListKeyManager } from './list-key-manager' ;
56import { ActiveDescendantKeyManager } from './activedescendant-key-manager' ;
67
78class FakeFocusable {
89 disabled = false ;
910 focus ( ) { }
11+
12+ getFocusableLabel ( ) {
13+ return this . _label ;
14+ }
15+
16+ constructor ( private _label ?: string ) { }
1017}
1118
1219class FakeHighlightable {
@@ -21,6 +28,7 @@ class FakeQueryList<T> extends QueryList<T> {
2128 toArray ( ) {
2229 return this . items ;
2330 }
31+ get first ( ) { return this . items [ 0 ] ; }
2432}
2533
2634export class FakeEvent {
@@ -394,9 +402,9 @@ describe('Key managers', () => {
394402
395403 beforeEach ( ( ) => {
396404 itemList . items = [
397- new FakeFocusable ( ) ,
398- new FakeFocusable ( ) ,
399- new FakeFocusable ( )
405+ new FakeFocusable ( 'one' ) ,
406+ new FakeFocusable ( 'two' ) ,
407+ new FakeFocusable ( 'three' )
400408 ] ;
401409
402410 keyManager = new FocusKeyManager ( itemList ) ;
@@ -409,40 +417,81 @@ describe('Key managers', () => {
409417 spyOn ( itemList . items [ 2 ] , 'focus' ) ;
410418 } ) ;
411419
412- it ( 'should focus subsequent items when down arrow is pressed' , ( ) => {
413- keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
420+ it ( 'should focus subsequent items when down arrow is pressed' , ( ) => {
421+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
414422
415- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
416- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
417- expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
423+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
424+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
425+ expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
418426
419- keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
420- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
421- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
422- expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
423- } ) ;
427+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
428+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
429+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
430+ expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
431+ } ) ;
424432
425- it ( 'should focus previous items when up arrow is pressed' , ( ) => {
426- keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
433+ it ( 'should focus previous items when up arrow is pressed' , ( ) => {
434+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
427435
428- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
429- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
436+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
437+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
430438
431- keyManager . onKeydown ( UP_ARROW_EVENT ) ;
439+ keyManager . onKeydown ( UP_ARROW_EVENT ) ;
432440
433- expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
434- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
435- } ) ;
441+ expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
442+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
443+ } ) ;
436444
437- it ( 'should allow setting the focused item without calling focus' , ( ) => {
438- expect ( keyManager . activeItemIndex )
439- . toBe ( 0 , `Expected first item of the list to be active.` ) ;
445+ it ( 'should allow setting the focused item without calling focus' , ( ) => {
446+ expect ( keyManager . activeItemIndex )
447+ . toBe ( 0 , `Expected first item of the list to be active.` ) ;
440448
441- keyManager . updateActiveItemIndex ( 1 ) ;
442- expect ( keyManager . activeItemIndex )
443- . toBe ( 1 , `Expected activeItemIndex to update after calling updateActiveItemIndex().` ) ;
444- expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalledTimes ( 1 ) ;
445- } ) ;
449+ keyManager . updateActiveItemIndex ( 1 ) ;
450+ expect ( keyManager . activeItemIndex )
451+ . toBe ( 1 , `Expected activeItemIndex to update after calling updateActiveItemIndex().` ) ;
452+ expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalledTimes ( 1 ) ;
453+ } ) ;
454+
455+ it ( 'should debounce the input key presses' , fakeAsync ( ( ) => {
456+ keyManager . onKeydown ( new FakeEvent ( 79 ) as KeyboardEvent ) ; // types "o"
457+ keyManager . onKeydown ( new FakeEvent ( 78 ) as KeyboardEvent ) ; // types "n"
458+ keyManager . onKeydown ( new FakeEvent ( 69 ) as KeyboardEvent ) ; // types "e"
459+
460+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
461+
462+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
463+
464+ expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalled ( ) ;
465+ } ) ) ;
466+
467+ it ( 'should focus the first item that starts with a letter' , fakeAsync ( ( ) => {
468+ keyManager . onKeydown ( new FakeEvent ( 84 ) as KeyboardEvent ) ; // types "t"
469+
470+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
471+
472+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalled ( ) ;
473+ } ) ) ;
474+
475+ it ( 'should focus the first item that starts with sequence of letters' , fakeAsync ( ( ) => {
476+ keyManager . onKeydown ( new FakeEvent ( 84 ) as KeyboardEvent ) ; // types "t"
477+ keyManager . onKeydown ( new FakeEvent ( 72 ) as KeyboardEvent ) ; // types "h"
478+
479+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
480+
481+ expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalled ( ) ;
482+ expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalled ( ) ;
483+ } ) ) ;
484+
485+ it ( 'should cancel any pending timers if a non-input key is pressed' , fakeAsync ( ( ) => {
486+ keyManager . onKeydown ( new FakeEvent ( 84 ) as KeyboardEvent ) ; // types "t"
487+ keyManager . onKeydown ( new FakeEvent ( 72 ) as KeyboardEvent ) ; // types "h"
488+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
489+
490+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
491+
492+ expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
493+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalled ( ) ;
494+ } ) ) ;
446495
447496 } ) ;
448497
0 commit comments