[v11.1.x] Scenes: Setting default_home_dashboard_path returns blank page and no controls (#89360)

Scenes: Setting default_home_dashboard_path returns blank page and no controls (#89304)

(cherry picked from commit 3fdc66d284)

Co-authored-by: Ivan Ortega Alba <ivanortegaalba@gmail.com>
This commit is contained in:
grafana-delivery-bot[bot]
2024-06-19 18:54:27 +03:00
committed by GitHub
co-authored by Ivan Ortega Alba
parent bbefb6a4eb
commit b97bf4c632
6 changed files with 80 additions and 17 deletions
@@ -11,9 +11,11 @@ import { config, getPluginLinkExtensions, locationService, setPluginImportUtils
import { VizPanel } from '@grafana/scenes';
import { Dashboard } from '@grafana/schema';
import { getRouteComponentProps } from 'app/core/navigation/__mocks__/routeProps';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import store from 'app/core/store';
import { DashboardLoaderSrv, setDashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
import { DASHBOARD_FROM_LS_KEY } from 'app/features/dashboard/state/initDashboard';
import { DashboardRoutes } from 'app/types';
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
@@ -24,6 +26,11 @@ jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
setPluginExtensionGetter: jest.fn(),
getPluginLinkExtensions: jest.fn(),
getBackendSrv: () => {
return {
get: jest.fn().mockResolvedValue({ dashboard: simpleDashboard, meta: { url: '' } }),
};
},
getDataSourceSrv: () => {
return {
get: jest.fn().mockResolvedValue({}),
@@ -37,12 +44,19 @@ jest.mock('@grafana/runtime', () => ({
const getPluginLinkExtensionsMock = jest.mocked(getPluginLinkExtensions);
function setup() {
function setup({ routeProps }: { routeProps?: Partial<GrafanaRouteComponentProps> } = {}) {
const context = getGrafanaContextMock();
const defaultRouteProps = getRouteComponentProps();
const props: Props = {
...getRouteComponentProps(),
...defaultRouteProps,
match: {
...defaultRouteProps.match,
params: {
uid: 'my-dash-uid',
},
},
...routeProps,
};
props.match.params.uid = 'my-dash-uid';
const renderResult = render(
<TestProvider grafanaContext={context}>
@@ -258,14 +272,39 @@ describe('DashboardScenePage', () => {
});
describe('home page', () => {
it('should not show controls', async () => {
it('should render the dashboard when the route is home', async () => {
setup({
routeProps: {
route: {
...getRouteComponentProps().route,
routeName: DashboardRoutes.Home,
},
match: {
...getRouteComponentProps().match,
path: '/',
params: {},
},
},
});
await waitForDashbordToRender();
expect(await screen.findByTitle('Panel A')).toBeInTheDocument();
expect(await screen.findByText('Content A')).toBeInTheDocument();
expect(await screen.findByTitle('Panel B')).toBeInTheDocument();
expect(await screen.findByText('Content B')).toBeInTheDocument();
});
it('should show controls', async () => {
getDashboardScenePageStateManager().clearDashboardCache();
loadDashboardMock.mockClear();
loadDashboardMock.mockResolvedValue({ dashboard: { panels: [] }, meta: {} });
setup();
await waitFor(() => expect(screen.queryByText('Refresh')).not.toBeInTheDocument());
await waitFor(() => expect(screen.queryByText('Refresh')).toBeInTheDocument());
await waitFor(() => expect(screen.queryByText('Last 6 hours')).toBeInTheDocument());
});
});
});
@@ -75,7 +75,12 @@ export function DashboardScenePage({ match, route, queryParams, history }: Props
}
// Do not render anything when transitioning from one dashboard to another
if (match.params.type !== 'snapshot' && dashboard.state.uid && dashboard.state.uid !== match.params.uid) {
if (
match.params.type !== 'snapshot' &&
dashboard.state.uid &&
dashboard.state.uid !== match.params.uid &&
route.routeName !== DashboardRoutes.Home
) {
return null;
}
@@ -104,17 +104,29 @@ describe('DashboardControls', () => {
expect(scene.state.hideTimeControls).toBeTruthy();
expect(scene.state.hideVariableControls).toBeTruthy();
expect(scene.state.hideLinksControls).toBeTruthy();
});
it('should not override state if no new state comes from url', () => {
const scene = buildTestScene({ hideTimeControls: true, hideVariableControls: true, hideLinksControls: true });
scene.updateFromUrl({});
expect(scene.state.hideTimeControls).toBeFalsy();
expect(scene.state.hideVariableControls).toBeFalsy();
expect(scene.state.hideLinksControls).toBeFalsy();
expect(scene.state.hideTimeControls).toBeTruthy();
expect(scene.state.hideVariableControls).toBeTruthy();
expect(scene.state.hideLinksControls).toBeTruthy();
});
it('should not call setState if no changes', () => {
const scene = buildTestScene();
const setState = jest.spyOn(scene, 'setState');
scene.updateFromUrl({});
scene.updateFromUrl({});
scene.updateFromUrl({
'_dash.hideTimePicker': 'true',
'_dash.hideVariables': 'true',
'_dash.hideLinks': 'true',
});
scene.updateFromUrl({
'_dash.hideTimePicker': 'true',
'_dash.hideVariables': 'true',
'_dash.hideLinks': 'true',
});
expect(setState).toHaveBeenCalledTimes(1);
});
});
@@ -54,9 +54,14 @@ export class DashboardControls extends SceneObjectBase<DashboardControlsState> {
updateFromUrl(values: SceneObjectUrlValues) {
const update: Partial<DashboardControlsState> = {};
update.hideTimeControls = values['_dash.hideTimePicker'] === 'true' || values['_dash.hideTimePicker'] === '';
update.hideVariableControls = values['_dash.hideVariables'] === 'true' || values['_dash.hideVariables'] === '';
update.hideLinksControls = values['_dash.hideLinks'] === 'true' || values['_dash.hideLinks'] === '';
update.hideTimeControls =
values['_dash.hideTimePicker'] === 'true' || values['_dash.hideTimePicker'] === '' || this.state.hideTimeControls;
update.hideVariableControls =
values['_dash.hideVariables'] === 'true' ||
values['_dash.hideVariables'] === '' ||
this.state.hideVariableControls;
update.hideLinksControls =
values['_dash.hideLinks'] === 'true' || values['_dash.hideLinks'] === '' || this.state.hideLinksControls;
if (Object.entries(update).some(([k, v]) => v !== this.state[k as keyof DashboardControlsState])) {
this.setState(update);
@@ -57,7 +57,7 @@ export function DashboardSceneRenderer({ model }: SceneComponentProps<DashboardS
>
{scopes && <scopes.Component model={scopes} />}
<NavToolbarActions dashboard={model} />
{!isHomePage && controls && hasControls && (
{controls && hasControls && (
<div
className={cx(styles.controlsWrapper, scopes && !isScopesExpanded && styles.controlsWrapperWithScopes)}
>
@@ -1,4 +1,4 @@
import { render, screen, waitFor } from '@testing-library/react';
import { act, render, screen, waitFor } from '@testing-library/react';
import React from 'react';
import { selectors } from '@grafana/e2e-selectors';
@@ -24,7 +24,9 @@ function renderComponent({ initialValue = '', onChange = jest.fn(), onRunQuery =
describe('MonacoFieldWrapper', () => {
test('Renders with no errors', async () => {
renderComponent();
await act(() => {
renderComponent();
});
await waitFor(async () => {
const monacoEditor = await screen.findByTestId(selectors.components.ReactMonacoEditor.editorLazy);