Add tests to SceneToSaveModelV2 transformer (#96700)

* Add tests to SceneToSaveModelV2 transformer

* Add text properties always
This commit is contained in:
Ivan Ortega Alba
2024-11-20 14:53:58 +02:00
committed by GitHub
parent cb7dd25f8a
commit 1a7faed56a
8 changed files with 633 additions and 9 deletions
@@ -31,9 +31,13 @@ export interface DashboardV2Spec {
// |* more element types in the future
elements: Record<string, PanelKind>;
annotations: AnnotationQueryKind[];
layout: GridLayoutKind;
// Version of the JSON schema, incremented each time a Grafana update brings
// changes to said schema.
// version: will rely on k8s resource versioning, via metadata.resorceVersion
// revision?: int // for plugins only
// gnetId?: string // ??? Wat is this used for?
layout: GridLayoutKind;
schemaVersion: number;
}
export const defaultDashboardV2Spec = (): DashboardV2Spec => ({
@@ -47,6 +51,7 @@ export const defaultDashboardV2Spec = (): DashboardV2Spec => ({
elements: {},
annotations: [],
layout: defaultGridLayoutKind(),
schemaVersion: 39,
});
export interface AnnotationPanelFilter {
@@ -45,8 +45,12 @@ DashboardV2Spec: {
layout: GridLayoutKind
// version: will rely on k8s resource versioning, via metadata.resorceVersion
// Version of the JSON schema, incremented each time a Grafana update brings
// changes to said schema.
schemaVersion: uint16 | *39
// version: will rely on k8s resource versioning, via metadata.resorceVersion
// revision?: int // for plugins only
// gnetId?: string // ??? Wat is this used for?
}
@@ -10,6 +10,7 @@ export const handyTestingSchema: DashboardV2Spec = {
editable: true,
links: [],
tags: [],
schemaVersion: 39,
timeSettings: {
timezone: 'browser',
from: 'now-6h',
@@ -0,0 +1,319 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model schema v2 1`] = `
{
"annotations": [],
"cursorSync": "Crosshair",
"description": "Test Description",
"editable": true,
"elements": {
"test-panel-uid": {
"kind": "Panel",
"spec": {
"data": {
"kind": "QueryGroup",
"spec": {
"queries": [],
"queryOptions": {},
"transformations": [],
},
},
"description": "Test Description",
"links": [],
"title": "Test Panel",
"uid": "test-panel-uid",
"vizConfig": {
"kind": "timeseries",
"spec": {
"fieldConfig": {
"defaults": {},
"overrides": [],
},
"options": {},
"pluginVersion": "7.0.0",
},
},
},
},
},
"layout": {
"kind": "GridLayout",
"spec": {
"items": [
{
"kind": "GridLayoutItem",
"spec": {
"element": {
"kind": "ElementReference",
"name": "test-panel-uid",
},
"height": 0,
"width": 0,
"x": 0,
"y": 0,
},
},
],
},
},
"links": [
{
"asDropdown": false,
"icon": "",
"includeVars": false,
"keepTime": false,
"tags": [],
"targetBlank": false,
"title": "Test Link",
"tooltip": "",
"type": "link",
"url": "http://test.com",
},
],
"liveNow": true,
"preload": true,
"schemaVersion": 40,
"tags": [
"tag1",
"tag2",
],
"timeSettings": {
"autoRefresh": "5s",
"autoRefreshIntervals": [
"5s",
"10s",
"30s",
],
"fiscalYearStartMonth": 1,
"from": "now-1h",
"hideTimepicker": false,
"nowDelay": "1m",
"quickRanges": [],
"timezone": "UTC",
"to": "now",
"weekStart": "monday",
},
"title": "Test Dashboard",
"variables": [
{
"kind": "QueryVariable",
"spec": {
"allValue": "*",
"current": {
"text": "text1",
"value": "value1",
},
"datasource": {
"type": "prometheus",
"uid": "datasource1",
},
"definition": "definition1",
"description": "A query variable",
"hide": "hideLabel",
"includeAll": true,
"label": "Query Variable",
"multi": true,
"name": "queryVar",
"options": [],
"query": "query1",
"refresh": "onDashboardLoad",
"regex": "regex1",
"skipUrlSync": false,
"sort": "alphabeticalDesc",
},
},
{
"kind": "CustomVariable",
"spec": {
"allValue": "All",
"current": {
"text": "option1",
"value": "option1",
},
"description": "A custom variable",
"hide": "dontHide",
"includeAll": true,
"label": "Custom Variable",
"multi": true,
"name": "customVar",
"options": [
{
"selected": true,
"text": "option1",
"value": "option1",
},
{
"selected": false,
"text": "option2",
"value": "option2",
},
],
"query": "option1, option2",
"skipUrlSync": false,
},
},
{
"kind": "DatasourceVariable",
"spec": {
"allValue": undefined,
"current": {
"text": "text1",
"value": "value1",
},
"defaultOptionEnabled": true,
"description": "A datasource variable",
"hide": "dontHide",
"includeAll": false,
"label": "Datasource Variable",
"multi": false,
"name": "datasourceVar",
"options": [],
"pluginId": "datasource1",
"refresh": "onDashboardLoad",
"regex": "regex1",
"skipUrlSync": false,
},
},
{
"kind": "ConstantVariable",
"spec": {
"current": {
"text": "value4",
"value": "value4",
},
"description": "A constant variable",
"hide": "dontHide",
"label": "Constant Variable",
"name": "constantVar",
"query": "value4",
"skipUrlSync": true,
},
},
{
"kind": "IntervalVariable",
"spec": {
"auto": false,
"auto_count": 10,
"auto_min": "1m",
"current": {
"text": "1m",
"value": "1m",
},
"description": "An interval variable",
"hide": "dontHide",
"label": "Interval Variable",
"name": "intervalVar",
"options": [
{
"selected": true,
"text": "1m",
"value": "1m",
},
{
"selected": false,
"text": "5m",
"value": "5m",
},
{
"selected": false,
"text": "10m",
"value": "10m",
},
],
"query": "1m,5m,10m",
"refresh": "onTimeRangeChanged",
"skipUrlSync": false,
},
},
{
"kind": "TextVariable",
"spec": {
"current": {
"text": "value6",
"value": "value6",
},
"description": "A text variable",
"hide": "dontHide",
"label": "Text Variable",
"name": "textVar",
"query": "value6",
"skipUrlSync": false,
},
},
{
"kind": "GroupByVariable",
"spec": {
"current": {
"text": "text7",
"value": "value7",
},
"datasource": {
"type": "prometheus",
"uid": "datasource2",
},
"description": "A group by variable",
"hide": "dontHide",
"includeAll": false,
"label": "Group By Variable",
"multi": false,
"name": "groupByVar",
"options": [
{
"text": "option1",
"value": "option1",
},
{
"text": "option2",
"value": "option2",
},
],
"skipUrlSync": false,
},
},
{
"kind": "AdhocVariable",
"spec": {
"baseFilters": [
{
"condition": "AND",
"key": "key1",
"operator": "=",
"value": "value1",
},
{
"condition": "OR",
"key": "key2",
"operator": "=",
"value": "value2",
},
],
"datasource": {
"type": "prometheus",
"uid": "datasource3",
},
"defaultKeys": [
{
"expandable": true,
"group": "defaultGroup1",
"text": "defaultKey1",
"value": "defaultKey1",
},
],
"description": "An adhoc variable",
"filters": [
{
"condition": "AND",
"key": "key3",
"operator": "=",
"value": "value3",
},
],
"hide": "dontHide",
"label": "Adhoc Variable",
"name": "adhocVar",
"skipUrlSync": false,
},
},
],
}
`;
@@ -911,7 +911,7 @@ describe('sceneVariablesSetToVariables', () => {
"kind": "ConstantVariable",
"spec": {
"current": {
"text": undefined,
"text": "constant value",
"value": "constant value",
},
"description": "test-desc",
@@ -979,7 +979,7 @@ describe('sceneVariablesSetToVariables', () => {
"auto_count": 30,
"auto_min": "10s",
"current": {
"text": undefined,
"text": "1m",
"value": "1m",
},
"description": undefined,
@@ -334,7 +334,11 @@ export function sceneVariablesSetToSchemaV2Variables(
kind: 'ConstantVariable',
spec: {
...commonProperties,
current: currentVariableOption,
current: {
...currentVariableOption,
// Constant variable doesn't use text state
text: String(variable.state.value),
},
// @ts-expect-error
query: variable.state.value,
},
@@ -346,7 +350,11 @@ export function sceneVariablesSetToSchemaV2Variables(
kind: 'IntervalVariable',
spec: {
...commonProperties,
current: currentVariableOption,
current: {
...currentVariableOption,
// Interval variable doesn't use text state
text: variable.state.value,
},
query: intervals,
refresh: VariableRefresh.OnTimeRangeChanged,
options: variable.state.intervals.map((interval) => ({
@@ -410,7 +418,7 @@ export function sceneVariablesSetToSchemaV2Variables(
};
variables.push(adhocVariable);
} else {
throw new Error('Unsupported variable type');
throw new Error('Unsupported variable type: ' + variable.state.type);
}
}
@@ -0,0 +1,285 @@
import { VariableRefresh } from '@grafana/data';
import { config } from '@grafana/runtime';
import {
AdHocFiltersVariable,
behaviors,
ConstantVariable,
CustomVariable,
DataSourceVariable,
GroupByVariable,
IntervalVariable,
QueryVariable,
SceneGridLayout,
SceneRefreshPicker,
SceneTimePicker,
SceneTimeRange,
SceneVariableSet,
TextBoxVariable,
VizPanel,
} from '@grafana/scenes';
import {
DashboardCursorSync as DashboardCursorSyncV1,
VariableHide as VariableHideV1,
VariableSort as VariableSortV1,
} from '@grafana/schema/dist/esm/index.gen';
import { DashboardControls } from '../scene/DashboardControls';
import { DashboardScene, DashboardSceneState } from '../scene/DashboardScene';
import { DashboardGridItem } from '../scene/layout-default/DashboardGridItem';
import { DefaultGridLayoutManager } from '../scene/layout-default/DefaultGridLayoutManager';
import { transformSceneToSaveModelSchemaV2 } from './transformSceneToSaveModelSchemaV2';
function setupDashboardScene(state: DashboardSceneState): DashboardScene {
return new DashboardScene(state);
}
describe('transformSceneToSaveModelSchemaV2', () => {
let dashboardScene: DashboardScene;
let prevFeatureToggleValue: boolean;
beforeAll(() => {
prevFeatureToggleValue = !!config.featureToggles.groupByVariable;
config.featureToggles.groupByVariable = true;
});
afterAll(() => {
config.featureToggles.groupByVariable = prevFeatureToggleValue;
});
beforeEach(() => {
// The intention is to have a complete dashboard scene
// with all the possible properties set
dashboardScene = setupDashboardScene({
title: 'Test Dashboard',
description: 'Test Description',
preload: true,
tags: ['tag1', 'tag2'],
uid: 'test-uid',
version: 1,
$timeRange: new SceneTimeRange({
timeZone: 'UTC',
from: 'now-1h',
to: 'now',
weekStart: 'monday',
fiscalYearStartMonth: 1,
UNSAFE_nowDelay: '1m',
refreshOnActivate: {
afterMs: 10,
percent: 0.1,
},
}),
controls: new DashboardControls({
refreshPicker: new SceneRefreshPicker({
refresh: '5s',
intervals: ['5s', '10s', '30s'],
autoEnabled: true,
autoMinInterval: '5s',
autoValue: '5s',
isOnCanvas: true,
primary: true,
withText: true,
minRefreshInterval: '5s',
}),
timePicker: new SceneTimePicker({
isOnCanvas: true,
hidePicker: true,
}),
}),
links: [
{
title: 'Test Link',
url: 'http://test.com',
asDropdown: false,
icon: '',
includeVars: false,
keepTime: false,
tags: [],
targetBlank: false,
tooltip: '',
type: 'link',
},
],
body: new DefaultGridLayoutManager({
grid: new SceneGridLayout({
isLazy: false,
children: [
new DashboardGridItem({
body: new VizPanel({
key: 'test-panel-uid',
pluginId: 'timeseries',
title: 'Test Panel',
description: 'Test Description',
hoverHeader: true,
hoverHeaderOffset: 10,
fieldConfig: { defaults: {}, overrides: [] },
displayMode: 'transparent',
pluginVersion: '7.0.0',
$timeRange: new SceneTimeRange({
timeZone: 'UTC',
from: 'now-3h',
to: 'now',
}),
}),
// Props related to repeatable panels
// repeatedPanels?: VizPanel[],
// variableName?: string,
// itemHeight?: number,
// repeatDirection?: RepeatDirection,
// maxPerRow?: number,
}),
],
}),
}),
meta: {},
$behaviors: [
new behaviors.CursorSync({
sync: DashboardCursorSyncV1.Crosshair,
}),
new behaviors.LiveNowTimer({
enabled: true,
}),
],
$variables: new SceneVariableSet({
// Test each of the variables
variables: [
new QueryVariable({
name: 'queryVar',
label: 'Query Variable',
description: 'A query variable',
skipUrlSync: false,
hide: VariableHideV1.hideLabel,
value: 'value1',
text: 'text1',
query: 'query1',
definition: 'definition1',
datasource: { uid: 'datasource1', type: 'prometheus' },
sort: VariableSortV1.alphabeticalDesc,
refresh: VariableRefresh.onDashboardLoad,
regex: 'regex1',
allValue: '*',
includeAll: true,
isMulti: true,
}),
new CustomVariable({
name: 'customVar',
label: 'Custom Variable',
description: 'A custom variable',
skipUrlSync: false,
hide: VariableHideV1.dontHide,
value: 'option1',
text: 'option1',
query: 'option1, option2',
options: [
{ label: 'option1', value: 'option1' },
{ label: 'option2', value: 'option2' },
],
isMulti: true,
allValue: 'All',
includeAll: true,
}),
new DataSourceVariable({
name: 'datasourceVar',
label: 'Datasource Variable',
description: 'A datasource variable',
skipUrlSync: false,
hide: VariableHideV1.dontHide,
value: 'value1',
text: 'text1',
regex: 'regex1',
pluginId: 'datasource1',
defaultOptionEnabled: true,
}),
new ConstantVariable({
name: 'constantVar',
label: 'Constant Variable',
description: 'A constant variable',
skipUrlSync: false,
hide: VariableHideV1.dontHide,
value: 'value4',
}),
new IntervalVariable({
name: 'intervalVar',
label: 'Interval Variable',
description: 'An interval variable',
skipUrlSync: false,
hide: VariableHideV1.dontHide,
value: '1m',
intervals: ['1m', '5m', '10m'],
autoEnabled: false,
autoMinInterval: '1m',
autoStepCount: 10,
}),
new TextBoxVariable({
name: 'textVar',
label: 'Text Variable',
description: 'A text variable',
skipUrlSync: false,
hide: VariableHideV1.dontHide,
value: 'value6',
}),
new GroupByVariable({
name: 'groupByVar',
label: 'Group By Variable',
description: 'A group by variable',
skipUrlSync: false,
hide: VariableHideV1.dontHide,
value: 'value7',
text: 'text7',
datasource: { uid: 'datasource2', type: 'prometheus' },
defaultOptions: [
{ text: 'option1', value: 'option1' },
{ text: 'option2', value: 'option2' },
],
isMulti: false,
includeAll: false,
}),
new AdHocFiltersVariable({
name: 'adhocVar',
label: 'Adhoc Variable',
description: 'An adhoc variable',
skipUrlSync: false,
hide: VariableHideV1.dontHide,
datasource: { uid: 'datasource3', type: 'prometheus' },
baseFilters: [
{
key: 'key1',
operator: '=',
value: 'value1',
condition: 'AND',
},
{
key: 'key2',
operator: '=',
value: 'value2',
condition: 'OR',
},
],
filters: [
{
key: 'key3',
operator: '=',
value: 'value3',
condition: 'AND',
},
],
defaultKeys: [
{
text: 'defaultKey1',
value: 'defaultKey1',
group: 'defaultGroup1',
expandable: true,
},
],
}),
],
}),
});
});
it('should transform scene to save model schema v2', () => {
const result = transformSceneToSaveModelSchemaV2(dashboardScene);
expect(result).toMatchSnapshot();
});
});
@@ -1,5 +1,4 @@
import { behaviors, SceneDataQuery, SceneDataTransformer, SceneVariableSet, VizPanel } from '@grafana/scenes';
import {
DashboardV2Spec,
defaultDashboardV2Spec,
@@ -24,7 +23,9 @@ import {
ConstantVariableKind,
GroupByVariableKind,
AdhocVariableKind,
} from '../../../../../packages/grafana-schema/src/schema/dashboard/v2alpha0/dashboard.gen';
} from '@grafana/schema/src/schema/dashboard/v2alpha0/dashboard.gen';
import { DASHBOARD_SCHEMA_VERSION } from 'app/features/dashboard/state/DashboardMigrator';
import { DashboardScene, DashboardSceneState } from '../scene/DashboardScene';
import { PanelTimeRange } from '../scene/PanelTimeRange';
import { DashboardGridItem } from '../scene/layout-default/DashboardGridItem';
@@ -59,6 +60,7 @@ export function transformSceneToSaveModelSchemaV2(scene: DashboardScene, isSnaps
editable: oldDash.editable,
links: transformDashboardLinksToEnums(oldDash.links),
tags: oldDash.tags,
schemaVersion: DASHBOARD_SCHEMA_VERSION,
// EOF dashboard settings
// time settings