Commit 85dad73e by Andrej Ocenas Committed by GitHub

Influxdb: Fix cascader when doing log query in explore (#21787)

* Fix cascader options and add tests

* Add comment

* Fix typo
parent b4570b49
...@@ -29,9 +29,11 @@ interface CascaderState { ...@@ -29,9 +29,11 @@ interface CascaderState {
export interface CascaderOption { export interface CascaderOption {
value: any; value: any;
label: string; label: string;
// Items will be just flattened into the main list of items recursively.
items?: CascaderOption[]; items?: CascaderOption[];
disabled?: boolean; disabled?: boolean;
title?: string; title?: string;
// Children will be shown in a submenu.
children?: CascaderOption[]; children?: CascaderOption[];
} }
......
import { pairsAreValid } from './InfluxLogsQueryField'; import React from 'react';
import { mount } from 'enzyme';
import { InfluxLogsQueryField, pairsAreValid } from './InfluxLogsQueryField';
import { InfluxDatasourceMock } from '../datasource.mock';
import InfluxDatasource from '../datasource';
import { InfluxQuery } from '../types';
import { ButtonCascader } from '@grafana/ui';
describe('pairsAreValid()', () => { describe('pairsAreValid()', () => {
describe('when all pairs are fully defined', () => { describe('when all pairs are fully defined', () => {
...@@ -51,3 +57,43 @@ describe('pairsAreValid()', () => { ...@@ -51,3 +57,43 @@ describe('pairsAreValid()', () => {
}); });
}); });
}); });
describe('InfluxLogsQueryField', () => {
it('should load and show correct measurements and fields in cascader', async () => {
const wrapper = getInfluxLogsQueryField();
// Looks strange but we do async stuff in didMount and this will push the stack at the end of eval loop, effectively
// waiting for the didMount to finish.
await Promise.resolve();
wrapper.update();
const cascader = wrapper.find(ButtonCascader);
expect(cascader.prop('options')).toEqual([
{ label: 'logs', value: 'logs', children: [{ label: 'description', value: 'description', children: [] }] },
]);
});
});
function getInfluxLogsQueryField(props?: any) {
const datasource: InfluxDatasource = new InfluxDatasourceMock(
props?.measurements || {
logs: [{ name: 'description', type: 'string' }],
}
) as any;
const defaultProps = {
datasource,
history: [] as any[],
onRunQuery: () => {},
onChange: (query: InfluxQuery) => {},
query: {
refId: '',
} as InfluxQuery,
};
return mount(
<InfluxLogsQueryField
{...{
...defaultProps,
...props,
}}
/>
);
}
...@@ -75,7 +75,7 @@ export class InfluxLogsQueryField extends React.PureComponent<Props, State> { ...@@ -75,7 +75,7 @@ export class InfluxLogsQueryField extends React.PureComponent<Props, State> {
measurements.push({ measurements.push({
label: measurementObj.text, label: measurementObj.text,
value: measurementObj.text, value: measurementObj.text,
items: fields, children: fields,
}); });
} }
this.setState({ measurements }); this.setState({ measurements });
......
type FieldsDefinition = {
name: string;
// String type, usually something like 'string' or 'float'.
type: string;
};
type Measurements = { [measurement: string]: FieldsDefinition[] };
type FieldReturnValue = { text: string };
/**
* Datasource mock for influx. At the moment this only works for queries that should return measurements or their
* fields and no other functionality is implemented.
*/
export class InfluxDatasourceMock {
constructor(private measurements: Measurements) {}
metricFindQuery(query: string) {
if (isMeasurementsQuery(query)) {
return this.getMeasurements();
} else {
return this.getMeasurementFields(query);
}
}
private getMeasurements(): FieldReturnValue[] {
return Object.keys(this.measurements).map(key => ({ text: key }));
}
private getMeasurementFields(query: string): FieldReturnValue[] {
const match = query.match(/SHOW FIELD KEYS FROM \"(.+)\"/);
if (!match) {
throw new Error(`Failed to match query="${query}"`);
}
const measurementName = match[1];
if (!measurementName) {
throw new Error(`Failed to match measurement name from query="${query}"`);
}
const fields = this.measurements[measurementName];
if (!fields) {
throw new Error(
`Failed to find measurement with name="${measurementName}" in measurements="[${Object.keys(
this.measurements
).join(', ')}]"`
);
}
return fields.map(field => ({
text: field.name,
}));
}
}
function isMeasurementsQuery(query: string) {
return /SHOW MEASUREMENTS/.test(query);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment