grafana/data: Move getPanelOptionsWithDefaults from core (#60813)

* grafana/data: Move getPanelOptionsWithDefaults from core

* Add internal comments
This commit is contained in:
Dominik Prokop
2022-12-29 05:48:22 -08:00
committed by GitHub
parent 168afa99d1
commit c3c4a57c79
27 changed files with 215 additions and 183 deletions

View File

@@ -1,4 +1,4 @@
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { setContextSrv } from '../../../../core/services/context_srv';
import { PanelModel } from '../../state/PanelModel';

View File

@@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react';
import React from 'react';
import { FieldType, getDefaultTimeRange, LoadingState, toDataFrame } from '@grafana/data';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { PanelModel } from '../../state/PanelModel';

View File

@@ -12,9 +12,9 @@ import {
standardFieldConfigEditorRegistry,
toDataFrame,
} from '@grafana/data';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { selectors } from '@grafana/e2e-selectors';
import { getAllOptionEditors, getAllStandardFieldConfigs } from 'app/core/components/OptionsUI/registry';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { PanelModel } from '../../state';
import { createDashboardModelFixture } from '../../state/__fixtures__/dashboardFixtures';

View File

@@ -1,6 +1,6 @@
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { createDashboardModelFixture } from 'app/features/dashboard/state/__fixtures__/dashboardFixtures';
import { panelModelAndPluginReady, removePanel } from 'app/features/panel/state/reducers';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { thunkTester } from '../../../../../../test/core/thunk/thunkTester';
import { PanelModel } from '../../../state';

View File

@@ -1,11 +1,11 @@
import { each, map } from 'lodash';
import { DataLinkBuiltInVars, MappingType } from '@grafana/data';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { setDataSourceSrv } from '@grafana/runtime';
import { config } from 'app/core/config';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants';
import { mockDataSource, MockDataSourceSrv } from 'app/features/alerting/unified/mocks';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
import { VariableHide } from '../../variables/types';

View File

@@ -10,11 +10,11 @@ import {
dateTime,
TimeRange,
} from '@grafana/data';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { mockStandardFieldConfigOptions } from '@grafana/data/test/helpers/fieldConfig';
import { setTemplateSrv } from '@grafana/runtime';
import { queryBuilder } from 'app/features/variables/shared/testing/builders';
import { mockStandardFieldConfigOptions } from '../../../../test/helpers/fieldConfig';
import { getPanelPlugin } from '../../plugins/__mocks__/pluginMocks';
import { PanelQueryRunner } from '../../query/state/PanelQueryRunner';
import { TemplateSrv } from '../../templating/template_srv';
import { variableAdapters } from '../../variables/adapters';

View File

@@ -17,6 +17,10 @@ import {
PanelModel as IPanelModel,
DataSourceRef,
CoreApp,
filterFieldConfigOverrides,
getPanelOptionsWithDefaults,
isStandardFieldProp,
restoreCustomOverrideRules,
} from '@grafana/data';
import { getTemplateSrv, RefreshEvent } from '@grafana/runtime';
import config from 'app/core/config';
@@ -37,13 +41,6 @@ import { getVariablesUrlParams } from '../../variables/getAllVariableValuesForUr
import { getTimeSrv } from '../services/TimeSrv';
import { TimeOverrideResult } from '../utils/panel';
import {
filterFieldConfigOverrides,
getPanelOptionsWithDefaults,
isStandardFieldProp,
restoreCustomOverrideRules,
} from './getPanelOptionsWithDefaults';
export interface GridPos {
x: number;
y: number;

View File

@@ -1,439 +0,0 @@
import { mockStandardFieldConfigOptions } from 'test/helpers/fieldConfig';
import {
ConfigOverrideRule,
FieldColorModeId,
FieldConfig,
FieldConfigProperty,
FieldConfigSource,
PanelPlugin,
standardEditorsRegistry,
standardFieldConfigEditorRegistry,
StandardOptionConfig,
ThresholdsMode,
} from '@grafana/data';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { getPanelOptionsWithDefaults, restoreCustomOverrideRules } from './getPanelOptionsWithDefaults';
standardFieldConfigEditorRegistry.setInit(() => mockStandardFieldConfigOptions());
standardEditorsRegistry.setInit(() => mockStandardFieldConfigOptions());
const pluginA = getPanelPlugin({ id: 'graph' });
pluginA.useFieldConfig({
useCustomConfig: (builder) => {
builder.addBooleanSwitch({
name: 'Hide lines',
path: 'hideLines',
defaultValue: false,
});
},
});
pluginA.setPanelOptions((builder) => {
builder.addBooleanSwitch({
name: 'Show thresholds',
path: 'showThresholds',
defaultValue: true,
});
builder.addTextInput({
name: 'Name',
path: 'name',
defaultValue: 'hello',
});
builder.addNumberInput({
name: 'Number',
path: 'number',
defaultValue: 10,
});
});
describe('getPanelOptionsWithDefaults', () => {
describe('When panel plugin has no options', () => {
it('Should set defaults', () => {
const result = runScenario({
plugin: getPanelPlugin({ id: 'graph' }),
options: {},
defaults: {},
overrides: [],
});
expect(result).toMatchInlineSnapshot(`
{
"fieldConfig": {
"defaults": {},
"overrides": [],
},
"options": {},
}
`);
});
});
describe('When current options are emtpy', () => {
it('Should set defaults', () => {
const result = getPanelOptionsWithDefaults({
plugin: pluginA,
currentOptions: {},
currentFieldConfig: {
defaults: {},
overrides: [],
},
isAfterPluginChange: false,
});
expect(result).toMatchInlineSnapshot(`
{
"fieldConfig": {
"defaults": {
"custom": {
"hideLines": false,
},
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": -Infinity,
},
{
"color": "red",
"value": 80,
},
],
},
},
"overrides": [],
},
"options": {
"name": "hello",
"number": 10,
"showThresholds": true,
},
}
`);
});
});
describe('When there are current options and overrides', () => {
it('Should set defaults', () => {
const result = getPanelOptionsWithDefaults({
plugin: pluginA,
currentOptions: {
number: 20,
showThresholds: false,
},
currentFieldConfig: {
defaults: {
unit: 'bytes',
decimals: 2,
},
overrides: [],
},
isAfterPluginChange: true,
});
expect(result).toMatchInlineSnapshot(`
{
"fieldConfig": {
"defaults": {
"custom": {
"hideLines": false,
},
"decimals": 2,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": -Infinity,
},
{
"color": "red",
"value": 80,
},
],
},
"unit": "bytes",
},
"overrides": [],
},
"options": {
"name": "hello",
"number": 20,
"showThresholds": false,
},
}
`);
});
});
describe('when changing panel type to one that does not support by value color mode', () => {
it('should change color mode', () => {
const plugin = getPanelPlugin({ id: 'graph' }).useFieldConfig({
standardOptions: {
[FieldConfigProperty.Color]: {
settings: {
byValueSupport: false,
},
},
},
});
const result = getPanelOptionsWithDefaults({
plugin,
currentOptions: {},
currentFieldConfig: {
defaults: {
color: { mode: FieldColorModeId.Thresholds },
},
overrides: [],
},
isAfterPluginChange: true,
});
expect(result.fieldConfig.defaults.color!.mode).toBe(FieldColorModeId.PaletteClassic);
});
});
describe('when changing panel type from one not supporting by value color mode to one that supports it', () => {
it('should keep supported mode', () => {
const result = runScenario({
defaults: {
color: { mode: FieldColorModeId.PaletteClassic },
},
standardOptions: {
[FieldConfigProperty.Color]: {
settings: {
byValueSupport: true,
},
},
},
});
expect(result.fieldConfig.defaults.color!.mode).toBe(FieldColorModeId.PaletteClassic);
});
it('should change to thresholds mode when it prefers to', () => {
const result = runScenario({
defaults: {
color: { mode: FieldColorModeId.PaletteClassic },
},
standardOptions: {
[FieldConfigProperty.Color]: {
settings: {
byValueSupport: true,
preferThresholdsMode: true,
},
},
},
isAfterPluginChange: true,
});
expect(result.fieldConfig.defaults.color!.mode).toBe(FieldColorModeId.Thresholds);
});
it('should change to classic mode when panel supports bySeries', () => {
const result = runScenario({
defaults: {
color: { mode: FieldColorModeId.Thresholds },
},
standardOptions: {
[FieldConfigProperty.Color]: {
settings: {
byValueSupport: true,
bySeriesSupport: true,
},
},
},
isAfterPluginChange: true,
});
expect(result.fieldConfig.defaults.color!.mode).toBe(FieldColorModeId.PaletteClassic);
});
});
describe('when changing panel type to one that does not use standard field config', () => {
it('should clean defaults', () => {
const plugin = getPanelPlugin({ id: 'graph' });
const result = getPanelOptionsWithDefaults({
plugin,
currentOptions: {},
currentFieldConfig: {
defaults: {
color: { mode: FieldColorModeId.Thresholds },
thresholds: {
mode: ThresholdsMode.Absolute,
steps: [],
},
},
overrides: [],
},
isAfterPluginChange: true,
});
expect(result.fieldConfig.defaults.thresholds).toBeUndefined();
});
});
describe('when applying defaults clean properties that are no longer part of the registry', () => {
it('should remove custom defaults that no longer exist', () => {
const result = runScenario({
defaults: {
unit: 'bytes',
custom: {
customProp: 20,
customPropNoExist: true,
nested: {
nestedA: 'A',
nestedB: 'B',
},
},
},
});
expect(result.fieldConfig.defaults).toMatchInlineSnapshot(`
{
"custom": {
"customProp": 20,
"nested": {
"nestedA": "A",
},
},
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": -Infinity,
},
{
"color": "red",
"value": 80,
},
],
},
"unit": "bytes",
}
`);
});
it('should remove custom overrides that no longer exist', () => {
const result = runScenario({
defaults: {},
overrides: [
{
matcher: { id: 'byName', options: 'D-series' },
properties: [
{
id: 'custom.customPropNoExist',
value: 'google',
},
],
},
{
matcher: { id: 'byName', options: 'D-series' },
properties: [
{
id: 'custom.customProp',
value: 30,
},
],
},
],
});
expect(result.fieldConfig.overrides.length).toBe(1);
expect(result.fieldConfig.overrides[0].properties[0].id).toBe('custom.customProp');
});
});
});
describe('restoreCustomOverrideRules', () => {
it('should add back custom rules', () => {
const current = {
defaults: {},
overrides: [
{
matcher: { id: 'byName', options: 'SeriesA' },
properties: [
{
id: 'decimals',
value: 2,
},
],
},
],
};
const old = {
defaults: {},
overrides: [
{
matcher: { id: 'byName', options: 'SeriesA' },
properties: [
{
id: 'custom.propName',
value: 10,
},
],
},
{
matcher: { id: 'byName', options: 'SeriesB' },
properties: [
{
id: 'custom.propName',
value: 20,
},
],
},
],
};
const result = restoreCustomOverrideRules(current, old);
expect(result.overrides.length).toBe(2);
expect(result.overrides[0].properties[0].id).toBe('decimals');
expect(result.overrides[0].properties[1].id).toBe('custom.propName');
expect(result.overrides[1].properties.length).toBe(1);
expect(result.overrides[1].matcher.options).toBe('SeriesB');
});
});
interface ScenarioOptions {
defaults?: FieldConfig<any>;
overrides?: ConfigOverrideRule[];
disabledStandardOptions?: FieldConfigProperty[];
standardOptions?: Partial<Record<FieldConfigProperty, StandardOptionConfig>>;
plugin?: PanelPlugin;
options?: any;
isAfterPluginChange?: boolean;
}
function runScenario(options: ScenarioOptions) {
const fieldConfig: FieldConfigSource = {
defaults: options.defaults || {},
overrides: options.overrides || [],
};
const plugin =
options.plugin ??
getPanelPlugin({ id: 'graph' }).useFieldConfig({
standardOptions: options.standardOptions,
useCustomConfig: (builder) => {
builder.addNumberInput({
name: 'Custom prop',
path: 'customProp',
defaultValue: 10,
});
builder.addTextInput({
name: 'Nested prop',
path: 'nested.nestedA',
});
},
});
return getPanelOptionsWithDefaults({
plugin,
currentOptions: options.options || {},
currentFieldConfig: fieldConfig,
isAfterPluginChange: !!options.isAfterPluginChange,
});
}

View File

@@ -1,230 +0,0 @@
import { mergeWith, isArray, isObject, unset, isEqual } from 'lodash';
import {
ConfigOverrideRule,
DynamicConfigValue,
FieldColorConfigSettings,
FieldColorModeId,
fieldColorModeRegistry,
FieldConfigOptionsRegistry,
FieldConfigProperty,
FieldConfigSource,
PanelPlugin,
ThresholdsConfig,
ThresholdsMode,
} from '@grafana/data';
export interface Props {
plugin: PanelPlugin;
currentFieldConfig: FieldConfigSource;
currentOptions: Record<string, any>;
isAfterPluginChange: boolean;
}
export interface OptionDefaults {
options: any;
fieldConfig: FieldConfigSource;
}
export function getPanelOptionsWithDefaults({
plugin,
currentOptions,
currentFieldConfig,
isAfterPluginChange,
}: Props): OptionDefaults {
const optionsWithDefaults = mergeWith(
{},
plugin.defaults,
currentOptions || {},
(objValue: any, srcValue: any): any => {
if (isArray(srcValue)) {
return srcValue;
}
}
);
const fieldConfigWithDefaults = applyFieldConfigDefaults(currentFieldConfig, plugin);
const fieldConfigWithOptimalColorMode = adaptFieldColorMode(plugin, fieldConfigWithDefaults, isAfterPluginChange);
return { options: optionsWithDefaults, fieldConfig: fieldConfigWithOptimalColorMode };
}
function applyFieldConfigDefaults(existingFieldConfig: FieldConfigSource, plugin: PanelPlugin): FieldConfigSource {
const pluginDefaults = plugin.fieldConfigDefaults;
const result: FieldConfigSource = {
defaults: mergeWith(
{},
pluginDefaults.defaults,
existingFieldConfig ? existingFieldConfig.defaults : {},
(objValue: any, srcValue: any): any => {
if (isArray(srcValue)) {
return srcValue;
}
}
),
overrides: existingFieldConfig?.overrides ?? [],
};
cleanProperties(result.defaults, '', plugin.fieldConfigRegistry);
// Thresholds base values are null in JSON but need to be converted to -Infinity
if (result.defaults.thresholds) {
fixThresholds(result.defaults.thresholds);
}
// Filter out overrides for properties that cannot be found in registry
result.overrides = filterFieldConfigOverrides(result.overrides, (prop) => {
return plugin.fieldConfigRegistry.getIfExists(prop.id) !== undefined;
});
for (const override of result.overrides) {
for (const property of override.properties) {
if (property.id === 'thresholds') {
fixThresholds(property.value as ThresholdsConfig);
}
}
}
return result;
}
export function filterFieldConfigOverrides(
overrides: ConfigOverrideRule[],
condition: (value: DynamicConfigValue) => boolean
): ConfigOverrideRule[] {
return overrides
.map((x) => {
const properties = x.properties.filter(condition);
return {
...x,
properties,
};
})
.filter((x) => x.properties.length > 0);
}
function cleanProperties(obj: any, parentPath: string, fieldConfigRegistry: FieldConfigOptionsRegistry) {
let found = false;
for (const propName of Object.keys(obj)) {
const value = obj[propName];
const fullPath = `${parentPath}${propName}`;
const existsInRegistry = !!fieldConfigRegistry.getIfExists(fullPath);
// need to check early here as some standard properties have nested properies
if (existsInRegistry) {
found = true;
continue;
}
if (isArray(value) || !isObject(value)) {
if (!existsInRegistry) {
unset(obj, propName);
}
} else {
const childPropFound = cleanProperties(value, `${fullPath}.`, fieldConfigRegistry);
// If no child props found unset the main object
if (!childPropFound) {
unset(obj, propName);
}
}
}
return found;
}
function adaptFieldColorMode(
plugin: PanelPlugin,
fieldConfig: FieldConfigSource,
isAfterPluginChange: boolean
): FieldConfigSource {
if (!isAfterPluginChange) {
return fieldConfig;
}
// adjust to prefered field color setting if needed
const color = plugin.fieldConfigRegistry.getIfExists(FieldConfigProperty.Color);
if (color && color.settings) {
const colorSettings = color.settings as FieldColorConfigSettings;
const mode = fieldColorModeRegistry.getIfExists(fieldConfig.defaults.color?.mode);
// When no support fo value colors, use classic palette
if (!colorSettings.byValueSupport) {
if (!mode || mode.isByValue) {
fieldConfig.defaults.color = { mode: FieldColorModeId.PaletteClassic };
return fieldConfig;
}
}
// When supporting value colors and prefering thresholds, use Thresholds mode.
// Otherwise keep current mode
if (colorSettings.byValueSupport && colorSettings.preferThresholdsMode && mode?.id !== FieldColorModeId.Fixed) {
if (!mode || !mode.isByValue) {
fieldConfig.defaults.color = { mode: FieldColorModeId.Thresholds };
return fieldConfig;
}
}
// If panel support bySeries then we should default to that when switching to this panel as that is most likely
// what users will expect. Example scenario a user who has a graph panel (time series) and switches to Gauge and
// then back to time series we want the graph panel color mode to reset to classic palette and not preserve the
// Gauge prefered thresholds mode.
if (colorSettings.bySeriesSupport && mode?.isByValue) {
fieldConfig.defaults.color = { mode: FieldColorModeId.PaletteClassic };
return fieldConfig;
}
}
return fieldConfig;
}
function fixThresholds(thresholds: ThresholdsConfig) {
if (!thresholds.mode) {
thresholds.mode = ThresholdsMode.Absolute;
}
if (!thresholds.steps) {
thresholds.steps = [];
} else if (thresholds.steps.length) {
// First value is always -Infinity
// JSON saves it as null
thresholds.steps[0].value = -Infinity;
}
}
export function restoreCustomOverrideRules(current: FieldConfigSource, old: FieldConfigSource): FieldConfigSource {
const result = {
defaults: {
...current.defaults,
custom: old.defaults.custom,
},
overrides: [...current.overrides],
};
for (const override of old.overrides) {
for (const prop of override.properties) {
if (isCustomFieldProp(prop)) {
const currentOverride = result.overrides.find((o) => isEqual(o.matcher, override.matcher));
if (currentOverride) {
if (currentOverride !== override) {
currentOverride.properties.push(prop);
}
} else {
result.overrides.push(override);
}
}
}
}
return result;
}
export function isCustomFieldProp(prop: DynamicConfigValue): boolean {
return prop.id.startsWith('custom.');
}
export function isStandardFieldProp(prop: DynamicConfigValue): boolean {
return !isCustomFieldProp(prop);
}

View File

@@ -2,9 +2,9 @@ import { advanceTo, clear } from 'jest-date-mock';
import { ComponentClass } from 'react';
import { dateTime, DateTime, PanelProps, TimeRange } from '@grafana/data';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { applyPanelTimeOverrides, calculateInnerPanelHeight } from 'app/features/dashboard/utils/panel';
import { getPanelPlugin } from '../../plugins/__mocks__/pluginMocks';
import { PanelModel } from '../state';
const dashboardTimeRange: TimeRange = {

View File

@@ -1,5 +1,5 @@
import { DataSourcePluginMeta } from '@grafana/data';
import { getMockPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { getMockPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { buildCategories } from './buildCategories';

View File

@@ -1,4 +1,4 @@
import { getMockPlugin, getMockPlugins } from 'app/features/plugins/__mocks__/pluginMocks';
import { getMockPlugin, getMockPlugins } from '@grafana/data/test/__mocks__/pluginMocks';
import { nameExits, findNewName } from './utils';

View File

@@ -11,12 +11,13 @@ import {
compareDataFrameStructures,
PluginContextProvider,
ScopedVars,
getPanelOptionsWithDefaults,
OptionDefaults,
} from '@grafana/data';
import { getTemplateSrv, PanelRendererProps } from '@grafana/runtime';
import { ErrorBoundaryAlert, useTheme2 } from '@grafana/ui';
import { appEvents } from 'app/core/core';
import { getPanelOptionsWithDefaults, OptionDefaults } from '../../dashboard/state/getPanelOptionsWithDefaults';
import { importPanelPlugin, syncGetPanelPlugin } from '../../plugins/importPanelPlugin';
const defaultFieldConfig = { defaults: {}, overrides: [] };

View File

@@ -1,8 +1,7 @@
import { mockStandardFieldConfigOptions } from 'test/helpers/fieldConfig';
import { standardEditorsRegistry, standardFieldConfigEditorRegistry } from '@grafana/data';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { mockStandardFieldConfigOptions } from '@grafana/data/test/helpers/fieldConfig';
import { PanelModel } from 'app/features/dashboard/state';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { panelPluginLoaded } from 'app/features/plugins/admin/state/actions';
import { thunkTester } from '../../../../test/core/thunk/thunkTester';

View File

@@ -1,6 +1,5 @@
import { DataTransformerConfig, FieldConfigSource } from '@grafana/data';
import { DataTransformerConfig, FieldConfigSource, getPanelOptionsWithDefaults } from '@grafana/data';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import { getPanelOptionsWithDefaults } from 'app/features/dashboard/state/getPanelOptionsWithDefaults';
import { getLibraryPanel } from 'app/features/library-panels/state/api';
import { LibraryElementDTO } from 'app/features/library-panels/types';
import { getPanelPluginNotFound } from 'app/features/panel/components/PanelPluginError';

View File

@@ -1,99 +0,0 @@
import { ComponentType } from 'enzyme';
import { defaultsDeep } from 'lodash';
import { PanelPluginMeta, PluginMeta, PluginType, PanelPlugin, PanelProps } from '@grafana/data';
export const getMockPlugins = (amount: number): PluginMeta[] => {
const plugins = [];
for (let i = 0; i <= amount; i++) {
plugins.push({
defaultNavUrl: 'some/url',
enabled: false,
hasUpdate: false,
id: `${i}`,
info: {
author: {
name: 'Grafana Labs',
url: 'url/to/GrafanaLabs',
},
description: 'pretty decent plugin',
links: ['one link'],
logos: { small: 'small/logo', large: 'large/logo' },
screenshots: [{ path: `screenshot/${i}` }],
updated: '2018-09-26',
version: '1',
},
latestVersion: `1.${i}`,
name: `pretty cool plugin-${i}`,
pinned: false,
state: '',
type: '',
module: {},
});
}
return plugins as any;
};
export function getPanelPlugin(
options: Partial<PanelPluginMeta>,
reactPanel?: ComponentType<PanelProps>,
angularPanel?: any
): PanelPlugin {
const plugin = new PanelPlugin(reactPanel!);
plugin.angularPanelCtrl = angularPanel;
plugin.meta = {
id: options.id!,
type: PluginType.panel,
name: options.id!,
sort: options.sort || 1,
info: {
author: {
name: options.id + 'name',
},
description: '',
links: [],
logos: {
large: '',
small: '',
},
screenshots: [],
updated: '',
version: '',
},
hideFromList: options.hideFromList === true,
module: options.module ?? '',
baseUrl: '',
};
return plugin;
}
export function getMockPlugin(overrides?: Partial<PluginMeta>): PluginMeta {
const defaults: PluginMeta = {
defaultNavUrl: 'some/url',
enabled: false,
hasUpdate: false,
id: '1',
info: {
author: {
name: 'Grafana Labs',
url: 'url/to/GrafanaLabs',
},
description: 'pretty decent plugin',
links: [{ name: 'project', url: 'one link' }],
logos: { small: 'small/logo', large: 'large/logo' },
screenshots: [{ path: `screenshot`, name: 'test' }],
updated: '2018-09-26',
version: '1',
},
latestVersion: '1',
name: 'pretty cool plugin 1',
baseUrl: 'path/to/plugin',
pinned: false,
type: PluginType.panel,
module: 'path/to/module',
};
return defaultsDeep(overrides || {}, defaults) as PluginMeta;
}

View File

@@ -5,13 +5,13 @@ import { Route, Router } from 'react-router-dom';
import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
import { AppPlugin, PluginType, AppRootProps, NavModelItem } from '@grafana/data';
import { getMockPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { locationService, setEchoSrv } from '@grafana/runtime';
import { GrafanaContext } from 'app/core/context/GrafanaContext';
import { GrafanaRoute } from 'app/core/navigation/GrafanaRoute';
import { Echo } from 'app/core/services/echo/Echo';
import { configureStore } from 'app/store/configureStore';
import { getMockPlugin } from '../__mocks__/pluginMocks';
import { getPluginSettings } from '../pluginSettings';
import { importAppPlugin } from '../plugin_loader';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { FieldConfigProperty, PanelPlugin } from '@grafana/data';
import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { VizPanel } from './VizPanel';

View File

@@ -1,12 +1,18 @@
import { DeepPartial } from '@reduxjs/toolkit';
import React from 'react';
import { AbsoluteTimeRange, FieldConfigSource, PanelModel, PanelPlugin, toUtc } from '@grafana/data';
import {
AbsoluteTimeRange,
FieldConfigSource,
PanelModel,
PanelPlugin,
toUtc,
getPanelOptionsWithDefaults,
} from '@grafana/data';
import { config } from '@grafana/runtime';
import { Field, Input } from '@grafana/ui';
import { importPanelPlugin, syncGetPanelPlugin } from 'app/features/plugins/importPanelPlugin';
import { getPanelOptionsWithDefaults } from '../../../dashboard/state/getPanelOptionsWithDefaults';
import { SceneObjectBase } from '../../core/SceneObjectBase';
import { sceneGraph } from '../../core/sceneGraph';
import { SceneComponentProps, SceneLayoutChildState } from '../../core/types';

View File

@@ -1,7 +1,7 @@
import { lastValueFrom } from 'rxjs';
import { DataSourceInstanceSettings, ScopedVars } from '@grafana/data';
import { getMockPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
import { getMockPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { SceneObject } from '../../core/types';
import { CustomFormatterFn } from '../interpolation/sceneInterpolator';

View File

@@ -1,7 +1,7 @@
import { DataSourceInstanceSettings } from '@grafana/data';
import { getMockPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { reduxTester } from '../../../../test/core/redux/reduxTester';
import { getMockPlugin } from '../../plugins/__mocks__/pluginMocks';
import { variableAdapters } from '../adapters';
import { changeVariableEditorExtended } from '../editor/reducer';
import { datasourceBuilder } from '../shared/testing/builders';

View File

@@ -1,9 +1,9 @@
import { cloneDeep } from 'lodash';
import { DataSourceInstanceSettings } from '@grafana/data';
import { getMockPlugins } from '@grafana/data/test/__mocks__/pluginMocks';
import { reducerTester } from '../../../../test/core/redux/reducerTester';
import { getMockPlugins } from '../../plugins/__mocks__/pluginMocks';
import { getDataSourceInstanceSetting } from '../shared/testing/helpers';
import { getVariableTestContext } from '../state/helpers';
import { VariablesState } from '../state/types';

View File

@@ -1,112 +0,0 @@
import { identityOverrideProcessor, ThresholdsMode } from '@grafana/data';
export function mockStandardFieldConfigOptions() {
const category = ['Standard options'];
const unit = {
category,
id: 'unit',
path: 'unit',
name: 'Unit',
description: 'Value units',
// @ts-ignore
editor: () => null,
// @ts-ignore
override: () => null,
process: identityOverrideProcessor,
shouldApply: () => true,
};
const decimals = {
category,
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 = {
category,
id: 'boolean',
path: 'boolean',
name: 'Boolean',
description: '',
// @ts-ignore
editor: () => null,
// @ts-ignore
override: () => null,
process: identityOverrideProcessor,
shouldApply: () => true,
};
const fieldColor = {
category,
id: 'color',
path: 'color',
name: 'color',
description: '',
// @ts-ignore
editor: () => null,
// @ts-ignore
override: () => null,
process: identityOverrideProcessor,
shouldApply: () => true,
};
const text = {
category,
id: 'text',
path: 'text',
name: 'text',
description: '',
// @ts-ignore
editor: () => null,
// @ts-ignore
override: () => null,
process: identityOverrideProcessor,
shouldApply: () => true,
};
const number = {
category,
id: 'number',
path: 'number',
name: 'number',
description: '',
// @ts-ignore
editor: () => null,
// @ts-ignore
override: () => null,
process: identityOverrideProcessor,
shouldApply: () => true,
};
const thresholds = {
category: ['Thresholds'],
id: 'thresholds',
path: 'thresholds',
name: 'thresholds',
description: '',
// @ts-ignore
editor: () => null,
// @ts-ignore
override: () => null,
process: identityOverrideProcessor,
shouldApply: () => true,
defaultValue: {
mode: ThresholdsMode.Absolute,
steps: [
{ value: -Infinity, color: 'green' },
{ value: 80, color: 'red' },
],
},
};
return [unit, decimals, boolean, fieldColor, text, number, thresholds];
}