|
|
|
@ -12,11 +12,14 @@ import { |
|
|
|
|
defaultDashboardV2Spec, |
|
|
|
|
defaultPanelSpec, |
|
|
|
|
defaultTimeSettingsSpec, |
|
|
|
|
PanelSpec, |
|
|
|
|
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0'; |
|
|
|
|
import { AnnoKeyDashboardSnapshotOriginalUrl } from 'app/features/apiserver/types'; |
|
|
|
|
import { SaveDashboardAsOptions } from 'app/features/dashboard/components/SaveDashboard/types'; |
|
|
|
|
import { DASHBOARD_SCHEMA_VERSION } from 'app/features/dashboard/state/DashboardMigrator'; |
|
|
|
|
|
|
|
|
|
import { buildPanelEditScene } from '../panel-edit/PanelEditor'; |
|
|
|
|
import { DashboardScene } from '../scene/DashboardScene'; |
|
|
|
|
import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene'; |
|
|
|
|
import { transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel'; |
|
|
|
|
import { findVizPanelByKey } from '../utils/utils'; |
|
|
|
@ -602,25 +605,204 @@ describe('DashboardSceneSerializer', () => { |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should throw on getSaveAsModel', () => { |
|
|
|
|
const serializer = new V2DashboardSerializer(); |
|
|
|
|
const dashboard = setup(); |
|
|
|
|
expect(() => serializer.getSaveAsModel(dashboard, {})).toThrow('Method not implemented.'); |
|
|
|
|
describe('getSaveAsModel', () => { |
|
|
|
|
let serializer: V2DashboardSerializer; |
|
|
|
|
let dashboard: DashboardScene; |
|
|
|
|
let baseOptions: SaveDashboardAsOptions; |
|
|
|
|
|
|
|
|
|
beforeEach(() => { |
|
|
|
|
serializer = new V2DashboardSerializer(); |
|
|
|
|
dashboard = setupV2(); |
|
|
|
|
baseOptions = { |
|
|
|
|
title: 'I am a new dashboard', |
|
|
|
|
description: 'description goes here', |
|
|
|
|
isNew: true, |
|
|
|
|
copyTags: true, |
|
|
|
|
}; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should set basic dashboard properties correctly', () => { |
|
|
|
|
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions); |
|
|
|
|
|
|
|
|
|
expect(saveAsModel).toMatchObject({ |
|
|
|
|
title: baseOptions.title, |
|
|
|
|
description: baseOptions.description, |
|
|
|
|
id: undefined, |
|
|
|
|
editable: true, |
|
|
|
|
annotations: [], |
|
|
|
|
cursorSync: 'Off', |
|
|
|
|
liveNow: false, |
|
|
|
|
preload: false, |
|
|
|
|
tags: [], |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should handle time settings correctly', () => { |
|
|
|
|
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions); |
|
|
|
|
|
|
|
|
|
expect(saveAsModel.timeSettings).toEqual({ |
|
|
|
|
autoRefresh: '10s', |
|
|
|
|
autoRefreshIntervals: ['5s', '10s', '30s', '1m', '5m', '15m', '30m', '1h', '2h', '1d'], |
|
|
|
|
fiscalYearStartMonth: 0, |
|
|
|
|
from: 'now-1h', |
|
|
|
|
hideTimepicker: false, |
|
|
|
|
nowDelay: undefined, |
|
|
|
|
quickRanges: [], |
|
|
|
|
timezone: 'browser', |
|
|
|
|
to: 'now', |
|
|
|
|
weekStart: '', |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should correctly serialize panel elements', () => { |
|
|
|
|
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions); |
|
|
|
|
|
|
|
|
|
expect(saveAsModel.elements['panel-1']).toMatchObject({ |
|
|
|
|
kind: 'Panel', |
|
|
|
|
spec: { |
|
|
|
|
data: { |
|
|
|
|
kind: 'QueryGroup', |
|
|
|
|
spec: { |
|
|
|
|
queries: [], |
|
|
|
|
queryOptions: {}, |
|
|
|
|
transformations: [], |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
description: '', |
|
|
|
|
id: 1, |
|
|
|
|
links: [], |
|
|
|
|
title: 'Panel 1', |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should correctly serialize layout configuration', () => { |
|
|
|
|
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions); |
|
|
|
|
|
|
|
|
|
expect(saveAsModel.layout).toEqual({ |
|
|
|
|
kind: 'GridLayout', |
|
|
|
|
spec: { |
|
|
|
|
items: [ |
|
|
|
|
{ |
|
|
|
|
kind: 'GridLayoutItem', |
|
|
|
|
spec: { |
|
|
|
|
element: { |
|
|
|
|
kind: 'ElementReference', |
|
|
|
|
name: 'panel-1', |
|
|
|
|
}, |
|
|
|
|
height: 8, |
|
|
|
|
width: 12, |
|
|
|
|
x: 0, |
|
|
|
|
y: 0, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
], |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should correctly serialize variables', () => { |
|
|
|
|
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions); |
|
|
|
|
|
|
|
|
|
expect(saveAsModel.variables).toEqual([ |
|
|
|
|
{ |
|
|
|
|
kind: 'CustomVariable', |
|
|
|
|
spec: { |
|
|
|
|
allValue: undefined, |
|
|
|
|
current: { |
|
|
|
|
text: 'app1', |
|
|
|
|
value: 'app1', |
|
|
|
|
}, |
|
|
|
|
description: 'A query variable', |
|
|
|
|
hide: 'dontHide', |
|
|
|
|
includeAll: false, |
|
|
|
|
label: 'Query Variable', |
|
|
|
|
multi: false, |
|
|
|
|
name: 'app', |
|
|
|
|
options: [], |
|
|
|
|
query: 'app1', |
|
|
|
|
skipUrlSync: false, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
]); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should handle empty dashboard state', () => { |
|
|
|
|
const emptyDashboard = setupV2({ |
|
|
|
|
elements: {}, |
|
|
|
|
layout: { kind: 'GridLayout', spec: { items: [] } }, |
|
|
|
|
variables: [], |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const saveAsModel = serializer.getSaveAsModel(emptyDashboard, baseOptions); |
|
|
|
|
|
|
|
|
|
expect(saveAsModel.elements).toEqual({}); |
|
|
|
|
expect(saveAsModel.layout.spec.items).toEqual([]); |
|
|
|
|
expect(saveAsModel.variables).toEqual([]); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should preserve visualization config', () => { |
|
|
|
|
const dashboardWithVizConfig = setupV2({ |
|
|
|
|
elements: { |
|
|
|
|
'panel-1': { |
|
|
|
|
kind: 'Panel', |
|
|
|
|
spec: { |
|
|
|
|
...defaultPanelSpec(), |
|
|
|
|
id: 1, |
|
|
|
|
title: 'Panel 1', |
|
|
|
|
vizConfig: { |
|
|
|
|
kind: 'graph', |
|
|
|
|
spec: { |
|
|
|
|
fieldConfig: { |
|
|
|
|
defaults: { custom: { lineWidth: 2 } }, |
|
|
|
|
overrides: [], |
|
|
|
|
}, |
|
|
|
|
options: { legend: { show: true } }, |
|
|
|
|
pluginVersion: '1.0.0', |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const saveAsModel = serializer.getSaveAsModel(dashboardWithVizConfig, baseOptions); |
|
|
|
|
|
|
|
|
|
const panelSpec = saveAsModel.elements['panel-1'].spec as PanelSpec; |
|
|
|
|
expect(panelSpec.vizConfig).toMatchObject({ |
|
|
|
|
kind: 'graph', |
|
|
|
|
spec: { |
|
|
|
|
fieldConfig: { |
|
|
|
|
defaults: { custom: { lineWidth: 2 } }, |
|
|
|
|
overrides: [], |
|
|
|
|
}, |
|
|
|
|
options: { legend: { show: true } }, |
|
|
|
|
pluginVersion: '1.0.0', |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should throw on onSaveComplete', () => { |
|
|
|
|
describe('onSaveComplete', () => { |
|
|
|
|
it('should set the initialSaveModel correctly', () => { |
|
|
|
|
const serializer = new V2DashboardSerializer(); |
|
|
|
|
const saveModel = defaultDashboardV2Spec(); |
|
|
|
|
const response = { |
|
|
|
|
id: 1, |
|
|
|
|
uid: 'aa', |
|
|
|
|
slug: 'slug', |
|
|
|
|
url: 'url', |
|
|
|
|
version: 2, |
|
|
|
|
status: 'status', |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
expect(() => |
|
|
|
|
serializer.onSaveComplete({} as DashboardV2Spec, { |
|
|
|
|
id: 1, |
|
|
|
|
uid: 'aa', |
|
|
|
|
slug: 'slug', |
|
|
|
|
url: 'url', |
|
|
|
|
version: 2, |
|
|
|
|
status: 'status', |
|
|
|
|
}) |
|
|
|
|
).toThrow('Method not implemented.'); |
|
|
|
|
serializer.onSaveComplete(saveModel, response); |
|
|
|
|
|
|
|
|
|
expect(serializer.initialSaveModel).toEqual({ |
|
|
|
|
...saveModel, |
|
|
|
|
id: response.id, |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
it('should allow retrieving snapshot url', () => { |
|
|
|
|