grafana_bak/public/app/features/dashboard/containers/DashboardPageProxy.test.tsx
2025-04-01 10:38:02 +09:00

284 lines
8.5 KiB
TypeScript

import { act, screen, waitFor } from '@testing-library/react';
import { useParams } from 'react-router-dom-v5-compat';
import { Props } from 'react-virtualized-auto-sizer';
import { render } from 'test/test-utils';
import { selectors } from '@grafana/e2e-selectors';
import { config, locationService } from '@grafana/runtime';
import {
HOME_DASHBOARD_CACHE_KEY,
getDashboardScenePageStateManager,
} from 'app/features/dashboard-scene/pages/DashboardScenePageStateManager';
import {
setupLoadDashboardMockReject,
setupLoadDashboardRuntimeErrorMock,
} from 'app/features/dashboard-scene/utils/test-utils';
import { DashboardDTO, DashboardRoutes } from 'app/types';
import { DashboardLoaderSrv, setDashboardLoaderSrv } from '../services/DashboardLoaderSrv';
import DashboardPageProxy, { DashboardPageProxyProps } from './DashboardPageProxy';
const dashMock: DashboardDTO = {
dashboard: {
id: 1,
annotations: {
list: [],
},
uid: 'uid',
title: 'title',
panels: [],
version: 1,
schemaVersion: 1,
},
meta: {
canEdit: false,
},
};
const homeMock = {
...dashMock,
dashboard: {
...dashMock.dashboard,
uid: '',
title: 'Home',
},
};
const homeMockEditable = {
...homeMock,
meta: {
...homeMock.meta,
canEdit: true,
},
};
const dashMockEditable = {
...dashMock,
meta: {
...dashMock.meta,
canEdit: true,
},
};
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
getDataSourceSrv: jest.fn().mockReturnValue({
getInstanceSettings: () => {
return { name: 'Grafana' };
},
get: jest.fn().mockResolvedValue({}),
}),
useChromeHeaderHeight: jest.fn(),
getBackendSrv: () => {
return {
get: jest.fn().mockResolvedValue({ dashboard: {}, meta: { url: '' } }),
};
},
}));
jest.mock('react-virtualized-auto-sizer', () => {
return ({ children }: Props) =>
children({
height: 1,
scaledHeight: 1,
scaledWidth: 1,
width: 1,
});
});
setDashboardLoaderSrv({
loadDashboard: jest.fn().mockResolvedValue(dashMock),
// disabling type checks since this is a test util
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
} as unknown as DashboardLoaderSrv);
jest.mock('react-router-dom-v5-compat', () => ({
...jest.requireActual('react-router-dom-v5-compat'),
useParams: jest.fn().mockReturnValue({}),
}));
function setup(props: Partial<DashboardPageProxyProps> & { uid?: string }) {
(useParams as jest.Mock).mockReturnValue({ uid: props.uid });
return render(
<DashboardPageProxy
location={locationService.getLocation()}
queryParams={{}}
route={{ routeName: DashboardRoutes.Home, component: () => null, path: '/' }}
{...props}
/>
);
}
describe('DashboardPageProxy', () => {
describe('when dashboardSceneForViewers feature toggle disabled', () => {
beforeEach(() => {
config.featureToggles.dashboardSceneForViewers = false;
});
it('home dashboard', async () => {
getDashboardScenePageStateManager().setDashboardCache(HOME_DASHBOARD_CACHE_KEY, dashMock);
act(() => {
setup({
route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' },
});
});
await waitFor(() => {
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(0);
});
});
it('uid dashboard', async () => {
getDashboardScenePageStateManager().setDashboardCache('abc-def', dashMock);
act(() => {
setup({
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
uid: 'abc-def',
});
});
await waitFor(() => {
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(0);
});
});
});
describe('when dashboardSceneForViewers feature toggle enabled', () => {
beforeEach(() => {
config.featureToggles.dashboardSceneForViewers = true;
});
describe('when user can edit a dashboard ', () => {
it('should not render DashboardScenePage if route is Home', async () => {
getDashboardScenePageStateManager().setDashboardCache(HOME_DASHBOARD_CACHE_KEY, homeMockEditable);
act(() => {
setup({
route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' },
uid: '',
});
});
await waitFor(() => {
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(0);
});
});
it('should not render DashboardScenePage if route is Normal and has uid', async () => {
getDashboardScenePageStateManager().setDashboardCache('abc-def', dashMockEditable);
act(() => {
setup({
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
uid: 'abc-def',
});
});
await waitFor(() => {
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(0);
});
});
});
describe('when user can only view a dashboard ', () => {
it('should render DashboardScenePage if route is Home', async () => {
getDashboardScenePageStateManager().setDashboardCache(HOME_DASHBOARD_CACHE_KEY, homeMock);
act(() => {
setup({
route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' },
uid: '',
});
});
await waitFor(() => {
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(1);
});
});
it('should render DashboardScenePage if route is Normal and has uid', async () => {
getDashboardScenePageStateManager().setDashboardCache('uid', dashMock);
act(() => {
setup({
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
uid: 'uid',
});
});
await waitFor(() => {
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(1);
});
});
it('should render not DashboardScenePage if dashboard UID does not match route UID', async () => {
getDashboardScenePageStateManager().setDashboardCache('uid', dashMock);
act(() => {
setup({
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
uid: 'wrongUID',
});
});
await waitFor(() => {
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(0);
});
});
});
});
describe('errors rendering', () => {
it('should render dashboard not found notice when dashboard... not found', async () => {
setupLoadDashboardMockReject({
status: 404,
statusText: 'Not Found',
data: {
message: 'Dashboard not found',
},
config: {
method: 'GET',
url: 'api/dashboards/uid/adfjq9edwm0hsdsa',
retry: 0,
headers: {
'X-Grafana-Org-Id': 1,
},
hideFromInspector: true,
},
isHandled: true,
});
setup({ route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, uid: 'abc' });
expect(await screen.findByTestId(selectors.components.EntityNotFound.container)).toBeInTheDocument();
});
it('should render error alert for backend errors', async () => {
setupLoadDashboardMockReject({
status: 500,
statusText: 'internal server error',
data: {
message: 'Internal server error',
},
config: {
method: 'GET',
url: 'api/dashboards/uid/adfjq9edwm0hsdsa',
retry: 0,
headers: {
'X-Grafana-Org-Id': 1,
},
hideFromInspector: true,
},
isHandled: true,
});
setup({ route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, uid: 'abc' });
expect(await screen.findByTestId('dashboard-page-error')).toBeInTheDocument();
expect(await screen.findByTestId('dashboard-page-error')).toHaveTextContent('Internal server error');
});
it('should render error alert for runtime errors', async () => {
setupLoadDashboardRuntimeErrorMock();
setup({ route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, uid: 'abc' });
expect(await screen.findByTestId('dashboard-page-error')).toBeInTheDocument();
expect(await screen.findByTestId('dashboard-page-error')).toHaveTextContent('Runtime error');
});
});
});