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 {
@@ -356,9 +364,9 @@ describe('Key managers', () => {
356364
357365 beforeEach ( ( ) => {
358366 itemList . items = [
359- new FakeFocusable ( ) ,
360- new FakeFocusable ( ) ,
361- new FakeFocusable ( )
367+ new FakeFocusable ( 'one' ) ,
368+ new FakeFocusable ( 'two' ) ,
369+ new FakeFocusable ( 'three' )
362370 ] ;
363371
364372 keyManager = new FocusKeyManager ( itemList ) ;
@@ -371,40 +379,81 @@ describe('Key managers', () => {
371379 spyOn ( itemList . items [ 2 ] , 'focus' ) ;
372380 } ) ;
373381
374- it ( 'should focus subsequent items when down arrow is pressed' , ( ) => {
375- keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
382+ it ( 'should focus subsequent items when down arrow is pressed' , ( ) => {
383+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
376384
377- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
378- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
379- expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
385+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
386+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
387+ expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
380388
381- keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
382- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
383- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
384- expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
385- } ) ;
389+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
390+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
391+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
392+ expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
393+ } ) ;
386394
387- it ( 'should focus previous items when up arrow is pressed' , ( ) => {
388- keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
395+ it ( 'should focus previous items when up arrow is pressed' , ( ) => {
396+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
389397
390- expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
391- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
398+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
399+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
392400
393- keyManager . onKeydown ( UP_ARROW_EVENT ) ;
401+ keyManager . onKeydown ( UP_ARROW_EVENT ) ;
394402
395- expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
396- expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
397- } ) ;
403+ expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
404+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
405+ } ) ;
398406
399- it ( 'should allow setting the focused item without calling focus' , ( ) => {
400- expect ( keyManager . activeItemIndex )
401- . toBe ( 0 , `Expected first item of the list to be active.` ) ;
407+ it ( 'should allow setting the focused item without calling focus' , ( ) => {
408+ expect ( keyManager . activeItemIndex )
409+ . toBe ( 0 , `Expected first item of the list to be active.` ) ;
402410
403- keyManager . updateActiveItemIndex ( 1 ) ;
404- expect ( keyManager . activeItemIndex )
405- . toBe ( 1 , `Expected activeItemIndex to update after calling updateActiveItemIndex().` ) ;
406- expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalledTimes ( 1 ) ;
407- } ) ;
411+ keyManager . updateActiveItemIndex ( 1 ) ;
412+ expect ( keyManager . activeItemIndex )
413+ . toBe ( 1 , `Expected activeItemIndex to update after calling updateActiveItemIndex().` ) ;
414+ expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalledTimes ( 1 ) ;
415+ } ) ;
416+
417+ it ( 'should debounce the input key presses' , fakeAsync ( ( ) => {
418+ keyManager . onKeydown ( new FakeEvent ( 79 ) as KeyboardEvent ) ; // types "o"
419+ keyManager . onKeydown ( new FakeEvent ( 78 ) as KeyboardEvent ) ; // types "n"
420+ keyManager . onKeydown ( new FakeEvent ( 69 ) as KeyboardEvent ) ; // types "e"
421+
422+ expect ( itemList . items [ 0 ] . focus ) . not . toHaveBeenCalled ( ) ;
423+
424+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
425+
426+ expect ( itemList . items [ 0 ] . focus ) . toHaveBeenCalled ( ) ;
427+ } ) ) ;
428+
429+ it ( 'should focus the first item that starts with a letter' , fakeAsync ( ( ) => {
430+ keyManager . onKeydown ( new FakeEvent ( 84 ) as KeyboardEvent ) ; // types "t"
431+
432+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
433+
434+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalled ( ) ;
435+ } ) ) ;
436+
437+ it ( 'should focus the first item that starts with sequence of letters' , fakeAsync ( ( ) => {
438+ keyManager . onKeydown ( new FakeEvent ( 84 ) as KeyboardEvent ) ; // types "t"
439+ keyManager . onKeydown ( new FakeEvent ( 72 ) as KeyboardEvent ) ; // types "h"
440+
441+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
442+
443+ expect ( itemList . items [ 1 ] . focus ) . not . toHaveBeenCalled ( ) ;
444+ expect ( itemList . items [ 2 ] . focus ) . toHaveBeenCalled ( ) ;
445+ } ) ) ;
446+
447+ it ( 'should cancel any pending timers if a non-input key is pressed' , fakeAsync ( ( ) => {
448+ keyManager . onKeydown ( new FakeEvent ( 84 ) as KeyboardEvent ) ; // types "t"
449+ keyManager . onKeydown ( new FakeEvent ( 72 ) as KeyboardEvent ) ; // types "h"
450+ keyManager . onKeydown ( DOWN_ARROW_EVENT ) ;
451+
452+ tick ( FOCUS_KEY_MANAGER_DEBOUNCE_INTERVAL ) ;
453+
454+ expect ( itemList . items [ 2 ] . focus ) . not . toHaveBeenCalled ( ) ;
455+ expect ( itemList . items [ 1 ] . focus ) . toHaveBeenCalled ( ) ;
456+ } ) ) ;
408457
409458 } ) ;
410459
0 commit comments