DashboardScene: Update timerange in datalinks on change (#94419)

* fix types

* mods

* refactor

* refactor
pull/93496/head^2
Victor Marin 1 year ago committed by GitHub
parent e32caccc15
commit 516e0cf7e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 77
      public/app/features/dashboard-scene/scene/DashboardControls.test.tsx
  2. 3
      public/app/features/dashboard-scene/scene/DashboardControls.tsx

@ -1,22 +1,40 @@
import { render } from '@testing-library/react';
import { act, render } from '@testing-library/react';
import { toUtc } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { SceneDataLayerControls, SceneVariableSet, TextBoxVariable, VariableValueSelectors } from '@grafana/scenes';
import { DashboardControls, DashboardControlsState } from './DashboardControls';
import { DashboardScene } from './DashboardScene';
const mockGetAnchorInfo = jest.fn((link) => ({
href: `/dashboard/${link.title}`,
title: link.title,
tooltip: link.tooltip || null,
}));
// Mock the getLinkSrv function
jest.mock('app/features/panel/panellinks/link_srv', () => ({
getLinkSrv: jest.fn(() => ({
getAnchorInfo: mockGetAnchorInfo,
})),
}));
describe('DashboardControls', () => {
describe('Given a standard scene', () => {
it('should initialize with default values', () => {
const scene = buildTestScene();
const { controls: scene } = buildTestScene();
expect(scene.state.variableControls).toEqual([]);
expect(scene.state.timePicker).toBeDefined();
expect(scene.state.refreshPicker).toBeDefined();
});
it('should return if time controls are hidden', () => {
const scene = buildTestScene({ hideTimeControls: false, hideVariableControls: false, hideLinksControls: false });
const { controls: scene } = buildTestScene({
hideTimeControls: false,
hideVariableControls: false,
hideLinksControls: false,
});
expect(scene.hasControls()).toBeTruthy();
scene.setState({ hideTimeControls: true });
expect(scene.hasControls()).toBeTruthy();
@ -27,14 +45,14 @@ describe('DashboardControls', () => {
describe('Component', () => {
it('should render', () => {
const scene = buildTestScene();
const { controls: scene } = buildTestScene();
expect(() => {
render(<scene.Component model={scene} />);
}).not.toThrow();
});
it('should render visible controls', async () => {
const scene = buildTestScene({
const { controls: scene } = buildTestScene({
variableControls: [new VariableValueSelectors({}), new SceneDataLayerControls()],
});
const renderer = render(<scene.Component model={scene} />);
@ -47,7 +65,7 @@ describe('DashboardControls', () => {
});
it('should render with hidden controls', async () => {
const scene = buildTestScene({
const { controls: scene } = buildTestScene({
hideTimeControls: true,
hideVariableControls: true,
hideLinksControls: true,
@ -61,13 +79,13 @@ describe('DashboardControls', () => {
describe('UrlSync', () => {
it('should return keys', () => {
const scene = buildTestScene();
const { controls: scene } = buildTestScene();
// @ts-expect-error
expect(scene._urlSync.getKeys()).toEqual(['_dash.hideTimePicker', '_dash.hideVariables', '_dash.hideLinks']);
});
it('should not return url state for hide flags', () => {
const scene = buildTestScene();
const { controls: scene } = buildTestScene();
expect(scene.getUrlState()).toEqual({});
scene.setState({
hideTimeControls: true,
@ -78,7 +96,7 @@ describe('DashboardControls', () => {
});
it('should update from url', () => {
const scene = buildTestScene();
const { controls: scene } = buildTestScene();
scene.updateFromUrl({
'_dash.hideTimePicker': 'true',
'_dash.hideVariables': 'true',
@ -98,7 +116,11 @@ describe('DashboardControls', () => {
});
it('should not override state if no new state comes from url', () => {
const scene = buildTestScene({ hideTimeControls: true, hideVariableControls: true, hideLinksControls: true });
const { controls: scene } = buildTestScene({
hideTimeControls: true,
hideVariableControls: true,
hideLinksControls: true,
});
scene.updateFromUrl({});
expect(scene.state.hideTimeControls).toBeTruthy();
expect(scene.state.hideVariableControls).toBeTruthy();
@ -106,7 +128,11 @@ describe('DashboardControls', () => {
});
it('should not call setState if no changes', () => {
const scene = buildTestScene({ hideTimeControls: true, hideVariableControls: true, hideLinksControls: true });
const { controls: scene } = buildTestScene({
hideTimeControls: true,
hideVariableControls: true,
hideLinksControls: true,
});
const setState = jest.spyOn(scene, 'setState');
scene.updateFromUrl({
@ -118,9 +144,34 @@ describe('DashboardControls', () => {
expect(setState).toHaveBeenCalledTimes(0);
});
});
it('Should update link hrefs when time range changes', () => {
const { controls, dashboard } = buildTestScene();
render(<controls.Component model={controls} />);
//clear initial calls to getAnchorInfo
mockGetAnchorInfo.mockClear();
act(() => {
// Update time range
dashboard.state.$timeRange?.setState({
value: {
from: toUtc('2021-01-01'),
to: toUtc('2021-01-02'),
raw: { from: toUtc('2020-01-01'), to: toUtc('2020-01-02') },
},
});
});
//expect getAnchorInfo to be called after time range change
expect(mockGetAnchorInfo).toHaveBeenCalledTimes(1);
});
});
function buildTestScene(state?: Partial<DashboardControlsState>): DashboardControls {
function buildTestScene(state?: Partial<DashboardControlsState>): {
dashboard: DashboardScene;
controls: DashboardControls;
} {
const variable = new TextBoxVariable({
name: 'A',
label: 'A',
@ -155,5 +206,5 @@ function buildTestScene(state?: Partial<DashboardControlsState>): DashboardContr
dashboard.activate();
variable.activate();
return dashboard.state.controls as DashboardControls;
return { dashboard, controls: dashboard.state.controls as DashboardControls };
}

@ -122,9 +122,10 @@ function DashboardControlsRenderer({ model }: SceneComponentProps<DashboardContr
const { variableControls, refreshPicker, timePicker, hideTimeControls, hideVariableControls, hideLinksControls } =
model.useState();
const dashboard = getDashboardSceneFor(model);
const { links, editPanel } = dashboard.useState();
const { links, editPanel, $timeRange } = dashboard.useState();
const styles = useStyles2(getStyles);
const showDebugger = location.search.includes('scene-debugger');
$timeRange!.useState();
if (!model.hasControls()) {
return null;

Loading…
Cancel
Save