@@ -32,6 +32,13 @@ const scrollToAllDay = ClientFunction(() => {
3232 instance . scrollTo ( date , undefined , true ) ;
3333} ) ;
3434
35+ const getWSScrollLeft = ClientFunction ( ( ) => {
36+ const instance = ( $ ( '#container' ) as any ) . dxScheduler ( 'instance' ) ;
37+ return instance . getWorkSpaceScrollable ( ) . scrollLeft ( ) ;
38+ } ) ;
39+
40+ const getHeaderScrollLeft = ClientFunction ( ( ) => $ ( '.dx-scheduler-header-scrollable .dx-scrollable-container' ) . scrollLeft ( ) ) ;
41+
3542test ( 'ScrollTo works correctly with week and day views' , async ( t ) => {
3643 const scheduler = new Scheduler ( '#container' ) ;
3744
@@ -230,3 +237,200 @@ test('ScrollTo works correctly in timeline RTL (native, sync header/workspace)',
230237 height : 580 ,
231238 rtlEnabled : true ,
232239} ) ) ;
240+
241+ test ( 'T1310544: ScrollTo should scroll to date with offset: 720 (12 hours)' , async ( t ) => {
242+ const scheduler = new Scheduler ( '#container' ) ;
243+
244+ await scheduler . option ( 'currentView' , 'timelineDay' ) ;
245+ await scheduler . option ( 'useNative' , true ) ;
246+ await t . wait ( 200 ) ;
247+
248+ const getExpectedScrollLeft = ClientFunction ( ( ) => {
249+ const instance = ( $ ( '#container' ) as any ) . dxScheduler ( 'instance' ) ;
250+ const workspace = instance . getWorkSpace ( ) ;
251+ const scrollable = workspace . getScrollable ( ) ;
252+ const $scrollable = scrollable . $element ( ) ;
253+ const scrollableWidth = $scrollable . width ( ) ;
254+
255+ const targetDateValue = new Date ( 2021 , 1 , 2 , 22 , 0 ) ;
256+
257+ const cell = workspace . viewDataProvider . findGlobalCellPosition (
258+ targetDateValue ,
259+ 0 ,
260+ false ,
261+ true ,
262+ ) ;
263+ const { startDate : cellStartDate , endDate : cellEndDate } = cell . cellData ;
264+
265+ const isDateValid = targetDateValue . getTime ( ) >= cellStartDate . getTime ( )
266+ && targetDateValue . getTime ( ) < cellEndDate . getTime ( ) ;
267+
268+ // eslint-disable-next-line no-underscore-dangle
269+ const cellCoordinates = workspace . _getScrollCoordinates ( targetDateValue , 0 , false ) ;
270+ const cellWidth = workspace . getCellWidth ( ) ;
271+ const expectedScrollLeft = cellCoordinates . left - ( scrollableWidth - cellWidth ) / 2 ;
272+
273+ return {
274+ expectedScrollLeft,
275+ isDateValid,
276+ cellStartDate : cellStartDate . getTime ( ) ,
277+ cellEndDate : cellEndDate . getTime ( ) ,
278+ targetDate : targetDateValue . getTime ( ) ,
279+ } ;
280+ } ) ;
281+
282+ const initialLeft = await getWSScrollLeft ( ) ;
283+ const initialHeaderLeft = await getHeaderScrollLeft ( ) ;
284+
285+ await t . expect ( initialLeft ) . eql ( initialHeaderLeft , 'Initial header/workspace sync' ) ;
286+
287+ const cellData = await getExpectedScrollLeft ( ) ;
288+
289+ await t
290+ . expect ( cellData . isDateValid )
291+ . ok ( 'Target date should be within cell range' ) ;
292+
293+ const scrollToTargetDate = ClientFunction ( ( targetDate : Date ) => {
294+ const instance = ( $ ( '#container' ) as any ) . dxScheduler ( 'instance' ) ;
295+ instance . scrollTo ( targetDate , undefined , false ) ;
296+ } ) ;
297+
298+ await scrollToTargetDate ( new Date ( 2021 , 1 , 2 , 22 , 0 ) ) ;
299+ await t . wait ( 300 ) ;
300+
301+ const actualLeft = await getWSScrollLeft ( ) ;
302+ const headerLeft = await getHeaderScrollLeft ( ) ;
303+
304+ await t
305+ . expect ( actualLeft ) . notEql ( initialLeft , 'Workspace should be scrolled' )
306+ . expect ( headerLeft ) . eql ( actualLeft , 'Header should be synchronized with workspace' )
307+ . expect ( actualLeft )
308+ . eql ( cellData . expectedScrollLeft , 'Scroll position should match expected' ) ;
309+ } ) . before ( async ( ) => createScheduler ( {
310+ dataSource : [ ] ,
311+ views : [ 'timelineDay' ] ,
312+ currentView : 'timelineDay' ,
313+ currentDate : new Date ( 2021 , 1 , 2 ) ,
314+ firstDayOfWeek : 0 ,
315+ startDayHour : 6 ,
316+ endDayHour : 18 ,
317+ offset : 720 ,
318+ cellDuration : 60 ,
319+ height : 580 ,
320+ } ) ) ;
321+
322+ [
323+ {
324+ startDayHour : 6 ,
325+ endDayHour : 18 ,
326+ offset : 0 ,
327+ hours : [ 4 , 12 , 20 ] ,
328+ } ,
329+ {
330+ startDayHour : 6 ,
331+ endDayHour : 18 ,
332+ offset : 360 ,
333+ hours : [ 10 , 15 , 22 ] ,
334+ } ,
335+ {
336+ startDayHour : 6 ,
337+ endDayHour : 18 ,
338+ offset : - 120 ,
339+ hours : [ 3 , 10 , 20 ] ,
340+ } ,
341+ {
342+ startDayHour : 6 ,
343+ endDayHour : 18 ,
344+ offset : 720 ,
345+ hours : [ 10 , 22 , 3 ] ,
346+ } ,
347+ {
348+ startDayHour : 0 ,
349+ endDayHour : 12 ,
350+ offset : 0 ,
351+ hours : [ 0 , 6 , 13 ] ,
352+ } ,
353+ {
354+ startDayHour : 12 ,
355+ endDayHour : 24 ,
356+ offset : 0 ,
357+ hours : [ 11 , 18 , 23 ] ,
358+ } ,
359+ ] . forEach ( ( {
360+ startDayHour,
361+ endDayHour,
362+ offset,
363+ hours,
364+ } ) => {
365+ hours . forEach ( ( hour ) => {
366+ const getExpectedScrollPosition = ClientFunction ( ( targetHour : number ) => {
367+ const instance = ( $ ( '#container' ) as any ) . dxScheduler ( 'instance' ) ;
368+ const workspace = instance . getWorkSpace ( ) ;
369+ const scrollable = workspace . getScrollable ( ) ;
370+ const $scrollable = scrollable . $element ( ) ;
371+ const scrollableWidth = $scrollable . width ( ) ;
372+ const targetDate = new Date ( 2021 , 1 , 2 , targetHour , 0 ) ;
373+
374+ // eslint-disable-next-line no-underscore-dangle
375+ const isValidDate = workspace . _isValidScrollDate ( targetDate , false ) ;
376+
377+ // eslint-disable-next-line no-underscore-dangle
378+ const cellCoordinates = workspace . _getScrollCoordinates ( targetDate , 0 , false ) ;
379+ const cellWidth = workspace . getCellWidth ( ) ;
380+ const expectedScrollLeft = cellCoordinates . left - ( scrollableWidth - cellWidth ) / 2 ;
381+
382+ return {
383+ expectedScrollLeft,
384+ isValidDate,
385+ } ;
386+ } ) ;
387+
388+ const scrollToHour = ClientFunction ( ( targetHour : number ) => {
389+ const instance = ( $ ( '#container' ) as any ) . dxScheduler ( 'instance' ) ;
390+ instance . scrollTo ( new Date ( 2021 , 1 , 2 , targetHour , 0 ) , undefined , false ) ;
391+ } ) ;
392+
393+ test ( `Hour normalization: startDayHour: ${ startDayHour } , endDayHour: ${ endDayHour } , offset: ${ offset } , hour: ${ hour } ` , async ( t ) => {
394+ const scheduler = new Scheduler ( '#container' ) ;
395+
396+ await scheduler . option ( 'currentView' , 'timelineWeek' ) ;
397+ await scheduler . option ( 'useNative' , true ) ;
398+ await t . wait ( 200 ) ;
399+
400+ const initialLeft = await getWSScrollLeft ( ) ;
401+ const initialHeaderLeft = await getHeaderScrollLeft ( ) ;
402+
403+ await t . expect ( initialLeft ) . eql ( initialHeaderLeft , 'Initial header/workspace sync' ) ;
404+
405+ const { expectedScrollLeft, isValidDate } = await getExpectedScrollPosition ( hour ) ;
406+
407+ await t
408+ . expect ( isValidDate )
409+ . ok ( `Target date (hour: ${ hour } ) should be within valid scroll range` ) ;
410+
411+ await scrollToHour ( hour ) ;
412+ await t . wait ( 300 ) ;
413+
414+ const actualLeft = await getWSScrollLeft ( ) ;
415+ const headerLeft = await getHeaderScrollLeft ( ) ;
416+
417+ await t
418+ . expect ( actualLeft ) . notEql ( initialLeft , 'Workspace should be scrolled' )
419+ . expect ( headerLeft ) . eql ( actualLeft , 'Header should be synchronized with workspace' )
420+ . expect ( actualLeft )
421+ . eql ( expectedScrollLeft , 'Scroll position should match expected' ) ;
422+ } ) . before ( async ( ) => createScheduler ( {
423+ dataSource : [ ] ,
424+ views : [ {
425+ type : 'timelineWeek' ,
426+ offset,
427+ cellDuration : 60 ,
428+ } ] ,
429+ currentView : 'timelineWeek' ,
430+ currentDate : new Date ( 2021 , 1 , 2 ) ,
431+ startDayHour,
432+ endDayHour,
433+ height : 580 ,
434+ } ) ) ;
435+ } ) ;
436+ } ) ;
0 commit comments