mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 15:45:43 -06:00
Panel edit: Run queries when time range changes in table view (#53111)
This commit is contained in:
parent
6ed0787376
commit
f4fa3e4ff4
@ -0,0 +1,181 @@
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import React, { FC } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { ReplaySubject } from 'rxjs';
|
||||
import { TimeSrvStub } from 'test/specs/helpers';
|
||||
|
||||
import {
|
||||
dateTime,
|
||||
EventBusSrv,
|
||||
getDefaultTimeRange,
|
||||
LoadingState,
|
||||
PanelData,
|
||||
PanelPlugin,
|
||||
PanelProps,
|
||||
TimeRange,
|
||||
} from '@grafana/data';
|
||||
import { getTimeSrv, TimeSrv, setTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
|
||||
import { PanelQueryRunner } from '../../../query/state/PanelQueryRunner';
|
||||
import { DashboardModel, PanelModel } from '../../state';
|
||||
|
||||
import { PanelEditorTableView, Props } from './PanelEditorTableView';
|
||||
|
||||
jest.mock('../../utils/panel', () => ({
|
||||
applyPanelTimeOverrides: jest.fn((panel, timeRange) => ({
|
||||
...timeRange,
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('app/features/panel/components/PanelRenderer', () => ({
|
||||
PanelRenderer: jest.fn(() => <div>PanelRenderer Mock</div>),
|
||||
}));
|
||||
|
||||
function setupTestContext(options: Partial<Props> = {}) {
|
||||
const mockStore = configureMockStore();
|
||||
const subject: ReplaySubject<PanelData> = new ReplaySubject<PanelData>();
|
||||
const panelQueryRunner = {
|
||||
getData: () => subject,
|
||||
run: () => {
|
||||
subject.next({ state: LoadingState.Done, series: [], timeRange: getDefaultTimeRange() });
|
||||
},
|
||||
} as unknown as PanelQueryRunner;
|
||||
|
||||
const defaults = {
|
||||
panel: new PanelModel({
|
||||
id: 123,
|
||||
hasTitle: jest.fn(),
|
||||
replaceVariables: jest.fn(),
|
||||
events: new EventBusSrv(),
|
||||
getQueryRunner: () => panelQueryRunner,
|
||||
getOptions: jest.fn(),
|
||||
getDisplayTitle: jest.fn(),
|
||||
runAllPanelQueries: jest.fn(),
|
||||
}),
|
||||
dashboard: new DashboardModel({
|
||||
id: 1,
|
||||
uid: 'super-unique-id',
|
||||
panelInitialized: jest.fn(),
|
||||
events: new EventBusSrv(),
|
||||
meta: {
|
||||
isPublic: false,
|
||||
},
|
||||
panels: [],
|
||||
}),
|
||||
plugin: {
|
||||
meta: { skipDataQuery: false },
|
||||
panel: TestPanelComponent,
|
||||
} as unknown as PanelPlugin,
|
||||
isViewing: false,
|
||||
isEditing: true,
|
||||
isInView: false,
|
||||
width: 100,
|
||||
height: 100,
|
||||
onInstanceStateChange: () => {},
|
||||
};
|
||||
|
||||
// Set up the mock store with the defaults
|
||||
const store = mockStore({ dashboard: defaults.dashboard });
|
||||
const timeSrv = getTimeSrv();
|
||||
|
||||
const props = { ...defaults, ...options };
|
||||
const { rerender } = render(
|
||||
<Provider store={store}>
|
||||
<PanelEditorTableView {...props} />
|
||||
</Provider>
|
||||
);
|
||||
|
||||
return { rerender, props, subject, store, timeSrv };
|
||||
}
|
||||
|
||||
describe('PanelEditorTableView', () => {
|
||||
beforeAll(() => {
|
||||
// Mock the timeSrv singleton
|
||||
const timeSrvMock2 = new TimeSrvStub() as unknown as TimeSrv;
|
||||
setTimeSrv(timeSrvMock2);
|
||||
});
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should render', async () => {
|
||||
const { rerender, props, subject, store } = setupTestContext({});
|
||||
|
||||
// only render the panel when loading is done
|
||||
act(() => {
|
||||
subject.next({ state: LoadingState.Loading, series: [], timeRange: getDefaultTimeRange() });
|
||||
subject.next({ state: LoadingState.Done, series: [], timeRange: getDefaultTimeRange() });
|
||||
});
|
||||
|
||||
const newProps = { ...props, isInView: true };
|
||||
rerender(
|
||||
<Provider store={store}>
|
||||
<PanelEditorTableView {...newProps} />
|
||||
</Provider>
|
||||
);
|
||||
expect(screen.getByText(/PanelRenderer Mock/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should run all panel queries if time changes', async () => {
|
||||
const { rerender, props, subject, store, timeSrv } = setupTestContext({});
|
||||
|
||||
const timeRangeUpdated = {
|
||||
from: dateTime([2019, 1, 11, 12, 0]),
|
||||
to: dateTime([2019, 1, 11, 18, 0]),
|
||||
} as unknown as TimeRange;
|
||||
|
||||
// only render the panel when loading is done
|
||||
act(() => {
|
||||
subject.next({ state: LoadingState.Loading, series: [], timeRange: getDefaultTimeRange() });
|
||||
subject.next({ state: LoadingState.Done, series: [], timeRange: getDefaultTimeRange() });
|
||||
});
|
||||
|
||||
const newProps = { ...props, isInView: true };
|
||||
rerender(
|
||||
<Provider store={store}>
|
||||
<PanelEditorTableView {...newProps} />
|
||||
</Provider>
|
||||
);
|
||||
|
||||
expect(screen.getByText(/PanelRenderer Mock/i)).toBeInTheDocument();
|
||||
|
||||
// updating the global time range
|
||||
act(() => {
|
||||
timeSrv.setTime(timeRangeUpdated);
|
||||
props.panel.refresh();
|
||||
});
|
||||
|
||||
// panel queries should have the updated time range
|
||||
expect(props.panel.runAllPanelQueries).toHaveBeenNthCalledWith(1, {
|
||||
dashboardId: props.dashboard.id,
|
||||
dashboardTimezone: '',
|
||||
dashboardUID: props.dashboard.uid,
|
||||
timeData: timeRangeUpdated,
|
||||
width: 100,
|
||||
});
|
||||
|
||||
// update global time second time
|
||||
|
||||
const timeRangeUpdated2 = {
|
||||
from: dateTime([2018, 1, 11, 12, 0]),
|
||||
to: dateTime([2018, 1, 11, 18, 0]),
|
||||
} as unknown as TimeRange;
|
||||
|
||||
act(() => {
|
||||
timeSrv.setTime(timeRangeUpdated2);
|
||||
props.panel.refresh();
|
||||
});
|
||||
|
||||
// panel queries should have the updated time range
|
||||
expect(props.panel.runAllPanelQueries).toHaveBeenLastCalledWith({
|
||||
dashboardId: props.dashboard.id,
|
||||
dashboardTimezone: '',
|
||||
dashboardUID: props.dashboard.uid,
|
||||
timeData: timeRangeUpdated2,
|
||||
width: 100,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const TestPanelComponent: FC<PanelProps> = () => <div>Plugin Panel to Render</div>;
|
@ -12,7 +12,7 @@ import { DashboardModel, PanelModel } from '../../state';
|
||||
|
||||
import { usePanelLatestData } from './usePanelLatestData';
|
||||
|
||||
interface Props {
|
||||
export interface Props {
|
||||
width: number;
|
||||
height: number;
|
||||
panel: PanelModel;
|
||||
@ -30,9 +30,9 @@ export function PanelEditorTableView({ width, height, panel, dashboard }: Props)
|
||||
// Subscribe to panel event
|
||||
useEffect(() => {
|
||||
const timeSrv = getTimeSrv();
|
||||
const timeData = applyPanelTimeOverrides(panel, timeSrv.timeRange());
|
||||
|
||||
const sub = panel.events.subscribe(RefreshEvent, () => {
|
||||
const timeData = applyPanelTimeOverrides(panel, timeSrv.timeRange());
|
||||
panel.runAllPanelQueries({
|
||||
dashboardId: dashboard.id,
|
||||
dashboardUID: dashboard.uid,
|
||||
@ -49,7 +49,6 @@ export function PanelEditorTableView({ width, height, panel, dashboard }: Props)
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<PanelChrome width={width} height={height} padding="none">
|
||||
{(innerWidth, innerHeight) => (
|
||||
|
Loading…
Reference in New Issue
Block a user