1- import { Component , ViewChild } from '@angular/core' ;
1+ import { Component , ViewChild , ElementRef } from '@angular/core' ;
22import { async , fakeAsync , TestBed , tick , flush , ComponentFixture } from '@angular/core/testing' ;
33import { FormsModule , FormGroup , FormBuilder , FormControl , ReactiveFormsModule } from '@angular/forms' ;
44import { By } from '@angular/platform-browser' ;
@@ -31,7 +31,8 @@ describe('IgxDatePicker', () => {
3131 IgxDatePickerCustomizedComponent ,
3232 IgxDropDownDatePickerRetemplatedComponent ,
3333 IgxDatePickerOpeningComponent ,
34- IgxDatePickerReactiveFormComponent
34+ IgxDatePickerReactiveFormComponent ,
35+ IgxDatePickerDropdownButtonsComponent
3536 ] ,
3637 imports : [ IgxDatePickerModule , FormsModule , ReactiveFormsModule , NoopAnimationsModule , IgxInputGroupModule , IgxCalendarModule ,
3738 IgxButtonModule , IgxTextSelectionModule ]
@@ -181,7 +182,7 @@ describe('IgxDatePicker', () => {
181182 expect ( overlays . length ) . toEqual ( 0 ) ;
182183 } ) ) ;
183184
184- it ( 'When datepicker is closed and the dialog disappear, the focus should remain on the input' ,
185+ it ( 'When modal datepicker is closed via `Escape` Key and the dialog disappear, the focus should remain on the input' ,
185186 fakeAsync ( ( ) => {
186187 const datePickerDom = fixture . debugElement . query ( By . css ( 'igx-date-picker' ) ) ;
187188 let overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper--modal' ) ;
@@ -205,6 +206,56 @@ describe('IgxDatePicker', () => {
205206 expect ( input ) . toEqual ( document . activeElement ) ;
206207 } ) ) ;
207208
209+ it ( 'When a modal datepicker is closed via outside click, the focus should remain on the input' ,
210+ fakeAsync ( ( ) => {
211+ const datePickerDom = fixture . debugElement . query ( By . css ( 'igx-date-picker' ) ) ;
212+ let overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper--modal' ) ;
213+ expect ( overlayToggle . length ) . toEqual ( 0 ) ;
214+
215+ UIInteractions . triggerKeyDownEvtUponElem ( 'space' , datePickerDom . nativeElement , false ) ;
216+ flush ( ) ;
217+ fixture . detectChanges ( ) ;
218+
219+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper--modal' ) ;
220+ expect ( overlayToggle [ 0 ] ) . not . toBeNull ( ) ;
221+ expect ( overlayToggle [ 0 ] ) . not . toBeUndefined ( ) ;
222+
223+ UIInteractions . clickElement ( overlayToggle [ 0 ] ) ;
224+ flush ( ) ;
225+ fixture . detectChanges ( ) ;
226+
227+ const input = fixture . debugElement . query ( By . directive ( IgxInputDirective ) ) . nativeElement ;
228+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper--modal' ) ;
229+ expect ( overlayToggle [ 0 ] ) . toEqual ( undefined ) ;
230+ expect ( input ) . toEqual ( document . activeElement ) ;
231+ } ) ) ;
232+
233+ it ( 'When datepicker is closed upon selecting a date, the focus should remain on the input' ,
234+ fakeAsync ( ( ) => {
235+ const datePickerDom = fixture . debugElement . query ( By . css ( 'igx-date-picker' ) ) ;
236+ let overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper--modal' ) ;
237+ expect ( overlayToggle . length ) . toEqual ( 0 ) ;
238+
239+ UIInteractions . triggerKeyDownEvtUponElem ( 'space' , datePickerDom . nativeElement , false ) ;
240+ flush ( ) ;
241+ fixture . detectChanges ( ) ;
242+
243+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper--modal' ) ;
244+ expect ( overlayToggle [ 0 ] ) . not . toBeNull ( ) ;
245+ expect ( overlayToggle [ 0 ] ) . not . toBeUndefined ( ) ;
246+
247+ // select a date
248+ const dateElemToSelect = document . getElementsByClassName ( 'igx-calendar__date' ) [ 10 ] ;
249+ UIInteractions . clickElement ( dateElemToSelect ) ;
250+ flush ( ) ;
251+ fixture . detectChanges ( ) ;
252+
253+ const input = fixture . debugElement . query ( By . directive ( IgxInputDirective ) ) . nativeElement ;
254+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper--modal' ) ;
255+ expect ( overlayToggle [ 0 ] ) . toEqual ( undefined ) ;
256+ expect ( input ) . toEqual ( document . activeElement ) ;
257+ } ) ) ;
258+
208259 } ) ;
209260
210261 describe ( 'DatePicker with passed date' , ( ) => {
@@ -249,6 +300,99 @@ describe('IgxDatePicker', () => {
249300 } ) ;
250301 } ) ;
251302
303+ it ( 'When datepicker in "dropdown" mode is closed via outside click, the input should not receive focus' ,
304+ fakeAsync ( ( ) => {
305+ const fixture = TestBed . createComponent ( IgxDatePickerDropdownButtonsComponent ) ;
306+ fixture . detectChanges ( ) ;
307+
308+ const datePickerDom = fixture . debugElement . query ( By . css ( 'igx-date-picker' ) ) ;
309+ const input = fixture . debugElement . query ( By . directive ( IgxInputDirective ) ) . nativeElement ;
310+ let overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper' ) ;
311+
312+ expect ( overlayToggle . length ) . toEqual ( 0 ) ;
313+
314+ UIInteractions . triggerKeyDownEvtUponElem ( 'space' , datePickerDom . nativeElement , false ) ;
315+ flush ( ) ;
316+ fixture . detectChanges ( ) ;
317+
318+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper' ) ;
319+ expect ( overlayToggle [ 0 ] ) . not . toBeNull ( ) ;
320+ expect ( overlayToggle [ 0 ] ) . not . toBeUndefined ( ) ;
321+
322+ const dummyInput = fixture . componentInstance . dummyInput . nativeElement ;
323+ dummyInput . focus ( ) ;
324+ dummyInput . click ( ) ;
325+ tick ( ) ;
326+ fixture . detectChanges ( ) ;
327+
328+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper' ) ;
329+ expect ( overlayToggle [ 0 ] ) . toEqual ( undefined ) ;
330+ expect ( input ) . not . toEqual ( document . activeElement ) ;
331+ expect ( dummyInput ) . toEqual ( document . activeElement ) ;
332+ } ) ) ;
333+
334+ it ( 'When datepicker in "dropdown" mode, should focus input on user interaction with Today btn, Cancel btn, Enter Key, Escape key' ,
335+ fakeAsync ( ( ) => {
336+ const fixture = TestBed . createComponent ( IgxDatePickerDropdownButtonsComponent ) ;
337+ fixture . detectChanges ( ) ;
338+ const datePickerDom = fixture . debugElement . query ( By . css ( 'igx-date-picker' ) ) ;
339+ const input = fixture . debugElement . query ( By . directive ( IgxInputDirective ) ) . nativeElement ;
340+ let overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper' ) ;
341+ expect ( overlayToggle . length ) . toEqual ( 0 ) ;
342+
343+ UIInteractions . triggerKeyDownEvtUponElem ( 'space' , datePickerDom . nativeElement , false ) ;
344+ flush ( ) ;
345+ fixture . detectChanges ( ) ;
346+ const buttons = document . getElementsByClassName ( 'igx-button--flat' ) ;
347+ expect ( buttons . length ) . toEqual ( 2 ) ;
348+
349+ // Today btn
350+ const todayBtn = buttons [ 1 ] as HTMLElement ;
351+ expect ( todayBtn . innerText ) . toBe ( 'Today' ) ;
352+ todayBtn . click ( ) ;
353+ tick ( ) ;
354+ fixture . detectChanges ( ) ;
355+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper' ) ;
356+ expect ( overlayToggle [ 0 ] ) . toEqual ( undefined ) ;
357+ expect ( input ) . toEqual ( document . activeElement ) ;
358+
359+ // Cancel btn
360+ UIInteractions . triggerKeyDownEvtUponElem ( 'space' , datePickerDom . nativeElement , false ) ;
361+ flush ( ) ;
362+ fixture . detectChanges ( ) ;
363+ const cancelBtn = buttons [ 0 ] as HTMLElement ;
364+ expect ( cancelBtn . innerText ) . toBe ( 'Cancel' ) ;
365+ cancelBtn . click ( ) ;
366+ tick ( ) ;
367+ fixture . detectChanges ( ) ;
368+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper' ) ;
369+ expect ( overlayToggle [ 0 ] ) . toEqual ( undefined ) ;
370+ expect ( input ) . toEqual ( document . activeElement ) ;
371+
372+ // Enter key
373+ UIInteractions . triggerKeyDownEvtUponElem ( 'space' , datePickerDom . nativeElement , false ) ;
374+ flush ( ) ;
375+ fixture . detectChanges ( ) ;
376+ document . activeElement . dispatchEvent ( new KeyboardEvent ( 'keydown' , { key : 'Enter' , bubbles : true } ) ) ;
377+ tick ( ) ;
378+ fixture . detectChanges ( ) ;
379+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper' ) ;
380+ expect ( overlayToggle [ 0 ] ) . toEqual ( undefined ) ;
381+ expect ( input ) . toEqual ( document . activeElement ) ;
382+
383+ // Esc key
384+ UIInteractions . triggerKeyDownEvtUponElem ( 'space' , datePickerDom . nativeElement , false ) ;
385+ flush ( ) ;
386+ fixture . detectChanges ( ) ;
387+ document . activeElement . dispatchEvent ( new KeyboardEvent ( 'keydown' , { key : 'Enter' , bubbles : true } ) ) ;
388+ tick ( ) ;
389+ fixture . detectChanges ( ) ;
390+
391+ overlayToggle = document . getElementsByClassName ( 'igx-overlay__wrapper' ) ;
392+ expect ( overlayToggle [ 0 ] ) . toEqual ( undefined ) ;
393+ expect ( input ) . toEqual ( document . activeElement ) ;
394+ } ) ) ;
395+
252396 it ( 'Datepicker week start day (Monday)' , ( ) => {
253397 const fixture = TestBed . createComponent ( IgxDatePickerWithWeekStartComponent ) ;
254398 fixture . detectChanges ( ) ;
@@ -1318,3 +1462,17 @@ class IgxDatePickerReactiveFormComponent {
13181462 }
13191463 onSubmitReactive ( ) { }
13201464}
1465+
1466+ @Component ( {
1467+ template : `
1468+ <input class="dummyInput" #dummyInput/>
1469+ <igx-date-picker id="dropdownButtonsDatePicker" mode="dropdown" cancelButtonLabel="Cancel" todayButtonLabel="Today" >
1470+ </igx-date-picker>
1471+ `
1472+ } )
1473+ class IgxDatePickerDropdownButtonsComponent {
1474+ @ViewChild ( 'dropdownButtonsDatePicker' , { read : IgxDatePickerComponent , static : true } )
1475+ public datePicker : IgxDatePickerComponent ;
1476+
1477+ @ViewChild ( 'dummyInput' , { static : true } ) public dummyInput : ElementRef ;
1478+ }
0 commit comments