Skip to content

Commit ddb4690

Browse files
authored
Heatmap: Add timeRangePan (grafana#113889)
* Heatmap: Add timeRangePan * Add tests * Consolidate tests * Optimize time range pan tests
1 parent 749cc73 commit ddb4690

File tree

2 files changed

+112
-2
lines changed

2 files changed

+112
-2
lines changed

e2e-playwright/panels-suite/heatmap.spec.ts

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { test, expect } from '@grafana/plugin-e2e';
22

33
const DASHBOARD_UID = '5Y0jv6pVz';
4-
5-
// test.use();
4+
const TIME_RANGE_PAN_DASHBOARD_UID = 'YoacZIq7z';
65

76
test.describe('Panels test: Heatmap', { tag: ['@panels', '@heatmap'] }, () => {
87
test('renders successfully', async ({ gotoDashboardPage, selectors, page }) => {
@@ -34,3 +33,112 @@ test.describe('Panels test: Heatmap', { tag: ['@panels', '@heatmap'] }, () => {
3433

3534
// TODO tooltips, legends, and panel editing
3635
});
36+
37+
test.use({
38+
featureToggles: {
39+
timeRangePan: true,
40+
},
41+
});
42+
43+
test.describe('Panels test: Heatmap X-axis panning', { tag: ['@panels', '@heatmap'] }, () => {
44+
test('x-axis panning functionality', async ({ gotoDashboardPage, page, selectors }) => {
45+
let centerX: number;
46+
let centerY: number;
47+
let initialFromTime: number;
48+
let initialToTime: number;
49+
50+
const dashboardPage = await test.step('Load dashboard and verify cursor changes to grab', async () => {
51+
const dashboardPage = await gotoDashboardPage({ uid: TIME_RANGE_PAN_DASHBOARD_UID });
52+
53+
const heatmapPanel = page.locator('.uplot').first();
54+
await expect(heatmapPanel, 'panel rendered').toBeVisible();
55+
56+
const xAxis = heatmapPanel.locator('.u-axis').first();
57+
await expect(xAxis, 'x-axis rendered').toBeVisible();
58+
59+
await xAxis.hover();
60+
61+
const cursorStyle = await xAxis.evaluate((el: HTMLElement) => window.getComputedStyle(el).cursor);
62+
expect(cursorStyle, 'cursor is grab').toBe('grab');
63+
64+
return dashboardPage;
65+
});
66+
67+
await test.step('Capture initial time range', async () => {
68+
const heatmapPanel = page.locator('.uplot').first();
69+
const xAxis = heatmapPanel.locator('.u-axis').first();
70+
71+
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
72+
await timePickerButton.click();
73+
74+
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
75+
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
76+
77+
const initialFrom = await fromField.inputValue();
78+
const initialTo = await toField.inputValue();
79+
initialFromTime = new Date(initialFrom).getTime();
80+
initialToTime = new Date(initialTo).getTime();
81+
82+
await page.keyboard.press('Escape');
83+
84+
const axisBox = await xAxis.boundingBox();
85+
if (!axisBox) {
86+
throw new Error('X-axis bounding box not found');
87+
}
88+
89+
centerX = axisBox.x + axisBox.width / 2;
90+
centerY = axisBox.y + axisBox.height / 2;
91+
});
92+
93+
await test.step('Drag right pans backward in time', async () => {
94+
await page.mouse.move(centerX, centerY);
95+
await page.mouse.down();
96+
await page.mouse.move(centerX + 100, centerY);
97+
await page.mouse.up();
98+
99+
await page.waitForTimeout(1000);
100+
101+
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
102+
await timePickerButton.click();
103+
104+
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
105+
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
106+
107+
const afterRightFrom = await fromField.inputValue();
108+
const afterRightTo = await toField.inputValue();
109+
const afterRightFromTime = new Date(afterRightFrom).getTime();
110+
const afterRightToTime = new Date(afterRightTo).getTime();
111+
112+
expect(afterRightFromTime, 'panned backward').toBeLessThan(initialFromTime);
113+
expect(afterRightToTime, 'panned backward').toBeLessThan(initialToTime);
114+
115+
await page.keyboard.press('Escape');
116+
117+
initialFromTime = afterRightFromTime;
118+
initialToTime = afterRightToTime;
119+
});
120+
121+
await test.step('Drag left pans forward in time', async () => {
122+
await page.mouse.move(centerX, centerY);
123+
await page.mouse.down();
124+
await page.mouse.move(centerX - 100, centerY);
125+
await page.mouse.up();
126+
127+
await page.waitForTimeout(1000);
128+
129+
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
130+
await timePickerButton.click();
131+
132+
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
133+
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
134+
135+
const afterLeftFrom = await fromField.inputValue();
136+
const afterLeftTo = await toField.inputValue();
137+
const afterLeftFromTime = new Date(afterLeftFrom).getTime();
138+
const afterLeftToTime = new Date(afterLeftTo).getTime();
139+
140+
expect(afterLeftFromTime, 'panned forward').toBeGreaterThan(initialFromTime);
141+
expect(afterLeftToTime, 'panned forward').toBeGreaterThan(initialToTime);
142+
});
143+
});
144+
});

public/app/plugins/panel/heatmap/HeatmapPanel.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
useTheme2,
1515
VizLayout,
1616
EventBusPlugin,
17+
XAxisInteractionAreaPlugin,
1718
} from '@grafana/ui';
1819
import { FacetedData, TimeRange2, TooltipHoverMode } from '@grafana/ui/internal';
1920
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
@@ -199,6 +200,7 @@ const HeatmapPanelViz = ({
199200
{cursorSync !== DashboardCursorSync.Off && (
200201
<EventBusPlugin config={builder} eventBus={eventBus} frame={info.series ?? info.heatmap} />
201202
)}
203+
<XAxisInteractionAreaPlugin config={builder} queryZoom={onChangeTimeRange} />
202204
{options.tooltip.mode !== TooltipDisplayMode.None && (
203205
<TooltipPlugin2
204206
config={builder}

0 commit comments

Comments
 (0)