From 516e0cf7e22fab3a522366aef97df1705928d0bf Mon Sep 17 00:00:00 2001 From: Victor Marin <36818606+mdvictor@users.noreply.github.com> Date: Thu, 10 Oct 2024 19:11:58 +0300 Subject: [PATCH] DashboardScene: Update timerange in datalinks on change (#94419) * fix types * mods * refactor * refactor --- .../scene/DashboardControls.test.tsx | 77 +++++++++++++++---- .../scene/DashboardControls.tsx | 3 +- 2 files changed, 66 insertions(+), 14 deletions(-) diff --git a/public/app/features/dashboard-scene/scene/DashboardControls.test.tsx b/public/app/features/dashboard-scene/scene/DashboardControls.test.tsx index aefb2953e2b..34c5f3fe057 100644 --- a/public/app/features/dashboard-scene/scene/DashboardControls.test.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardControls.test.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(); }).not.toThrow(); }); it('should render visible controls', async () => { - const scene = buildTestScene({ + const { controls: scene } = buildTestScene({ variableControls: [new VariableValueSelectors({}), new SceneDataLayerControls()], }); const renderer = render(); @@ -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(); + + //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): DashboardControls { +function buildTestScene(state?: Partial): { + dashboard: DashboardScene; + controls: DashboardControls; +} { const variable = new TextBoxVariable({ name: 'A', label: 'A', @@ -155,5 +206,5 @@ function buildTestScene(state?: Partial): DashboardContr dashboard.activate(); variable.activate(); - return dashboard.state.controls as DashboardControls; + return { dashboard, controls: dashboard.state.controls as DashboardControls }; } diff --git a/public/app/features/dashboard-scene/scene/DashboardControls.tsx b/public/app/features/dashboard-scene/scene/DashboardControls.tsx index 3805792f93b..41e125957a5 100644 --- a/public/app/features/dashboard-scene/scene/DashboardControls.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardControls.tsx @@ -122,9 +122,10 @@ function DashboardControlsRenderer({ model }: SceneComponentProps