8
8
dispatchMouseEvent ,
9
9
} from '@angular/cdk/testing' ;
10
10
import { Component , ViewChild } from '@angular/core' ;
11
- import { async , ComponentFixture , inject , TestBed } from '@angular/core/testing' ;
11
+ import { async , ComponentFixture , inject , TestBed , fakeAsync , flush } from '@angular/core/testing' ;
12
12
import { FormControl , FormsModule , ReactiveFormsModule } from '@angular/forms' ;
13
13
import {
14
14
DEC ,
@@ -63,6 +63,7 @@ describe('MatDatepicker', () => {
63
63
NoInputDatepicker ,
64
64
StandardDatepicker ,
65
65
DatepickerWithEvents ,
66
+ DatepickerOpeningOnFocus ,
66
67
] ,
67
68
} ) ;
68
69
@@ -248,7 +249,7 @@ describe('MatDatepicker', () => {
248
249
} ) ;
249
250
250
251
it ( 'clicking the currently selected date should close the calendar ' +
251
- 'without firing selectedChanged' , ( ) => {
252
+ 'without firing selectedChanged' , fakeAsync ( ( ) => {
252
253
const selectedChangedSpy =
253
254
spyOn ( testComponent . datepicker . selectedChanged , 'emit' ) . and . callThrough ( ) ;
254
255
@@ -263,12 +264,13 @@ describe('MatDatepicker', () => {
263
264
let cells = document . querySelectorAll ( '.mat-calendar-body-cell' ) ;
264
265
dispatchMouseEvent ( cells [ 1 ] , 'click' ) ;
265
266
fixture . detectChanges ( ) ;
267
+ flush ( ) ;
266
268
}
267
269
268
270
expect ( selectedChangedSpy . calls . count ( ) ) . toEqual ( 1 ) ;
269
271
expect ( document . querySelector ( 'mat-dialog-container' ) ) . toBeNull ( ) ;
270
272
expect ( testComponent . datepickerInput . value ) . toEqual ( new Date ( 2020 , JAN , 2 ) ) ;
271
- } ) ;
273
+ } ) ) ;
272
274
273
275
it ( 'pressing enter on the currently selected date should close the calendar without ' +
274
276
'firing selectedChanged' , ( ) => {
@@ -1020,18 +1022,65 @@ describe('MatDatepicker', () => {
1020
1022
expect ( testComponent . openedSpy ) . toHaveBeenCalled ( ) ;
1021
1023
} ) ;
1022
1024
1023
- it ( 'should dispatch an event when a datepicker is closed' , ( ) => {
1025
+ it ( 'should dispatch an event when a datepicker is closed' , fakeAsync ( ( ) => {
1024
1026
testComponent . datepicker . open ( ) ;
1025
1027
fixture . detectChanges ( ) ;
1026
1028
1027
1029
testComponent . datepicker . close ( ) ;
1030
+ flush ( ) ;
1028
1031
fixture . detectChanges ( ) ;
1029
1032
1030
1033
expect ( testComponent . closedSpy ) . toHaveBeenCalled ( ) ;
1031
- } ) ;
1034
+ } ) ) ;
1032
1035
1033
1036
} ) ;
1034
1037
1038
+ describe ( 'datepicker that opens on focus' , ( ) => {
1039
+ let fixture : ComponentFixture < DatepickerOpeningOnFocus > ;
1040
+ let testComponent : DatepickerOpeningOnFocus ;
1041
+ let input : HTMLInputElement ;
1042
+
1043
+ beforeEach ( fakeAsync ( ( ) => {
1044
+ fixture = TestBed . createComponent ( DatepickerOpeningOnFocus ) ;
1045
+ fixture . detectChanges ( ) ;
1046
+ testComponent = fixture . componentInstance ;
1047
+ input = fixture . debugElement . query ( By . css ( 'input' ) ) . nativeElement ;
1048
+ } ) ) ;
1049
+
1050
+ it ( 'should not reopen if the browser fires the focus event asynchronously' , fakeAsync ( ( ) => {
1051
+ // Stub out the real focus method so we can call it reliably.
1052
+ spyOn ( input , 'focus' ) . and . callFake ( ( ) => {
1053
+ // Dispatch the event handler async to simulate the IE11 behavior.
1054
+ Promise . resolve ( ) . then ( ( ) => dispatchFakeEvent ( input , 'focus' ) ) ;
1055
+ } ) ;
1056
+
1057
+ // Open initially by focusing.
1058
+ input . focus ( ) ;
1059
+ fixture . detectChanges ( ) ;
1060
+ flush ( ) ;
1061
+
1062
+ // Due to some browser limitations we can't install a stub on `document.activeElement`
1063
+ // so instead we have to override the previously-focused element manually.
1064
+ ( fixture . componentInstance . datepicker as any ) . _focusedElementBeforeOpen = input ;
1065
+
1066
+ // Ensure that the datepicker is actually open.
1067
+ expect ( testComponent . datepicker . opened ) . toBe ( true , 'Expected datepicker to be open.' ) ;
1068
+
1069
+ // Close the datepicker.
1070
+ testComponent . datepicker . close ( ) ;
1071
+ fixture . detectChanges ( ) ;
1072
+
1073
+ // Schedule the input to be focused asynchronously.
1074
+ input . focus ( ) ;
1075
+ fixture . detectChanges ( ) ;
1076
+
1077
+ // Flush out the scheduled tasks.
1078
+ flush ( ) ;
1079
+
1080
+ expect ( testComponent . datepicker . opened ) . toBe ( false , 'Expected datepicker to be closed.' ) ;
1081
+ } ) ) ;
1082
+ } ) ;
1083
+
1035
1084
} ) ;
1036
1085
1037
1086
describe ( 'with missing DateAdapter and MAT_DATE_FORMATS' , ( ) => {
@@ -1390,3 +1439,14 @@ class DatepickerWithEvents {
1390
1439
closedSpy = jasmine . createSpy ( 'closed spy' ) ;
1391
1440
@ViewChild ( 'd' ) datepicker : MatDatepicker < Date > ;
1392
1441
}
1442
+
1443
+
1444
+ @Component ( {
1445
+ template : `
1446
+ <input (focus)="d.open()" [matDatepicker]="d">
1447
+ <mat-datepicker #d="matDatepicker"></mat-datepicker>
1448
+ ` ,
1449
+ } )
1450
+ class DatepickerOpeningOnFocus {
1451
+ @ViewChild ( MatDatepicker ) datepicker : MatDatepicker < Date > ;
1452
+ }
0 commit comments