@@ -63,6 +63,7 @@ describe('IgxDateRangePicker', () => {
6363 let mockCalendar : IgxCalendarComponent ;
6464 let mockDaysView : any ;
6565 let mockAnimationService : AnimationService ;
66+ let mockCdr : any ;
6667 const elementRef = { nativeElement : null } ;
6768 const platform = { } as any ;
6869 const mockNgControl = jasmine . createSpyObj ( 'NgControl' ,
@@ -88,6 +89,9 @@ describe('IgxDateRangePicker', () => {
8889 mockInjector = jasmine . createSpyObj ( 'Injector' , {
8990 get : mockNgControl
9091 } ) ;
92+ mockCdr = jasmine . createSpyObj ( 'ChangeDetectorRef' , {
93+ detectChanges : ( ) => { }
94+ } ) ;
9195 mockAnimationBuilder = {
9296 build : ( a : AnimationMetadata | AnimationMetadata [ ] ) => ( {
9397 create : ( e : any , opt ?: AnimationOptions ) => ( {
@@ -244,7 +248,7 @@ describe('IgxDateRangePicker', () => {
244248 } ) ;
245249
246250 it ( 'should disable calendar dates when min and/or max values as dates are provided' , ( ) => {
247- const dateRange = new IgxDateRangePickerComponent ( elementRef , 'en-US' , platform , mockInjector , null , overlay ) ;
251+ const dateRange = new IgxDateRangePickerComponent ( elementRef , 'en-US' , platform , mockInjector , mockCdr , overlay ) ;
248252 dateRange . ngOnInit ( ) ;
249253
250254 spyOnProperty ( ( dateRange as any ) , 'calendar' ) . and . returnValue ( mockCalendar ) ;
@@ -260,7 +264,7 @@ describe('IgxDateRangePicker', () => {
260264 } ) ;
261265
262266 it ( 'should disable calendar dates when min and/or max values as strings are provided' , fakeAsync ( ( ) => {
263- const dateRange = new IgxDateRangePickerComponent ( elementRef , 'en' , platform , mockInjector , null , null , null ) ;
267+ const dateRange = new IgxDateRangePickerComponent ( elementRef , 'en' , platform , mockInjector , mockCdr , null , null ) ;
264268 dateRange . ngOnInit ( ) ;
265269
266270 spyOnProperty ( ( dateRange as any ) , 'calendar' ) . and . returnValue ( mockCalendar ) ;
@@ -277,7 +281,7 @@ describe('IgxDateRangePicker', () => {
277281 } ) ) ;
278282
279283 it ( 'should validate correctly when disabledDates are set' , ( ) => {
280- const dateRange = new IgxDateRangePickerComponent ( elementRef , 'en-US' , platform , mockInjector , null , null , null ) ;
284+ const dateRange = new IgxDateRangePickerComponent ( elementRef , 'en-US' , platform , mockInjector , mockCdr , null , null ) ;
281285 dateRange . ngOnInit ( ) ;
282286
283287 dateRange . registerOnChange ( mockNgControl . registerOnChangeCb ) ;
@@ -1317,6 +1321,60 @@ describe('IgxDateRangePicker', () => {
13171321 expect ( dateRange . opening . emit ) . toHaveBeenCalledTimes ( 0 ) ;
13181322 expect ( dateRange . opened . emit ) . toHaveBeenCalledTimes ( 0 ) ;
13191323 } ) ) ;
1324+
1325+ it ( 'should update the calendar selection on typing' , fakeAsync ( ( ) => {
1326+ const range = { start : new Date ( 2025 , 0 , 16 ) , end : new Date ( 2025 , 0 , 20 ) } ;
1327+ dateRange . value = range ;
1328+ fixture . detectChanges ( ) ;
1329+ dateRange . open ( ) ;
1330+ fixture . detectChanges ( ) ;
1331+
1332+ expect ( ( dateRange [ '_calendar' ] . value as Date [ ] ) . length ) . toBe ( 5 ) ;
1333+
1334+ startInput . triggerEventHandler ( 'focus' , { } ) ;
1335+ fixture . detectChanges ( ) ;
1336+ UIInteractions . simulateTyping ( '01/18/2025' , startInput ) ;
1337+
1338+ tick ( DEBOUNCE_TIME ) ;
1339+ fixture . detectChanges ( ) ;
1340+
1341+ expect ( ( dateRange [ '_calendar' ] . value as Date [ ] ) . length ) . toBe ( 3 ) ;
1342+
1343+ startDate = new Date ( 2025 , 0 , 18 ) ;
1344+ const expectedRange = { start : startDate , end : new Date ( 2025 , 0 , 20 ) } ;
1345+ expect ( dateRange . value ) . toEqual ( expectedRange ) ;
1346+ expect ( dateRange . activeDate ) . toEqual ( expectedRange . start ) ;
1347+
1348+ const activeDescendantDate = new Date ( startDate . setHours ( 0 , 0 , 0 , 0 ) ) . getTime ( ) . toString ( ) ;
1349+ expect ( dateRange [ '_calendar' ] . activeDate ) . toEqual ( startDate ) ;
1350+ expect ( dateRange [ '_calendar' ] . viewDate . getMonth ( ) ) . toEqual ( startDate . getMonth ( ) ) ;
1351+ expect ( dateRange [ '_calendar' ] . value [ 0 ] ) . toEqual ( startDate ) ;
1352+ expect ( dateRange [ '_calendar' ] . wrapper . nativeElement . getAttribute ( 'aria-activedescendant' ) ) . toEqual ( activeDescendantDate ) ;
1353+ } ) ) ;
1354+
1355+ it ( 'should update the calendar view and active date on typing a date that is not in the current view' , fakeAsync ( ( ) => {
1356+ const range = { start : new Date ( 2025 , 0 , 16 ) , end : new Date ( 2025 , 0 , 20 ) } ;
1357+ dateRange . value = range ;
1358+ fixture . detectChanges ( ) ;
1359+ dateRange . open ( ) ;
1360+ fixture . detectChanges ( ) ;
1361+
1362+ expect ( ( dateRange [ '_calendar' ] . value as Date [ ] ) . length ) . toBe ( 5 ) ;
1363+
1364+ startInput . triggerEventHandler ( 'focus' , { } ) ;
1365+ fixture . detectChanges ( ) ;
1366+ UIInteractions . simulateTyping ( '11/18/2025' , startInput ) ;
1367+
1368+ tick ( DEBOUNCE_TIME ) ;
1369+ fixture . detectChanges ( ) ;
1370+
1371+ startDate = new Date ( 2025 , 10 , 18 ) ;
1372+
1373+ const activeDescendantDate = new Date ( startDate . setHours ( 0 , 0 , 0 , 0 ) ) . getTime ( ) . toString ( ) ;
1374+ expect ( dateRange [ '_calendar' ] . activeDate ) . toEqual ( startDate ) ;
1375+ expect ( dateRange [ '_calendar' ] . viewDate . getMonth ( ) ) . toEqual ( startDate . getMonth ( ) ) ;
1376+ expect ( dateRange [ '_calendar' ] . wrapper . nativeElement . getAttribute ( 'aria-activedescendant' ) ) . toEqual ( activeDescendantDate ) ;
1377+ } ) ) ;
13201378 } ) ;
13211379
13221380 it ( 'should focus the last focused input after the calendar closes - dropdown' , fakeAsync ( ( ) => {
@@ -1739,13 +1797,70 @@ describe('IgxDateRangePicker', () => {
17391797 fixture . detectChanges ( ) ;
17401798
17411799 expect ( dateRange [ '_calendar' ] . disabledDates ) . toEqual ( disabledDates ) ;
1800+ } ) ) ;
17421801
1743- // should not allow to select a date from the disabled dates
1744- startDate = new Date ( new Date ( ) . getFullYear ( ) , new Date ( ) . getMonth ( ) , 4 ) ;
1745- endDate = new Date ( new Date ( ) . getFullYear ( ) , new Date ( ) . getMonth ( ) , 6 ) ;
1802+ it ( 'should initialize activeDate with current date, when not set' , fakeAsync ( ( ) => {
1803+ fixture = TestBed . createComponent ( DateRangeDefaultComponent ) ;
1804+ fixture . detectChanges ( ) ;
1805+ dateRange = fixture . componentInstance . dateRange ;
1806+ const todayDate = new Date ( ) ;
1807+ const today = new Date ( todayDate . setHours ( 0 , 0 , 0 , 0 ) ) . getTime ( ) . toString ( ) ;
1808+
1809+ expect ( dateRange . activeDate ) . toEqual ( todayDate ) ;
1810+
1811+ dateRange . open ( ) ;
1812+ fixture . detectChanges ( ) ;
1813+
1814+ expect ( dateRange [ '_calendar' ] . activeDate ) . toEqual ( todayDate ) ;
1815+ expect ( dateRange [ '_calendar' ] . value ) . toEqual ( [ ] ) ;
1816+ const wrapper = fixture . debugElement . query ( By . css ( '.igx-calendar__wrapper' ) ) . nativeElement ;
1817+ expect ( wrapper . getAttribute ( 'aria-activedescendant' ) ) . toEqual ( today ) ;
1818+ } ) ) ;
1819+
1820+ it ( 'should initialize activeDate = first defined in value (start/end) when it is not set, but value is' , fakeAsync ( ( ) => {
1821+ fixture = TestBed . createComponent ( DateRangeDefaultComponent ) ;
1822+ fixture . detectChanges ( ) ;
1823+ dateRange = fixture . componentInstance . dateRange ;
1824+ let range = { start : new Date ( 2025 , 0 , 1 ) , end : new Date ( 2025 , 0 , 5 ) } ;
1825+ dateRange . value = range ;
1826+ fixture . detectChanges ( ) ;
1827+
1828+ expect ( dateRange . activeDate ) . toEqual ( range . start ) ;
1829+ dateRange . open ( ) ;
1830+ fixture . detectChanges ( ) ;
1831+
1832+ const activeDescendantDate = new Date ( range . start . setHours ( 0 , 0 , 0 , 0 ) ) . getTime ( ) . toString ( ) ;
1833+ expect ( dateRange [ '_calendar' ] . activeDate ) . toEqual ( range . start ) ;
1834+ expect ( dateRange [ '_calendar' ] . value [ 0 ] ) . toEqual ( range . start ) ;
1835+ const wrapper = fixture . debugElement . query ( By . css ( '.igx-calendar__wrapper' ) ) . nativeElement ;
1836+ expect ( wrapper . getAttribute ( 'aria-activedescendant' ) ) . toEqual ( activeDescendantDate ) ;
1837+
1838+ range = { ...range , start : null } ;
1839+ dateRange . value = range ;
1840+ fixture . detectChanges ( ) ;
1841+
1842+ expect ( dateRange . activeDate ) . toEqual ( range . end ) ;
1843+ } ) ) ;
1844+
1845+ it ( 'should set activeDate correctly' , fakeAsync ( ( ) => {
1846+ const targetDate = new Date ( 2025 , 11 , 1 ) ;
1847+ fixture = TestBed . createComponent ( DateRangeDefaultComponent ) ;
1848+ fixture . detectChanges ( ) ;
1849+ dateRange = fixture . componentInstance . dateRange ;
1850+ const range = { start : new Date ( 2025 , 0 , 1 ) , end : new Date ( 2025 , 0 , 5 ) } ;
1851+ dateRange . value = range ;
1852+ dateRange . activeDate = targetDate ;
1853+ fixture . detectChanges ( ) ;
1854+
1855+ expect ( dateRange . activeDate ) . toEqual ( targetDate ) ;
1856+ dateRange . open ( ) ;
1857+ fixture . detectChanges ( ) ;
17461858
1747- selectDateRangeFromCalendar ( startDate , endDate ) ;
1748- expect ( dateRange . value ) . toBeNull ( ) ;
1859+ const activeDescendantDate = new Date ( targetDate . setHours ( 0 , 0 , 0 , 0 ) ) . getTime ( ) . toString ( ) ;
1860+ expect ( dateRange [ '_calendar' ] . activeDate ) . toEqual ( targetDate ) ;
1861+ expect ( dateRange [ '_calendar' ] . value [ 0 ] ) . toEqual ( range . start ) ;
1862+ const wrapper = fixture . debugElement . query ( By . css ( '.igx-calendar__wrapper' ) ) . nativeElement ;
1863+ expect ( wrapper . getAttribute ( 'aria-activedescendant' ) ) . toEqual ( activeDescendantDate ) ;
17491864 } ) ) ;
17501865
17511866 describe ( 'Templated Calendar Header' , ( ) => {
0 commit comments