Chore: Cover CloudMonitoring function utils with tests (#46878)
This commit is contained in:
@@ -1,9 +1,126 @@
|
||||
import { getAlignmentOptionsByMetric } from './functions';
|
||||
import { ValueTypes, MetricKind } from './types';
|
||||
import { AGGREGATIONS, SYSTEM_LABELS } from './constants';
|
||||
import {
|
||||
extractServicesFromMetricDescriptors,
|
||||
getAggregationOptionsByMetric,
|
||||
getAlignmentOptionsByMetric,
|
||||
getAlignmentPickerData,
|
||||
getLabelKeys,
|
||||
getMetricTypes,
|
||||
getMetricTypesByService,
|
||||
labelsToGroupedOptions,
|
||||
stringArrayToFilters,
|
||||
} from './functions';
|
||||
import { newMockDatasource } from './specs/testData';
|
||||
import { AlignmentTypes, MetricDescriptor, MetricKind, ValueTypes } from './types';
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
...(jest.requireActual('@grafana/runtime') as unknown as object),
|
||||
getTemplateSrv: () => ({
|
||||
replace: jest.fn().mockImplementation((s: string) => s),
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('functions', () => {
|
||||
let result: any;
|
||||
describe('extractServicesFromMetricDescriptors', () => {
|
||||
it('should return unique metric descriptors', () => {
|
||||
const desc: MetricDescriptor = {
|
||||
valueType: '',
|
||||
metricKind: MetricKind.CUMULATIVE,
|
||||
type: '',
|
||||
unit: '',
|
||||
service: '1',
|
||||
serviceShortName: '',
|
||||
displayName: '',
|
||||
description: '',
|
||||
};
|
||||
expect(extractServicesFromMetricDescriptors([desc, desc])).toEqual([desc]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMetricTypesByService', () => {
|
||||
it('filters by metric descriptiors', () => {
|
||||
const desc1: MetricDescriptor = {
|
||||
valueType: '',
|
||||
metricKind: MetricKind.CUMULATIVE,
|
||||
type: '',
|
||||
unit: '',
|
||||
service: '1',
|
||||
serviceShortName: '',
|
||||
displayName: '',
|
||||
description: '',
|
||||
};
|
||||
const desc2: MetricDescriptor = {
|
||||
valueType: '',
|
||||
metricKind: MetricKind.CUMULATIVE,
|
||||
type: '',
|
||||
unit: '',
|
||||
service: '2',
|
||||
serviceShortName: '',
|
||||
displayName: '',
|
||||
description: '',
|
||||
};
|
||||
expect(getMetricTypesByService([desc1, desc2], '1')).toEqual([desc1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMetricTypes', () => {
|
||||
it('gets metric type that exists in the array', () => {
|
||||
const desc1: MetricDescriptor = {
|
||||
valueType: '',
|
||||
metricKind: MetricKind.CUMULATIVE,
|
||||
type: '1',
|
||||
unit: '',
|
||||
service: 'svc1',
|
||||
serviceShortName: '',
|
||||
displayName: 'uno',
|
||||
description: '',
|
||||
};
|
||||
const desc2: MetricDescriptor = {
|
||||
valueType: '',
|
||||
metricKind: MetricKind.CUMULATIVE,
|
||||
type: '2',
|
||||
unit: '',
|
||||
service: 'svc2',
|
||||
serviceShortName: '',
|
||||
displayName: 'dos',
|
||||
description: '',
|
||||
};
|
||||
expect(getMetricTypes([desc1, desc2], '1', '1', 'svc1')).toEqual({
|
||||
metricTypes: [{ name: 'uno', value: '1' }],
|
||||
selectedMetricType: '1',
|
||||
});
|
||||
});
|
||||
|
||||
it('gets metric type that does not exist in the array', () => {
|
||||
const desc1: MetricDescriptor = {
|
||||
valueType: '',
|
||||
metricKind: MetricKind.CUMULATIVE,
|
||||
type: '1',
|
||||
unit: '',
|
||||
service: 'svc1',
|
||||
serviceShortName: '',
|
||||
displayName: 'uno',
|
||||
description: '',
|
||||
};
|
||||
const desc2: MetricDescriptor = {
|
||||
valueType: '',
|
||||
metricKind: MetricKind.CUMULATIVE,
|
||||
type: '2',
|
||||
unit: '',
|
||||
service: 'svc2',
|
||||
serviceShortName: '',
|
||||
displayName: 'dos',
|
||||
description: '',
|
||||
};
|
||||
expect(getMetricTypes([desc1, desc2], '3', '4', 'svc1')).toEqual({
|
||||
metricTypes: [{ name: 'uno', value: '1' }],
|
||||
selectedMetricType: '1',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAlignmentOptionsByMetric', () => {
|
||||
let result: any;
|
||||
describe('when double and gauge is passed', () => {
|
||||
beforeEach(() => {
|
||||
result = getAlignmentOptionsByMetric(ValueTypes.DOUBLE, MetricKind.GAUGE);
|
||||
@@ -35,4 +152,78 @@ describe('functions', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAggregationOptionsByMetric', () => {
|
||||
it('gets a result for a type and a metric kind', () => {
|
||||
expect(getAggregationOptionsByMetric(ValueTypes.BOOL, MetricKind.CUMULATIVE)).toEqual([
|
||||
AGGREGATIONS[0],
|
||||
AGGREGATIONS[6],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLabelKeys', () => {
|
||||
it('should return labels', async () => {
|
||||
const ds = newMockDatasource();
|
||||
ds.getLabels = jest.fn().mockResolvedValue({ l1: true, l2: true });
|
||||
expect(await getLabelKeys(ds, 'type', 'project')).toEqual(['l1', 'l2', ...SYSTEM_LABELS]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAlignmentPickerData', () => {
|
||||
it('should return default data', () => {
|
||||
const res = getAlignmentPickerData();
|
||||
expect(res.alignOptions).toHaveLength(9);
|
||||
expect(res.perSeriesAligner).toEqual(AlignmentTypes.ALIGN_MEAN);
|
||||
});
|
||||
|
||||
it('should use provided data', () => {
|
||||
const res = getAlignmentPickerData(ValueTypes.BOOL, MetricKind.CUMULATIVE);
|
||||
expect(res.alignOptions).toHaveLength(0);
|
||||
expect(res.perSeriesAligner).toEqual(AlignmentTypes.ALIGN_MEAN);
|
||||
});
|
||||
});
|
||||
|
||||
describe('labelsToGroupedOptions', () => {
|
||||
it('should group in the same label', () => {
|
||||
expect(labelsToGroupedOptions(['foo', 'bar'])).toEqual([
|
||||
{
|
||||
expanded: true,
|
||||
label: '',
|
||||
options: [
|
||||
{ label: 'foo', value: 'foo' },
|
||||
{ label: 'bar', value: 'bar' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should group in different labels', () => {
|
||||
expect(labelsToGroupedOptions(['foo.bar', 'foobar'])).toEqual([
|
||||
{
|
||||
expanded: true,
|
||||
label: 'Foo Bar',
|
||||
options: [{ label: 'foo.bar', value: 'foo.bar' }],
|
||||
},
|
||||
{
|
||||
expanded: true,
|
||||
label: '',
|
||||
options: [{ label: 'foobar', value: 'foobar' }],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stringArrayToFilters', () => {
|
||||
it('chunks an array', () => {
|
||||
expect(stringArrayToFilters(['key', 'operator', 'value', 'condition'])).toEqual([
|
||||
{
|
||||
condition: 'condition',
|
||||
key: 'key',
|
||||
operator: 'operator',
|
||||
value: 'value',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { chunk, flatten, initial, startCase, uniqBy } from 'lodash';
|
||||
import { ALIGNMENTS, AGGREGATIONS, SYSTEM_LABELS } from './constants';
|
||||
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
import { chunk, initial, startCase, uniqBy } from 'lodash';
|
||||
|
||||
import { AGGREGATIONS, ALIGNMENTS, SYSTEM_LABELS } from './constants';
|
||||
import CloudMonitoringDatasource from './datasource';
|
||||
import { TemplateSrv, getTemplateSrv } from '@grafana/runtime';
|
||||
import { MetricDescriptor, ValueTypes, MetricKind, AlignmentTypes, PreprocessorType, Filter } from './types';
|
||||
import { AlignmentTypes, MetricDescriptor, MetricKind, PreprocessorType, ValueTypes } from './types';
|
||||
|
||||
const templateSrv: TemplateSrv = getTemplateSrv();
|
||||
|
||||
@@ -104,11 +105,6 @@ export const labelsToGroupedOptions = (groupBys: string[]) => {
|
||||
return Object.entries(groups).map(([label, options]) => ({ label, options, expanded: true }), []);
|
||||
};
|
||||
|
||||
export const filtersToStringArray = (filters: Filter[]) => {
|
||||
const strArr = flatten(filters.map(({ key, operator, value, condition }) => [key, operator, value, condition!]));
|
||||
return strArr.filter((_, i) => i !== strArr.length - 1);
|
||||
};
|
||||
|
||||
export const stringArrayToFilters = (filterArray: string[]) =>
|
||||
chunk(filterArray, 4).map(([key, operator, value, condition = 'AND']) => ({
|
||||
key,
|
||||
@@ -116,22 +112,3 @@ export const stringArrayToFilters = (filterArray: string[]) =>
|
||||
value,
|
||||
condition,
|
||||
}));
|
||||
|
||||
export const formatCloudMonitoringError = (error: any) => {
|
||||
let message = error.statusText ?? '';
|
||||
if (error.data && error.data.error) {
|
||||
try {
|
||||
const res = JSON.parse(error.data.error);
|
||||
message += res.error.code + '. ' + res.error.message;
|
||||
} catch (err) {
|
||||
message += error.data.error;
|
||||
}
|
||||
} else if (error.data && error.data.message) {
|
||||
try {
|
||||
message = JSON.parse(error.data.message).error.message;
|
||||
} catch (err) {
|
||||
error.error = err;
|
||||
}
|
||||
}
|
||||
return message;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
import { PluginType } from '@grafana/data';
|
||||
import { GoogleAuthType } from '@grafana/google-sdk';
|
||||
|
||||
import CloudMonitoringDatasource from '../datasource';
|
||||
|
||||
export const metricDescriptors = [
|
||||
{
|
||||
name: 'projects/grafana-prod/metricDescriptors/agent.googleapis.com/agent/api_request_count',
|
||||
@@ -40,3 +45,36 @@ export const metricDescriptors = [
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const newMockDatasource = () =>
|
||||
new CloudMonitoringDatasource({
|
||||
id: 1,
|
||||
uid: 'cm-id',
|
||||
type: 'cloud-monitoring-datasource',
|
||||
name: 'Cloud Monitoring Data Source',
|
||||
jsonData: {
|
||||
authenticationType: GoogleAuthType.JWT,
|
||||
},
|
||||
access: 'proxy',
|
||||
meta: {
|
||||
id: 'cloud-monitoring-datasource',
|
||||
name: 'Cloud Monitoring Data Source',
|
||||
type: PluginType.datasource,
|
||||
module: '',
|
||||
baseUrl: '',
|
||||
info: {
|
||||
description: '',
|
||||
screenshots: [],
|
||||
updated: '',
|
||||
version: '',
|
||||
logos: {
|
||||
small: '',
|
||||
large: '',
|
||||
},
|
||||
author: {
|
||||
name: '',
|
||||
},
|
||||
links: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user