/usr/share/grafana/public/app/features/dashboard/components/PanelEditor
import { act, fireEvent, render, screen } from '@testing-library/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, TimeRange, } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { getTimeSrv, TimeSrv, setTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { PanelQueryRunner } from '../../../query/state/PanelQueryRunner'; import { PanelModel } from '../../state/PanelModel'; import { createDashboardModelFixture } from '../../state/__fixtures__/dashboardFixtures'; 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: createDashboardModelFixture({ id: 1, uid: 'super-unique-id', // panelInitialized: jest.fn(), // events: new EventBusSrv(), 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, { dashboardTimezone: '', dashboardTitle: 'No Title', 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({ dashboardTimezone: '', dashboardTitle: 'No Title', dashboardUID: props.dashboard.uid, timeData: timeRangeUpdated2, width: 100, }); }); it('should render an error', 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.Error, series: [], errors: [{ message: 'boom!' }], timeRange: getDefaultTimeRange(), }); }); const newProps = { ...props, isInView: true }; rerender( <Provider store={store}> <PanelEditorTableView {...newProps} /> </Provider> ); const button = screen.getByRole('button', { name: selectors.components.Panels.Panel.headerCornerInfo('error') }); expect(button).toBeInTheDocument(); await act(async () => { fireEvent.focus(button); }); expect(await screen.findByText('boom!')).toBeInTheDocument(); }); it('should render a description for multiple errors', 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.Error, series: [], errors: [{ message: 'boom 1!' }, { message: 'boom 2!' }], timeRange: getDefaultTimeRange(), }); }); const newProps = { ...props, isInView: true }; rerender( <Provider store={store}> <PanelEditorTableView {...newProps} /> </Provider> ); const button = screen.getByRole('button', { name: selectors.components.Panels.Panel.headerCornerInfo('error') }); expect(button).toBeInTheDocument(); await act(async () => { fireEvent.focus(button); }); expect(await screen.findByText('Multiple errors found. Click for more details')).toBeInTheDocument(); }); }); const TestPanelComponent = () => <div>Plugin Panel to Render</div>;
.
Edit
..
Edit
DynamicConfigValueEditor.tsx
Edit
OptionsPane.tsx
Edit
OptionsPaneCategory.tsx
Edit
OptionsPaneCategoryDescriptor.tsx
Edit
OptionsPaneItemDescriptor.tsx
Edit
OptionsPaneItemOverrides.tsx
Edit
OptionsPaneOptions.test.tsx
Edit
OptionsPaneOptions.tsx
Edit
OverrideCategoryTitle.tsx
Edit
PanelEditor.tsx
Edit
PanelEditorQueries.tsx
Edit
PanelEditorTableView.test.tsx
Edit
PanelEditorTableView.tsx
Edit
PanelEditorTabs.tsx
Edit
PanelHeaderCorner.test.tsx
Edit
PanelHeaderCorner.tsx
Edit
PanelNotSupported.test.tsx
Edit
PanelNotSupported.tsx
Edit
VisualizationButton.tsx
Edit
VisualizationSelectPane.tsx
Edit
getFieldOverrideElements.tsx
Edit
getLibraryPanelOptions.tsx
Edit
getPanelFrameOptions.tsx
Edit
getVisualizationOptions.test.ts
Edit
getVisualizationOptions.tsx
Edit
state
Edit
types.ts
Edit
usePanelLatestData.ts
Edit
utils.test.ts
Edit
utils.ts
Edit