2021-11-01 10:39:06 -05:00
import {
addDays ,
addHours ,
differenceInCalendarDays ,
differenceInMinutes ,
format ,
isBefore ,
parseISO ,
toDate ,
} from 'date-fns' ;
2020-05-11 04:46:57 -05:00
2022-04-22 08:33:13 -05:00
import { e2e } from '@grafana/e2e' ;
2020-05-11 04:46:57 -05:00
e2e . scenario ( {
describeName : 'Dashboard time zone support' ,
itName : 'Tests dashboard time zone scenarios' ,
addScenarioDataSource : false ,
addScenarioDashBoard : false ,
2021-11-08 10:05:01 -06:00
skipScenario : false ,
2020-05-11 04:46:57 -05:00
scenario : ( ) = > {
2020-06-26 12:33:05 -05:00
e2e . flows . openDashboard ( { uid : '5SdHCasdf' } ) ;
2020-05-11 04:46:57 -05:00
2021-11-08 10:05:01 -06:00
const fromTimeZone = 'UTC' ;
2020-05-11 04:46:57 -05:00
const toTimeZone = 'America/Chicago' ;
2021-11-08 10:05:01 -06:00
const offset = offsetBetweenTimeZones ( toTimeZone , fromTimeZone ) ;
2020-05-11 04:46:57 -05:00
const panelsToCheck = [
'Random walk series' ,
'Millisecond res x-axis and tooltip' ,
'2 yaxis and axis labels' ,
'Stacking value ontop of nulls' ,
'Null between points' ,
'Legend Table No Scroll Visible' ,
] ;
const timesInUtc : Record < string , string > = { } ;
for ( const title of panelsToCheck ) {
e2e . components . Panels . Panel . containerByTitle ( title )
. should ( 'be.visible' )
. within ( ( ) = >
e2e . components . Panels . Visualization . Graph . xAxis
. labels ( )
. should ( 'be.visible' )
. last ( )
2021-01-20 00:59:48 -06:00
. should ( ( element ) = > {
2020-05-11 04:46:57 -05:00
timesInUtc [ title ] = element . text ( ) ;
} )
) ;
}
2021-01-27 08:02:04 -06:00
e2e . components . PageToolbar . item ( 'Dashboard settings' ) . click ( ) ;
2020-05-11 04:46:57 -05:00
2021-11-17 07:45:45 -06:00
e2e . components . TimeZonePicker . containerV2 ( )
2020-05-11 04:46:57 -05:00
. should ( 'be.visible' )
. within ( ( ) = > {
2021-11-26 09:38:48 -06:00
e2e . components . Select . singleValue ( ) . should ( 'have.text' , 'Coordinated Universal Time' ) ;
2021-01-20 00:59:48 -06:00
e2e . components . Select . input ( ) . should ( 'be.visible' ) . click ( ) ;
2020-05-11 04:46:57 -05:00
} ) ;
2021-07-14 08:04:23 -05:00
e2e . components . Select . option ( ) . should ( 'be.visible' ) . contains ( toTimeZone ) . click ( ) ;
2021-06-16 07:34:56 -05:00
// click to go back to the dashboard.
2022-08-24 11:05:12 -05:00
e2e . components . BackButton . backArrow ( ) . click ( { force : true } ) . wait ( 5000 ) ;
e2e . components . RefreshPicker . runButtonV2 ( ) . click ( ) ;
2020-05-11 04:46:57 -05:00
for ( const title of panelsToCheck ) {
e2e . components . Panels . Panel . containerByTitle ( title )
. should ( 'be.visible' )
. within ( ( ) = >
e2e . components . Panels . Visualization . Graph . xAxis
. labels ( )
. should ( 'be.visible' )
. last ( )
2021-01-20 00:59:48 -06:00
. should ( ( element ) = > {
2021-06-16 07:34:56 -05:00
const inUtc = timesInUtc [ title ] ;
const inTz = element . text ( ) ;
const isCorrect = isTimeCorrect ( inUtc , inTz , offset ) ;
2020-05-11 04:46:57 -05:00
assert . isTrue ( isCorrect , ` Panel with title: " ${ title } " ` ) ;
} )
) ;
}
} ,
} ) ;
2021-06-16 07:34:56 -05:00
const isTimeCorrect = ( inUtc : string , inTz : string , offset : number ) : boolean = > {
if ( inUtc === inTz ) {
// we need to catch issues when timezone isn't changed for some reason like https://github.com/grafana/grafana/issues/35504
return false ;
}
2020-05-11 04:46:57 -05:00
2021-11-01 10:39:06 -05:00
const reference = format ( new Date ( ) , 'yyyy-LL-dd' ) ;
2020-05-11 04:46:57 -05:00
2021-11-01 10:39:06 -05:00
const utcDate = toDate ( parseISO ( ` ${ reference } ${ inUtc } ` ) ) ;
const utcDateWithOffset = addHours ( toDate ( parseISO ( ` ${ reference } ${ inUtc } ` ) ) , offset ) ;
2021-06-16 07:34:56 -05:00
const dayDifference = differenceInCalendarDays ( utcDate , utcDateWithOffset ) ; // if the utcDate +/- offset is the day before/after then we need to adjust reference
const dayOffset = isBefore ( utcDateWithOffset , utcDate ) ? dayDifference * - 1 : dayDifference ;
2021-11-01 10:39:06 -05:00
const tzDate = addDays ( toDate ( parseISO ( ` ${ reference } ${ inTz } ` ) ) , dayOffset ) ; // adjust tzDate with any dayOffset
2021-06-16 07:34:56 -05:00
const diff = Math . abs ( differenceInMinutes ( utcDate , tzDate ) ) ; // use Math.abs if tzDate is in future
2020-05-11 04:46:57 -05:00
2021-06-16 07:34:56 -05:00
return diff <= Math . abs ( offset * 60 ) ;
2020-05-11 04:46:57 -05:00
} ;
2021-11-08 10:05:01 -06:00
const offsetBetweenTimeZones = ( timeZone1 : string , timeZone2 : string , when : Date = new Date ( ) ) : number = > {
const t1 = convertDateToAnotherTimeZone ( when , timeZone1 ) ;
const t2 = convertDateToAnotherTimeZone ( when , timeZone2 ) ;
return ( t1 . getTime ( ) - t2 . getTime ( ) ) / ( 1000 * 60 * 60 ) ;
} ;
const convertDateToAnotherTimeZone = ( date : Date , timeZone : string ) : Date = > {
const dateString = date . toLocaleString ( 'en-US' , {
timeZone : timeZone ,
} ) ;
return new Date ( dateString ) ;
} ;