11import { Directionality } from '@angular/cdk/bidi' ;
2- import { DOWN_ARROW , END , ENTER , HOME , SPACE , TAB , UP_ARROW } from '@angular/cdk/keycodes' ;
2+ import {
3+ DOWN_ARROW ,
4+ END ,
5+ ENTER ,
6+ HOME ,
7+ SPACE ,
8+ TAB ,
9+ UP_ARROW ,
10+ LEFT_ARROW ,
11+ RIGHT_ARROW ,
12+ } from '@angular/cdk/keycodes' ;
313import { OverlayContainer } from '@angular/cdk/overlay' ;
414import { Platform } from '@angular/cdk/platform' ;
515import { ScrollDispatcher , ViewportRuler } from '@angular/cdk/scrolling' ;
@@ -219,7 +229,7 @@ describe('MatSelect', () => {
219229 expect ( select . getAttribute ( 'tabindex' ) ) . toEqual ( '0' ) ;
220230 } ) ) ;
221231
222- it ( 'should select options via the arrow keys on a closed select' , fakeAsync ( ( ) => {
232+ it ( 'should select options via the UP/DOWN arrow keys on a closed select' , fakeAsync ( ( ) => {
223233 const formControl = fixture . componentInstance . control ;
224234 const options = fixture . componentInstance . options . toArray ( ) ;
225235
@@ -246,6 +256,33 @@ describe('MatSelect', () => {
246256 'Expected value from second option to have been set on the model.' ) ;
247257 } ) ) ;
248258
259+ it ( 'should select options via LEFT/RIGHT arrow keys on a closed select' , fakeAsync ( ( ) => {
260+ const formControl = fixture . componentInstance . control ;
261+ const options = fixture . componentInstance . options . toArray ( ) ;
262+
263+ expect ( formControl . value ) . toBeFalsy ( 'Expected no initial value.' ) ;
264+
265+ dispatchKeyboardEvent ( select , 'keydown' , RIGHT_ARROW ) ;
266+
267+ expect ( options [ 0 ] . selected ) . toBe ( true , 'Expected first option to be selected.' ) ;
268+ expect ( formControl . value ) . toBe ( options [ 0 ] . value ,
269+ 'Expected value from first option to have been set on the model.' ) ;
270+
271+ dispatchKeyboardEvent ( select , 'keydown' , RIGHT_ARROW ) ;
272+ dispatchKeyboardEvent ( select , 'keydown' , RIGHT_ARROW ) ;
273+
274+ // Note that the third option is skipped, because it is disabled.
275+ expect ( options [ 3 ] . selected ) . toBe ( true , 'Expected fourth option to be selected.' ) ;
276+ expect ( formControl . value ) . toBe ( options [ 3 ] . value ,
277+ 'Expected value from fourth option to have been set on the model.' ) ;
278+
279+ dispatchKeyboardEvent ( select , 'keydown' , LEFT_ARROW ) ;
280+
281+ expect ( options [ 1 ] . selected ) . toBe ( true , 'Expected second option to be selected.' ) ;
282+ expect ( formControl . value ) . toBe ( options [ 1 ] . value ,
283+ 'Expected value from second option to have been set on the model.' ) ;
284+ } ) ) ;
285+
249286 it ( 'should open a single-selection select using ALT + DOWN_ARROW' , fakeAsync ( ( ) => {
250287 const { control : formControl , select : selectInstance } = fixture . componentInstance ;
251288
@@ -331,26 +368,47 @@ describe('MatSelect', () => {
331368 'Expected value from sixth option to have been set on the model.' ) ;
332369 } ) ) ;
333370
334- it ( 'should open the panel when pressing the arrow keys on a closed multiple select' ,
335- fakeAsync ( ( ) => {
336- fixture . destroy ( ) ;
371+ it ( 'should open the panel when pressing a vertical arrow key on a closed multiple select' ,
372+ fakeAsync ( ( ) => {
373+ fixture . destroy ( ) ;
337374
338- const multiFixture = TestBed . createComponent ( MultiSelect ) ;
339- const instance = multiFixture . componentInstance ;
375+ const multiFixture = TestBed . createComponent ( MultiSelect ) ;
376+ const instance = multiFixture . componentInstance ;
340377
341- multiFixture . detectChanges ( ) ;
342- select = multiFixture . debugElement . query ( By . css ( 'mat-select' ) ) . nativeElement ;
378+ multiFixture . detectChanges ( ) ;
379+ select = multiFixture . debugElement . query ( By . css ( 'mat-select' ) ) . nativeElement ;
343380
344- const initialValue = instance . control . value ;
381+ const initialValue = instance . control . value ;
345382
346- expect ( instance . select . panelOpen ) . toBe ( false , 'Expected panel to be closed.' ) ;
383+ expect ( instance . select . panelOpen ) . toBe ( false , 'Expected panel to be closed.' ) ;
347384
348- const event = dispatchKeyboardEvent ( select , 'keydown' , DOWN_ARROW ) ;
385+ const event = dispatchKeyboardEvent ( select , 'keydown' , DOWN_ARROW ) ;
349386
350- expect ( instance . select . panelOpen ) . toBe ( true , 'Expected panel to be open.' ) ;
351- expect ( instance . control . value ) . toBe ( initialValue , 'Expected value to stay the same.' ) ;
352- expect ( event . defaultPrevented ) . toBe ( true , 'Expected default to be prevented.' ) ;
353- } ) ) ;
387+ expect ( instance . select . panelOpen ) . toBe ( true , 'Expected panel to be open.' ) ;
388+ expect ( instance . control . value ) . toBe ( initialValue , 'Expected value to stay the same.' ) ;
389+ expect ( event . defaultPrevented ) . toBe ( true , 'Expected default to be prevented.' ) ;
390+ } ) ) ;
391+
392+ it ( 'should open the panel when pressing a horizontal arrow key on closed multiple select' ,
393+ fakeAsync ( ( ) => {
394+ fixture . destroy ( ) ;
395+
396+ const multiFixture = TestBed . createComponent ( MultiSelect ) ;
397+ const instance = multiFixture . componentInstance ;
398+
399+ multiFixture . detectChanges ( ) ;
400+ select = multiFixture . debugElement . query ( By . css ( 'mat-select' ) ) . nativeElement ;
401+
402+ const initialValue = instance . control . value ;
403+
404+ expect ( instance . select . panelOpen ) . toBe ( false , 'Expected panel to be closed.' ) ;
405+
406+ const event = dispatchKeyboardEvent ( select , 'keydown' , RIGHT_ARROW ) ;
407+
408+ expect ( instance . select . panelOpen ) . toBe ( true , 'Expected panel to be open.' ) ;
409+ expect ( instance . control . value ) . toBe ( initialValue , 'Expected value to stay the same.' ) ;
410+ expect ( event . defaultPrevented ) . toBe ( true , 'Expected default to be prevented.' ) ;
411+ } ) ) ;
354412
355413 it ( 'should do nothing when typing on a closed multi-select' , fakeAsync ( ( ) => {
356414 fixture . destroy ( ) ;
@@ -623,6 +681,26 @@ describe('MatSelect', () => {
623681 expect ( host . getAttribute ( 'aria-activedescendant' ) ) . toBe ( options [ 3 ] . id ) ;
624682 } ) ) ;
625683
684+ it ( 'should not change the aria-activedescendant using the horizontal arrow keys' ,
685+ fakeAsync ( ( ) => {
686+ const host = fixture . debugElement . query ( By . css ( 'mat-select' ) ) . nativeElement ;
687+
688+ fixture . componentInstance . select . open ( ) ;
689+ fixture . detectChanges ( ) ;
690+ flush ( ) ;
691+
692+ const options = overlayContainerElement . querySelectorAll ( 'mat-option' ) ;
693+
694+ expect ( host . getAttribute ( 'aria-activedescendant' ) ) . toBe ( options [ 0 ] . id ) ;
695+
696+ [ 1 , 2 , 3 ] . forEach ( ( ) => {
697+ dispatchKeyboardEvent ( host , 'keydown' , RIGHT_ARROW ) ;
698+ fixture . detectChanges ( ) ;
699+ } ) ;
700+
701+ expect ( host . getAttribute ( 'aria-activedescendant' ) ) . toBe ( options [ 0 ] . id ) ;
702+ } ) ) ;
703+
626704 } ) ;
627705
628706 describe ( 'for options' , ( ) => {
0 commit comments