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 , HOME , END } from '../keyboard/keycodes' ;
55import { ListKeyManager } from './list-key-manager' ;
66import { ActiveDescendantKeyManager } from './activedescendant-key-manager' ;
77
88class FakeFocusable {
99 disabled = false ;
1010 focus ( ) { }
11+
12+ getFocusableLabel ( ) {
13+ return this . _label ;
14+ }
15+
16+ constructor ( private _label ?: string ) { }
1117}
1218
1319class FakeHighlightable {
@@ -22,6 +28,7 @@ class FakeQueryList<T> extends QueryList<T> {
2228 toArray ( ) {
2329 return this . items ;
2430 }
31+ get first ( ) { return this . items [ 0 ] ; }
2532}
2633
2734export class FakeEvent {
@@ -405,9 +412,9 @@ describe('Key managers', () => {
405412
406413 beforeEach ( ( ) => {
407414 itemList . items = [
408- new FakeFocusable ( ) ,
409- new FakeFocusable ( ) ,
410- new FakeFocusable ( )
415+ new FakeFocusable ( 'one' ) ,
416+ new FakeFocusable ( 'two' ) ,
417+ new FakeFocusable ( 'three' )
411418 ] ;
412419
413420 keyManager = new FocusKeyManager ( itemList ) ;
@@ -420,40 +427,81 @@ describe('Key managers', () => {
420427 spyOn ( itemList . items [ 2 ] , 'focus' ) ;
421428 } ) ;
422429
423- it ( 'should focus subsequent items when down arrow is pressed' , ( ) => {
424- keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
430+ it ( 'should focus subsequent items when down arrow is pressed' , ( ) => {
431+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
425432
426- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
427- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
428- expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
433+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
434+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
435+ expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
429436
430- keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
431- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
432- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
433- expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
434- } ) ;
437+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
438+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
439+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
440+ expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
441+ } ) ;
435442
436- it ( 'should focus previous items when up arrow is pressed' , ( ) => {
437- keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
443+ it ( 'should focus previous items when up arrow is pressed' , ( ) => {
444+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
438445
439- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
440- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
446+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
447+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
441448
442- keyManager . onKeydown ( UP_ARROW_EVENT ) ;
449+ keyManager . onKeydown ( UP_ARROW_EVENT ) ;
443450
444- expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
445- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
446- } ) ;
451+ expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
452+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
453+ } ) ;
447454
448- it ( 'should allow setting the focused item without calling focus' , ( ) => {
449- expect ( keyManager . activeItemIndex )
450- . toBe ( 0 , `Expected first item of the list to be active.` ) ;
455+ it ( 'should allow setting the focused item without calling focus' , ( ) => {
456+ expect ( keyManager . activeItemIndex )
457+ . toBe ( 0 , `Expected first item of the list to be active.` ) ;
451458
452- keyManager . updateActiveItemIndex ( 1 ) ;
453- expect ( keyManager . activeItemIndex )
454- . toBe ( 1 , `Expected activeItemIndex to update after calling updateActiveItemIndex().` ) ;
455- expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalledTimes ( 1 ) ;
456- } ) ;
459+ keyManager . updateActiveItemIndex ( 1 ) ;
460+ expect ( keyManager . activeItemIndex )
461+ . toBe ( 1 , `Expected activeItemIndex to update after calling updateActiveItemIndex().` ) ;
462+ expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalledTimes ( 1 ) ;
463+ } ) ;
464+
465+ it ( 'should debounce the input key presses' , fakeAsync ( ( ) => {
466+ keyManager . onKeydown ( new FakeEvent ( 79 ) as KeyboardEvent ) ; // types "o"
467+ keyManager . onKeydown ( new FakeEvent ( 78 ) as KeyboardEvent ) ; // types "n"
468+ keyManager . onKeydown ( new FakeEvent ( 69 ) as KeyboardEvent ) ; // types "e"
469+
470+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
471+
472+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
473+
474+ expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalled ( ) ;
475+ } ) ) ;
476+
477+ it ( 'should focus the first item that starts with a letter' , fakeAsync ( ( ) => {
478+ keyManager . onKeydown ( new FakeEvent ( 84 ) as KeyboardEvent ) ; // types "t"
479+
480+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
481+
482+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalled ( ) ;
483+ } ) ) ;
484+
485+ it ( 'should focus the first item that starts with sequence of letters' , fakeAsync ( ( ) => {
486+ keyManager . onKeydown ( new FakeEvent ( 84 ) as KeyboardEvent ) ; // types "t"
487+ keyManager . onKeydown ( new FakeEvent ( 72 ) as KeyboardEvent ) ; // types "h"
488+
489+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
490+
491+ expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalled ( ) ;
492+ expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalled ( ) ;
493+ } ) ) ;
494+
495+ it ( 'should cancel any pending timers if a non-input key is pressed' , fakeAsync ( ( ) => {
496+ keyManager . onKeydown ( new FakeEvent ( 84 ) as KeyboardEvent ) ; // types "t"
497+ keyManager . onKeydown ( new FakeEvent ( 72 ) as KeyboardEvent ) ; // types "h"
498+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
499+
500+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
501+
502+ expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
503+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalled ( ) ;
504+ } ) ) ;
457505
458506 } ) ;
459507
0 commit comments