| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | import { advanceTo } from 'jest-date-mock'; | 
					
						
							|  |  |  | import { map, of } from 'rxjs'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   DataFrame, | 
					
						
							|  |  |  |   DataQueryRequest, | 
					
						
							|  |  |  |   DataSourceApi, | 
					
						
							|  |  |  |   dateTime, | 
					
						
							|  |  |  |   FieldType, | 
					
						
							|  |  |  |   PanelData, | 
					
						
							|  |  |  |   standardTransformersRegistry, | 
					
						
							|  |  |  |   StandardVariableQuery, | 
					
						
							|  |  |  |   toDataFrame, | 
					
						
							|  |  |  |   VariableSupportType, | 
					
						
							|  |  |  | } from '@grafana/data'; | 
					
						
							|  |  |  | import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks'; | 
					
						
							| 
									
										
										
										
											2023-11-28 19:26:09 +08:00
										 |  |  | import { getPluginLinkExtensions, setPluginImportUtils } from '@grafana/runtime'; | 
					
						
							| 
									
										
										
										
											2023-09-20 17:50:35 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   MultiValueVariable, | 
					
						
							|  |  |  |   SceneDataLayers, | 
					
						
							|  |  |  |   SceneGridItemLike, | 
					
						
							|  |  |  |   SceneGridLayout, | 
					
						
							|  |  |  |   SceneGridRow, | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  |   VizPanel, | 
					
						
							| 
									
										
										
										
											2023-09-20 17:50:35 +08:00
										 |  |  | } from '@grafana/scenes'; | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | import { Dashboard, LoadingState, Panel, RowPanel, VariableRefresh } from '@grafana/schema'; | 
					
						
							| 
									
										
										
										
											2023-09-01 16:21:41 +08:00
										 |  |  | import { PanelModel } from 'app/features/dashboard/state'; | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | import { getTimeRange } from 'app/features/dashboard/utils/timeRange'; | 
					
						
							|  |  |  | import { reduceTransformRegistryItem } from 'app/features/transformers/editors/ReduceTransformerEditor'; | 
					
						
							| 
									
										
										
										
											2023-10-04 17:31:16 +08:00
										 |  |  | import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard'; | 
					
						
							| 
									
										
										
										
											2023-09-01 16:21:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 18:02:04 +08:00
										 |  |  | import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior'; | 
					
						
							| 
									
										
										
										
											2024-01-16 19:24:54 +08:00
										 |  |  | import { NEW_LINK } from '../settings/links/utils'; | 
					
						
							| 
									
										
										
										
											2023-10-23 17:46:35 +08:00
										 |  |  | import { activateFullSceneTree, buildPanelRepeaterScene } from '../utils/test-utils'; | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | import { getVizPanelKeyForPanelId } from '../utils/utils'; | 
					
						
							| 
									
										
										
										
											2023-09-11 18:02:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | import { GRAFANA_DATASOURCE_REF } from './const'; | 
					
						
							| 
									
										
										
										
											2023-08-29 20:17:55 +08:00
										 |  |  | import dashboard_to_load1 from './testfiles/dashboard_to_load1.json'; | 
					
						
							| 
									
										
										
										
											2023-09-11 18:02:04 +08:00
										 |  |  | import repeatingRowsAndPanelsDashboardJson from './testfiles/repeating_rows_and_panels.json'; | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | import snapshotableDashboardJson from './testfiles/snapshotable_dashboard.json'; | 
					
						
							|  |  |  | import snapshotableWithRowsDashboardJson from './testfiles/snapshotable_with_rows.json'; | 
					
						
							| 
									
										
										
										
											2023-10-06 20:32:29 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   buildGridItemForLibPanel, | 
					
						
							|  |  |  |   buildGridItemForPanel, | 
					
						
							|  |  |  |   transformSaveModelToScene, | 
					
						
							|  |  |  | } from './transformSaveModelToScene'; | 
					
						
							| 
									
										
										
										
											2023-10-23 17:46:35 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   gridItemToPanel, | 
					
						
							|  |  |  |   gridRowToSaveModel, | 
					
						
							|  |  |  |   panelRepeaterToPanels, | 
					
						
							|  |  |  |   transformSceneToSaveModel, | 
					
						
							|  |  |  |   trimDashboardForSnapshot, | 
					
						
							|  |  |  | } from './transformSceneToSaveModel'; | 
					
						
							| 
									
										
										
										
											2023-08-29 20:17:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | standardTransformersRegistry.setInit(() => [reduceTransformRegistryItem]); | 
					
						
							|  |  |  | setPluginImportUtils({ | 
					
						
							|  |  |  |   importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})), | 
					
						
							|  |  |  |   getPanelPluginFromCache: (id: string) => undefined, | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const AFrame = toDataFrame({ | 
					
						
							|  |  |  |   name: 'A', | 
					
						
							|  |  |  |   fields: [ | 
					
						
							|  |  |  |     { name: 'time', type: FieldType.time, values: [100, 200, 300] }, | 
					
						
							|  |  |  |     { name: 'values', type: FieldType.number, values: [1, 2, 3] }, | 
					
						
							|  |  |  |   ], | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const BFrame = toDataFrame({ | 
					
						
							|  |  |  |   name: 'B', | 
					
						
							|  |  |  |   fields: [ | 
					
						
							|  |  |  |     { name: 'time', type: FieldType.time, values: [100, 200, 300] }, | 
					
						
							|  |  |  |     { name: 'values', type: FieldType.number, values: [10, 20, 30] }, | 
					
						
							|  |  |  |   ], | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const CFrame = toDataFrame({ | 
					
						
							|  |  |  |   name: 'C', | 
					
						
							|  |  |  |   fields: [ | 
					
						
							|  |  |  |     { name: 'time', type: FieldType.time, values: [1000, 2000, 3000] }, | 
					
						
							|  |  |  |     { name: 'values', type: FieldType.number, values: [100, 200, 300] }, | 
					
						
							|  |  |  |   ], | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const AnnoFrame = toDataFrame({ | 
					
						
							|  |  |  |   fields: [ | 
					
						
							|  |  |  |     { name: 'time', values: [1, 2, 2, 5, 5] }, | 
					
						
							|  |  |  |     { name: 'id', values: ['1', '2', '2', '5', '5'] }, | 
					
						
							|  |  |  |     { name: 'text', values: ['t1', 't2', 't3', 't4', 't5'] }, | 
					
						
							|  |  |  |   ], | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const VariableQueryFrame = toDataFrame({ | 
					
						
							|  |  |  |   fields: [{ name: 'text', type: FieldType.string, values: ['val1', 'val2', 'val11'] }], | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const testSeries: Record<string, DataFrame> = { | 
					
						
							|  |  |  |   A: AFrame, | 
					
						
							|  |  |  |   B: BFrame, | 
					
						
							|  |  |  |   C: CFrame, | 
					
						
							|  |  |  |   Anno: AnnoFrame, | 
					
						
							|  |  |  |   VariableQuery: VariableQueryFrame, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const runRequestMock = jest.fn().mockImplementation((ds: DataSourceApi, request: DataQueryRequest) => { | 
					
						
							|  |  |  |   const result: PanelData = { | 
					
						
							|  |  |  |     state: LoadingState.Loading, | 
					
						
							|  |  |  |     series: [], | 
					
						
							|  |  |  |     timeRange: request.range, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return of([]).pipe( | 
					
						
							|  |  |  |     map(() => { | 
					
						
							|  |  |  |       result.state = LoadingState.Done; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const refId = request.targets[0].refId; | 
					
						
							|  |  |  |       result.series = [testSeries[refId]]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return result; | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2023-11-23 22:15:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | jest.mock('@grafana/runtime', () => ({ | 
					
						
							|  |  |  |   ...jest.requireActual('@grafana/runtime'), | 
					
						
							|  |  |  |   getDataSourceSrv: () => ({ | 
					
						
							|  |  |  |     get: () => ({ | 
					
						
							|  |  |  |       getRef: () => ({ type: 'mock-ds', uid: 'mock-uid' }), | 
					
						
							|  |  |  |       variables: { | 
					
						
							|  |  |  |         getType: () => VariableSupportType.Standard, | 
					
						
							|  |  |  |         toDataQuery: (q: StandardVariableQuery) => q, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }), | 
					
						
							|  |  |  |   }), | 
					
						
							|  |  |  |   getRunRequest: () => (ds: DataSourceApi, request: DataQueryRequest) => { | 
					
						
							|  |  |  |     return runRequestMock(ds, request); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   config: { | 
					
						
							| 
									
										
										
										
											2023-11-23 22:15:36 +08:00
										 |  |  |     panels: { | 
					
						
							|  |  |  |       text: { skipDataQuery: true }, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2023-11-15 19:28:29 +08:00
										 |  |  |     featureToggles: { | 
					
						
							|  |  |  |       dataTrails: false, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  |     theme2: { | 
					
						
							|  |  |  |       visualization: { | 
					
						
							|  |  |  |         getColorByName: jest.fn().mockReturnValue('red'), | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }, | 
					
						
							| 
									
										
										
										
											2023-11-28 19:26:09 +08:00
										 |  |  |   setPluginExtensionGetter: jest.fn(), | 
					
						
							|  |  |  |   getPluginLinkExtensions: jest.fn(), | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | })); | 
					
						
							| 
									
										
										
										
											2023-11-15 20:05:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-28 19:26:09 +08:00
										 |  |  | const getPluginLinkExtensionsMock = jest.mocked(getPluginLinkExtensions); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-15 20:05:54 +08:00
										 |  |  | jest.mock('@grafana/scenes', () => ({ | 
					
						
							|  |  |  |   ...jest.requireActual('@grafana/scenes'), | 
					
						
							|  |  |  |   sceneUtils: { | 
					
						
							|  |  |  |     ...jest.requireActual('@grafana/scenes').sceneUtils, | 
					
						
							|  |  |  |     registerVariableMacro: jest.fn(), | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-29 20:17:55 +08:00
										 |  |  | describe('transformSceneToSaveModel', () => { | 
					
						
							| 
									
										
										
										
											2023-11-28 19:26:09 +08:00
										 |  |  |   beforeEach(() => { | 
					
						
							|  |  |  |     getPluginLinkExtensionsMock.mockRestore(); | 
					
						
							|  |  |  |     getPluginLinkExtensionsMock.mockReturnValue({ extensions: [] }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 23:04:56 +08:00
										 |  |  |   describe('Given a simple scene with custom settings', () => { | 
					
						
							|  |  |  |     it('Should transform back to persisted model', () => { | 
					
						
							|  |  |  |       const dashboardWithCustomSettings = { | 
					
						
							|  |  |  |         ...dashboard_to_load1, | 
					
						
							|  |  |  |         title: 'My custom title', | 
					
						
							|  |  |  |         description: 'My custom description', | 
					
						
							|  |  |  |         tags: ['tag1', 'tag2'], | 
					
						
							|  |  |  |         timezone: 'America/New_York', | 
					
						
							|  |  |  |         weekStart: 'monday', | 
					
						
							|  |  |  |         graphTooltip: 1, | 
					
						
							|  |  |  |         editable: false, | 
					
						
							|  |  |  |         timepicker: { | 
					
						
							|  |  |  |           ...dashboard_to_load1.timepicker, | 
					
						
							|  |  |  |           refresh_intervals: ['5m', '15m', '30m', '1h'], | 
					
						
							|  |  |  |           time_options: ['5m', '15m', '30m'], | 
					
						
							|  |  |  |           hidden: true, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2024-01-16 19:24:54 +08:00
										 |  |  |         links: [{ ...NEW_LINK, title: 'Link 1' }], | 
					
						
							| 
									
										
										
										
											2023-12-01 23:04:56 +08:00
										 |  |  |       }; | 
					
						
							|  |  |  |       const scene = transformSaveModelToScene({ dashboard: dashboardWithCustomSettings as any, meta: {} }); | 
					
						
							|  |  |  |       const saveModel = transformSceneToSaveModel(scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(saveModel).toMatchSnapshot(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-16 23:34:09 +08:00
										 |  |  |   describe('Given a simple scene with variables', () => { | 
					
						
							|  |  |  |     it('Should transform back to persisted model', () => { | 
					
						
							| 
									
										
										
										
											2023-08-29 20:17:55 +08:00
										 |  |  |       const scene = transformSaveModelToScene({ dashboard: dashboard_to_load1 as any, meta: {} }); | 
					
						
							|  |  |  |       const saveModel = transformSceneToSaveModel(scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(saveModel).toMatchSnapshot(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2023-09-01 16:21:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-11 18:02:04 +08:00
										 |  |  |   describe('Given a scene with rows', () => { | 
					
						
							| 
									
										
										
										
											2023-10-16 23:34:09 +08:00
										 |  |  |     it('Should transform back to persisted model', () => { | 
					
						
							| 
									
										
										
										
											2023-09-11 18:02:04 +08:00
										 |  |  |       const scene = transformSaveModelToScene({ dashboard: repeatingRowsAndPanelsDashboardJson as any, meta: {} }); | 
					
						
							|  |  |  |       const saveModel = transformSceneToSaveModel(scene); | 
					
						
							|  |  |  |       const row2: RowPanel = saveModel.panels![2] as RowPanel; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(row2.type).toBe('row'); | 
					
						
							|  |  |  |       expect(row2.repeat).toBe('server'); | 
					
						
							|  |  |  |       expect(saveModel).toMatchSnapshot(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('Should remove repeated rows in save model', () => { | 
					
						
							|  |  |  |       const scene = transformSaveModelToScene({ dashboard: repeatingRowsAndPanelsDashboardJson as any, meta: {} }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const variable = scene.state.$variables?.state.variables[0] as MultiValueVariable; | 
					
						
							|  |  |  |       variable.changeValueTo(['a', 'b', 'c']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const grid = scene.state.body as SceneGridLayout; | 
					
						
							|  |  |  |       const rowWithRepeat = grid.state.children[1] as SceneGridRow; | 
					
						
							|  |  |  |       const rowRepeater = rowWithRepeat.state.$behaviors![0] as RowRepeaterBehavior; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // trigger row repeater
 | 
					
						
							| 
									
										
										
										
											2024-01-23 02:22:04 +08:00
										 |  |  |       rowRepeater.variableDependency?.variableUpdateCompleted(variable, true); | 
					
						
							| 
									
										
										
										
											2023-09-11 18:02:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // Make sure the repeated rows have been added to runtime scene model
 | 
					
						
							|  |  |  |       expect(grid.state.children.length).toBe(5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const saveModel = transformSceneToSaveModel(scene); | 
					
						
							|  |  |  |       const rows = saveModel.panels!.filter((p) => p.type === 'row'); | 
					
						
							|  |  |  |       // Verify the save model does not contain any repeated rows
 | 
					
						
							|  |  |  |       expect(rows.length).toBe(3); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-01 16:21:41 +08:00
										 |  |  |   describe('Panel options', () => { | 
					
						
							|  |  |  |     it('Given panel with time override', () => { | 
					
						
							| 
									
										
										
										
											2023-09-05 19:51:46 +08:00
										 |  |  |       const gridItem = buildGridItemFromPanelSchema({ | 
					
						
							| 
									
										
										
										
											2023-09-01 16:21:41 +08:00
										 |  |  |         timeFrom: '2h', | 
					
						
							|  |  |  |         timeShift: '1d', | 
					
						
							|  |  |  |         hideTimeOverride: true, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const saveModel = gridItemToPanel(gridItem); | 
					
						
							|  |  |  |       expect(saveModel.timeFrom).toBe('2h'); | 
					
						
							|  |  |  |       expect(saveModel.timeShift).toBe('1d'); | 
					
						
							|  |  |  |       expect(saveModel.hideTimeOverride).toBe(true); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('transparent panel', () => { | 
					
						
							| 
									
										
										
										
											2023-09-05 19:51:46 +08:00
										 |  |  |       const gridItem = buildGridItemFromPanelSchema({ transparent: true }); | 
					
						
							| 
									
										
										
										
											2023-09-01 16:21:41 +08:00
										 |  |  |       const saveModel = gridItemToPanel(gridItem); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(saveModel.transparent).toBe(true); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2023-09-05 19:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('Given panel with repeat', () => { | 
					
						
							|  |  |  |       const gridItem = buildGridItemFromPanelSchema({ | 
					
						
							|  |  |  |         title: '', | 
					
						
							|  |  |  |         type: 'text-plugin-34', | 
					
						
							|  |  |  |         gridPos: { x: 1, y: 2, w: 12, h: 8 }, | 
					
						
							|  |  |  |         repeat: 'server', | 
					
						
							|  |  |  |         repeatDirection: 'v', | 
					
						
							|  |  |  |         maxPerRow: 8, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const saveModel = gridItemToPanel(gridItem); | 
					
						
							|  |  |  |       expect(saveModel.repeat).toBe('server'); | 
					
						
							|  |  |  |       expect(saveModel.repeatDirection).toBe('v'); | 
					
						
							|  |  |  |       expect(saveModel.maxPerRow).toBe(8); | 
					
						
							|  |  |  |       expect(saveModel.gridPos?.x).toBe(1); | 
					
						
							|  |  |  |       expect(saveModel.gridPos?.y).toBe(2); | 
					
						
							|  |  |  |       expect(saveModel.gridPos?.w).toBe(12); | 
					
						
							|  |  |  |       expect(saveModel.gridPos?.h).toBe(8); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-01-31 19:30:27 +08:00
										 |  |  |     it('Given panel with links', () => { | 
					
						
							|  |  |  |       const gridItem = buildGridItemFromPanelSchema({ | 
					
						
							|  |  |  |         title: '', | 
					
						
							|  |  |  |         type: 'text-plugin-34', | 
					
						
							|  |  |  |         gridPos: { x: 1, y: 2, w: 12, h: 8 }, | 
					
						
							|  |  |  |         links: [ | 
					
						
							|  |  |  |           // @ts-expect-error Panel link is wrongly typed as DashboardLink
 | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             title: 'Link 1', | 
					
						
							|  |  |  |             url: 'http://some.test.link1', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           // @ts-expect-error Panel link is wrongly typed as DashboardLink
 | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             targetBlank: true, | 
					
						
							|  |  |  |             title: 'Link 2', | 
					
						
							|  |  |  |             url: 'http://some.test.link2', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const saveModel = gridItemToPanel(gridItem); | 
					
						
							|  |  |  |       expect(saveModel.links).toEqual([ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           title: 'Link 1', | 
					
						
							|  |  |  |           url: 'http://some.test.link1', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           targetBlank: true, | 
					
						
							|  |  |  |           title: 'Link 2', | 
					
						
							|  |  |  |           url: 'http://some.test.link2', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2023-09-01 16:21:41 +08:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2023-09-20 17:50:35 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-06 20:32:29 +08:00
										 |  |  |   describe('Library panels', () => { | 
					
						
							|  |  |  |     it('given a library panel', () => { | 
					
						
							|  |  |  |       const panel = buildGridItemFromPanelSchema({ | 
					
						
							|  |  |  |         id: 4, | 
					
						
							|  |  |  |         gridPos: { | 
					
						
							|  |  |  |           h: 8, | 
					
						
							|  |  |  |           w: 12, | 
					
						
							|  |  |  |           x: 0, | 
					
						
							|  |  |  |           y: 0, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         libraryPanel: { | 
					
						
							|  |  |  |           name: 'Some lib panel panel', | 
					
						
							|  |  |  |           uid: 'lib-panel-uid', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         title: 'A panel', | 
					
						
							|  |  |  |         transformations: [], | 
					
						
							|  |  |  |         fieldConfig: { | 
					
						
							|  |  |  |           defaults: {}, | 
					
						
							|  |  |  |           overrides: [], | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const result = gridItemToPanel(panel); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(result.id).toBe(4); | 
					
						
							|  |  |  |       expect(result.libraryPanel).toEqual({ | 
					
						
							|  |  |  |         name: 'Some lib panel panel', | 
					
						
							|  |  |  |         uid: 'lib-panel-uid', | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       expect(result.gridPos).toEqual({ | 
					
						
							|  |  |  |         h: 8, | 
					
						
							|  |  |  |         w: 12, | 
					
						
							|  |  |  |         x: 0, | 
					
						
							|  |  |  |         y: 0, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       expect(result.title).toBe('A panel'); | 
					
						
							|  |  |  |       expect(result.transformations).toBeUndefined(); | 
					
						
							|  |  |  |       expect(result.fieldConfig).toBeUndefined(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-20 17:50:35 +08:00
										 |  |  |   describe('Annotations', () => { | 
					
						
							|  |  |  |     it('should transform annotations to save model', () => { | 
					
						
							|  |  |  |       const scene = transformSaveModelToScene({ dashboard: dashboard_to_load1 as any, meta: {} }); | 
					
						
							|  |  |  |       const saveModel = transformSceneToSaveModel(scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(saveModel.annotations?.list?.length).toBe(4); | 
					
						
							|  |  |  |       expect(saveModel.annotations?.list).toMatchSnapshot(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('should transform annotations to save model after state changes', () => { | 
					
						
							|  |  |  |       const scene = transformSaveModelToScene({ dashboard: dashboard_to_load1 as any, meta: {} }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const layers = (scene.state.$data as SceneDataLayers)?.state.layers; | 
					
						
							|  |  |  |       const enabledLayer = layers[1]; | 
					
						
							|  |  |  |       const hiddenLayer = layers[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       enabledLayer.setState({ | 
					
						
							|  |  |  |         isEnabled: false, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       hiddenLayer.setState({ | 
					
						
							|  |  |  |         isHidden: false, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const saveModel = transformSceneToSaveModel(scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(saveModel.annotations?.list?.length).toBe(4); | 
					
						
							|  |  |  |       expect(saveModel.annotations?.list?.[1].enable).toEqual(false); | 
					
						
							|  |  |  |       expect(saveModel.annotations?.list?.[3].hide).toEqual(false); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2023-10-04 17:31:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('Queries', () => { | 
					
						
							|  |  |  |     it('Given panel with queries', () => { | 
					
						
							|  |  |  |       const panel = buildGridItemFromPanelSchema({ | 
					
						
							|  |  |  |         datasource: { | 
					
						
							|  |  |  |           type: 'grafana-testdata', | 
					
						
							|  |  |  |           uid: 'abc', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         maxDataPoints: 100, | 
					
						
							|  |  |  |         targets: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             refId: 'A', | 
					
						
							|  |  |  |             expr: 'A', | 
					
						
							|  |  |  |             datasource: { | 
					
						
							|  |  |  |               type: 'grafana-testdata', | 
					
						
							|  |  |  |               uid: 'abc', | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             refId: 'B', | 
					
						
							|  |  |  |             expr: 'B', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const result = gridItemToPanel(panel); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(result.maxDataPoints).toBe(100); | 
					
						
							|  |  |  |       expect(result.targets?.length).toBe(2); | 
					
						
							|  |  |  |       expect(result.targets?.[0]).toEqual({ | 
					
						
							|  |  |  |         refId: 'A', | 
					
						
							|  |  |  |         expr: 'A', | 
					
						
							|  |  |  |         datasource: { | 
					
						
							|  |  |  |           type: 'grafana-testdata', | 
					
						
							|  |  |  |           uid: 'abc', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(result.datasource).toEqual({ | 
					
						
							|  |  |  |         type: 'grafana-testdata', | 
					
						
							|  |  |  |         uid: 'abc', | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('Given panel with transformations', () => { | 
					
						
							|  |  |  |       const panel = buildGridItemFromPanelSchema({ | 
					
						
							|  |  |  |         datasource: { | 
					
						
							|  |  |  |           type: 'grafana-testdata', | 
					
						
							|  |  |  |           uid: 'abc', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         maxDataPoints: 100, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         transformations: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             id: 'reduce', | 
					
						
							|  |  |  |             options: { | 
					
						
							|  |  |  |               reducers: ['max'], | 
					
						
							|  |  |  |               mode: 'reduceFields', | 
					
						
							|  |  |  |               includeTimeField: false, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         targets: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             refId: 'A', | 
					
						
							|  |  |  |             expr: 'A', | 
					
						
							|  |  |  |             datasource: { | 
					
						
							|  |  |  |               type: 'grafana-testdata', | 
					
						
							|  |  |  |               uid: 'abc', | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             refId: 'B', | 
					
						
							|  |  |  |             expr: 'B', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const result = gridItemToPanel(panel); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-11 21:56:42 +08:00
										 |  |  |       expect(result.transformations?.length).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-10-04 17:31:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       expect(result.maxDataPoints).toBe(100); | 
					
						
							|  |  |  |       expect(result.targets?.length).toBe(2); | 
					
						
							|  |  |  |       expect(result.targets?.[0]).toEqual({ | 
					
						
							|  |  |  |         refId: 'A', | 
					
						
							|  |  |  |         expr: 'A', | 
					
						
							|  |  |  |         datasource: { | 
					
						
							|  |  |  |           type: 'grafana-testdata', | 
					
						
							|  |  |  |           uid: 'abc', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(result.datasource).toEqual({ | 
					
						
							|  |  |  |         type: 'grafana-testdata', | 
					
						
							|  |  |  |         uid: 'abc', | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     it('Given panel with shared query', () => { | 
					
						
							|  |  |  |       const panel = buildGridItemFromPanelSchema({ | 
					
						
							|  |  |  |         datasource: { | 
					
						
							|  |  |  |           type: 'datasource', | 
					
						
							|  |  |  |           uid: SHARED_DASHBOARD_QUERY, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         targets: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             refId: 'A', | 
					
						
							|  |  |  |             panelId: 1, | 
					
						
							|  |  |  |             datasource: { | 
					
						
							|  |  |  |               type: 'datasource', | 
					
						
							|  |  |  |               uid: SHARED_DASHBOARD_QUERY, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const result = gridItemToPanel(panel); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(result.targets?.length).toBe(1); | 
					
						
							|  |  |  |       expect(result.targets?.[0]).toEqual({ | 
					
						
							|  |  |  |         refId: 'A', | 
					
						
							|  |  |  |         panelId: 1, | 
					
						
							|  |  |  |         datasource: { | 
					
						
							|  |  |  |           type: 'datasource', | 
					
						
							|  |  |  |           uid: SHARED_DASHBOARD_QUERY, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(result.datasource).toEqual({ | 
					
						
							|  |  |  |         type: 'datasource', | 
					
						
							|  |  |  |         uid: SHARED_DASHBOARD_QUERY, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('Given panel with shared query and transformations', () => { | 
					
						
							|  |  |  |       const panel = buildGridItemFromPanelSchema({ | 
					
						
							|  |  |  |         datasource: { | 
					
						
							|  |  |  |           type: 'datasource', | 
					
						
							|  |  |  |           uid: SHARED_DASHBOARD_QUERY, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         targets: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             refId: 'A', | 
					
						
							|  |  |  |             panelId: 1, | 
					
						
							|  |  |  |             datasource: { | 
					
						
							|  |  |  |               type: 'datasource', | 
					
						
							|  |  |  |               uid: SHARED_DASHBOARD_QUERY, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         transformations: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             id: 'reduce', | 
					
						
							|  |  |  |             options: { | 
					
						
							|  |  |  |               reducers: ['max'], | 
					
						
							|  |  |  |               mode: 'reduceFields', | 
					
						
							|  |  |  |               includeTimeField: false, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const result = gridItemToPanel(panel); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-11 21:56:42 +08:00
										 |  |  |       expect(result.transformations?.length).toBe(1); | 
					
						
							| 
									
										
										
										
											2023-10-04 17:31:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       expect(result.targets?.length).toBe(1); | 
					
						
							|  |  |  |       expect(result.targets?.[0]).toEqual({ | 
					
						
							|  |  |  |         refId: 'A', | 
					
						
							|  |  |  |         panelId: 1, | 
					
						
							|  |  |  |         datasource: { | 
					
						
							|  |  |  |           type: 'datasource', | 
					
						
							|  |  |  |           uid: SHARED_DASHBOARD_QUERY, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(result.datasource).toEqual({ | 
					
						
							|  |  |  |         type: 'datasource', | 
					
						
							|  |  |  |         uid: SHARED_DASHBOARD_QUERY, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-02-15 01:19:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('Given panel with query caching options', () => { | 
					
						
							|  |  |  |       const panel = buildGridItemFromPanelSchema({ | 
					
						
							|  |  |  |         datasource: { | 
					
						
							|  |  |  |           type: 'grafana-testdata', | 
					
						
							|  |  |  |           uid: 'abc', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         cacheTimeout: '10', | 
					
						
							|  |  |  |         queryCachingTTL: 200000, | 
					
						
							|  |  |  |         maxDataPoints: 100, | 
					
						
							|  |  |  |         targets: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             refId: 'A', | 
					
						
							|  |  |  |             expr: 'A', | 
					
						
							|  |  |  |             datasource: { | 
					
						
							|  |  |  |               type: 'grafana-testdata', | 
					
						
							|  |  |  |               uid: 'abc', | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             refId: 'B', | 
					
						
							|  |  |  |             expr: 'B', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const result = gridItemToPanel(panel); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(result.cacheTimeout).toBe('10'); | 
					
						
							|  |  |  |       expect(result.queryCachingTTL).toBe(200000); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2023-10-04 17:31:16 +08:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('Snapshots', () => { | 
					
						
							|  |  |  |     const fakeCurrentDate = dateTime('2023-01-01T20:00:00.000Z').toDate(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       advanceTo(fakeCurrentDate); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('attaches snapshot data to panels using Grafana snapshot query', async () => { | 
					
						
							|  |  |  |       const scene = transformSaveModelToScene({ dashboard: snapshotableDashboardJson as any, meta: {} }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       activateFullSceneTree(scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       await new Promise((r) => setTimeout(r, 1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const snapshot = transformSceneToSaveModel(scene, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.length).toBe(3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Regular panel with SceneQueryRunner
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[0].datasource).toEqual(GRAFANA_DATASOURCE_REF); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[0].targets?.[0].datasource).toEqual(GRAFANA_DATASOURCE_REF); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[0].targets?.[0].snapshot[0].data).toEqual({ | 
					
						
							|  |  |  |         values: [ | 
					
						
							|  |  |  |           [100, 200, 300], | 
					
						
							|  |  |  |           [1, 2, 3], | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Panel with transformations
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[1].datasource).toEqual(GRAFANA_DATASOURCE_REF); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[1].targets?.[0].datasource).toEqual(GRAFANA_DATASOURCE_REF); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[1].targets?.[0].snapshot[0].data).toEqual({ | 
					
						
							|  |  |  |         values: [ | 
					
						
							|  |  |  |           [100, 200, 300], | 
					
						
							|  |  |  |           [10, 20, 30], | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[1].transformations).toEqual([ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           id: 'reduce', | 
					
						
							|  |  |  |           options: {}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Panel with a shared query (dahsboard query)
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[2].datasource).toEqual(GRAFANA_DATASOURCE_REF); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[2].targets?.[0].datasource).toEqual(GRAFANA_DATASOURCE_REF); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[2].targets?.[0].snapshot[0].data).toEqual({ | 
					
						
							|  |  |  |         values: [ | 
					
						
							|  |  |  |           [100, 200, 300], | 
					
						
							|  |  |  |           [1, 2, 3], | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('handles basic rows', async () => { | 
					
						
							|  |  |  |       const scene = transformSaveModelToScene({ dashboard: snapshotableWithRowsDashboardJson as any, meta: {} }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       activateFullSceneTree(scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       await new Promise((r) => setTimeout(r, 1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const snapshot = transformSceneToSaveModel(scene, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.length).toBe(5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[0].targets?.[0].datasource).toEqual(GRAFANA_DATASOURCE_REF); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[0].targets?.[0].snapshot[0].data).toEqual({ | 
					
						
							|  |  |  |         values: [ | 
					
						
							|  |  |  |           [100, 200, 300], | 
					
						
							|  |  |  |           [1, 2, 3], | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[1].targets).toBeUndefined(); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[1].panels).toEqual([]); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[1].collapsed).toEqual(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[2].targets?.[0].datasource).toEqual(GRAFANA_DATASOURCE_REF); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[2].targets?.[0].snapshot[0].data).toEqual({ | 
					
						
							|  |  |  |         values: [ | 
					
						
							|  |  |  |           [100, 200, 300], | 
					
						
							|  |  |  |           [10, 20, 30], | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[3].targets?.[0].datasource).toEqual(GRAFANA_DATASOURCE_REF); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[3].targets?.[0].snapshot[0].data).toEqual({ | 
					
						
							|  |  |  |         values: [ | 
					
						
							|  |  |  |           [1000, 2000, 3000], | 
					
						
							|  |  |  |           [100, 200, 300], | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[4].targets).toBeUndefined(); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[4].panels).toHaveLength(1); | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(snapshot.panels?.[4].collapsed).toEqual(true); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-23 17:46:35 +08:00
										 |  |  |     describe('repeats', () => { | 
					
						
							|  |  |  |       it('handles repeated panels', async () => { | 
					
						
							|  |  |  |         const { scene, repeater } = buildPanelRepeaterScene({ variableQueryTime: 0, numberOfOptions: 2 }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         activateFullSceneTree(scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(repeater.state.repeatedPanels?.length).toBe(2); | 
					
						
							|  |  |  |         const result = panelRepeaterToPanels(repeater, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(result).toHaveLength(2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // @ts-expect-error
 | 
					
						
							|  |  |  |         expect(result[0].scopedVars).toEqual({ | 
					
						
							|  |  |  |           server: { | 
					
						
							|  |  |  |             text: 'A', | 
					
						
							|  |  |  |             value: '1', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         // @ts-expect-error
 | 
					
						
							|  |  |  |         expect(result[1].scopedVars).toEqual({ | 
					
						
							|  |  |  |           server: { | 
					
						
							|  |  |  |             text: 'B', | 
					
						
							|  |  |  |             value: '2', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(result[0].title).toEqual('Panel $server'); | 
					
						
							|  |  |  |         expect(result[1].title).toEqual('Panel $server'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('handles row repeats ', () => { | 
					
						
							|  |  |  |         const { scene, row } = buildPanelRepeaterScene({ | 
					
						
							|  |  |  |           variableQueryTime: 0, | 
					
						
							|  |  |  |           numberOfOptions: 2, | 
					
						
							|  |  |  |           useRowRepeater: true, | 
					
						
							|  |  |  |           usePanelRepeater: false, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         activateFullSceneTree(scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let panels: Panel[] = []; | 
					
						
							|  |  |  |         gridRowToSaveModel(row, panels, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(panels).toHaveLength(2); | 
					
						
							|  |  |  |         expect(panels[0].repeat).toBe('handler'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // @ts-expect-error
 | 
					
						
							|  |  |  |         expect(panels[0].scopedVars).toEqual({ | 
					
						
							|  |  |  |           handler: { | 
					
						
							|  |  |  |             text: 'AA', | 
					
						
							|  |  |  |             value: '11', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(panels[1].title).toEqual('Panel $server'); | 
					
						
							|  |  |  |         expect(panels[1].gridPos).toEqual({ x: 0, y: 0, w: 10, h: 10 }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('handles row repeats with panel repeater', () => { | 
					
						
							|  |  |  |         const { scene, row } = buildPanelRepeaterScene({ | 
					
						
							|  |  |  |           variableQueryTime: 0, | 
					
						
							|  |  |  |           numberOfOptions: 2, | 
					
						
							|  |  |  |           useRowRepeater: true, | 
					
						
							|  |  |  |           usePanelRepeater: true, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         activateFullSceneTree(scene); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let panels: Panel[] = []; | 
					
						
							|  |  |  |         gridRowToSaveModel(row, panels, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(panels[0].repeat).toBe('handler'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // @ts-expect-error
 | 
					
						
							|  |  |  |         expect(panels[0].scopedVars).toEqual({ | 
					
						
							|  |  |  |           handler: { | 
					
						
							|  |  |  |             text: 'AA', | 
					
						
							|  |  |  |             value: '11', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // @ts-expect-error
 | 
					
						
							|  |  |  |         expect(panels[1].scopedVars).toEqual({ | 
					
						
							|  |  |  |           server: { | 
					
						
							|  |  |  |             text: 'A', | 
					
						
							|  |  |  |             value: '1', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         // @ts-expect-error
 | 
					
						
							|  |  |  |         expect(panels[2].scopedVars).toEqual({ | 
					
						
							|  |  |  |           server: { | 
					
						
							|  |  |  |             text: 'B', | 
					
						
							|  |  |  |             value: '2', | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(panels[1].title).toEqual('Panel $server'); | 
					
						
							|  |  |  |         expect(panels[2].title).toEqual('Panel $server'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  |     describe('trimDashboardForSnapshot', () => { | 
					
						
							|  |  |  |       let snapshot: Dashboard = {} as Dashboard; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       beforeEach(() => { | 
					
						
							|  |  |  |         const scene = transformSaveModelToScene({ dashboard: snapshotableDashboardJson as any, meta: {} }); | 
					
						
							|  |  |  |         activateFullSceneTree(scene); | 
					
						
							|  |  |  |         snapshot = transformSceneToSaveModel(scene, true); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not mutate provided dashboard', () => { | 
					
						
							|  |  |  |         const result = trimDashboardForSnapshot('Snap title', getTimeRange({ from: 'now-6h', to: 'now' }), snapshot); | 
					
						
							|  |  |  |         expect(result).not.toBe(snapshot); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should apply provided title and absolute time range', async () => { | 
					
						
							|  |  |  |         const result = trimDashboardForSnapshot('Snap title', getTimeRange({ from: 'now-6h', to: 'now' }), snapshot); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(result.title).toBe('Snap title'); | 
					
						
							|  |  |  |         expect(result.time).toBeDefined(); | 
					
						
							|  |  |  |         expect(result.time!.from).toEqual('2023-01-01T14:00:00.000Z'); | 
					
						
							|  |  |  |         expect(result.time!.to).toEqual('2023-01-01T20:00:00.000Z'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should remove queries from annotations and attach empty snapshotData', () => { | 
					
						
							|  |  |  |         expect(snapshot.annotations?.list?.[0].target).toBeDefined(); | 
					
						
							|  |  |  |         expect(snapshot.annotations?.list?.[1].target).toBeDefined(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const result = trimDashboardForSnapshot('Snap title', getTimeRange({ from: 'now-6h', to: 'now' }), snapshot); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(result.annotations?.list?.length).toBe(2); | 
					
						
							|  |  |  |         expect(result.annotations?.list?.[0].target).toBeUndefined(); | 
					
						
							|  |  |  |         expect(result.annotations?.list?.[0].snapshotData).toEqual([]); | 
					
						
							|  |  |  |         expect(result.annotations?.list?.[1].target).toBeUndefined(); | 
					
						
							|  |  |  |         expect(result.annotations?.list?.[1].snapshotData).toEqual([]); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       it('should remove queries from variables', () => { | 
					
						
							|  |  |  |         expect(snapshot.templating?.list?.length).toBe(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const result = trimDashboardForSnapshot('Snap title', getTimeRange({ from: 'now-6h', to: 'now' }), snapshot); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(result.templating?.list?.length).toBe(1); | 
					
						
							|  |  |  |         expect(result.templating?.list?.[0].query).toBe(''); | 
					
						
							|  |  |  |         expect(result.templating?.list?.[0].refresh).toBe(VariableRefresh.never); | 
					
						
							|  |  |  |         expect(result.templating?.list?.[0].options).toHaveLength(1); | 
					
						
							|  |  |  |         expect(result.templating?.list?.[0].options?.[0]).toEqual({ | 
					
						
							|  |  |  |           text: 'annotations', | 
					
						
							|  |  |  |           value: 'annotations', | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should snapshot a single panel when provided', () => { | 
					
						
							|  |  |  |         const vizPanel = new VizPanel({ | 
					
						
							|  |  |  |           key: getVizPanelKeyForPanelId(2), | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const result = trimDashboardForSnapshot( | 
					
						
							|  |  |  |           'Snap title', | 
					
						
							|  |  |  |           getTimeRange({ from: 'now-6h', to: 'now' }), | 
					
						
							|  |  |  |           snapshot, | 
					
						
							|  |  |  |           vizPanel | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(snapshot.panels?.length).toBe(3); | 
					
						
							|  |  |  |         expect(result.panels?.length).toBe(1); | 
					
						
							|  |  |  |         expect(result.panels?.[0].gridPos).toEqual({ w: 24, x: 0, y: 0, h: 20 }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-16 19:24:54 +08:00
										 |  |  |       it('should remove links', async () => { | 
					
						
							|  |  |  |         const scene = transformSaveModelToScene({ dashboard: snapshotableDashboardJson as any, meta: {} }); | 
					
						
							|  |  |  |         activateFullSceneTree(scene); | 
					
						
							|  |  |  |         const snapshot = transformSceneToSaveModel(scene, true); | 
					
						
							|  |  |  |         expect(snapshot.links?.length).toBe(1); | 
					
						
							|  |  |  |         const result = trimDashboardForSnapshot('Snap title', getTimeRange({ from: 'now-6h', to: 'now' }), snapshot); | 
					
						
							|  |  |  |         expect(result.links?.length).toBe(0); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2023-10-11 19:24:18 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2023-08-29 20:17:55 +08:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2023-09-01 16:21:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 19:51:46 +08:00
										 |  |  | export function buildGridItemFromPanelSchema(panel: Partial<Panel>): SceneGridItemLike { | 
					
						
							| 
									
										
										
										
											2023-10-06 20:32:29 +08:00
										 |  |  |   if (panel.libraryPanel) { | 
					
						
							|  |  |  |     return buildGridItemForLibPanel(new PanelModel(panel))!; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-09-05 19:51:46 +08:00
										 |  |  |   return buildGridItemForPanel(new PanelModel(panel)); | 
					
						
							| 
									
										
										
										
											2023-09-01 16:21:41 +08:00
										 |  |  | } |