| 
									
										
										
										
											2024-03-11 11:11:11 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   createTheme, | 
					
						
							|  |  |  |   FieldType, | 
					
						
							|  |  |  |   ThresholdsMode, | 
					
						
							|  |  |  |   TimeRange, | 
					
						
							|  |  |  |   toDataFrame, | 
					
						
							|  |  |  |   dateTime, | 
					
						
							|  |  |  |   DataFrame, | 
					
						
							|  |  |  |   fieldMatchers, | 
					
						
							|  |  |  |   FieldMatcherID, | 
					
						
							|  |  |  | } from '@grafana/data'; | 
					
						
							| 
									
										
										
										
											2022-11-29 23:52:08 +08:00
										 |  |  | import { LegendDisplayMode, VizLegendOptions } from '@grafana/schema'; | 
					
						
							| 
									
										
										
										
											2022-04-22 21:33:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 11:11:11 +08:00
										 |  |  | import { preparePlotFrame } from '../GraphNG/utils'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-24 20:32:55 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   findNextStateIndex, | 
					
						
							|  |  |  |   fmtDuration, | 
					
						
							|  |  |  |   getThresholdItems, | 
					
						
							| 
									
										
										
										
											2024-08-09 10:44:17 +08:00
										 |  |  |   makeFramePerSeries, | 
					
						
							| 
									
										
										
										
											2022-01-24 20:32:55 +08:00
										 |  |  |   prepareTimelineFields, | 
					
						
							|  |  |  |   prepareTimelineLegendItems, | 
					
						
							|  |  |  | } from './utils'; | 
					
						
							| 
									
										
										
										
											2021-05-18 04:00:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 23:43:57 +08:00
										 |  |  | const theme = createTheme(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-18 04:00:04 +08:00
										 |  |  | describe('prepare timeline graph', () => { | 
					
						
							| 
									
										
										
										
											2022-06-04 05:22:57 +08:00
										 |  |  |   const timeRange: TimeRange = { | 
					
						
							|  |  |  |     from: dateTime(1), | 
					
						
							|  |  |  |     to: dateTime(3), | 
					
						
							| 
									
										
										
										
											2022-11-29 23:52:08 +08:00
										 |  |  |     raw: { | 
					
						
							|  |  |  |       from: dateTime(1), | 
					
						
							|  |  |  |       to: dateTime(3), | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2022-06-04 05:22:57 +08:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2021-05-18 04:00:04 +08:00
										 |  |  |   it('errors with no time fields', () => { | 
					
						
							|  |  |  |     const frames = [ | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'a', values: [1, 2, 3] }, | 
					
						
							|  |  |  |           { name: 'b', values: ['a', 'b', 'c'] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ]; | 
					
						
							| 
									
										
										
										
											2022-06-04 05:22:57 +08:00
										 |  |  |     const info = prepareTimelineFields(frames, true, timeRange, theme); | 
					
						
							| 
									
										
										
										
											2021-05-18 04:00:04 +08:00
										 |  |  |     expect(info.warn).toEqual('Data does not have a time field'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('requires a number, string, or boolean value', () => { | 
					
						
							|  |  |  |     const frames = [ | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'a', type: FieldType.time, values: [1, 2, 3] }, | 
					
						
							|  |  |  |           { name: 'b', type: FieldType.other, values: [{}, {}, {}] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ]; | 
					
						
							| 
									
										
										
										
											2022-06-04 05:22:57 +08:00
										 |  |  |     const info = prepareTimelineFields(frames, true, timeRange, theme); | 
					
						
							| 
									
										
										
										
											2021-05-18 04:00:04 +08:00
										 |  |  |     expect(info.warn).toEqual('No graphable fields'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('will merge duplicate values', () => { | 
					
						
							|  |  |  |     const frames = [ | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'a', type: FieldType.time, values: [1, 2, 3, 4, 5, 6, 7] }, | 
					
						
							|  |  |  |           { name: 'b', values: [1, 1, undefined, 1, 2, 2, null, 2, 3] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ]; | 
					
						
							| 
									
										
										
										
											2022-06-04 05:22:57 +08:00
										 |  |  |     const info = prepareTimelineFields(frames, true, timeRange, theme); | 
					
						
							| 
									
										
										
										
											2021-05-18 04:00:04 +08:00
										 |  |  |     expect(info.warn).toBeUndefined(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const out = info.frames![0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const field = out.fields.find((f) => f.name === 'b'); | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |     expect(field?.values).toMatchInlineSnapshot(`
 | 
					
						
							| 
									
										
										
										
											2022-11-24 22:00:41 +08:00
										 |  |  |       [ | 
					
						
							| 
									
										
										
										
											2022-02-03 00:25:49 +08:00
										 |  |  |         1, | 
					
						
							| 
									
										
										
										
											2021-05-18 04:00:04 +08:00
										 |  |  |         1, | 
					
						
							|  |  |  |         undefined, | 
					
						
							| 
									
										
										
										
											2022-02-03 00:25:49 +08:00
										 |  |  |         1, | 
					
						
							|  |  |  |         2, | 
					
						
							| 
									
										
										
										
											2021-05-18 04:00:04 +08:00
										 |  |  |         2, | 
					
						
							|  |  |  |         null, | 
					
						
							|  |  |  |         2, | 
					
						
							|  |  |  |         3, | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |     `);
 | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2022-07-04 16:11:33 +08:00
										 |  |  |   it('should try to sort time fields', () => { | 
					
						
							|  |  |  |     const frames = [ | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'a', type: FieldType.time, values: [4, 3, 1, 2] }, | 
					
						
							|  |  |  |           { name: 'b', values: [1, 1, 2, 2] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  |     const result = prepareTimelineFields(frames, true, timeRange, theme); | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |     expect(result.frames?.[0].fields[0].values).toEqual([1, 2, 3, 4]); | 
					
						
							| 
									
										
										
										
											2022-07-04 16:11:33 +08:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2024-03-11 11:11:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('join multiple frames with NULL_RETAIN rather than NULL_EXPAND', () => { | 
					
						
							|  |  |  |     const timeRange2: TimeRange = { | 
					
						
							|  |  |  |       from: dateTime('2023-10-20T05:04:00.000Z'), | 
					
						
							|  |  |  |       to: dateTime('2023-10-20T07:22:00.000Z'), | 
					
						
							|  |  |  |       raw: { | 
					
						
							|  |  |  |         from: dateTime('2023-10-20T05:04:00.000Z'), | 
					
						
							|  |  |  |         to: dateTime('2023-10-20T07:22:00.000Z'), | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const frames = [ | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         name: 'Mix', | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'time', type: FieldType.time, values: [1697778291972, 1697778393992, 1697778986994, 1697786485890] }, | 
					
						
							|  |  |  |           { name: 'state', type: FieldType.string, values: ['RUN', null, 'RUN', null] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         name: 'Cook', | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             name: 'time', | 
					
						
							|  |  |  |             type: FieldType.time, | 
					
						
							|  |  |  |             values: [ | 
					
						
							|  |  |  |               1697779163986, 1697779921045, 1697780221094, 1697780521111, 1697781186192, 1697781786291, 1697783332361, | 
					
						
							|  |  |  |               1697783784395, 1697783790397, 1697784146478, 1697784517471, 1697784523487, 1697784949480, 1697785369505, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             name: 'state', | 
					
						
							|  |  |  |             type: FieldType.string, | 
					
						
							|  |  |  |             values: [ | 
					
						
							|  |  |  |               'Heat', | 
					
						
							|  |  |  |               'Stage', | 
					
						
							|  |  |  |               null, | 
					
						
							|  |  |  |               'Heat', | 
					
						
							|  |  |  |               'Stage', | 
					
						
							|  |  |  |               null, | 
					
						
							|  |  |  |               'Heat', | 
					
						
							|  |  |  |               'Stage', | 
					
						
							|  |  |  |               null, | 
					
						
							|  |  |  |               'Heat', | 
					
						
							|  |  |  |               'Stage', | 
					
						
							|  |  |  |               null, | 
					
						
							|  |  |  |               'CCP', | 
					
						
							|  |  |  |               null, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const info = prepareTimelineFields(frames, true, timeRange2, theme); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let joined = preparePlotFrame( | 
					
						
							|  |  |  |       info.frames!, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         x: fieldMatchers.get(FieldMatcherID.firstTimeField).get({}), | 
					
						
							|  |  |  |         y: fieldMatchers.get(FieldMatcherID.byType).get('string'), | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       timeRange2 | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let vals = joined!.fields.map((f) => f.values); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(vals).toEqual([ | 
					
						
							|  |  |  |       [ | 
					
						
							|  |  |  |         1697778291972, 1697778393992, 1697778986994, 1697779163986, 1697779921045, 1697780221094, 1697780521111, | 
					
						
							|  |  |  |         1697781186192, 1697781786291, 1697783332361, 1697783784395, 1697783790397, 1697784146478, 1697784517471, | 
					
						
							|  |  |  |         1697784523487, 1697784949480, 1697785369505, 1697786485890, | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |       [ | 
					
						
							|  |  |  |         'RUN', | 
					
						
							|  |  |  |         null, | 
					
						
							|  |  |  |         'RUN', | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         null, | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |       [ | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |         'Heat', | 
					
						
							|  |  |  |         'Stage', | 
					
						
							|  |  |  |         null, | 
					
						
							|  |  |  |         'Heat', | 
					
						
							|  |  |  |         'Stage', | 
					
						
							|  |  |  |         null, | 
					
						
							|  |  |  |         'Heat', | 
					
						
							|  |  |  |         'Stage', | 
					
						
							|  |  |  |         null, | 
					
						
							|  |  |  |         'Heat', | 
					
						
							|  |  |  |         'Stage', | 
					
						
							|  |  |  |         null, | 
					
						
							|  |  |  |         'CCP', | 
					
						
							|  |  |  |         null, | 
					
						
							|  |  |  |         undefined, | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('join multiple frames with start and end time fields', () => { | 
					
						
							|  |  |  |     const timeRange2: TimeRange = { | 
					
						
							|  |  |  |       from: dateTime('2024-02-28T07:47:21.428Z'), | 
					
						
							|  |  |  |       to: dateTime('2024-02-28T14:12:43.391Z'), | 
					
						
							|  |  |  |       raw: { | 
					
						
							|  |  |  |         from: dateTime('2024-02-28T07:47:21.428Z'), | 
					
						
							|  |  |  |         to: dateTime('2024-02-28T14:12:43.391Z'), | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const frames = [ | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         name: 'Channel 1', | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'starttime', type: FieldType.time, values: [1709107200000, 1709118000000] }, | 
					
						
							|  |  |  |           { name: 'endtime', type: FieldType.time, values: [1709114400000, 1709128800000] }, | 
					
						
							|  |  |  |           { name: 'state', type: FieldType.string, values: ['OK', 'NO_DATA'] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         name: 'Channel 2', | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'starttime', type: FieldType.time, values: [1709110800000, 1709123400000] }, | 
					
						
							|  |  |  |           { name: 'endtime', type: FieldType.time, values: [1709116200000, 1709127000000] }, | 
					
						
							|  |  |  |           { name: 'state', type: FieldType.string, values: ['ERROR', 'WARNING'] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const info = prepareTimelineFields(frames, true, timeRange2, theme); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let joined = preparePlotFrame( | 
					
						
							|  |  |  |       info.frames!, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         x: fieldMatchers.get(FieldMatcherID.firstTimeField).get({}), | 
					
						
							|  |  |  |         y: fieldMatchers.get(FieldMatcherID.byType).get('string'), | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       timeRange2 | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let vals = joined!.fields.map((f) => f.values); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(vals).toEqual([ | 
					
						
							|  |  |  |       [ | 
					
						
							|  |  |  |         1709107200000, 1709110800000, 1709114400000, 1709116200000, 1709118000000, 1709123400000, 1709127000000, | 
					
						
							|  |  |  |         1709128800000, | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |       ['OK', undefined, null, undefined, 'NO_DATA', undefined, undefined, null], | 
					
						
							|  |  |  |       [undefined, 'ERROR', undefined, null, undefined, 'WARNING', null, undefined], | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-05-18 04:00:04 +08:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-06-03 10:43:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-09 10:44:17 +08:00
										 |  |  | describe('prepareFieldsForPagination', () => { | 
					
						
							|  |  |  |   it('ignores frames without any time fields', () => { | 
					
						
							|  |  |  |     const frames = [ | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'a', type: FieldType.number, values: [1, 2, 3] }, | 
					
						
							|  |  |  |           { name: 'b', type: FieldType.string, values: ['a', 'b', 'c'] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  |     const normalizedFrames = makeFramePerSeries(frames); | 
					
						
							|  |  |  |     expect(normalizedFrames.length).toEqual(0); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('returns normalized frames, each with one time field and one value field', () => { | 
					
						
							|  |  |  |     const frames = [ | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'a', type: FieldType.time, values: [1, 2, 3] }, | 
					
						
							|  |  |  |           { name: 'b', type: FieldType.number, values: [100, 200, 300] }, | 
					
						
							|  |  |  |           { name: 'c', type: FieldType.string, values: ['h', 'i', 'j'] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |       toDataFrame({ | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'x', type: FieldType.time, values: [10, 20, 30] }, | 
					
						
							|  |  |  |           { name: 'y', type: FieldType.string, values: ['e', 'f', 'g'] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  |     const normalizedFrames = makeFramePerSeries(frames); | 
					
						
							|  |  |  |     expect(normalizedFrames.length).toEqual(3); | 
					
						
							|  |  |  |     expect(normalizedFrames).toMatchObject([ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'a', values: [1, 2, 3] }, | 
					
						
							|  |  |  |           { name: 'b', values: [100, 200, 300] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'a', values: [1, 2, 3] }, | 
					
						
							|  |  |  |           { name: 'c', values: ['h', 'i', 'j'] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { name: 'x', values: [10, 20, 30] }, | 
					
						
							|  |  |  |           { name: 'y', values: ['e', 'f', 'g'] }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 10:43:47 +08:00
										 |  |  | describe('findNextStateIndex', () => { | 
					
						
							|  |  |  |   it('handles leading datapoint index', () => { | 
					
						
							|  |  |  |     const field = { | 
					
						
							|  |  |  |       name: 'time', | 
					
						
							|  |  |  |       type: FieldType.number, | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |       values: [1, undefined, undefined, 2, undefined, undefined], | 
					
						
							| 
									
										
										
										
											2022-11-29 23:52:08 +08:00
										 |  |  |       config: {}, | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-06-03 10:43:47 +08:00
										 |  |  |     const result = findNextStateIndex(field, 0); | 
					
						
							|  |  |  |     expect(result).toEqual(3); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('handles trailing datapoint index', () => { | 
					
						
							|  |  |  |     const field = { | 
					
						
							|  |  |  |       name: 'time', | 
					
						
							|  |  |  |       type: FieldType.number, | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |       values: [1, undefined, undefined, 2, undefined, 3], | 
					
						
							| 
									
										
										
										
											2022-11-29 23:52:08 +08:00
										 |  |  |       config: {}, | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-06-03 10:43:47 +08:00
										 |  |  |     const result = findNextStateIndex(field, 5); | 
					
						
							|  |  |  |     expect(result).toEqual(null); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('handles trailing undefined', () => { | 
					
						
							|  |  |  |     const field = { | 
					
						
							|  |  |  |       name: 'time', | 
					
						
							|  |  |  |       type: FieldType.number, | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |       values: [1, undefined, undefined, 2, undefined, 3, undefined], | 
					
						
							| 
									
										
										
										
											2022-11-29 23:52:08 +08:00
										 |  |  |       config: {}, | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-06-03 10:43:47 +08:00
										 |  |  |     const result = findNextStateIndex(field, 5); | 
					
						
							|  |  |  |     expect(result).toEqual(null); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('handles datapoint index inside range', () => { | 
					
						
							|  |  |  |     const field = { | 
					
						
							|  |  |  |       name: 'time', | 
					
						
							|  |  |  |       type: FieldType.number, | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |       values: [1, undefined, undefined, 3, undefined, undefined, undefined, undefined, 2, undefined, undefined], | 
					
						
							| 
									
										
										
										
											2022-11-29 23:52:08 +08:00
										 |  |  |       config: {}, | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-06-03 10:43:47 +08:00
										 |  |  |     const result = findNextStateIndex(field, 3); | 
					
						
							|  |  |  |     expect(result).toEqual(8); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('single data points', () => { | 
					
						
							|  |  |  |     const field = { | 
					
						
							|  |  |  |       name: 'time', | 
					
						
							|  |  |  |       type: FieldType.number, | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |       values: [1, 3, 2], | 
					
						
							| 
									
										
										
										
											2022-11-29 23:52:08 +08:00
										 |  |  |       config: {}, | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-06-03 10:43:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     test('leading', () => { | 
					
						
							|  |  |  |       const result = findNextStateIndex(field, 0); | 
					
						
							|  |  |  |       expect(result).toEqual(1); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     test('trailing', () => { | 
					
						
							|  |  |  |       const result = findNextStateIndex(field, 2); | 
					
						
							|  |  |  |       expect(result).toEqual(null); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     test('inside', () => { | 
					
						
							|  |  |  |       const result = findNextStateIndex(field, 1); | 
					
						
							|  |  |  |       expect(result).toEqual(2); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-10-14 19:03:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | describe('getThresholdItems', () => { | 
					
						
							|  |  |  |   it('should handle only one threshold', () => { | 
					
						
							|  |  |  |     const result = getThresholdItems( | 
					
						
							|  |  |  |       { thresholds: { mode: ThresholdsMode.Absolute, steps: [{ color: 'black', value: 0 }] } }, | 
					
						
							|  |  |  |       theme | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(result).toHaveLength(1); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe('prepareTimelineLegendItems', () => { | 
					
						
							| 
									
										
										
										
											2022-12-14 13:56:59 +08:00
										 |  |  |   it('should return legend items without crashing when single (base) threshold', () => { | 
					
						
							| 
									
										
										
										
											2023-02-14 23:46:42 +08:00
										 |  |  |     const frames = [ | 
					
						
							| 
									
										
										
										
											2021-10-14 19:03:20 +08:00
										 |  |  |       { | 
					
						
							|  |  |  |         refId: 'A', | 
					
						
							|  |  |  |         fields: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             name: 'time', | 
					
						
							|  |  |  |             config: { | 
					
						
							|  |  |  |               color: { | 
					
						
							|  |  |  |                 mode: 'thresholds', | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               thresholds: { | 
					
						
							|  |  |  |                 mode: 'absolute', | 
					
						
							|  |  |  |                 steps: [ | 
					
						
							|  |  |  |                   { | 
					
						
							|  |  |  |                     color: 'green', | 
					
						
							|  |  |  |                     value: null, | 
					
						
							|  |  |  |                   }, | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |             values: [ | 
					
						
							| 
									
										
										
										
											2022-02-02 20:02:32 +08:00
										 |  |  |               1634092733455, 1634092763455, 1634092793455, 1634092823455, 1634092853455, 1634092883455, 1634092913455, | 
					
						
							|  |  |  |               1634092943455, 1634092973455, 1634093003455, | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |             ], | 
					
						
							| 
									
										
										
										
											2021-10-14 19:03:20 +08:00
										 |  |  |             display: (value: string) => ({ | 
					
						
							|  |  |  |               text: value, | 
					
						
							|  |  |  |               color: undefined, | 
					
						
							|  |  |  |               numeric: NaN, | 
					
						
							|  |  |  |             }), | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             name: 'A-series', | 
					
						
							|  |  |  |             config: { | 
					
						
							|  |  |  |               color: { | 
					
						
							|  |  |  |                 mode: 'thresholds', | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               thresholds: { | 
					
						
							|  |  |  |                 mode: 'absolute', | 
					
						
							|  |  |  |                 steps: [ | 
					
						
							|  |  |  |                   { | 
					
						
							|  |  |  |                     color: 'green', | 
					
						
							|  |  |  |                     value: null, | 
					
						
							|  |  |  |                   }, | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |             values: ['< -∞', null, null, null, null, null, null, null, null, null], | 
					
						
							| 
									
										
										
										
											2021-10-14 19:03:20 +08:00
										 |  |  |             display: (value?: string) => ({ | 
					
						
							|  |  |  |               text: value || '', | 
					
						
							|  |  |  |               color: 'green', | 
					
						
							|  |  |  |               numeric: NaN, | 
					
						
							|  |  |  |             }), | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2023-02-14 23:46:42 +08:00
										 |  |  |     ] as unknown as DataFrame[]; | 
					
						
							| 
									
										
										
										
											2021-10-14 19:03:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 23:52:08 +08:00
										 |  |  |     const result = prepareTimelineLegendItems( | 
					
						
							| 
									
										
										
										
											2023-02-14 23:46:42 +08:00
										 |  |  |       frames, | 
					
						
							| 
									
										
										
										
											2022-11-29 23:52:08 +08:00
										 |  |  |       { displayMode: LegendDisplayMode.List } as VizLegendOptions, | 
					
						
							|  |  |  |       theme | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2021-10-14 19:03:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     expect(result).toHaveLength(1); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2022-01-24 20:32:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | describe('duration', () => { | 
					
						
							|  |  |  |   it.each`
 | 
					
						
							|  |  |  |     value               | expected | 
					
						
							|  |  |  |     ${-1}               | ${''} | 
					
						
							|  |  |  |     ${20}               | ${'20ms'} | 
					
						
							|  |  |  |     ${1000}             | ${'1s'} | 
					
						
							|  |  |  |     ${1020}             | ${'1s 20ms'} | 
					
						
							|  |  |  |     ${60000}            | ${'1m'} | 
					
						
							|  |  |  |     ${61020}            | ${'1m 1s'} | 
					
						
							|  |  |  |     ${3600000}          | ${'1h'} | 
					
						
							|  |  |  |     ${6600000}          | ${'1h 50m'} | 
					
						
							|  |  |  |     ${86400000}         | ${'1d'} | 
					
						
							|  |  |  |     ${96640000}         | ${'1d 2h'} | 
					
						
							|  |  |  |     ${604800000}        | ${'1w'} | 
					
						
							|  |  |  |     ${691200000}        | ${'1w 1d'} | 
					
						
							|  |  |  |     ${2419200000}       | ${'4w'} | 
					
						
							|  |  |  |     ${2678400000}       | ${'1mo 1d'} | 
					
						
							|  |  |  |     ${3196800000}       | ${'1mo 1w'} | 
					
						
							|  |  |  |     ${3456000000}       | ${'1mo 1w 3d'} | 
					
						
							|  |  |  |     ${6739200000}       | ${'2mo 2w 4d'} | 
					
						
							|  |  |  |     ${31536000000}      | ${'1y'} | 
					
						
							|  |  |  |     ${31968000000}      | ${'1y 5d'} | 
					
						
							|  |  |  |     ${32140800000}      | ${'1y 1w'} | 
					
						
							|  |  |  |     ${67910400000}      | ${'2y 1mo 3w 5d'} | 
					
						
							|  |  |  |     ${40420800000}      | ${'1y 3mo 1w 5d'} | 
					
						
							|  |  |  |     ${9007199254740991} | ${'285616y 5mo 1d'} | 
					
						
							|  |  |  |   `(' function should format $value ms to $expected', ({ value, expected }) => {
 | 
					
						
							|  |  |  |     const result = fmtDuration(value); | 
					
						
							|  |  |  |     expect(result).toEqual(expected); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); |