grafana/public/app/features/dashboard/state/PanelModel.test.ts

341 lines
9.8 KiB
TypeScript
Raw Normal View History

2019-02-21 07:44:21 -06:00
import { PanelModel } from './PanelModel';
import { getPanelPlugin } from '../../plugins/__mocks__/pluginMocks';
import {
FieldConfigProperty,
identityOverrideProcessor,
PanelProps,
standardEditorsRegistry,
standardFieldConfigEditorRegistry,
} from '@grafana/data';
import { ComponentClass } from 'react';
class TablePanelCtrl {}
export const mockStandardProperties = () => {
const unit = {
id: 'unit',
path: 'unit',
name: 'Unit',
description: 'Value units',
// @ts-ignore
editor: () => null,
// @ts-ignore
override: () => null,
process: identityOverrideProcessor,
shouldApply: () => true,
};
const decimals = {
id: 'decimals',
path: 'decimals',
name: 'Decimals',
description: 'Number of decimal to be shown for a value',
// @ts-ignore
editor: () => null,
// @ts-ignore
override: () => null,
process: identityOverrideProcessor,
shouldApply: () => true,
};
const boolean = {
id: 'boolean',
path: 'boolean',
name: 'Boolean',
description: '',
// @ts-ignore
editor: () => null,
// @ts-ignore
override: () => null,
process: identityOverrideProcessor,
shouldApply: () => true,
};
return [unit, decimals, boolean];
};
standardFieldConfigEditorRegistry.setInit(() => mockStandardProperties());
standardEditorsRegistry.setInit(() => mockStandardProperties());
describe('PanelModel', () => {
describe('when creating new panel model', () => {
let model: any;
let modelJson: any;
let persistedOptionsMock;
beforeEach(() => {
persistedOptionsMock = {
fieldOptions: {
thresholds: [
{
color: '#F2495C',
index: 1,
value: 50,
},
{
color: '#73BF69',
index: 0,
value: null,
},
],
},
arrayWith2Values: [{ name: 'changed to only one value' }],
};
modelJson = {
type: 'table',
showColumns: true,
targets: [{ refId: 'A' }, { noRefId: true }],
options: persistedOptionsMock,
FieldOverrides: Move FieldConfigSource from fieldOptions to PanelModel.fieldConfig (#22600) * Apply field overrides in PanelChrome * Move applyFieldOverrides to panel query runner * Review updates * Make sure overrides are applied back on souce panel when exiting the new edit mode * TS ignores in est * Make field display work in viz repeater * Review updates * Review and test updates * Change the way overrides and trransformations are retrieved in PQR * Add fieldConfig property to PanelModel * Dashboard migration v1 * Use field config when exiting new panel edit mode * Gauge - use fieldConfig from panel model * FieldDisplayOptions - don's extend FieldConfigSource * Fix fieldDisplay ts * StatPanel updated * Stat panel defaults applied * Table2 panel options update * React graph updates * BarGauge updated * PieChart, Gauge, BarGauge and Stat updates * PieChart - remove field config defaults from options * FieldDisplayEditor - remove unused methos * PanelModel - remove debugger * Remove fieldConfig from field options when migrating dashboard * Update data links migrations * Update fieldDisaplay tests to respect new fieldConfig * Update dashboard schema version in snapshots * Fix BarGaugePanel test * Rebase fixes * Add onFieldConfigChange to PanelProps type * Update shared single stat migration * Pass PanelModel instead of options only for panel type change handler [breaking] * Renames * Don't mutate panel options * Migrations update * Remove obsolete snap * Minor updates after review * Fix null checks * Temporarily (until we decide to switch to new pane edit) bring back old aditors * Temporarily rename ValueMappingEditor and MappingRow to Legacy* * Migrations update * Updae setFieldConfigDefaults API * Update the way field config defaults are applied * Use standard field config for gauge, bar gauge and stat panels * refactoring * Revert dashboard fieldOptions migrations as those are handled by single stat migrator * Fix ts in tests * Strict null fix and some minor fixes Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2020-03-19 05:50:31 -05:00
fieldConfig: {
defaults: {
unit: 'mpg',
},
overrides: [
{
matcher: {
id: '1',
options: {},
},
properties: [],
},
],
},
};
model = new PanelModel(modelJson);
FieldOverrides: Move FieldConfigSource from fieldOptions to PanelModel.fieldConfig (#22600) * Apply field overrides in PanelChrome * Move applyFieldOverrides to panel query runner * Review updates * Make sure overrides are applied back on souce panel when exiting the new edit mode * TS ignores in est * Make field display work in viz repeater * Review updates * Review and test updates * Change the way overrides and trransformations are retrieved in PQR * Add fieldConfig property to PanelModel * Dashboard migration v1 * Use field config when exiting new panel edit mode * Gauge - use fieldConfig from panel model * FieldDisplayOptions - don's extend FieldConfigSource * Fix fieldDisplay ts * StatPanel updated * Stat panel defaults applied * Table2 panel options update * React graph updates * BarGauge updated * PieChart, Gauge, BarGauge and Stat updates * PieChart - remove field config defaults from options * FieldDisplayEditor - remove unused methos * PanelModel - remove debugger * Remove fieldConfig from field options when migrating dashboard * Update data links migrations * Update fieldDisaplay tests to respect new fieldConfig * Update dashboard schema version in snapshots * Fix BarGaugePanel test * Rebase fixes * Add onFieldConfigChange to PanelProps type * Update shared single stat migration * Pass PanelModel instead of options only for panel type change handler [breaking] * Renames * Don't mutate panel options * Migrations update * Remove obsolete snap * Minor updates after review * Fix null checks * Temporarily (until we decide to switch to new pane edit) bring back old aditors * Temporarily rename ValueMappingEditor and MappingRow to Legacy* * Migrations update * Updae setFieldConfigDefaults API * Update the way field config defaults are applied * Use standard field config for gauge, bar gauge and stat panels * refactoring * Revert dashboard fieldOptions migrations as those are handled by single stat migrator * Fix ts in tests * Strict null fix and some minor fixes Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2020-03-19 05:50:31 -05:00
const panelPlugin = getPanelPlugin(
{
id: 'table',
},
(null as unknown) as ComponentClass<PanelProps>, // react
TablePanelCtrl // angular
);
panelPlugin.setPanelOptions(builder => {
builder.addBooleanSwitch({
name: 'Show thresholds',
path: 'showThresholds',
defaultValue: true,
description: '',
});
});
panelPlugin.useFieldConfig({
standardOptions: [FieldConfigProperty.Unit, FieldConfigProperty.Decimals],
standardOptionsDefaults: {
[FieldConfigProperty.Unit]: 'flop',
[FieldConfigProperty.Decimals]: 2,
},
FieldOverrides: Move FieldConfigSource from fieldOptions to PanelModel.fieldConfig (#22600) * Apply field overrides in PanelChrome * Move applyFieldOverrides to panel query runner * Review updates * Make sure overrides are applied back on souce panel when exiting the new edit mode * TS ignores in est * Make field display work in viz repeater * Review updates * Review and test updates * Change the way overrides and trransformations are retrieved in PQR * Add fieldConfig property to PanelModel * Dashboard migration v1 * Use field config when exiting new panel edit mode * Gauge - use fieldConfig from panel model * FieldDisplayOptions - don's extend FieldConfigSource * Fix fieldDisplay ts * StatPanel updated * Stat panel defaults applied * Table2 panel options update * React graph updates * BarGauge updated * PieChart, Gauge, BarGauge and Stat updates * PieChart - remove field config defaults from options * FieldDisplayEditor - remove unused methos * PanelModel - remove debugger * Remove fieldConfig from field options when migrating dashboard * Update data links migrations * Update fieldDisaplay tests to respect new fieldConfig * Update dashboard schema version in snapshots * Fix BarGaugePanel test * Rebase fixes * Add onFieldConfigChange to PanelProps type * Update shared single stat migration * Pass PanelModel instead of options only for panel type change handler [breaking] * Renames * Don't mutate panel options * Migrations update * Remove obsolete snap * Minor updates after review * Fix null checks * Temporarily (until we decide to switch to new pane edit) bring back old aditors * Temporarily rename ValueMappingEditor and MappingRow to Legacy* * Migrations update * Updae setFieldConfigDefaults API * Update the way field config defaults are applied * Use standard field config for gauge, bar gauge and stat panels * refactoring * Revert dashboard fieldOptions migrations as those are handled by single stat migrator * Fix ts in tests * Strict null fix and some minor fixes Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2020-03-19 05:50:31 -05:00
});
model.pluginLoaded(panelPlugin);
});
it('should apply defaults', () => {
expect(model.gridPos.h).toBe(3);
});
it('should apply option defaults', () => {
expect(model.getOptions().showThresholds).toBeTruthy();
});
it('should apply option defaults but not override if array is changed', () => {
expect(model.getOptions().arrayWith2Values.length).toBe(1);
});
FieldOverrides: Move FieldConfigSource from fieldOptions to PanelModel.fieldConfig (#22600) * Apply field overrides in PanelChrome * Move applyFieldOverrides to panel query runner * Review updates * Make sure overrides are applied back on souce panel when exiting the new edit mode * TS ignores in est * Make field display work in viz repeater * Review updates * Review and test updates * Change the way overrides and trransformations are retrieved in PQR * Add fieldConfig property to PanelModel * Dashboard migration v1 * Use field config when exiting new panel edit mode * Gauge - use fieldConfig from panel model * FieldDisplayOptions - don's extend FieldConfigSource * Fix fieldDisplay ts * StatPanel updated * Stat panel defaults applied * Table2 panel options update * React graph updates * BarGauge updated * PieChart, Gauge, BarGauge and Stat updates * PieChart - remove field config defaults from options * FieldDisplayEditor - remove unused methos * PanelModel - remove debugger * Remove fieldConfig from field options when migrating dashboard * Update data links migrations * Update fieldDisaplay tests to respect new fieldConfig * Update dashboard schema version in snapshots * Fix BarGaugePanel test * Rebase fixes * Add onFieldConfigChange to PanelProps type * Update shared single stat migration * Pass PanelModel instead of options only for panel type change handler [breaking] * Renames * Don't mutate panel options * Migrations update * Remove obsolete snap * Minor updates after review * Fix null checks * Temporarily (until we decide to switch to new pane edit) bring back old aditors * Temporarily rename ValueMappingEditor and MappingRow to Legacy* * Migrations update * Updae setFieldConfigDefaults API * Update the way field config defaults are applied * Use standard field config for gauge, bar gauge and stat panels * refactoring * Revert dashboard fieldOptions migrations as those are handled by single stat migrator * Fix ts in tests * Strict null fix and some minor fixes Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2020-03-19 05:50:31 -05:00
it('should apply field config defaults', () => {
// default unit is overriden by model
expect(model.getFieldOverrideOptions().fieldConfig.defaults.unit).toBe('mpg');
FieldOverrides: Move FieldConfigSource from fieldOptions to PanelModel.fieldConfig (#22600) * Apply field overrides in PanelChrome * Move applyFieldOverrides to panel query runner * Review updates * Make sure overrides are applied back on souce panel when exiting the new edit mode * TS ignores in est * Make field display work in viz repeater * Review updates * Review and test updates * Change the way overrides and trransformations are retrieved in PQR * Add fieldConfig property to PanelModel * Dashboard migration v1 * Use field config when exiting new panel edit mode * Gauge - use fieldConfig from panel model * FieldDisplayOptions - don's extend FieldConfigSource * Fix fieldDisplay ts * StatPanel updated * Stat panel defaults applied * Table2 panel options update * React graph updates * BarGauge updated * PieChart, Gauge, BarGauge and Stat updates * PieChart - remove field config defaults from options * FieldDisplayEditor - remove unused methos * PanelModel - remove debugger * Remove fieldConfig from field options when migrating dashboard * Update data links migrations * Update fieldDisaplay tests to respect new fieldConfig * Update dashboard schema version in snapshots * Fix BarGaugePanel test * Rebase fixes * Add onFieldConfigChange to PanelProps type * Update shared single stat migration * Pass PanelModel instead of options only for panel type change handler [breaking] * Renames * Don't mutate panel options * Migrations update * Remove obsolete snap * Minor updates after review * Fix null checks * Temporarily (until we decide to switch to new pane edit) bring back old aditors * Temporarily rename ValueMappingEditor and MappingRow to Legacy* * Migrations update * Updae setFieldConfigDefaults API * Update the way field config defaults are applied * Use standard field config for gauge, bar gauge and stat panels * refactoring * Revert dashboard fieldOptions migrations as those are handled by single stat migrator * Fix ts in tests * Strict null fix and some minor fixes Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2020-03-19 05:50:31 -05:00
// default decimals are aplied
expect(model.getFieldOverrideOptions().fieldConfig.defaults.decimals).toBe(2);
FieldOverrides: Move FieldConfigSource from fieldOptions to PanelModel.fieldConfig (#22600) * Apply field overrides in PanelChrome * Move applyFieldOverrides to panel query runner * Review updates * Make sure overrides are applied back on souce panel when exiting the new edit mode * TS ignores in est * Make field display work in viz repeater * Review updates * Review and test updates * Change the way overrides and trransformations are retrieved in PQR * Add fieldConfig property to PanelModel * Dashboard migration v1 * Use field config when exiting new panel edit mode * Gauge - use fieldConfig from panel model * FieldDisplayOptions - don's extend FieldConfigSource * Fix fieldDisplay ts * StatPanel updated * Stat panel defaults applied * Table2 panel options update * React graph updates * BarGauge updated * PieChart, Gauge, BarGauge and Stat updates * PieChart - remove field config defaults from options * FieldDisplayEditor - remove unused methos * PanelModel - remove debugger * Remove fieldConfig from field options when migrating dashboard * Update data links migrations * Update fieldDisaplay tests to respect new fieldConfig * Update dashboard schema version in snapshots * Fix BarGaugePanel test * Rebase fixes * Add onFieldConfigChange to PanelProps type * Update shared single stat migration * Pass PanelModel instead of options only for panel type change handler [breaking] * Renames * Don't mutate panel options * Migrations update * Remove obsolete snap * Minor updates after review * Fix null checks * Temporarily (until we decide to switch to new pane edit) bring back old aditors * Temporarily rename ValueMappingEditor and MappingRow to Legacy* * Migrations update * Updae setFieldConfigDefaults API * Update the way field config defaults are applied * Use standard field config for gauge, bar gauge and stat panels * refactoring * Revert dashboard fieldOptions migrations as those are handled by single stat migrator * Fix ts in tests * Strict null fix and some minor fixes Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2020-03-19 05:50:31 -05:00
});
it('should set model props on instance', () => {
expect(model.showColumns).toBe(true);
});
it('should add missing refIds', () => {
expect(model.targets[1].refId).toBe('B');
});
it("shouldn't break panel with non-array targets", () => {
modelJson.targets = {
0: { refId: 'A' },
foo: { bar: 'baz' },
};
model = new PanelModel(modelJson);
expect(model.targets[0].refId).toBe('A');
});
it('getSaveModel should remove defaults', () => {
const saveModel = model.getSaveModel();
expect(saveModel.gridPos).toBe(undefined);
});
it('getSaveModel should not remove datasource default', () => {
const saveModel = model.getSaveModel();
expect(saveModel.datasource).toBe(null);
});
it('getSaveModel should remove nonPersistedProperties', () => {
const saveModel = model.getSaveModel();
expect(saveModel.events).toBe(undefined);
});
describe('variables interpolation', () => {
beforeEach(() => {
model.scopedVars = {
aaa: { value: 'AAA', text: 'upperA' },
bbb: { value: 'BBB', text: 'upperB' },
};
});
it('should interpolate variables', () => {
const out = model.replaceVariables('hello $aaa');
expect(out).toBe('hello AAA');
});
it('should prefer the local variable value', () => {
const extra = { aaa: { text: '???', value: 'XXX' } };
const out = model.replaceVariables('hello $aaa and $bbb', extra);
expect(out).toBe('hello XXX and BBB');
});
});
describe('when changing panel type', () => {
beforeEach(() => {
const newPlugin = getPanelPlugin({ id: 'graph' });
newPlugin.setPanelOptions(builder => {
builder.addBooleanSwitch({
name: 'Show thresholds labels',
path: 'showThresholdLabels',
defaultValue: false,
description: '',
});
});
model.editSourceId = 1001;
model.changePlugin(newPlugin);
model.alert = { id: 2 };
});
it('should keep editSourceId', () => {
expect(model.editSourceId).toBe(1001);
});
it('should apply next panel option defaults', () => {
expect(model.getOptions().showThresholdLabels).toBeFalsy();
expect(model.getOptions().showThresholds).toBeUndefined();
});
it('should remove table properties but keep core props', () => {
expect(model.showColumns).toBe(undefined);
});
it('should restore table properties when changing back', () => {
model.changePlugin(getPanelPlugin({ id: 'table' }));
expect(model.showColumns).toBe(true);
});
it('should remove alert rule when changing type that does not support it', () => {
model.changePlugin(getPanelPlugin({ id: 'table' }));
expect(model.alert).toBe(undefined);
});
});
describe('when changing to react panel from angular panel', () => {
let panelQueryRunner: any;
const onPanelTypeChanged = jest.fn();
const reactPlugin = getPanelPlugin({ id: 'react' }).setPanelChangeHandler(onPanelTypeChanged as any);
beforeEach(() => {
model.changePlugin(reactPlugin);
panelQueryRunner = model.getQueryRunner();
});
it('should call react onPanelTypeChanged', () => {
expect(onPanelTypeChanged.mock.calls.length).toBe(1);
expect(onPanelTypeChanged.mock.calls[0][1]).toBe('table');
expect(onPanelTypeChanged.mock.calls[0][2].angular).toBeDefined();
});
it('getQueryRunner() should return same instance after changing to another react panel', () => {
model.changePlugin(getPanelPlugin({ id: 'react2' }));
const sameQueryRunner = model.getQueryRunner();
expect(panelQueryRunner).toBe(sameQueryRunner);
});
});
describe('variables interpolation', () => {
let panelQueryRunner: any;
const onPanelTypeChanged = jest.fn();
const reactPlugin = getPanelPlugin({ id: 'react' }).setPanelChangeHandler(onPanelTypeChanged as any);
beforeEach(() => {
model.changePlugin(reactPlugin);
panelQueryRunner = model.getQueryRunner();
});
it('should call react onPanelTypeChanged', () => {
expect(onPanelTypeChanged.mock.calls.length).toBe(1);
expect(onPanelTypeChanged.mock.calls[0][1]).toBe('table');
expect(onPanelTypeChanged.mock.calls[0][2].angular).toBeDefined();
});
it('getQueryRunner() should return same instance after changing to another react panel', () => {
model.changePlugin(getPanelPlugin({ id: 'react2' }));
const sameQueryRunner = model.getQueryRunner();
expect(panelQueryRunner).toBe(sameQueryRunner);
});
});
describe('restoreModel', () => {
it('Should clean state and set properties from model', () => {
model.restoreModel({
title: 'New title',
options: { new: true },
});
expect(model.title).toBe('New title');
expect(model.options.new).toBe(true);
});
it('Should delete properties that are now gone on new model', () => {
model.someProperty = 'value';
model.restoreModel({
title: 'New title',
options: {},
});
expect(model.someProperty).toBeUndefined();
});
it('Should preserve must keep properties', () => {
model.id = 10;
model.gridPos = { x: 0, y: 0, h: 10, w: 10 };
model.restoreModel({
title: 'New title',
options: {},
});
expect(model.id).toBe(10);
expect(model.gridPos.h).toBe(10);
});
it('Should remove old angular panel specfic props', () => {
model.axes = [{ prop: 1 }];
model.thresholds = [];
model.restoreModel({
title: 'New title',
options: {},
});
expect(model.axes).toBeUndefined();
expect(model.thresholds).toBeUndefined();
});
});
});
});