Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions public/app/features/dashboard/containers/DashboardPageProxy.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { render } from 'test/test-utils';

import { selectors } from '@grafana/e2e-selectors';
import { config, locationService } from '@grafana/runtime';
import { appEvents } from 'app/core/core';
import {
HOME_DASHBOARD_CACHE_KEY,
getDashboardScenePageStateManager,
Expand All @@ -14,11 +15,20 @@ import {
setupLoadDashboardRuntimeErrorMock,
} from 'app/features/dashboard-scene/utils/test-utils';
import { DashboardDTO, DashboardRoutes } from 'app/types';
import { NIRefreshDashboardEvent } from 'app/types/events';

import { DashboardLoaderSrv, setDashboardLoaderSrv } from '../services/DashboardLoaderSrv';

import DashboardPageProxy, { DashboardPageProxyProps } from './DashboardPageProxy';

const mockRefreshTimeModel = jest.fn();

jest.mock('../services/TimeSrv', () => ({
getTimeSrv: jest.fn(() => ({
refreshTimeModel: mockRefreshTimeModel,
})),
}));

const dashMock: DashboardDTO = {
dashboard: {
id: 1,
Expand Down Expand Up @@ -280,4 +290,111 @@ describe('DashboardPageProxy', () => {
expect(await screen.findByTestId('dashboard-page-error')).toHaveTextContent('Runtime error');
});
});

describe('NIRefreshDashboardEvent', () => {
beforeEach(() => {
mockRefreshTimeModel.mockClear();
getDashboardScenePageStateManager().setDashboardCache('test-uid', dashMock);
});

describe('when dashboard scenes is disabled', () => {
beforeEach(() => {
config.featureToggles.dashboardSceneForViewers = false;
});

it('should refresh the dashboard when NIRefreshDashboardEvent is emitted', async () => {
act(() => {
setup({
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
uid: 'test-uid',
});
});

await waitFor(() => {
expect(screen.queryByTestId('dashboard-scene-page')).not.toBeInTheDocument();
});

act(() => {
appEvents.publish(new NIRefreshDashboardEvent());
});

await waitFor(() => {
expect(mockRefreshTimeModel).toHaveBeenCalledTimes(1);
});
});

it('should refresh the dashboard multiple times when event is emitted multiple times', async () => {
act(() => {
setup({
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
uid: 'test-uid',
});
});

await waitFor(() => {
expect(screen.queryByTestId('dashboard-scene-page')).not.toBeInTheDocument();
});

act(() => {
appEvents.publish(new NIRefreshDashboardEvent());
appEvents.publish(new NIRefreshDashboardEvent());
appEvents.publish(new NIRefreshDashboardEvent());
});

await waitFor(() => {
expect(mockRefreshTimeModel).toHaveBeenCalledTimes(3);
});
});
});

describe('when dashboard scenes is enabled', () => {
beforeEach(() => {
config.featureToggles.dashboardSceneForViewers = true;
});

it('should refresh dashboard when NIRefreshDashboardEvent is emitted', async () => {
act(() => {
setup({
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
uid: 'test-uid',
});
});

await waitFor(() => {
expect(screen.queryByTestId('dashboard-scene-page')).toBeInTheDocument();
});

act(() => {
appEvents.publish(new NIRefreshDashboardEvent());
});

await waitFor(() => {
expect(mockRefreshTimeModel).toHaveBeenCalledTimes(1);
});
});

it('should refresh the dashboard multiple times when event is emitted multiple times', async () => {
act(() => {
setup({
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
uid: 'test-uid',
});
});

await waitFor(() => {
expect(screen.queryByTestId('dashboard-scene-page')).toBeInTheDocument();
});

act(() => {
appEvents.publish(new NIRefreshDashboardEvent());
appEvents.publish(new NIRefreshDashboardEvent());
appEvents.publish(new NIRefreshDashboardEvent());
});

await waitFor(() => {
expect(mockRefreshTimeModel).toHaveBeenCalledTimes(3);
});
});
});
});
});
15 changes: 15 additions & 0 deletions public/app/features/dashboard/containers/DashboardPageProxy.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { useEffect } from 'react';
import { useLocation, useParams } from 'react-router-dom-v5-compat';
import { useAsync } from 'react-use';

import { config } from '@grafana/runtime';
import { appEvents } from 'app/core/core';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import DashboardScenePage from 'app/features/dashboard-scene/pages/DashboardScenePage';
import { getDashboardScenePageStateManager } from 'app/features/dashboard-scene/pages/DashboardScenePageStateManager';
import { DashboardRoutes } from 'app/types';
import { NIRefreshDashboardEvent } from 'app/types/events';

import DashboardPage, { DashboardPageParams } from './DashboardPage';
import { DashboardPageError } from './DashboardPageError';
Expand All @@ -24,6 +28,17 @@ function DashboardPageProxy(props: DashboardPageProxyProps) {
const params = useParams<DashboardPageParams>();
const location = useLocation();

// Subscribe to NIRefreshDashboardEvent regardless of which dashboard implementation is used
useEffect(() => {
const subscription = appEvents.subscribe(NIRefreshDashboardEvent, () => {
getTimeSrv().refreshTimeModel();
});

return () => {
subscription.unsubscribe();
};
}, []);

// Force scenes if v2 api and scenes are enabled
if (config.featureToggles.useV2DashboardsAPI && config.featureToggles.dashboardScene && !forceOld) {
console.log('DashboardPageProxy: forcing scenes because of v2 api');
Expand Down
7 changes: 7 additions & 0 deletions public/app/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ export class DashboardSavedEvent extends BusEventBase {
static type = 'dashboard-saved';
}

/**
* Custom event that triggers a dashboard refresh.
*/
export class NIRefreshDashboardEvent extends BusEventBase {
static type = 'ni-refresh-dashboard';
}

export class AnnotationQueryStarted extends BusEventWithPayload<AnnotationQuery> {
static type = 'annotation-query-started';
}
Expand Down
Loading