1- import { Type , Component , ViewChild , ElementRef } from '@angular/core' ;
1+ import { Type , Component , ViewChild , ElementRef , Directive } from '@angular/core' ;
22import { ComponentFixture , TestBed , inject , fakeAsync , tick } from '@angular/core/testing' ;
3- import { FormsModule , ReactiveFormsModule , FormGroup , FormControl } from '@angular/forms' ;
3+ import {
4+ FormsModule ,
5+ ReactiveFormsModule ,
6+ FormGroup ,
7+ FormControl ,
8+ NG_VALIDATORS ,
9+ Validator ,
10+ } from '@angular/forms' ;
411import { NoopAnimationsModule } from '@angular/platform-browser/animations' ;
512import { OverlayContainer } from '@angular/cdk/overlay' ;
613import { MatNativeDateModule } from '@angular/material/core' ;
@@ -15,7 +22,9 @@ import {MatDateRangePicker} from './date-range-picker';
1522import { MatStartDate , MatEndDate } from './date-range-input-parts' ;
1623
1724describe ( 'MatDateRangeInput' , ( ) => {
18- function createComponent < T > ( component : Type < T > ) : ComponentFixture < T > {
25+ function createComponent < T > (
26+ component : Type < T > ,
27+ declarations : Type < any > [ ] = [ ] ) : ComponentFixture < T > {
1928 TestBed . configureTestingModule ( {
2029 imports : [
2130 FormsModule ,
@@ -26,7 +35,7 @@ describe('MatDateRangeInput', () => {
2635 ReactiveFormsModule ,
2736 MatNativeDateModule ,
2837 ] ,
29- declarations : [ component ] ,
38+ declarations : [ component , ... declarations ] ,
3039 } ) ;
3140
3241 return TestBed . createComponent ( component ) ;
@@ -626,6 +635,78 @@ describe('MatDateRangeInput', () => {
626635 endSubscription . unsubscribe ( ) ;
627636 } ) ;
628637
638+ it ( 'should not trigger validators if new date object for same date is set for `min`' , ( ) => {
639+ const fixture = createComponent ( RangePickerWithCustomValidator , [ CustomValidator ] ) ;
640+ fixture . detectChanges ( ) ;
641+ const minDate = new Date ( 2019 , 0 , 1 ) ;
642+ const validator = fixture . componentInstance . validator ;
643+
644+ validator . validate . calls . reset ( ) ;
645+ fixture . componentInstance . min = minDate ;
646+ fixture . detectChanges ( ) ;
647+ expect ( validator . validate ) . toHaveBeenCalledTimes ( 1 ) ;
648+
649+ fixture . componentInstance . min = new Date ( minDate ) ;
650+ fixture . detectChanges ( ) ;
651+
652+ expect ( validator . validate ) . toHaveBeenCalledTimes ( 1 ) ;
653+ } ) ;
654+
655+ it ( 'should not trigger validators if new date object for same date is set for `max`' , ( ) => {
656+ const fixture = createComponent ( RangePickerWithCustomValidator , [ CustomValidator ] ) ;
657+ fixture . detectChanges ( ) ;
658+ const maxDate = new Date ( 2120 , 0 , 1 ) ;
659+ const validator = fixture . componentInstance . validator ;
660+
661+ validator . validate . calls . reset ( ) ;
662+ fixture . componentInstance . max = maxDate ;
663+ fixture . detectChanges ( ) ;
664+ expect ( validator . validate ) . toHaveBeenCalledTimes ( 1 ) ;
665+
666+ fixture . componentInstance . max = new Date ( maxDate ) ;
667+ fixture . detectChanges ( ) ;
668+
669+ expect ( validator . validate ) . toHaveBeenCalledTimes ( 1 ) ;
670+ } ) ;
671+
672+ it ( 'should not emit to `stateChanges` if new date object for same date is set for `min`' , ( ) => {
673+ const fixture = createComponent ( StandardRangePicker ) ;
674+ fixture . detectChanges ( ) ;
675+
676+ const minDate = new Date ( 2019 , 0 , 1 ) ;
677+ const spy = jasmine . createSpy ( 'stateChanges spy' ) ;
678+ const subscription = fixture . componentInstance . rangeInput . stateChanges . subscribe ( spy ) ;
679+
680+ fixture . componentInstance . minDate = minDate ;
681+ fixture . detectChanges ( ) ;
682+ expect ( spy ) . toHaveBeenCalledTimes ( 1 ) ;
683+
684+ fixture . componentInstance . minDate = new Date ( minDate ) ;
685+ fixture . detectChanges ( ) ;
686+ expect ( spy ) . toHaveBeenCalledTimes ( 1 ) ;
687+
688+ subscription . unsubscribe ( ) ;
689+ } ) ;
690+
691+ it ( 'should not emit to `stateChanges` if new date object for same date is set for `max`' , ( ) => {
692+ const fixture = createComponent ( StandardRangePicker ) ;
693+ fixture . detectChanges ( ) ;
694+
695+ const maxDate = new Date ( 2120 , 0 , 1 ) ;
696+ const spy = jasmine . createSpy ( 'stateChanges spy' ) ;
697+ const subscription = fixture . componentInstance . rangeInput . stateChanges . subscribe ( spy ) ;
698+
699+ fixture . componentInstance . maxDate = maxDate ;
700+ fixture . detectChanges ( ) ;
701+ expect ( spy ) . toHaveBeenCalledTimes ( 1 ) ;
702+
703+ fixture . componentInstance . maxDate = new Date ( maxDate ) ;
704+ fixture . detectChanges ( ) ;
705+ expect ( spy ) . toHaveBeenCalledTimes ( 1 ) ;
706+
707+ subscription . unsubscribe ( ) ;
708+ } ) ;
709+
629710} ) ;
630711
631712@Component ( {
@@ -736,3 +817,37 @@ class RangePickerNoLabel {
736817 @ViewChild ( 'start' ) start : ElementRef < HTMLInputElement > ;
737818 @ViewChild ( 'end' ) end : ElementRef < HTMLInputElement > ;
738819}
820+
821+
822+ @Directive ( {
823+ selector : '[customValidator]' ,
824+ providers : [ {
825+ provide : NG_VALIDATORS ,
826+ useExisting : CustomValidator ,
827+ multi : true
828+ } ]
829+ } )
830+ class CustomValidator implements Validator {
831+ validate = jasmine . createSpy ( 'validate spy' ) . and . returnValue ( null ) ;
832+ }
833+
834+
835+ @Component ( {
836+ template : `
837+ <mat-form-field>
838+ <mat-date-range-input [rangePicker]="rangePicker" [min]="min" [max]="max">
839+ <input matStartDate [(ngModel)]="start" customValidator/>
840+ <input matEndDate [(ngModel)]="end" customValidator/>
841+ </mat-date-range-input>
842+
843+ <mat-date-range-picker #rangePicker></mat-date-range-picker>
844+ </mat-form-field>
845+ `
846+ } )
847+ class RangePickerWithCustomValidator {
848+ @ViewChild ( CustomValidator ) validator : CustomValidator ;
849+ start : Date | null = null ;
850+ end : Date | null = null ;
851+ min : Date ;
852+ max : Date ;
853+ }
0 commit comments