mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Support importing local cue modules when generating TS types with cog * Generate enums as unions of values instead of an actual `enum` statement * Update transformers to use the new TS enums * Update go workspaces --------- Co-authored-by: Ivan Ortega <ivanortegaalba@gmail.com>
214 lines
8.8 KiB
TypeScript
214 lines
8.8 KiB
TypeScript
import { cloneDeep } from 'lodash';
|
|
|
|
import { config } from '@grafana/runtime';
|
|
import { behaviors, sceneGraph, SceneQueryRunner } from '@grafana/scenes';
|
|
import { DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0/dashboard.gen';
|
|
import { handyTestingSchema } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0/examples';
|
|
import { DashboardWithAccessInfo } from 'app/features/dashboard/api/dashboard_api';
|
|
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
|
|
|
|
import { DashboardLayoutManager } from '../scene/types';
|
|
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
|
import { getQueryRunnerFor } from '../utils/utils';
|
|
|
|
import { transformSaveModelSchemaV2ToScene } from './transformSaveModelSchemaV2ToScene';
|
|
import { transformCursorSynctoEnum } from './transformToV2TypesUtils';
|
|
|
|
const defaultDashboard: DashboardWithAccessInfo<DashboardV2Spec> = {
|
|
kind: 'DashboardWithAccessInfo',
|
|
metadata: {
|
|
name: 'dashboard-uid',
|
|
namespace: 'default',
|
|
labels: {},
|
|
resourceVersion: '',
|
|
creationTimestamp: '',
|
|
},
|
|
spec: handyTestingSchema,
|
|
access: {},
|
|
apiVersion: 'v2',
|
|
};
|
|
|
|
jest.mock('@grafana/runtime', () => ({
|
|
...jest.requireActual('@grafana/runtime'),
|
|
getDataSourceSrv: () => ({
|
|
getInstanceSettings: jest.fn(),
|
|
}),
|
|
}));
|
|
|
|
describe('transformSaveModelSchemaV2ToScene', () => {
|
|
beforeAll(() => {
|
|
config.featureToggles.groupByVariable = true;
|
|
});
|
|
|
|
afterAll(() => {
|
|
config.featureToggles.groupByVariable = false;
|
|
});
|
|
|
|
it('should initialize the DashboardScene with the model state', () => {
|
|
const scene = transformSaveModelSchemaV2ToScene(defaultDashboard);
|
|
const dashboardControls = scene.state.controls!;
|
|
const dash = defaultDashboard.spec;
|
|
|
|
expect(scene.state.uid).toEqual(defaultDashboard.metadata.name);
|
|
expect(scene.state.title).toEqual(dash.title);
|
|
expect(scene.state.description).toEqual(dash.description);
|
|
expect(scene.state.editable).toEqual(dash.editable);
|
|
expect(scene.state.preload).toEqual(false);
|
|
expect(scene.state.version).toEqual(dash.schemaVersion);
|
|
expect(scene.state.tags).toEqual(dash.tags);
|
|
|
|
const liveNow = scene.state.$behaviors?.find((b) => b instanceof behaviors.LiveNowTimer);
|
|
expect(liveNow?.state.enabled).toEqual(dash.liveNow);
|
|
|
|
const cursorSync = scene.state.$behaviors?.find((b) => b instanceof behaviors.CursorSync);
|
|
expect(transformCursorSynctoEnum(cursorSync?.state.sync)).toEqual(dash.cursorSync);
|
|
|
|
// Dashboard links
|
|
expect(scene.state.links).toHaveLength(dash.links.length);
|
|
expect(scene.state.links![0].title).toBe(dash.links[0].title);
|
|
|
|
// Time settings
|
|
const time = dash.timeSettings;
|
|
const refreshPicker = dashboardSceneGraph.getRefreshPicker(scene)!;
|
|
const timeRange = sceneGraph.getTimeRange(scene)!;
|
|
|
|
// Time settings
|
|
expect(refreshPicker.state.refresh).toEqual(time.autoRefresh);
|
|
expect(refreshPicker.state.intervals).toEqual(time.autoRefreshIntervals);
|
|
expect(timeRange?.state.fiscalYearStartMonth).toEqual(dash.timeSettings.fiscalYearStartMonth);
|
|
expect(timeRange?.state.value.raw).toEqual({ from: dash.timeSettings.from, to: dash.timeSettings.to });
|
|
expect(dashboardControls.state.hideTimeControls).toEqual(dash.timeSettings.hideTimepicker);
|
|
expect(timeRange?.state.UNSAFE_nowDelay).toEqual(dash.timeSettings.nowDelay);
|
|
expect(timeRange?.state.timeZone).toEqual(dash.timeSettings.timezone);
|
|
expect(timeRange?.state.weekStart).toEqual(dash.timeSettings.weekStart);
|
|
expect(dashboardControls).toBeDefined();
|
|
expect(dashboardControls.state.refreshPicker.state.intervals).toEqual(time.autoRefreshIntervals);
|
|
expect(dashboardControls.state.hideTimeControls).toBe(time.hideTimepicker);
|
|
|
|
// TODO: Variables
|
|
// expect(scene.state?.$variables?.state.variables).toHaveLength(dash.variables.length);
|
|
// expect(scene.state?.$variables?.getByName(dash.variables[0].spec.name)).toBeInstanceOf(QueryVariable);
|
|
// expect(scene.state?.$variables?.getByName(dash.variables[1].spec.name)).toBeInstanceOf(TextBoxVariable); ...
|
|
|
|
// TODO: Annotations
|
|
// expect(scene.state.annotations).toHaveLength(dash.annotations.length);
|
|
// expect(scene.state.annotations[0].text).toBe(dash.annotations[0].text); ...
|
|
|
|
// To be implemented
|
|
// expect(timePicker.state.ranges).toEqual(dash.timeSettings.quickRanges);
|
|
|
|
// VizPanel
|
|
const vizPanels = (scene.state.body as DashboardLayoutManager).getVizPanels();
|
|
expect(vizPanels).toHaveLength(1);
|
|
const vizPanel = vizPanels[0];
|
|
expect(vizPanel.state.title).toBe(dash.elements['test-panel-uid'].spec.title);
|
|
expect(vizPanel.state.description).toBe(dash.elements['test-panel-uid'].spec.description);
|
|
expect(vizPanel.state.pluginId).toBe(dash.elements['test-panel-uid'].spec.vizConfig.kind);
|
|
expect(vizPanel.state.pluginVersion).toBe(dash.elements['test-panel-uid'].spec.vizConfig.spec.pluginVersion);
|
|
expect(vizPanel.state.options).toEqual(dash.elements['test-panel-uid'].spec.vizConfig.spec.options);
|
|
expect(vizPanel.state.fieldConfig).toEqual(dash.elements['test-panel-uid'].spec.vizConfig.spec.fieldConfig);
|
|
|
|
// FIXME: There is an error of data being undefined
|
|
// expect(vizPanel.state.$data).toBeInstanceOf(SceneDataTransformer);
|
|
// const dataTransformer = vizPanel.state.$data as SceneDataTransformer;
|
|
// expect(dataTransformer.state.transformations).toEqual([{ id: 'transform1', options: {} }]);
|
|
|
|
// expect(dataTransformer.state.$data).toBeInstanceOf(SceneQueryRunner);
|
|
const queryRunner = getQueryRunnerFor(vizPanel);
|
|
expect(queryRunner).toBeInstanceOf(SceneQueryRunner);
|
|
expect(queryRunner?.state.datasource).toBeUndefined();
|
|
// expect(queryRunner.state.queries).toEqual([{ query: 'test-query', datasource: { uid: 'datasource1', type: 'prometheus' } }]);
|
|
// expect(queryRunner.state.maxDataPoints).toBe(100);
|
|
// expect(queryRunner.state.cacheTimeout).toBe('1m');
|
|
// expect(queryRunner.state.queryCachingTTL).toBe(60);
|
|
// expect(queryRunner.state.minInterval).toBe('1m');
|
|
// expect(queryRunner.state.dataLayerFilter?.panelId).toBe(1);
|
|
|
|
// FIXME: Fix the key incompatibility since panel is not numeric anymore
|
|
// expect(vizPanel.state.key).toBe(dash.elements['test-panel-uid'].spec.uid);
|
|
|
|
// FIXME: Tests for layout
|
|
});
|
|
|
|
it('should set panel ds if it is mixed DS', () => {
|
|
const dashboard = cloneDeep(defaultDashboard);
|
|
dashboard.spec.elements['test-panel-uid'].spec.data.spec.queries.push({
|
|
kind: 'PanelQuery',
|
|
spec: {
|
|
refId: 'A',
|
|
datasource: {
|
|
type: 'graphite',
|
|
uid: 'datasource1',
|
|
},
|
|
hidden: false,
|
|
query: {
|
|
kind: 'prometheus',
|
|
spec: {
|
|
expr: 'test-query',
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
const scene = transformSaveModelSchemaV2ToScene(dashboard);
|
|
|
|
const vizPanels = (scene.state.body as DashboardLayoutManager).getVizPanels();
|
|
expect(vizPanels.length).toBe(1);
|
|
expect(getQueryRunnerFor(vizPanels[0])?.state.datasource?.type).toBe('mixed');
|
|
expect(getQueryRunnerFor(vizPanels[0])?.state.datasource?.uid).toBe(MIXED_DATASOURCE_NAME);
|
|
});
|
|
|
|
it('should set panel ds as undefined if it is not mixed DS', () => {
|
|
const dashboard = cloneDeep(defaultDashboard);
|
|
dashboard.spec.elements['test-panel-uid'].spec.data.spec.queries.push({
|
|
kind: 'PanelQuery',
|
|
spec: {
|
|
refId: 'A',
|
|
datasource: {
|
|
type: 'prometheus',
|
|
uid: 'datasource1',
|
|
},
|
|
hidden: false,
|
|
query: {
|
|
kind: 'prometheus',
|
|
spec: {
|
|
expr: 'test-query',
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
const scene = transformSaveModelSchemaV2ToScene(dashboard);
|
|
|
|
const vizPanels = (scene.state.body as DashboardLayoutManager).getVizPanels();
|
|
expect(vizPanels.length).toBe(1);
|
|
expect(getQueryRunnerFor(vizPanels[0])?.state.datasource).toBeUndefined();
|
|
});
|
|
|
|
// Skipping the test because the schema doesn't accept the ds to be undefined.
|
|
// In future PR, we will mark it as optional so, this test should pass and the runtime code should be updated.
|
|
it.skip('should set panel ds as undefined if it is not mixed DS', () => {
|
|
const dashboard = cloneDeep(defaultDashboard);
|
|
dashboard.spec.elements['test-panel-uid'].spec.data.spec.queries.push({
|
|
kind: 'PanelQuery',
|
|
// @ts-expect-error TODO: When marking DS as optional, this should be fixed
|
|
spec: {
|
|
refId: 'A',
|
|
hidden: false,
|
|
query: {
|
|
kind: 'prometheus',
|
|
spec: {
|
|
expr: 'test-query',
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
const scene = transformSaveModelSchemaV2ToScene(dashboard);
|
|
|
|
const vizPanels = (scene.state.body as DashboardLayoutManager).getVizPanels();
|
|
expect(vizPanels.length).toBe(1);
|
|
expect(getQueryRunnerFor(vizPanels[0])?.state.datasource).toBeUndefined();
|
|
});
|
|
});
|