mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			1106 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			1106 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
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';
 | 
						|
import { getPluginLinkExtensions, setPluginImportUtils } from '@grafana/runtime';
 | 
						|
import { MultiValueVariable, SceneGridLayout, SceneGridRow, SceneTimeRange, VizPanel } from '@grafana/scenes';
 | 
						|
import { Dashboard, LoadingState, Panel, RowPanel, VariableRefresh } from '@grafana/schema';
 | 
						|
import { PanelModel } from 'app/features/dashboard/state';
 | 
						|
import { getTimeRange } from 'app/features/dashboard/utils/timeRange';
 | 
						|
import { reduceTransformRegistryItem } from 'app/features/transformers/editors/ReduceTransformerEditor';
 | 
						|
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
 | 
						|
 | 
						|
import { buildPanelEditScene } from '../panel-edit/PanelEditor';
 | 
						|
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
 | 
						|
import { DashboardGridItem } from '../scene/DashboardGridItem';
 | 
						|
import { DashboardScene } from '../scene/DashboardScene';
 | 
						|
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
 | 
						|
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
 | 
						|
import { NEW_LINK } from '../settings/links/utils';
 | 
						|
import { activateFullSceneTree, buildPanelRepeaterScene } from '../utils/test-utils';
 | 
						|
import { getVizPanelKeyForPanelId } from '../utils/utils';
 | 
						|
 | 
						|
import { GRAFANA_DATASOURCE_REF } from './const';
 | 
						|
import dashboard_to_load1 from './testfiles/dashboard_to_load1.json';
 | 
						|
import repeatingRowsAndPanelsDashboardJson from './testfiles/repeating_rows_and_panels.json';
 | 
						|
import snapshotableDashboardJson from './testfiles/snapshotable_dashboard.json';
 | 
						|
import snapshotableWithRowsDashboardJson from './testfiles/snapshotable_with_rows.json';
 | 
						|
import {
 | 
						|
  buildGridItemForLibPanel,
 | 
						|
  buildGridItemForPanel,
 | 
						|
  transformSaveModelToScene,
 | 
						|
} from './transformSaveModelToScene';
 | 
						|
import {
 | 
						|
  gridItemToPanel,
 | 
						|
  gridRowToSaveModel,
 | 
						|
  panelRepeaterToPanels,
 | 
						|
  transformSceneToSaveModel,
 | 
						|
  trimDashboardForSnapshot,
 | 
						|
} from './transformSceneToSaveModel';
 | 
						|
 | 
						|
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;
 | 
						|
    })
 | 
						|
  );
 | 
						|
});
 | 
						|
 | 
						|
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: {
 | 
						|
    panels: {
 | 
						|
      text: { skipDataQuery: true },
 | 
						|
    },
 | 
						|
    featureToggles: {
 | 
						|
      dataTrails: false,
 | 
						|
    },
 | 
						|
    theme2: {
 | 
						|
      visualization: {
 | 
						|
        getColorByName: jest.fn().mockReturnValue('red'),
 | 
						|
      },
 | 
						|
    },
 | 
						|
  },
 | 
						|
  setPluginExtensionGetter: jest.fn(),
 | 
						|
  getPluginLinkExtensions: jest.fn(),
 | 
						|
}));
 | 
						|
 | 
						|
const getPluginLinkExtensionsMock = jest.mocked(getPluginLinkExtensions);
 | 
						|
 | 
						|
jest.mock('@grafana/scenes', () => ({
 | 
						|
  ...jest.requireActual('@grafana/scenes'),
 | 
						|
  sceneUtils: {
 | 
						|
    ...jest.requireActual('@grafana/scenes').sceneUtils,
 | 
						|
    registerVariableMacro: jest.fn(),
 | 
						|
  },
 | 
						|
}));
 | 
						|
 | 
						|
