Cloud Monitoring: Remove dependencies (#79282)

pull/79763/head
Alyssa Bull 2 years ago committed by GitHub
parent 8ff0cfddf4
commit e27e2f66ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      public/app/plugins/datasource/cloud-monitoring/__mocks__/cloudMonitoringDatasource.ts
  2. 21
      public/app/plugins/datasource/cloud-monitoring/components/Alignment.test.tsx
  3. 5
      public/app/plugins/datasource/cloud-monitoring/components/AnnotationQueryEditor.tsx
  4. 3
      public/app/plugins/datasource/cloud-monitoring/components/ConfigEditor/ConfigEditor.tsx
  5. 3
      public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.test.tsx
  6. 5
      public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.tsx
  7. 21
      public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.test.tsx
  8. 5
      public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.tsx
  9. 130
      public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.test.tsx
  10. 6
      public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.tsx
  11. 43
      public/app/plugins/datasource/cloud-monitoring/datasource.test.ts
  12. 17
      public/app/plugins/datasource/cloud-monitoring/datasource.ts
  13. 131
      public/app/plugins/datasource/cloud-monitoring/specs/datasource.test.ts

@ -1,11 +1,9 @@
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { TemplateSrvMock } from 'app/features/templating/template_srv.mock';
import { TemplateSrv, getTemplateSrv } from '@grafana/runtime';
import Datasource from '../datasource';
export const createMockDatasource = (overrides?: Partial<Datasource>) => {
const templateSrv = new TemplateSrvMock({ ALIGN_DELTA: 'delta' }) as unknown as TemplateSrv;
const templateSrv = getTemplateSrv() as unknown as TemplateSrv;
const datasource: Partial<Datasource> = {
intervalMs: 0,
@ -17,7 +15,6 @@ export const createMockDatasource = (overrides?: Partial<Datasource>) => {
filterMetricsByType: jest.fn().mockResolvedValue([]),
getSLOServices: jest.fn().mockResolvedValue([]),
migrateQuery: jest.fn().mockImplementation((query) => query),
timeSrv: getTimeSrv(),
...overrides,
};

@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event';
import React from 'react';
import { openMenu } from 'react-select-event';
import { TemplateSrvMock } from 'app/features/templating/template_srv.mock';
import { CustomVariableModel } from '@grafana/data';
import { createMockDatasource } from '../__mocks__/cloudMonitoringDatasource';
import { createMockMetricDescriptor } from '../__mocks__/cloudMonitoringMetricDescriptor';
@ -12,10 +12,21 @@ import { MetricKind, ValueTypes } from '../types/query';
import { Alignment } from './Alignment';
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
getTemplateSrv: () => new TemplateSrvMock({}),
}));
let getTempVars = () => [] as CustomVariableModel[];
let replace = () => '';
jest.mock('@grafana/runtime', () => {
return {
__esModule: true,
...jest.requireActual('@grafana/runtime'),
getTemplateSrv: () => ({
replace: replace,
getVariables: getTempVars,
updateTimeRange: jest.fn(),
containsTemplate: jest.fn(),
}),
};
});
describe('Alignment', () => {
it('renders alignment fields', () => {

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { useDebounce } from 'react-use';
import { QueryEditorProps, toOption } from '@grafana/data';
import { QueryEditorProps, getDefaultTimeRange, toOption } from '@grafana/data';
import { EditorField, EditorRows } from '@grafana/experimental';
import { Input } from '@grafana/ui';
@ -22,7 +22,7 @@ export const defaultQuery: (datasource: CloudMonitoringDatasource) => TimeSeries
});
export const AnnotationQueryEditor = (props: Props) => {
const { datasource, query, onRunQuery, data, onChange } = props;
const { datasource, query, onRunQuery, data, onChange, range } = props;
const meta = data?.series.length ? data?.series[0].meta : {};
const customMetaData = meta?.custom ?? {};
const timeSeriesList = { ...defaultQuery(datasource), ...query.timeSeriesList };
@ -73,6 +73,7 @@ export const AnnotationQueryEditor = (props: Props) => {
onRunQuery={onRunQuery}
datasource={datasource}
query={query}
range={range || getDefaultTimeRange()}
/>
<EditorField label="Title" htmlFor="annotation-query-title">
<Input id="annotation-query-title" value={title} onChange={handleTitleChange} />

@ -3,9 +3,8 @@ import React, { PureComponent } from 'react';
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { ConfigSection, DataSourceDescription } from '@grafana/experimental';
import { ConnectionConfig } from '@grafana/google-sdk';
import { reportInteraction } from '@grafana/runtime';
import { reportInteraction, config } from '@grafana/runtime';
import { Divider, SecureSocksProxySettings } from '@grafana/ui';
import { config } from 'app/core/config';
import { CloudMonitoringOptions, CloudMonitoringSecureJsonData } from '../../types/types';

@ -1,6 +1,8 @@
import { render, screen, waitFor } from '@testing-library/react';
import React from 'react';
import { getDefaultTimeRange } from '@grafana/data';
import { createMockDatasource } from '../__mocks__/cloudMonitoringDatasource';
import { createMockQuery } from '../__mocks__/cloudMonitoringQuery';
import { QueryType } from '../types/query';
@ -22,6 +24,7 @@ const defaultProps = {
onRunQuery: jest.fn(),
query: createMockQuery(),
datasource: createMockDatasource(),
range: getDefaultTimeRange(),
};
describe('MetricQueryEditor', () => {

@ -1,6 +1,6 @@
import React, { useCallback, useEffect } from 'react';
import { SelectableValue } from '@grafana/data';
import { SelectableValue, TimeRange } from '@grafana/data';
import { EditorRows, Stack } from '@grafana/experimental';
import CloudMonitoringDatasource from '../datasource';
@ -21,6 +21,7 @@ export interface Props {
onRunQuery: () => void;
query: CloudMonitoringQuery;
datasource: CloudMonitoringDatasource;
range: TimeRange;
}
export const defaultTimeSeriesList: (dataSource: CloudMonitoringDatasource) => TimeSeriesList = (dataSource) => ({
@ -45,6 +46,7 @@ function Editor({
onRunQuery,
customMetaData,
variableOptionGroup,
range,
}: React.PropsWithChildren<Props>) {
const onChangeTimeSeriesList = useCallback(
(timeSeriesList: TimeSeriesList) => {
@ -96,6 +98,7 @@ function Editor({
query={query.timeSeriesList}
aliasBy={query.aliasBy}
onChangeAliasBy={(aliasBy: string) => onQueryChange({ ...query, aliasBy })}
range={range}
/>
)}

@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { TemplateSrvMock } from 'app/features/templating/template_srv.mock';
import { CustomVariableModel } from '@grafana/data';
import { createMockMetricDescriptor } from '../__mocks__/cloudMonitoringMetricDescriptor';
import { createMockTimeSeriesList } from '../__mocks__/cloudMonitoringQuery';
@ -10,10 +10,21 @@ import { MetricKind, ValueTypes } from '../types/query';
import { Preprocessor } from './Preprocessor';
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
getTemplateSrv: () => new TemplateSrvMock({}),
}));
let getTempVars = () => [] as CustomVariableModel[];
let replace = () => '';
jest.mock('@grafana/runtime', () => {
return {
__esModule: true,
...jest.requireActual('@grafana/runtime'),
getTemplateSrv: () => ({
replace: replace,
getVariables: getTempVars,
updateTimeRange: jest.fn(),
containsTemplate: jest.fn(),
}),
};
});
describe('Preprocessor', () => {
it('only provides "None" as an option if no metric descriptor is provided', () => {

@ -1,7 +1,7 @@
import { isEqual } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import { QueryEditorProps, toOption } from '@grafana/data';
import { QueryEditorProps, getDefaultTimeRange, toOption } from '@grafana/data';
import { EditorRows } from '@grafana/experimental';
import { ConfirmModal } from '@grafana/ui';
@ -19,7 +19,7 @@ import { MetricQueryEditor, SLOQueryEditor } from './';
export type Props = QueryEditorProps<CloudMonitoringDatasource, CloudMonitoringQuery, CloudMonitoringOptions>;
export const QueryEditor = (props: Props) => {
const { datasource, query: oldQ, onRunQuery, onChange } = props;
const { datasource, query: oldQ, onRunQuery, onChange, range } = props;
const [modalIsOpen, setModalIsOpen] = useState<boolean>(false);
// Migrate query if needed
const [migrated, setMigrated] = useState(false);
@ -130,6 +130,7 @@ export const QueryEditor = (props: Props) => {
onRunQuery={onRunQuery}
datasource={datasource}
query={query}
range={range || getDefaultTimeRange()}
/>
)}

@ -3,8 +3,8 @@ import userEvent from '@testing-library/user-event';
import React from 'react';
import { openMenu, select } from 'react-select-event';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { CustomVariableModel, getDefaultTimeRange } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { createMockDatasource } from '../__mocks__/cloudMonitoringDatasource';
import { createMockMetricDescriptor } from '../__mocks__/cloudMonitoringMetricDescriptor';
@ -22,19 +22,49 @@ const defaultProps = {
onChangeAliasBy: jest.fn(),
};
let getTempVars = () => [] as CustomVariableModel[];
let replace = () => '';
jest.mock('@grafana/runtime', () => {
return {
__esModule: true,
...jest.requireActual('@grafana/runtime'),
getTemplateSrv: () => ({
replace: replace,
getVariables: getTempVars,
updateTimeRange: jest.fn(),
containsTemplate: jest.fn(),
}),
};
});
describe('VisualMetricQueryEditor', () => {
beforeEach(() => {
getTempVars = () => [] as CustomVariableModel[];
replace = () => '';
});
it('renders metrics fields', async () => {
const onChange = jest.fn();
const query = createMockTimeSeriesList();
const datasource = createMockDatasource();
const range = getDefaultTimeRange();
render(<VisualMetricQueryEditor {...defaultProps} onChange={onChange} datasource={datasource} query={query} />);
render(
<VisualMetricQueryEditor
{...defaultProps}
onChange={onChange}
datasource={datasource}
query={query}
range={range}
/>
);
expect(await screen.findByLabelText('Service')).toBeInTheDocument();
expect(await screen.findByLabelText('Metric name')).toBeInTheDocument();
});
it('can select a service', async () => {
replace = (target?: string) => target || '';
const onChange = jest.fn();
const query = createMockTimeSeriesList();
const mockMetricDescriptor = createMockMetricDescriptor();
@ -42,8 +72,17 @@ describe('VisualMetricQueryEditor', () => {
getMetricTypes: jest.fn().mockResolvedValue([mockMetricDescriptor]),
getLabels: jest.fn().mockResolvedValue([]),
});
const range = getDefaultTimeRange();
render(<VisualMetricQueryEditor {...defaultProps} onChange={onChange} datasource={datasource} query={query} />);
render(
<VisualMetricQueryEditor
{...defaultProps}
onChange={onChange}
datasource={datasource}
query={query}
range={range}
/>
);
const service = await screen.findByLabelText('Service');
openMenu(service);
@ -56,6 +95,7 @@ describe('VisualMetricQueryEditor', () => {
});
it('can select a metric name', async () => {
replace = (target?: string) => target || '';
const onChange = jest.fn();
const query = createMockTimeSeriesList();
const mockMetricDescriptor = createMockMetricDescriptor({ displayName: 'metricName_test', type: 'test_type' });
@ -64,8 +104,17 @@ describe('VisualMetricQueryEditor', () => {
filterMetricsByType: jest.fn().mockResolvedValue([createMockMetricDescriptor(), mockMetricDescriptor]),
getLabels: jest.fn().mockResolvedValue([]),
});
const range = getDefaultTimeRange();
render(<VisualMetricQueryEditor {...defaultProps} onChange={onChange} datasource={datasource} query={query} />);
render(
<VisualMetricQueryEditor
{...defaultProps}
onChange={onChange}
datasource={datasource}
query={query}
range={range}
/>
);
const service = await screen.findByLabelText('Service');
openMenu(service);
@ -112,14 +161,24 @@ describe('VisualMetricQueryEditor', () => {
]),
});
const query = createMockTimeSeriesList();
const range = getDefaultTimeRange();
render(<VisualMetricQueryEditor {...defaultProps} onChange={onChange} datasource={datasource} query={query} />);
render(
<VisualMetricQueryEditor
{...defaultProps}
onChange={onChange}
datasource={datasource}
query={query}
range={range}
/>
);
const service = await screen.findByLabelText('Service');
openMenu(service);
expect(screen.getAllByLabelText('Select option').length).toEqual(2);
});
it('resets query to default when service changes', async () => {
replace = (target?: string) => target || '';
const query = createMockTimeSeriesList({ filters: ['metric.test_label', '=', 'test', 'AND'] });
const onChange = jest.fn();
const datasource = createMockDatasource({
@ -132,8 +191,17 @@ describe('VisualMetricQueryEditor', () => {
getLabels: jest.fn().mockResolvedValue([]),
});
const defaultQuery = { ...query, ...defaultTimeSeriesList(datasource), filters: ['metric.type', '=', 'type2'] };
const range = getDefaultTimeRange();
render(<VisualMetricQueryEditor {...defaultProps} onChange={onChange} datasource={datasource} query={query} />);
render(
<VisualMetricQueryEditor
{...defaultProps}
onChange={onChange}
datasource={datasource}
query={query}
range={range}
/>
);
expect(screen.getByText('metric.test_label')).toBeInTheDocument();
const service = await screen.findByLabelText('Service');
@ -147,6 +215,7 @@ describe('VisualMetricQueryEditor', () => {
});
it('resets query to defaults (except filters) when metric changes', async () => {
replace = (target?: string) => target || '';
const groupBys = ['metric.test_groupby'];
const query = createMockTimeSeriesList({
filters: ['metric.test_label', '=', 'test', 'AND', 'metric.type', '=', 'type'],
@ -168,11 +237,20 @@ describe('VisualMetricQueryEditor', () => {
createMockMetricDescriptor({ type: 'type2', displayName: 'metricName2', metricKind: MetricKind.GAUGE }),
]),
getLabels: jest.fn().mockResolvedValue({ 'metric.test_groupby': '' }),
templateSrv: new TemplateSrv(),
templateSrv: getTemplateSrv(),
});
const defaultQuery = { ...query, ...defaultTimeSeriesList(datasource), filters: query.filters };
const range = getDefaultTimeRange();
render(<VisualMetricQueryEditor {...defaultProps} onChange={onChange} datasource={datasource} query={query} />);
render(
<VisualMetricQueryEditor
{...defaultProps}
onChange={onChange}
datasource={datasource}
query={query}
range={range}
/>
);
expect(document.body).toHaveTextContent('metric.test_label');
expect(await screen.findByText('Delta')).toBeInTheDocument();
expect(await screen.findByText('metric.test_groupby')).toBeInTheDocument();
@ -193,22 +271,28 @@ describe('VisualMetricQueryEditor', () => {
});
it('updates labels on time range change', async () => {
const timeSrv = getTimeSrv();
replace = (target?: string) => target || '';
const range = getDefaultTimeRange();
const query = createMockTimeSeriesList();
const onChange = jest.fn();
const datasource = createMockDatasource({
getMetricTypes: jest.fn().mockResolvedValue([createMockMetricDescriptor()]),
getLabels: jest
.fn()
.mockResolvedValue(
timeSrv.time.from === 'now-6h' ? { 'metric.test_groupby': '' } : { 'metric.test_groupby_1': '' }
.mockImplementation(async (_metricType, _refId, _projectName, _, timeRange) =>
timeRange.raw.from === 'now-6h' ? { 'metric.test_groupby': '' } : { 'metric.test_groupby_1': '' }
),
templateSrv: new TemplateSrv(),
timeSrv,
templateSrv: getTemplateSrv(),
});
const { rerender } = render(
<VisualMetricQueryEditor {...defaultProps} onChange={onChange} datasource={datasource} query={query} />
<VisualMetricQueryEditor
{...defaultProps}
onChange={onChange}
datasource={datasource}
query={query}
range={range}
/>
);
const service = await screen.findByLabelText('Service');
@ -225,13 +309,17 @@ describe('VisualMetricQueryEditor', () => {
const groupBy = await screen.findByLabelText('Group by');
openMenu(groupBy);
await waitFor(() => expect(document.body).toHaveTextContent('metric.test_groupby'));
timeSrv.setTime({ from: 'now-12h', to: 'now' });
const datasourceUpdated = createMockDatasource({
timeSrv,
getLabels: jest.fn().mockResolvedValue({ 'metric.test_groupby_1': '' }),
});
range.from.subtract('6', 'h');
range.raw.from = 'now-12h';
rerender(
<VisualMetricQueryEditor {...defaultProps} onChange={onChange} datasource={datasourceUpdated} query={query} />
<VisualMetricQueryEditor
{...defaultProps}
onChange={onChange}
datasource={datasource}
query={query}
range={{ ...range }}
/>
);
openMenu(groupBy);
await waitFor(() => expect(document.body).toHaveTextContent('metric.test_groupby_1'));

@ -30,6 +30,7 @@ export interface Props {
variableOptionGroup: SelectableValue<string>;
aliasBy?: string;
onChangeAliasBy: (aliasBy: string) => void;
range: TimeRange;
}
export function Editor({
@ -41,6 +42,7 @@ export function Editor({
customMetaData,
aliasBy,
onChangeAliasBy,
range,
}: React.PropsWithChildren<Props>) {
const [labels, setLabels] = useState<{ [k: string]: string[] }>({});
const [metricDescriptors, setMetricDescriptors] = useState<MetricDescriptor[]>([]);
@ -48,7 +50,7 @@ export function Editor({
const [metrics, setMetrics] = useState<Array<SelectableValue<string>>>([]);
const [services, setServices] = useState<Array<SelectableValue<string>>>([]);
const [service, setService] = useState<string>('');
const [timeRange, setTimeRange] = useState<TimeRange>({ ...datasource.timeSrv.timeRange() });
const [timeRange, setTimeRange] = useState<TimeRange>({ ...range });
const useTime = (time: TimeRange) => {
if (
@ -60,7 +62,7 @@ export function Editor({
}
};
useTime(datasource.timeSrv.timeRange());
useTime(range);
const theme = useTheme2();
const selectStyles = getSelectStyles(theme);

@ -1,16 +1,38 @@
import { get } from 'lodash';
import { lastValueFrom, of } from 'rxjs';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { CustomVariableModel } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { createMockInstanceSetttings } from './__mocks__/cloudMonitoringInstanceSettings';
import { createMockQuery } from './__mocks__/cloudMonitoringQuery';
import Datasource from './datasource';
import { CloudMonitoringQuery, PreprocessorType, QueryType, MetricKind } from './types/query';
let getTempVars = () => [] as CustomVariableModel[];
let replace = () => '';
jest.mock('@grafana/runtime', () => {
return {
__esModule: true,
...jest.requireActual('@grafana/runtime'),
getTemplateSrv: () => ({
replace: replace,
getVariables: getTempVars,
updateTimeRange: jest.fn(),
containsTemplate: jest.fn(),
}),
};
});
describe('Cloud Monitoring Datasource', () => {
describe('interpolateVariablesInQueries', () => {
beforeEach(() => {
getTempVars = () => [] as CustomVariableModel[];
replace = () => '';
});
it('should leave a query unchanged if there are no template variables', () => {
replace = (target?: string) => target || '';
const mockInstanceSettings = createMockInstanceSetttings();
const ds = new Datasource(mockInstanceSettings);
const query = createMockQuery();
@ -19,7 +41,7 @@ describe('Cloud Monitoring Datasource', () => {
});
it('should correctly apply template variables for metricQuery (deprecated)', () => {
const templateSrv = new TemplateSrv();
const templateSrv = getTemplateSrv();
templateSrv.replace = jest.fn().mockReturnValue('project-variable');
const mockInstanceSettings = createMockInstanceSetttings();
const ds = new Datasource(mockInstanceSettings, templateSrv);
@ -30,7 +52,7 @@ describe('Cloud Monitoring Datasource', () => {
});
it('should correctly apply template variables for timeSeriesList', () => {
const templateSrv = new TemplateSrv();
const templateSrv = getTemplateSrv();
templateSrv.replace = jest.fn().mockReturnValue('project-variable');
const mockInstanceSettings = createMockInstanceSetttings();
const ds = new Datasource(mockInstanceSettings, templateSrv);
@ -41,7 +63,7 @@ describe('Cloud Monitoring Datasource', () => {
});
it('should correctly apply template variables for timeSeriesQuery', () => {
const templateSrv = new TemplateSrv();
const templateSrv = getTemplateSrv();
templateSrv.replace = jest.fn().mockReturnValue('project-variable');
const mockInstanceSettings = createMockInstanceSetttings();
const ds = new Datasource(mockInstanceSettings, templateSrv);
@ -54,6 +76,10 @@ describe('Cloud Monitoring Datasource', () => {
describe('migrateQuery', () => {
describe('should migrate the query to the new format', () => {
beforeEach(() => {
getTempVars = () => [] as CustomVariableModel[];
replace = () => '';
});
[
{
description: 'a list query with a metric type and no filters',
@ -210,6 +236,10 @@ describe('Cloud Monitoring Datasource', () => {
});
describe('filterQuery', () => {
beforeEach(() => {
getTempVars = () => [] as CustomVariableModel[];
replace = () => '';
});
[
{
description: 'should filter out queries with no metric type',
@ -275,7 +305,12 @@ describe('Cloud Monitoring Datasource', () => {
});
describe('getLabels', () => {
beforeEach(() => {
getTempVars = () => [] as CustomVariableModel[];
replace = () => '';
});
it('should get labels', async () => {
replace = (target?: string) => target || '';
const mockInstanceSettings = createMockInstanceSetttings();
const ds = new Datasource(mockInstanceSettings);
ds.backendSrv = {

@ -9,10 +9,16 @@ import {
ScopedVars,
SelectableValue,
TimeRange,
getDefaultTimeRange,
} from '@grafana/data';
import { DataSourceWithBackend, getBackendSrv, toDataQueryResponse, BackendSrv } from '@grafana/runtime';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import {
DataSourceWithBackend,
getBackendSrv,
toDataQueryResponse,
BackendSrv,
getTemplateSrv,
TemplateSrv,
} from '@grafana/runtime';
import { CloudMonitoringAnnotationSupport } from './annotationSupport';
import { SLO_BURN_RATE_SELECTOR_NAME } from './constants';
@ -31,8 +37,7 @@ export default class CloudMonitoringDatasource extends DataSourceWithBackend<
constructor(
private instanceSettings: DataSourceInstanceSettings<CloudMonitoringOptions>,
public templateSrv: TemplateSrv = getTemplateSrv(),
readonly timeSrv: TimeSrv = getTimeSrv()
public templateSrv: TemplateSrv = getTemplateSrv()
) {
super(instanceSettings);
this.authenticationType = instanceSettings.jsonData.authenticationType || 'jwt';
@ -107,7 +112,7 @@ export default class CloudMonitoringDatasource extends DataSourceWithBackend<
),
},
],
range: timeRange ?? this.timeSrv.timeRange(),
range: timeRange || getDefaultTimeRange(),
};
const queries = options.targets;

@ -1,27 +1,28 @@
import { of, throwError } from 'rxjs';
import { createFetchResponse } from 'test/helpers/createFetchResponse';
import { DataQueryRequest, DataSourceInstanceSettings, toUtc } from '@grafana/data';
import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime'; // will use the version in __mocks__
import { initialCustomVariableModelState } from '../../../../features/variables/custom/reducer';
import { CustomVariableModel } from '../../../../features/variables/types';
import CloudMonitoringDataSource from '../datasource';
import { CloudMonitoringQuery } from '../types/query';
import { CloudMonitoringOptions } from '../types/types';
let getTempVars = () => [] as CustomVariableModel[];
let replace = () => '';
jest.mock('@grafana/runtime', () => ({
__esModule: true,
...jest.requireActual('@grafana/runtime'),
getBackendSrv: () => backendSrv,
getTemplateSrv: () => ({
replace: replace,
getVariables: getTempVars,
updateTimeRange: jest.fn(),
containsTemplate: jest.fn(),
}),
}));
type Args = { response?: unknown; throws?: boolean; templateSrv?: TemplateSrv };
const fetchMock = jest.spyOn(backendSrv, 'fetch');
function getTestcontext({ response = {}, throws = false, templateSrv = new TemplateSrv() }: Args = {}) {
function getTestcontext({ response = {}, throws = false, templateSrv = getTemplateSrv() }: Args = {}) {
jest.clearAllMocks();
const instanceSettings = {
@ -30,18 +31,7 @@ function getTestcontext({ response = {}, throws = false, templateSrv = new Templ
},
} as unknown as DataSourceInstanceSettings<CloudMonitoringOptions>;
const timeSrv = {
timeRange: () => ({
from: toUtc('2017-08-22T20:00:00Z'),
to: toUtc('2017-08-22T23:59:00Z'),
}),
} as TimeSrv;
throws
? fetchMock.mockImplementation(() => throwError(response))
: fetchMock.mockImplementation(() => of(createFetchResponse(response)));
const ds = new CloudMonitoringDataSource(instanceSettings, templateSrv, timeSrv);
const ds = new CloudMonitoringDataSource(instanceSettings, templateSrv);
return { ds };
}
@ -89,46 +79,15 @@ describe('CloudMonitoringDataSource', () => {
});
});
describe('When loading labels', () => {
describe('and no aggregation was specified', () => {
it('should use default values', async () => {
const { ds } = getTestcontext();
await ds.getLabels('cpu', 'a', 'default-proj');
await expect(fetchMock.mock.calls[0][0].data.queries[0].timeSeriesList).toMatchObject({
crossSeriesReducer: 'REDUCE_NONE',
groupBys: [],
filters: ['metric.type', '=', 'cpu'],
projectName: 'default-proj',
view: 'HEADERS',
});
});
});
describe('and an aggregation was specified', () => {
it('should use the provided aggregation', async () => {
const { ds } = getTestcontext();
await ds.getLabels('sql', 'b', 'default-proj', {
crossSeriesReducer: 'REDUCE_MEAN',
groupBys: ['metadata.system_label.name'],
});
await expect(fetchMock.mock.calls[0][0].data.queries[0].timeSeriesList).toMatchObject({
crossSeriesReducer: 'REDUCE_MEAN',
groupBys: ['metadata.system_label.name'],
filters: ['metric.type', '=', 'sql'],
projectName: 'default-proj',
view: 'HEADERS',
});
});
});
});
describe('when interpolating a template variable for the filter', () => {
beforeEach(() => {
getTempVars = () => [] as CustomVariableModel[];
replace = (target?: string) => target || '';
});
describe('and is single value variable', () => {
it('should replace the variable with the value', () => {
const templateSrv = initTemplateSrv('filtervalue1');
const { ds } = getTestcontext({ templateSrv });
replace = () => 'filtervalue1';
const { ds } = getTestcontext();
const interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '${test}'], {});
expect(interpolated.length).toBe(3);
@ -138,8 +97,8 @@ describe('CloudMonitoringDataSource', () => {
describe('and is single value variable for the label part', () => {
it('should replace the variable with the value and not with regex formatting', () => {
const templateSrv = initTemplateSrv('resource.label.zone');
const { ds } = getTestcontext({ templateSrv });
replace = () => 'resource.label.zone';
const { ds } = getTestcontext();
const interpolated = ds.interpolateFilters(['${test}', '=~', 'europe-north-1a'], {});
expect(interpolated.length).toBe(3);
@ -148,26 +107,30 @@ describe('CloudMonitoringDataSource', () => {
});
describe('and is multi value variable', () => {
beforeEach(() => {
getTempVars = () => [] as CustomVariableModel[];
replace = (target?: string) => target || '';
});
it('should replace the variable with a regex expression', () => {
const templateSrv = initTemplateSrv(['filtervalue1', 'filtervalue2'], true);
const { ds } = getTestcontext({ templateSrv });
const interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '[[test]]'], {});
replace = () => '(filtervalue1|filtervalue2)';
const { ds } = getTestcontext();
const interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '${test}'], {});
expect(interpolated[2]).toBe('(filtervalue1|filtervalue2)');
});
it('should not escape a regex', () => {
const templateSrv = initTemplateSrv('/[a-Z]*.html', true);
const { ds } = getTestcontext({ templateSrv });
const interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '[[test]]'], {});
replace = () => '/[a-Z]*.html';
const { ds } = getTestcontext();
const interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '${test}'], {});
expect(interpolated[2]).toBe('/[a-Z]*.html');
});
it('should not escape an array of regexes but join them as a regex', () => {
const templateSrv = initTemplateSrv(['/[a-Z]*.html', '/foo.html'], true);
const { ds } = getTestcontext({ templateSrv });
const interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '[[test]]'], {});
replace = () => '(/[a-Z]*.html|/foo.html)';
const { ds } = getTestcontext();
const interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '${test}'], {});
expect(interpolated[2]).toBe('(/[a-Z]*.html|/foo.html)');
});
@ -177,9 +140,9 @@ describe('CloudMonitoringDataSource', () => {
describe('when interpolating a template variable for group bys', () => {
describe('and is single value variable', () => {
it('should replace the variable with the value', () => {
const templateSrv = initTemplateSrv('groupby1');
const { ds } = getTestcontext({ templateSrv });
const interpolated = ds.interpolateGroupBys(['[[test]]'], {});
replace = () => 'groupby1';
const { ds } = getTestcontext();
const interpolated = ds.interpolateGroupBys(['${test}'], {});
expect(interpolated.length).toBe(1);
expect(interpolated[0]).toBe('groupby1');
@ -188,9 +151,9 @@ describe('CloudMonitoringDataSource', () => {
describe('and is multi value variable', () => {
it('should replace the variable with an array of group bys', () => {
const templateSrv = initTemplateSrv(['groupby1', 'groupby2'], true);
const { ds } = getTestcontext({ templateSrv });
const interpolated = ds.interpolateGroupBys(['[[test]]'], {});
replace = () => 'groupby1,groupby2';
const { ds } = getTestcontext();
const interpolated = ds.interpolateGroupBys(['${test}'], {});
expect(interpolated.length).toBe(2);
expect(interpolated[0]).toBe('groupby1');
@ -199,17 +162,3 @@ describe('CloudMonitoringDataSource', () => {
});
});
});
function initTemplateSrv(values: string | string[], multi = false) {
const templateSrv = new TemplateSrv();
const test: CustomVariableModel = {
...initialCustomVariableModelState,
id: 'test',
name: 'test',
current: { value: values, text: Array.isArray(values) ? values.toString() : values, selected: true },
options: [{ value: values, text: Array.isArray(values) ? values.toString() : values, selected: false }],
multi,
};
templateSrv.init([test]);
return templateSrv;
}

Loading…
Cancel
Save