mirror of
https://github.com/grafana/grafana.git
synced 2026-08-13 14:45:02 -05:00
Explore: Use PanelQueryState to handle querying (#18694)
* WIP: inital POC * Wip: Moving forward * Wip * Refactor: Makes loading indicator work for Prometheus * Refactor: Reverts prom observable queries because they did not work for multiple targets * Refactor: Transforms all epics into thunks * Fix: Fixes scanning * Fix: Fixes so that Instant and TimeSeries Prom query loads in parallel * Fix: Fixes negation logic error * Propagate errors in stream events, and close streams
This commit is contained in:
committed by
Torkel Ödegaard
parent
f942fecc52
commit
5ca643f2ba
@@ -1,149 +0,0 @@
|
||||
import { Epic, ActionsObservable, StateObservable } from 'redux-observable';
|
||||
import { Subject } from 'rxjs';
|
||||
import {
|
||||
DataSourceApi,
|
||||
DataQuery,
|
||||
DataSourceJsonData,
|
||||
DataQueryRequest,
|
||||
DataStreamObserver,
|
||||
DataQueryResponse,
|
||||
DataStreamState,
|
||||
} from '@grafana/ui';
|
||||
import { DefaultTimeZone } from '@grafana/data';
|
||||
|
||||
import { ActionOf } from 'app/core/redux/actionCreatorFactory';
|
||||
import { StoreState } from 'app/types/store';
|
||||
import { EpicDependencies } from 'app/store/configureStore';
|
||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { DEFAULT_RANGE } from 'app/core/utils/explore';
|
||||
|
||||
export const MOCKED_ABSOLUTE_RANGE = { from: 1, to: 2 };
|
||||
|
||||
export const epicTester = (
|
||||
epic: Epic<ActionOf<any>, ActionOf<any>, StoreState, EpicDependencies>,
|
||||
state?: Partial<StoreState>,
|
||||
dependencies?: Partial<EpicDependencies>
|
||||
) => {
|
||||
const resultingActions: Array<ActionOf<any>> = [];
|
||||
const action$ = new Subject<ActionOf<any>>();
|
||||
const state$ = new Subject<StoreState>();
|
||||
const actionObservable$ = new ActionsObservable(action$);
|
||||
const stateObservable$ = new StateObservable(state$, (state as StoreState) || ({} as StoreState));
|
||||
const queryResponse$ = new Subject<DataQueryResponse>();
|
||||
const observer$ = new Subject<DataStreamState>();
|
||||
const getQueryResponse = (
|
||||
datasourceInstance: DataSourceApi<DataQuery, DataSourceJsonData>,
|
||||
options: DataQueryRequest<DataQuery>,
|
||||
observer?: DataStreamObserver
|
||||
) => {
|
||||
if (observer) {
|
||||
observer$.subscribe({ next: event => observer(event) });
|
||||
}
|
||||
return queryResponse$;
|
||||
};
|
||||
const init = jest.fn();
|
||||
const getTimeSrv = (): TimeSrv => {
|
||||
const timeSrvMock: TimeSrv = {} as TimeSrv;
|
||||
|
||||
return Object.assign(timeSrvMock, { init });
|
||||
};
|
||||
|
||||
const getTimeRange = jest.fn().mockReturnValue(DEFAULT_RANGE);
|
||||
|
||||
const getShiftedTimeRange = jest.fn().mockReturnValue(MOCKED_ABSOLUTE_RANGE);
|
||||
|
||||
const getTimeZone = jest.fn().mockReturnValue(DefaultTimeZone);
|
||||
|
||||
const dateTimeForTimeZone = jest.fn().mockReturnValue(null);
|
||||
|
||||
const defaultDependencies: EpicDependencies = {
|
||||
getQueryResponse,
|
||||
getTimeSrv,
|
||||
getTimeRange,
|
||||
getTimeZone,
|
||||
getShiftedTimeRange,
|
||||
dateTimeForTimeZone,
|
||||
};
|
||||
|
||||
const theDependencies: EpicDependencies = { ...defaultDependencies, ...dependencies };
|
||||
|
||||
epic(actionObservable$, stateObservable$, theDependencies).subscribe({
|
||||
next: action => resultingActions.push(action),
|
||||
});
|
||||
|
||||
const whenActionIsDispatched = (action: ActionOf<any>) => {
|
||||
action$.next(action);
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
const whenQueryReceivesResponse = (response: DataQueryResponse) => {
|
||||
queryResponse$.next(response);
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
const whenQueryThrowsError = (error: any) => {
|
||||
queryResponse$.error(error);
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
const whenQueryObserverReceivesEvent = (event: DataStreamState) => {
|
||||
observer$.next(event);
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
const thenResultingActionsEqual = (...actions: Array<ActionOf<any>>) => {
|
||||
expect(actions).toEqual(resultingActions);
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
const thenNoActionsWhereDispatched = () => {
|
||||
expect(resultingActions).toEqual([]);
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
const getDependencyMock = (dependency: string, method?: string) => {
|
||||
// @ts-ignore
|
||||
const dep = theDependencies[dependency];
|
||||
let mock = null;
|
||||
if (dep instanceof Function) {
|
||||
mock = method ? dep()[method] : dep();
|
||||
} else {
|
||||
mock = method ? dep[method] : dep;
|
||||
}
|
||||
|
||||
return mock;
|
||||
};
|
||||
|
||||
const thenDependencyWasCalledTimes = (times: number, dependency: string, method?: string) => {
|
||||
const mock = getDependencyMock(dependency, method);
|
||||
expect(mock).toBeCalledTimes(times);
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
const thenDependencyWasCalledWith = (args: any[], dependency: string, method?: string) => {
|
||||
const mock = getDependencyMock(dependency, method);
|
||||
expect(mock).toBeCalledWith(...args);
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
const instance = {
|
||||
whenActionIsDispatched,
|
||||
whenQueryReceivesResponse,
|
||||
whenQueryThrowsError,
|
||||
whenQueryObserverReceivesEvent,
|
||||
thenResultingActionsEqual,
|
||||
thenNoActionsWhereDispatched,
|
||||
thenDependencyWasCalledTimes,
|
||||
thenDependencyWasCalledWith,
|
||||
};
|
||||
|
||||
return instance;
|
||||
};
|
||||
Reference in New Issue
Block a user