describe('transformSceneToSaveModel', () => {
 | 
						|
  beforeEach(() => {
 | 
						|
    getPluginLinkExtensionsMock.mockRestore();
 | 
						|
    getPluginLinkExtensionsMock.mockReturnValue({ extensions: [] });
 | 
						|
  });
 | 
						|
 | 
						|
  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,
 | 
						|
        refresh: '5m',
 | 
						|
        timepicker: {
 | 
						|
          ...dashboard_to_load1.timepicker,
 | 
						|
          refresh_intervals: ['5m', '15m', '30m', '1h'],
 | 
						|
          time_options: ['5m', '15m', '30m'],
 | 
						|
          hidden: true,
 | 
						|
        },
 | 
						|
        links: [{ ...NEW_LINK, title: 'Link 1' }],
 | 
						|
      };
 | 
						|
      const scene = transformSaveModelToScene({ dashboard: dashboardWithCustomSettings as any, meta: {} });
 | 
						|
      const saveModel = transformSceneToSaveModel(scene);
 | 
						|
 | 
						|
      expect(saveModel).toMatchSnapshot();
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('Given a simple scene with variables', () => {
 | 
						|
    it('Should transform back to persisted model', () => {
 | 
						|
      const scene = transformSaveModelToScene({ dashboard: dashboard_to_load1 as any, meta: {} });
 | 
						|
      const saveModel = transformSceneToSaveModel(scene);
 | 
						|
 | 
						|
      expect(saveModel).toMatchSnapshot();
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('Given a scene with rows', () => {
 | 
						|
    it('Should transform back to persisted model', () => {
 | 
						|
      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
 | 
						|
      rowRepeater.variableDependency?.variableUpdateCompleted(variable, true);
 | 
						|
 | 
						|
      // 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);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('Panel options', () => {
 | 
						|
    it('Given panel with time override', () => {
 | 
						|
      const gridItem = buildGridItemFromPanelSchema({
 | 
						|
        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', () => {
 | 
						|
      const gridItem = buildGridItemFromPanelSchema({ transparent: true });
 | 
						|
      const saveModel = gridItemToPanel(gridItem);
 | 
						|
 | 
						|
      expect(saveModel.transparent).toBe(true);
 | 
						|
    });
 | 
						|
 | 
						|
    it('interval', () => {
 | 
						|
      const gridItem = buildGridItemFromPanelSchema({ interval: '20m' });
 | 
						|
      const saveModel = gridItemToPanel(gridItem);
 | 
						|
 | 
						|
      expect(saveModel.interval).toBe('20m');
 | 
						|
    });
 | 
						|
 | 
						|
    it('With angular options', () => {
 | 
						|
      const gridItem = buildGridItemFromPanelSchema({});
 | 
						|
      const vizPanel = gridItem.state.body as VizPanel;
 | 
						|
      vizPanel.setState({
 | 
						|
        options: {
 | 
						|
          angularOptions: {
 | 
						|
            bars: true,
 | 
						|
          },
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const saveModel = gridItemToPanel(gridItem);
 | 
						|
      expect(saveModel.options?.angularOptions).toBe(undefined);
 | 
						|
      expect((saveModel as any).bars).toBe(true);
 | 
						|
    });
 | 
						|
 | 
						|
    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);
 | 
						|
    });
 | 
						|
    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',
 | 
						|
        },
 | 
						|
      ]);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('Library panels', () => {
 | 
						|
    it('given a library panel', () => {
 | 
						|
      // Not using buildGridItemFromPanelSchema since it strips options/fieldConfig
 | 
						|
      const libVizPanel = new LibraryVizPanel({
 | 
						|
        name: 'Some lib panel panel',
 | 
						|
        title: 'A panel',
 | 
						|
        uid: 'lib-panel-uid',
 | 
						|
        panelKey: 'lib-panel',
 | 
						|
        panel: new VizPanel({
 | 
						|
          key: 'panel-4',
 | 
						|
          title: 'Panel blahh blah',
 | 
						|
          fieldConfig: {
 | 
						|
            defaults: {},
 | 
						|
            overrides: [],
 | 
						|
          },
 | 
						|
          options: {
 | 
						|
            legend: {
 | 
						|
              calcs: [],
 | 
						|
              displayMode: 'list',
 | 
						|
              placement: 'bottom',
 | 
						|
              showLegend: true,
 | 
						|
            },
 | 
						|
            tooltip: {
 | 
						|
              maxHeight: 600,
 | 
						|
              mode: 'single',
 | 
						|
              sort: 'none',
 | 
						|
            },
 | 
						|
          },
 | 
						|
        }),
 | 
						|
      });
 | 
						|
 | 
						|
      const panel = new DashboardGridItem({
 | 
						|
        body: libVizPanel,
 | 
						|
        y: 0,
 | 
						|
        x: 0,
 | 
						|
        width: 12,
 | 
						|
        height: 8,
 | 
						|
      });
 | 
						|
 | 
						|
      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();
 | 
						|
      expect(result.options).toBeUndefined();
 | 
						|
    });
 | 
						|
 | 
						|
    it('given a library panel widget', () => {
 | 
						|
      const panel = buildGridItemFromPanelSchema({
 | 
						|
        id: 4,
 | 
						|
        gridPos: {
 | 
						|
          h: 8,
 | 
						|
          w: 12,
 | 
						|
          x: 0,
 | 
						|
          y: 0,
 | 
						|
        },
 | 
						|
        type: 'add-library-panel',
 | 
						|
      });
 | 
						|
 | 
						|
      const result = gridItemToPanel(panel);
 | 
						|
 | 
						|
      expect(result.id).toBe(4);
 | 
						|
      expect(result.gridPos).toEqual({
 | 
						|
        h: 8,
 | 
						|
        w: 12,
 | 
						|
        x: 0,
 | 
						|
        y: 0,
 | 
						|
      });
 | 
						|
      expect(result.type).toBe('add-library-panel');
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  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 DashboardDataLayerSet)?.state.annotationLayers;
 | 
						|
      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);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  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);
 | 
						|
 | 
						|
      expect(result.transformations?.length).toBe(1);
 | 
						|
 | 
						|
      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);
 | 
						|
 | 
						|
      expect(result.transformations?.length).toBe(1);
 | 
						|
 | 
						|
      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 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);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  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);
 | 
						|
    });
 | 
						|
 | 
						|
    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, undefined, 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 repeated library panels', () => {
 | 
						|
        const { scene, repeater } = buildPanelRepeaterScene(
 | 
						|
          { variableQueryTime: 0, numberOfOptions: 2 },
 | 
						|
          new LibraryVizPanel({
 | 
						|
            name: 'Some lib panel panel',
 | 
						|
            title: 'A panel',
 | 
						|
            uid: 'lib-panel-uid',
 | 
						|
            panelKey: 'lib-panel',
 | 
						|
            panel: new VizPanel({
 | 
						|
              key: 'panel-4',
 | 
						|
              title: 'Panel blahh blah',
 | 
						|
              fieldConfig: {
 | 
						|
                defaults: {},
 | 
						|
                overrides: [],
 | 
						|
              },
 | 
						|
              options: {
 | 
						|
                legend: {
 | 
						|
                  calcs: [],
 | 
						|
                  displayMode: 'list',
 | 
						|
                  placement: 'bottom',
 | 
						|
                  showLegend: true,
 | 
						|
                },
 | 
						|
                tooltip: {
 | 
						|
                  maxHeight: 600,
 | 
						|
                  mode: 'single',
 | 
						|
                  sort: 'none',
 | 
						|
                },
 | 
						|
              },
 | 
						|
            }),
 | 
						|
          })
 | 
						|
        );
 | 
						|
 | 
						|
        activateFullSceneTree(scene);
 | 
						|
        const result = panelRepeaterToPanels(repeater, undefined, true);
 | 
						|
 | 
						|
        expect(result).toHaveLength(1);
 | 
						|
 | 
						|
        expect(result[0]).toMatchObject({
 | 
						|
          id: 4,
 | 
						|
          title: 'A panel',
 | 
						|
          libraryPanel: {
 | 
						|
            name: 'Some lib panel panel',
 | 
						|
            uid: 'lib-panel-uid',
 | 
						|
          },
 | 
						|
        });
 | 
						|
      });
 | 
						|
 | 
						|
      it('handles row repeats ', () => {
 | 
						|
        const { scene, row } = buildPanelRepeaterScene({
 | 
						|
          variableQueryTime: 0,
 | 
						|
          numberOfOptions: 2,
 | 
						|
          useRowRepeater: true,
 | 
						|
          usePanelRepeater: false,
 | 
						|
        });
 | 
						|
 | 
						|
        activateFullSceneTree(scene);
 | 
						|
 | 
						|
        let panels: Panel[] = [];
 | 
						|
        gridRowToSaveModel(row, panels, undefined, 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, undefined, 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');
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    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 });
 | 
						|
      });
 | 
						|
 | 
						|
      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);
 | 
						|
      });
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('Given a scene with an open panel editor', () => {
 | 
						|
    it('should persist changes to panel model', async () => {
 | 
						|
      const panel = new VizPanel({
 | 
						|
        key: 'panel-1',
 | 
						|
        pluginId: 'text',
 | 
						|
      });
 | 
						|
 | 
						|
      const gridItem = new DashboardGridItem({ body: panel });
 | 
						|
 | 
						|
      const editScene = buildPanelEditScene(panel);
 | 
						|
      const scene = new DashboardScene({
 | 
						|
        editPanel: editScene,
 | 
						|
        isEditing: true,
 | 
						|
        body: new SceneGridLayout({
 | 
						|
          children: [gridItem],
 | 
						|
        }),
 | 
						|
        $timeRange: new SceneTimeRange({
 | 
						|
          from: 'now-6h',
 | 
						|
          to: 'now',
 | 
						|
          timeZone: '',
 | 
						|
        }),
 | 
						|
      });
 | 
						|
 | 
						|
      editScene!.state.vizManager.state.panel.setState({
 | 
						|
        options: {
 | 
						|
          mode: 'markdown',
 | 
						|
          code: {
 | 
						|
            language: 'plaintext',
 | 
						|
            showLineNumbers: false,
 | 
						|
            showMiniMap: false,
 | 
						|
          },
 | 
						|
          content: 'new content',
 | 
						|
        },
 | 
						|
      });
 | 
						|
      activateFullSceneTree(scene);
 | 
						|
      const saveModel = transformSceneToSaveModel(scene);
 | 
						|
      expect((saveModel.panels![0] as any).options.content).toBe('new content');
 | 
						|
    });
 | 
						|
 | 
						|
    it('should persist changes to panel model in row', async () => {
 | 
						|
      const panel = new VizPanel({
 | 
						|
        key: 'panel-1',
 | 
						|
        pluginId: 'text',
 | 
						|
        options: {
 | 
						|
          content: 'old content',
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const gridItem = new DashboardGridItem({ body: panel });
 | 
						|
 | 
						|
      const editScene = buildPanelEditScene(panel);
 | 
						|
      const scene = new DashboardScene({
 | 
						|
        editPanel: editScene,
 | 
						|
        isEditing: true,
 | 
						|
        body: new SceneGridLayout({
 | 
						|
          children: [
 | 
						|
            new SceneGridRow({
 | 
						|
              key: '23',
 | 
						|
              isCollapsed: false,
 | 
						|
              children: [gridItem],
 | 
						|
            }),
 | 
						|
          ],
 | 
						|
        }),
 | 
						|
        $timeRange: new SceneTimeRange({
 | 
						|
          from: 'now-6h',
 | 
						|
          to: 'now',
 | 
						|
          timeZone: '',
 | 
						|
        }),
 | 
						|
      });
 | 
						|
      activateFullSceneTree(scene);
 | 
						|
 | 
						|
      editScene!.state.vizManager.state.panel.setState({
 | 
						|
        options: {
 | 
						|
          mode: 'markdown',
 | 
						|
          code: {
 | 
						|
            language: 'plaintext',
 | 
						|
            showLineNumbers: false,
 | 
						|
            showMiniMap: false,
 | 
						|
          },
 | 
						|
          content: 'new content',
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const saveModel = transformSceneToSaveModel(scene);
 | 
						|
      expect((saveModel.panels![1] as any).options.content).toBe('new content');
 | 
						|
    });
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
export function buildGridItemFromPanelSchema(panel: Partial<Panel>) {
 | 
						|
  if (panel.libraryPanel) {
 | 
						|
    return buildGridItemForLibPanel(new PanelModel(panel))!;
 | 
						|
  }
 | 
						|
 | 
						|
  return buildGridItemForPanel(new PanelModel(panel));
 | 
						|
}
 |