2022-06-28 06:38:31 -05:00
|
|
|
import { render, screen } from '@testing-library/react';
|
|
|
|
|
2020-03-12 04:22:33 -05:00
|
|
|
import { DataQueryRequest, dateTime, LoadingState, PanelData, toDataFrame } from '@grafana/data';
|
2022-04-22 08:33:13 -05:00
|
|
|
|
2022-06-28 06:38:31 -05:00
|
|
|
import { filterPanelDataToQuery, QueryEditorRow } from './QueryEditorRow';
|
2019-04-20 14:26:49 -05:00
|
|
|
|
|
|
|
function makePretendRequest(requestId: string, subRequests?: DataQueryRequest[]): DataQueryRequest {
|
|
|
|
return {
|
|
|
|
requestId,
|
|
|
|
// subRequests,
|
|
|
|
} as DataQueryRequest;
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('filterPanelDataToQuery', () => {
|
2019-08-15 11:18:51 -05:00
|
|
|
const data: PanelData = {
|
2019-04-20 14:26:49 -05:00
|
|
|
state: LoadingState.Done,
|
|
|
|
series: [
|
2019-08-15 11:18:51 -05:00
|
|
|
toDataFrame({ refId: 'A', fields: [{ name: 'AAA' }], meta: {} }),
|
|
|
|
toDataFrame({ refId: 'B', fields: [{ name: 'B111' }], meta: {} }),
|
|
|
|
toDataFrame({ refId: 'B', fields: [{ name: 'B222' }], meta: {} }),
|
|
|
|
toDataFrame({ refId: 'B', fields: [{ name: 'B333' }], meta: {} }),
|
|
|
|
toDataFrame({ refId: 'C', fields: [{ name: 'CCCC' }], meta: { requestId: 'sub3' } }),
|
2019-04-20 14:26:49 -05:00
|
|
|
],
|
|
|
|
error: {
|
|
|
|
refId: 'B',
|
|
|
|
message: 'Error!!',
|
|
|
|
},
|
|
|
|
request: makePretendRequest('111', [
|
|
|
|
makePretendRequest('sub1'),
|
|
|
|
makePretendRequest('sub2'),
|
|
|
|
makePretendRequest('sub3'),
|
|
|
|
]),
|
2019-09-25 04:19:17 -05:00
|
|
|
timeRange: { from: dateTime(), to: dateTime(), raw: { from: 'now-1d', to: 'now' } },
|
2019-08-15 11:18:51 -05:00
|
|
|
};
|
2019-04-20 14:26:49 -05:00
|
|
|
|
|
|
|
it('should not have an error unless the refId matches', () => {
|
|
|
|
const panelData = filterPanelDataToQuery(data, 'A');
|
2020-03-12 04:22:33 -05:00
|
|
|
expect(panelData?.series.length).toBe(1);
|
|
|
|
expect(panelData?.series[0].refId).toBe('A');
|
|
|
|
expect(panelData?.error).toBeUndefined();
|
2019-04-20 14:26:49 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should match the error to the query', () => {
|
|
|
|
const panelData = filterPanelDataToQuery(data, 'B');
|
2020-03-12 04:22:33 -05:00
|
|
|
expect(panelData?.series.length).toBe(3);
|
|
|
|
expect(panelData?.series[0].refId).toBe('B');
|
|
|
|
expect(panelData?.error!.refId).toBe('B');
|
2019-04-20 14:26:49 -05:00
|
|
|
});
|
2020-04-18 16:59:36 -05:00
|
|
|
|
|
|
|
it('should include errors when missing data', () => {
|
2022-02-02 06:02:32 -06:00
|
|
|
const withError = {
|
2020-04-18 16:59:36 -05:00
|
|
|
series: [],
|
|
|
|
error: {
|
|
|
|
message: 'Error!!',
|
|
|
|
},
|
2022-02-02 06:02:32 -06:00
|
|
|
} as unknown as PanelData;
|
2020-04-18 16:59:36 -05:00
|
|
|
|
|
|
|
const panelData = filterPanelDataToQuery(withError, 'B');
|
2020-06-15 06:06:37 -05:00
|
|
|
expect(panelData).toBeDefined();
|
2022-02-16 03:34:29 -06:00
|
|
|
expect(panelData?.state).toBe(LoadingState.Error);
|
|
|
|
expect(panelData?.error).toBe(withError.error);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should set the state to done if the frame has no errors', () => {
|
|
|
|
const withError = {
|
|
|
|
...data,
|
|
|
|
};
|
|
|
|
withError.state = LoadingState.Error;
|
|
|
|
|
|
|
|
const panelDataB = filterPanelDataToQuery(withError, 'B');
|
|
|
|
expect(panelDataB?.series.length).toBe(3);
|
|
|
|
expect(panelDataB?.series[0].refId).toBe('B');
|
|
|
|
expect(panelDataB?.state).toBe(LoadingState.Error);
|
2020-06-15 06:06:37 -05:00
|
|
|
|
2022-02-16 03:34:29 -06:00
|
|
|
const panelDataA = filterPanelDataToQuery(withError, 'A');
|
|
|
|
expect(panelDataA?.series.length).toBe(1);
|
|
|
|
expect(panelDataA?.series[0].refId).toBe('A');
|
|
|
|
expect(panelDataA?.state).toBe(LoadingState.Done);
|
2020-04-18 16:59:36 -05:00
|
|
|
});
|
2022-02-16 04:48:22 -06:00
|
|
|
|
2022-04-14 05:57:56 -05:00
|
|
|
it('should return error for query that returns no data, but another query does return data', () => {
|
|
|
|
const withError = {
|
|
|
|
...data,
|
|
|
|
state: LoadingState.Error,
|
|
|
|
error: {
|
|
|
|
message: 'Sad',
|
|
|
|
refId: 'Q',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const panelDataB = filterPanelDataToQuery(withError, 'Q');
|
|
|
|
expect(panelDataB?.series.length).toBe(0);
|
|
|
|
expect(panelDataB?.error?.refId).toBe('Q');
|
|
|
|
});
|
|
|
|
|
2022-02-16 04:48:22 -06:00
|
|
|
it('should not set the state to done if the frame is loading and has no errors', () => {
|
|
|
|
const loadingData: PanelData = {
|
|
|
|
state: LoadingState.Loading,
|
|
|
|
series: [
|
|
|
|
toDataFrame({ refId: 'A', fields: [{ name: 'AAA' }], meta: {} }),
|
|
|
|
toDataFrame({ refId: 'B', fields: [{ name: 'B111' }], meta: {} }),
|
|
|
|
],
|
|
|
|
timeRange: { from: dateTime(), to: dateTime(), raw: { from: 'now-1d', to: 'now' } },
|
|
|
|
};
|
|
|
|
|
|
|
|
const panelDataB = filterPanelDataToQuery(loadingData, 'B');
|
|
|
|
expect(panelDataB?.state).toBe(LoadingState.Loading);
|
|
|
|
|
|
|
|
const panelDataA = filterPanelDataToQuery(loadingData, 'A');
|
|
|
|
expect(panelDataA?.state).toBe(LoadingState.Loading);
|
|
|
|
});
|
2022-10-05 14:19:49 -05:00
|
|
|
|
|
|
|
it('should not set the state to error if the frame is still loading', () => {
|
|
|
|
const loadingData: PanelData = {
|
|
|
|
state: LoadingState.Loading,
|
|
|
|
series: [],
|
|
|
|
error: {
|
|
|
|
refId: 'B',
|
|
|
|
message: 'Error',
|
|
|
|
},
|
|
|
|
timeRange: { from: dateTime(), to: dateTime(), raw: { from: 'now-1d', to: 'now' } },
|
|
|
|
};
|
|
|
|
|
|
|
|
const panelDataA = filterPanelDataToQuery(loadingData, 'A');
|
|
|
|
expect(panelDataA?.state).toBe(LoadingState.Loading);
|
|
|
|
});
|
2019-04-20 14:26:49 -05:00
|
|
|
});
|
2022-06-28 06:38:31 -05:00
|
|
|
|
|
|
|
describe('frame results with warnings', () => {
|
|
|
|
const meta = {
|
|
|
|
notices: [
|
|
|
|
{
|
|
|
|
severity: 'warning',
|
|
|
|
text: 'Reduce operation is not needed. Input query or expression A is already reduced data.',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
|
|
|
const dataWithWarnings: PanelData = {
|
|
|
|
state: LoadingState.Done,
|
|
|
|
series: [
|
|
|
|
toDataFrame({
|
|
|
|
refId: 'B',
|
|
|
|
fields: [{ name: 'B1' }],
|
|
|
|
meta,
|
|
|
|
}),
|
|
|
|
toDataFrame({
|
|
|
|
refId: 'B',
|
|
|
|
fields: [{ name: 'B2' }],
|
|
|
|
meta,
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
timeRange: { from: dateTime(), to: dateTime(), raw: { from: 'now-1d', to: 'now' } },
|
|
|
|
};
|
|
|
|
|
|
|
|
const dataWithoutWarnings: PanelData = {
|
|
|
|
state: LoadingState.Done,
|
|
|
|
series: [
|
|
|
|
toDataFrame({
|
|
|
|
refId: 'B',
|
|
|
|
fields: [{ name: 'B1' }],
|
|
|
|
meta: {},
|
|
|
|
}),
|
|
|
|
toDataFrame({
|
|
|
|
refId: 'B',
|
|
|
|
fields: [{ name: 'B2' }],
|
|
|
|
meta: {},
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
timeRange: { from: dateTime(), to: dateTime(), raw: { from: 'now-1d', to: 'now' } },
|
|
|
|
};
|
|
|
|
|
|
|
|
it('should show a warning badge and de-duplicate warning messages', () => {
|
|
|
|
// @ts-ignore: there are _way_ too many props to inject here :(
|
|
|
|
const editorRow = new QueryEditorRow({
|
|
|
|
data: dataWithWarnings,
|
|
|
|
query: {
|
|
|
|
refId: 'B',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const warningsComponent = editorRow.renderWarnings();
|
|
|
|
expect(warningsComponent).not.toBe(null);
|
|
|
|
|
|
|
|
render(warningsComponent!);
|
|
|
|
expect(screen.getByText('1 warning')).toBeInTheDocument();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not show a warning badge when there are no warnings', () => {
|
|
|
|
// @ts-ignore: there are _way_ too many props to inject here :(
|
|
|
|
const editorRow = new QueryEditorRow({
|
|
|
|
data: dataWithoutWarnings,
|
|
|
|
query: {
|
|
|
|
refId: 'B',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const warningsComponent = editorRow.renderWarnings();
|
|
|
|
expect(warningsComponent).toBe(null);
|
|
|
|
});
|
|
|
|
});
|