diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx new file mode 100644 index 00000000000..84685e6c1db --- /dev/null +++ b/public/app/features/dashboard/dashgrid/PanelChrome.test.tsx @@ -0,0 +1,80 @@ +import React, { FC } from 'react'; +import { ReplaySubject } from 'rxjs'; +import { act, render, screen } from '@testing-library/react'; +import { getDefaultTimeRange, LoadingState, PanelData, PanelPlugin, PanelProps } from '@grafana/data'; + +import { PanelChrome, Props } from './PanelChrome'; +import { DashboardModel, PanelModel } from '../state'; +import { updateLocation } from '../../../core/actions'; +import { PanelQueryRunner } from '../../query/state/PanelQueryRunner'; +import { setTimeSrv, TimeSrv } from '../services/TimeSrv'; + +jest.mock('app/core/profiler', () => ({ + profiler: { + renderingCompleted: jest.fn(), + }, +})); + +function setupTestContext(options: Partial) { + const subject: ReplaySubject = new ReplaySubject(); + const panelQueryRunner = ({ + getData: () => subject, + run: () => { + subject.next({ state: LoadingState.Done, series: [], timeRange: getDefaultTimeRange() }); + }, + } as unknown) as PanelQueryRunner; + const timeSrv = ({ + timeRange: jest.fn(), + } as unknown) as TimeSrv; + setTimeSrv(timeSrv); + const defaults: Props = { + panel: ({ + hasTitle: jest.fn(), + replaceVariables: jest.fn(), + events: { subscribe: jest.fn() }, + getQueryRunner: () => panelQueryRunner, + getOptions: jest.fn(), + } as unknown) as PanelModel, + dashboard: ({ + panelInitialized: jest.fn(), + getTimezone: () => 'browser', + } as unknown) as DashboardModel, + plugin: ({ + meta: { skipDataQuery: false }, + panel: TestPanelComponent, + } as unknown) as PanelPlugin, + isViewing: true, + isEditing: false, + isInView: false, + width: 100, + height: 100, + updateLocation: (jest.fn() as unknown) as typeof updateLocation, + }; + + const props = { ...defaults, ...options }; + const { rerender } = render(); + + return { rerender, props, subject }; +} + +describe('PanelChrome', () => { + describe('when the user scrolls by a panel so fast that it starts loading data but scrolls out of view', () => { + it('then it should load the panel successfully when scrolled into view again', () => { + const { rerender, props, subject } = setupTestContext({}); + + expect(screen.queryByText(/plugin panel to render/i)).not.toBeInTheDocument(); + + act(() => { + subject.next({ state: LoadingState.Loading, series: [], timeRange: getDefaultTimeRange() }); + subject.next({ state: LoadingState.Done, series: [], timeRange: getDefaultTimeRange() }); + }); + + const newProps = { ...props, isInView: true }; + rerender(); + + expect(screen.getByText(/plugin panel to render/i)).toBeInTheDocument(); + }); + }); +}); + +const TestPanelComponent: FC = () =>
Plugin Panel to Render
; diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 0414393c3b1..684faa94faf 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -140,6 +140,7 @@ export class PanelChrome extends Component { if (!this.props.isInView) { // Ignore events when not visible. // The call will be repeated when the panel comes into view + this.setState({ refreshWhenInView: true }); return; }