11import { QueryList } from '@angular/core' ;
22import { fakeAsync , tick } from '@angular/core/testing' ;
3- import { FocusKeyManager } from './focus-key-manager' ;
3+ import { FocusKeyManager , FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL } from './focus-key-manager' ;
44import { DOWN_ARROW , UP_ARROW , TAB } from '../keyboard/keycodes' ;
55import { ListKeyManager } from './list-key-manager' ;
66import { ActiveDescendantKeyManager } from './activedescendant-key-manager' ;
@@ -11,6 +11,12 @@ import {first} from '../rxjs/index';
1111class FakeFocusable {
1212 disabled = false ;
1313 focus ( ) { }
14+
15+ getFocusableLabel ( ) {
16+ return this . _label ;
17+ }
18+
19+ constructor ( private _label ?: string ) { }
1420}
1521
1622class FakeHighlightable {
@@ -25,6 +31,7 @@ class FakeQueryList<T> extends QueryList<T> {
2531 toArray ( ) {
2632 return this . items ;
2733 }
34+ get first ( ) { return this . items [ 0 ] ; }
2835}
2936
3037
@@ -389,7 +396,12 @@ describe('Key managers', () => {
389396 let keyManager : FocusKeyManager ;
390397
391398 beforeEach ( ( ) => {
392- itemList . items = [ new FakeFocusable ( ) , new FakeFocusable ( ) , new FakeFocusable ( ) ] ;
399+ itemList . items = [
400+ new FakeFocusable ( 'one' ) ,
401+ new FakeFocusable ( 'two' ) ,
402+ new FakeFocusable ( 'three' )
403+ ] ;
404+
393405 keyManager = new FocusKeyManager ( itemList ) ;
394406
395407 // first item is already focused
@@ -400,40 +412,81 @@ describe('Key managers', () => {
400412 spyOn ( itemList . items [ 2 ] , 'focus' ) ;
401413 } ) ;
402414
403- it ( 'should focus subsequent items when down arrow is pressed' , ( ) => {
404- keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
415+ it ( 'should focus subsequent items when down arrow is pressed' , ( ) => {
416+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
405417
406- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
407- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
408- expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
418+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
419+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
420+ expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
409421
410- keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
411- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
412- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
413- expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
414- } ) ;
422+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
423+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
424+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
425+ expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
426+ } ) ;
415427
416- it ( 'should focus previous items when up arrow is pressed' , ( ) => {
417- keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
428+ it ( 'should focus previous items when up arrow is pressed' , ( ) => {
429+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
418430
419- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
420- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
431+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
432+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
421433
422- keyManager . onKeydown ( fakeKeyEvents . upArrow ) ;
434+ keyManager . onKeydown ( fakeKeyEvents . upArrow ) ;
423435
424- expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
425- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
426- } ) ;
436+ expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
437+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
438+ } ) ;
427439
428- it ( 'should allow setting the focused item without calling focus' , ( ) => {
429- expect ( keyManager . activeItemIndex )
430- . toBe ( 0 , `Expected first item of the list to be active.` ) ;
440+ it ( 'should allow setting the focused item without calling focus' , ( ) => {
441+ expect ( keyManager . activeItemIndex )
442+ . toBe ( 0 , `Expected first item of the list to be active.` ) ;
431443
432- keyManager . updateActiveItemIndex ( 1 ) ;
433- expect ( keyManager . activeItemIndex )
434- . toBe ( 1 , `Expected activeItemIndex to update after calling updateActiveItemIndex().` ) ;
435- expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalledTimes ( 1 ) ;
436- } ) ;
444+ keyManager . updateActiveItemIndex ( 1 ) ;
445+ expect ( keyManager . activeItemIndex )
446+ . toBe ( 1 , `Expected activeItemIndex to update after calling updateActiveItemIndex().` ) ;
447+ expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalledTimes ( 1 ) ;
448+ } ) ;
449+
450+ it ( 'should debounce the input key presses' , fakeAsync ( ( ) => {
451+ keyManager . onKeydown ( createKeyboardEvent ( 'keydown' , 79 ) ) ; // types "o"
452+ keyManager . onKeydown ( createKeyboardEvent ( 'keydown' , 78 ) ) ; // types "n"
453+ keyManager . onKeydown ( createKeyboardEvent ( 'keydown' , 69 ) ) ; // types "e"
454+
455+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
456+
457+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
458+
459+ expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalled ( ) ;
460+ } ) ) ;
461+
462+ it ( 'should focus the first item that starts with a letter' , fakeAsync ( ( ) => {
463+ keyManager . onKeydown ( createKeyboardEvent ( 'keydown' , 84 ) ) ; // types "t"
464+
465+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
466+
467+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalled ( ) ;
468+ } ) ) ;
469+
470+ it ( 'should focus the first item that starts with sequence of letters' , fakeAsync ( ( ) => {
471+ keyManager . onKeydown ( createKeyboardEvent ( 'keydown' , 84 ) ) ; // types "t"
472+ keyManager . onKeydown ( createKeyboardEvent ( 'keydown' , 72 ) ) ; // types "h"
473+
474+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
475+
476+ expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalled ( ) ;
477+ expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalled ( ) ;
478+ } ) ) ;
479+
480+ it ( 'should cancel any pending timers if a non-input key is pressed' , fakeAsync ( ( ) => {
481+ keyManager . onKeydown ( createKeyboardEvent ( 'keydown' , 84 ) ) ; // types "t"
482+ keyManager . onKeydown ( createKeyboardEvent ( 'keydown' , 72 ) ) ; // types "h"
483+ keyManager . onKeydown ( fakeKeyEvents . downArrow ) ;
484+
485+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
486+
487+ expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
488+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalled ( ) ;
489+ } ) ) ;
437490
438491 } ) ;
439492
0 commit comments