The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/public/app/plugins/datasource/graphite/components/helpers.test.ts

254 lines
8.8 KiB

Graphite: Migrate to React (part 2B: migrate FunctionEditor) (#37070) * Add UMLs * Add rendered diagrams * Move QueryCtrl to flux * Remove redundant param in the reducer * Use named imports for lodash and fix typing for GraphiteTagOperator * Add missing async/await * Extract providers to a separate file * Clean up async await * Rename controller functions back to main * Simplify creating actions * Re-order controller functions * Separate helpers from actions * Rename vars * Simplify helpers * Move controller methods to state reducers * Remove docs (they are added in design doc) * Move actions.ts to state folder * Add docs * Add old methods stubs for easier review * Check how state dependencies will be mapped * Rename state to store * Rename state to store * Rewrite spec tests for Graphite Query Controller * Update docs * Update docs * Add GraphiteTextEditor * Add play button * Add AddGraphiteFunction * Use Segment to simplify AddGraphiteFunction * Memoize function defs * Fix useCallback deps * Update public/app/plugins/datasource/graphite/state/helpers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/helpers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/helpers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Add more type definitions * Remove submitOnClickAwayOption This behavior is actually needed to remove parameters in functions * Load function definitions before parsing the target on initial load * Add button padding * Fix loading function definitions * Change targetChanged to updateQuery to avoid mutating state directly It's also needed for extra refresh/runQuery execution as handleTargetChanged doesn't handle changing the raw query * Fix updating query after adding a function * Simplify updating function params * Migrate function editor to react * Simplify setting Segment Select min width * Remove unnecessary changes to SegmentInput * Extract view logic to a helper and update types definitions * Clean up types * Update FuncDef types and add tests * Show red border for unknown functions * Autofocus on new params * Extract params mapping to a helper * Split code between params and function editor * Focus on the first param when a function is added even if it's an optional argument * Add function editor tests * Remove todo marker * Fix adding new functions * Allow empty value in selects for removing function params * Add placeholders and fix styling * Add more docs * Rename .tsx -> .ts * Update types * Use ?? instead of || + add test for mapping options * Use const (let is not needed here) * Revert test name change * Allow removing only optional params and mark additional params as optional (only the first one is required) * Use theme.typography.bodySmall.fontSize Co-authored-by: Giordano Ricci <me@giordanoricci.com>
4 years ago
import { FuncDef, FuncDefs, FuncInstance } from '../gfunc';
Graphite: Migrate to React (part 2B: migrate FunctionEditor) (#37070) * Add UMLs * Add rendered diagrams * Move QueryCtrl to flux * Remove redundant param in the reducer * Use named imports for lodash and fix typing for GraphiteTagOperator * Add missing async/await * Extract providers to a separate file * Clean up async await * Rename controller functions back to main * Simplify creating actions * Re-order controller functions * Separate helpers from actions * Rename vars * Simplify helpers * Move controller methods to state reducers * Remove docs (they are added in design doc) * Move actions.ts to state folder * Add docs * Add old methods stubs for easier review * Check how state dependencies will be mapped * Rename state to store * Rename state to store * Rewrite spec tests for Graphite Query Controller * Update docs * Update docs * Add GraphiteTextEditor * Add play button * Add AddGraphiteFunction * Use Segment to simplify AddGraphiteFunction * Memoize function defs * Fix useCallback deps * Update public/app/plugins/datasource/graphite/state/helpers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/helpers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/helpers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Add more type definitions * Remove submitOnClickAwayOption This behavior is actually needed to remove parameters in functions * Load function definitions before parsing the target on initial load * Add button padding * Fix loading function definitions * Change targetChanged to updateQuery to avoid mutating state directly It's also needed for extra refresh/runQuery execution as handleTargetChanged doesn't handle changing the raw query * Fix updating query after adding a function * Simplify updating function params * Migrate function editor to react * Simplify setting Segment Select min width * Remove unnecessary changes to SegmentInput * Extract view logic to a helper and update types definitions * Clean up types * Update FuncDef types and add tests * Show red border for unknown functions * Autofocus on new params * Extract params mapping to a helper * Split code between params and function editor * Focus on the first param when a function is added even if it's an optional argument * Add function editor tests * Remove todo marker * Fix adding new functions * Allow empty value in selects for removing function params * Add placeholders and fix styling * Add more docs * Rename .tsx -> .ts * Update types * Use ?? instead of || + add test for mapping options * Use const (let is not needed here) * Revert test name change * Allow removing only optional params and mark additional params as optional (only the first one is required) * Use theme.typography.bodySmall.fontSize Co-authored-by: Giordano Ricci <me@giordanoricci.com>
4 years ago
import { EditableParam } from './FunctionParamEditor';
import { mapFuncDefsToSelectables, mapFuncInstanceToParams } from './helpers';
Graphite: Migrate to React (part 2B: migrate FunctionEditor) (#37070) * Add UMLs * Add rendered diagrams * Move QueryCtrl to flux * Remove redundant param in the reducer * Use named imports for lodash and fix typing for GraphiteTagOperator * Add missing async/await * Extract providers to a separate file * Clean up async await * Rename controller functions back to main * Simplify creating actions * Re-order controller functions * Separate helpers from actions * Rename vars * Simplify helpers * Move controller methods to state reducers * Remove docs (they are added in design doc) * Move actions.ts to state folder * Add docs * Add old methods stubs for easier review * Check how state dependencies will be mapped * Rename state to store * Rename state to store * Rewrite spec tests for Graphite Query Controller * Update docs * Update docs * Add GraphiteTextEditor * Add play button * Add AddGraphiteFunction * Use Segment to simplify AddGraphiteFunction * Memoize function defs * Fix useCallback deps * Update public/app/plugins/datasource/graphite/state/helpers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/helpers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/helpers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Update public/app/plugins/datasource/graphite/state/providers.ts Co-authored-by: Giordano Ricci <me@giordanoricci.com> * Add more type definitions * Remove submitOnClickAwayOption This behavior is actually needed to remove parameters in functions * Load function definitions before parsing the target on initial load * Add button padding * Fix loading function definitions * Change targetChanged to updateQuery to avoid mutating state directly It's also needed for extra refresh/runQuery execution as handleTargetChanged doesn't handle changing the raw query * Fix updating query after adding a function * Simplify updating function params * Migrate function editor to react * Simplify setting Segment Select min width * Remove unnecessary changes to SegmentInput * Extract view logic to a helper and update types definitions * Clean up types * Update FuncDef types and add tests * Show red border for unknown functions * Autofocus on new params * Extract params mapping to a helper * Split code between params and function editor * Focus on the first param when a function is added even if it's an optional argument * Add function editor tests * Remove todo marker * Fix adding new functions * Allow empty value in selects for removing function params * Add placeholders and fix styling * Add more docs * Rename .tsx -> .ts * Update types * Use ?? instead of || + add test for mapping options * Use const (let is not needed here) * Revert test name change * Allow removing only optional params and mark additional params as optional (only the first one is required) * Use theme.typography.bodySmall.fontSize Co-authored-by: Giordano Ricci <me@giordanoricci.com>
4 years ago
function createFunctionInstance(funcDef: FuncDef, currentParams: string[]): FuncInstance {
let funcInstance: FuncInstance = new FuncInstance(funcDef);
funcInstance.params = currentParams;
return funcInstance;
}
describe('Graphite components helpers', () => {
it('converts function definitions to selectable options', function () {
const functionDefs: FuncDefs = {
functionA1: { name: 'functionA1', category: 'A', params: [], defaultParams: [] },
functionB1: { name: 'functionB1', category: 'B', params: [], defaultParams: [] },
functionA2: { name: 'functionA2', category: 'A', params: [], defaultParams: [] },
functionB2: { name: 'functionB2', category: 'B', params: [], defaultParams: [] },
};
const options = mapFuncDefsToSelectables(functionDefs);
expect(options).toMatchObject([
{
label: 'A',
options: [
{ label: 'functionA1', value: 'functionA1' },
{ label: 'functionA2', value: 'functionA2' },
],
},
{
label: 'B',
options: [
{ label: 'functionB1', value: 'functionB1' },
{ label: 'functionB2', value: 'functionB2' },
],
},
]);
});
describe('mapFuncInstanceToParams', () => {
let funcDef: FuncDef;
function assertFunctionInstance(definition: FuncDef, params: string[], expected: EditableParam[]): void {
expect(mapFuncInstanceToParams(createFunctionInstance(definition, params))).toMatchObject(expected);
}
it('converts param options to selectable options', () => {
const funcDef = {
name: 'functionA1',
category: 'A',
params: [{ name: 'foo', type: 'any', optional: false, multiple: false, options: ['foo', 2] }],
defaultParams: [],
};
assertFunctionInstance(
funcDef,
[],
[
{
name: 'foo',
multiple: false,
optional: false,
options: [
{ label: 'foo', value: 'foo' },
{ label: '2', value: '2' },
],
value: '',
},
]
);
});
describe('when all parameters are required and no multiple values are allowed', () => {
beforeEach(() => {
funcDef = {
name: 'allRequiredNoMultiple',
category: 'A',
params: [
{ name: 'a', type: 'any', optional: false, multiple: false },
{ name: 'b', type: 'any', optional: false, multiple: false },
],
defaultParams: [],
};
});
it('creates required params', () => {
assertFunctionInstance(
funcDef,
[],
[
{ name: 'a', multiple: false, optional: false, options: [], value: '' },
{ name: 'b', multiple: false, optional: false, options: [], value: '' },
]
);
});
it('fills in provided parameters', () => {
assertFunctionInstance(
funcDef,
['a', 'b'],
[
{ name: 'a', multiple: false, optional: false, options: [], value: 'a' },
{ name: 'b', multiple: false, optional: false, options: [], value: 'b' },
]
);
});
});
describe('when all parameters are required and multiple values are allowed', () => {
beforeEach(() => {
funcDef = {
name: 'allRequiredWithMultiple',
category: 'A',
params: [
{ name: 'a', type: 'any', optional: false, multiple: false },
{ name: 'b', type: 'any', optional: false, multiple: true },
],
defaultParams: [],
};
});
it('does not add extra param to add multiple values if not all params are filled in', () => {
assertFunctionInstance(
funcDef,
[],
[
{ name: 'a', multiple: false, optional: false, options: [], value: '' },
{ name: 'b', multiple: true, optional: false, options: [], value: '' },
]
);
assertFunctionInstance(
funcDef,
['a'],
[
{ name: 'a', multiple: false, optional: false, options: [], value: 'a' },
{ name: 'b', multiple: true, optional: false, options: [], value: '' },
]
);
});
it('marks additional params as optional (only first one is required)', () => {
assertFunctionInstance(
funcDef,
['a', 'b', 'b2'],
[
{ name: 'a', multiple: false, optional: false, options: [], value: 'a' },
{ name: 'b', multiple: true, optional: false, options: [], value: 'b' },
{ name: 'b', multiple: true, optional: true, options: [], value: 'b2' },
{ name: 'b', multiple: true, optional: true, options: [], value: '' },
]
);
});
it('adds an extra param to allo adding multiple values if all params are filled in', () => {
assertFunctionInstance(
funcDef,
['a', 'b'],
[
{ name: 'a', multiple: false, optional: false, options: [], value: 'a' },
{ name: 'b', multiple: true, optional: false, options: [], value: 'b' },
{ name: 'b', multiple: true, optional: true, options: [], value: '' },
]
);
});
});
describe('when there are optional parameters but no multiple values are allowed', () => {
beforeEach(() => {
funcDef = {
name: 'twoOptionalNoMultiple',
category: 'A',
params: [
{ name: 'a', type: 'any', optional: false, multiple: false },
{ name: 'b', type: 'any', optional: false, multiple: false },
{ name: 'c', type: 'any', optional: true, multiple: false },
{ name: 'd', type: 'any', optional: true, multiple: false },
],
defaultParams: [],
};
});
it('creates non-required parameters', () => {
assertFunctionInstance(
funcDef,
[],
[
{ name: 'a', multiple: false, optional: false, options: [], value: '' },
{ name: 'b', multiple: false, optional: false, options: [], value: '' },
{ name: 'c', multiple: false, optional: true, options: [], value: '' },
{ name: 'd', multiple: false, optional: true, options: [], value: '' },
]
);
});
it('fills in provided parameters', () => {
assertFunctionInstance(
funcDef,
['a', 'b', 'c', 'd'],
[
{ name: 'a', multiple: false, optional: false, options: [], value: 'a' },
{ name: 'b', multiple: false, optional: false, options: [], value: 'b' },
{ name: 'c', multiple: false, optional: true, options: [], value: 'c' },
{ name: 'd', multiple: false, optional: true, options: [], value: 'd' },
]
);
});
});
describe('when there are optional parameters and multiple values are allowed', () => {
beforeEach(() => {
funcDef = {
name: 'twoOptionalWithMultiple',
category: 'A',
params: [
{ name: 'a', type: 'any', optional: false, multiple: false },
{ name: 'b', type: 'any', optional: false, multiple: false },
{ name: 'c', type: 'any', optional: true, multiple: false },
{ name: 'd', type: 'any', optional: true, multiple: true },
],
defaultParams: [],
};
});
it('does not add extra param to add multiple values if not all params are filled in', () => {
assertFunctionInstance(
funcDef,
['a', 'b', 'c'],
[
{ name: 'a', multiple: false, optional: false, options: [], value: 'a' },
{ name: 'b', multiple: false, optional: false, options: [], value: 'b' },
{ name: 'c', multiple: false, optional: true, options: [], value: 'c' },
{ name: 'd', multiple: true, optional: true, options: [], value: '' },
]
);
});
it('adds an extra param to add multiple values if all params are filled in', () => {
assertFunctionInstance(
funcDef,
['a', 'b', 'c', 'd'],
[
{ name: 'a', multiple: false, optional: false, options: [], value: 'a' },
{ name: 'b', multiple: false, optional: false, options: [], value: 'b' },
{ name: 'c', multiple: false, optional: true, options: [], value: 'c' },
{ name: 'd', multiple: true, optional: true, options: [], value: 'd' },
{ name: 'd', multiple: true, optional: true, options: [], value: '' },
]
);
});
});
});
});