Dashboards: Improve lazy loading (#108854)

This commit is contained in:
Bogdan Matei
2025-08-01 10:46:41 +00:00
committed by GitHub
parent f3cd54769c
commit 88a52bb6f4
17 changed files with 264 additions and 189 deletions
@@ -14,7 +14,7 @@ test.use({
// these tests require a larger viewport
test.use({
viewport: { width: 1280, height: 1080 },
viewport: { width: 1920, height: 1080 },
});
test.describe(
@@ -124,37 +124,49 @@ test.describe(
await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow).click();
await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addPanel).last().click();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 2'))
).toBeVisible();
const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row'));
await expect(firstRow).toBeVisible();
await firstRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(5);
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow })
).toHaveCount(3);
const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 1'));
await expect(secondRow).toBeVisible();
await secondRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow })
).toHaveCount(1);
const thirdRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 2'));
await expect(thirdRow).toBeVisible();
await thirdRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: thirdRow })
).toHaveCount(1);
// Save dashboard and reload
await saveDashboard(dashboardPage, selectors);
await page.reload();
await expect(firstRow).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 2'))
).toBeVisible();
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow })
).toHaveCount(3);
await expect(secondRow).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(5);
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow })
).toHaveCount(1);
thirdRow.scrollIntoViewIfNeeded();
await expect(thirdRow).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: thirdRow })
).toHaveCount(1);
await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click();
@@ -172,15 +184,9 @@ test.describe(
await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.deleteButton).click();
await dashboardPage.getByGrafanaSelector(selectors.pages.ConfirmModal.delete).click();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeHidden();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 2'))
).toBeHidden();
await expect(firstRow).toBeVisible();
await expect(secondRow).toBeHidden();
await expect(thirdRow).toBeHidden();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(3);
@@ -188,15 +194,9 @@ test.describe(
await saveDashboard(dashboardPage, selectors);
await page.reload();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeHidden();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 2'))
).toBeHidden();
await expect(firstRow).toBeVisible();
await expect(secondRow).toBeHidden();
await expect(thirdRow).toBeHidden();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(3);
@@ -224,15 +224,21 @@ test.describe(
.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow)
.scrollIntoViewIfNeeded();
const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row'));
await expect(firstRow).toBeVisible();
firstRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow })
).toHaveCount(3);
const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 1'));
await expect(secondRow).toBeVisible();
secondRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(6);
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow })
).toHaveCount(3);
await saveDashboard(dashboardPage, selectors);
await page.reload();
@@ -243,15 +249,18 @@ test.describe(
.last()
.scrollIntoViewIfNeeded();
await expect(firstRow).toBeVisible();
await expect(secondRow).toBeVisible();
firstRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow })
).toHaveCount(3);
secondRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(6);
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow })
).toHaveCount(3);
});
test('can duplicate a row', async ({ dashboardPage, selectors, page }) => {
@@ -274,15 +283,21 @@ test.describe(
.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow)
.scrollIntoViewIfNeeded();
const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row'));
await expect(firstRow).toBeVisible();
firstRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow })
).toHaveCount(3);
const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 1'));
await expect(secondRow).toBeVisible();
secondRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(6);
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow })
).toHaveCount(3);
await saveDashboard(dashboardPage, selectors);
await page.reload();
@@ -293,15 +308,18 @@ test.describe(
.last()
.scrollIntoViewIfNeeded();
await expect(firstRow).toBeVisible();
await expect(secondRow).toBeVisible();
firstRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow })
).toHaveCount(3);
secondRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(6);
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow })
).toHaveCount(3);
});
test('can collapse rows', async ({ dashboardPage, selectors, page }) => {
@@ -324,26 +342,29 @@ test.describe(
.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow)
.scrollIntoViewIfNeeded();
const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row'));
await expect(firstRow).toBeVisible();
firstRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow })
).toHaveCount(3);
const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 1'));
await expect(secondRow).toBeVisible();
secondRow.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(6);
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow })
).toHaveCount(3);
// Collapse rows by clicking on their titles
await dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')).click();
await dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')).click();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeVisible();
await expect(firstRow).toBeVisible();
await expect(secondRow).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(0);
@@ -351,12 +372,9 @@ test.describe(
await saveDashboard(dashboardPage, selectors);
await page.reload();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
).toBeVisible();
await expect(firstRow).toBeVisible();
await expect(secondRow).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(0);
@@ -684,67 +702,75 @@ test.describe(
// Select rows layout
await page.getByLabel('Rows').click();
await dashboardPage
.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 1'))
.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab'))
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 1'))
).toBeVisible();
await dashboardPage
.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 2'))
.scrollIntoViewIfNeeded();
const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab'));
const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 1'));
const thirdRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 2'));
firstRow.scrollIntoViewIfNeeded();
await expect(firstRow).toBeVisible();
// Wait for panels to load
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first()
).toBeVisible();
await dashboardPage
.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 1'))
.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 1'))
).toBeVisible();
await dashboardPage
.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 2'))
.scrollIntoViewIfNeeded();
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow })
).toHaveCount(3);
secondRow.scrollIntoViewIfNeeded();
await expect(secondRow).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 2'))
).toBeVisible();
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow })
).toHaveCount(3);
thirdRow.scrollIntoViewIfNeeded();
await expect(thirdRow).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: thirdRow })
).toHaveCount(3);
// scroll `New row` into view - this is at the bottom of the dashboard body
await dashboardPage
.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow)
.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(9);
await expect(dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow)).toBeVisible();
await saveDashboard(dashboardPage, selectors);
await page.reload();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab'))
).toBeVisible();
await expect(firstRow).toBeVisible();
// Wait for panels to load
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first()
).toBeVisible();
await dashboardPage
.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 1'))
.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 1'))
).toBeVisible();
await dashboardPage
.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 2'))
.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 2'))
).toBeVisible();
// scroll last `New panel` into view - this is at the bottom of the dashboard body
await dashboardPage
.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
.last()
.scrollIntoViewIfNeeded();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
).toHaveCount(9);
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow })
).toHaveCount(3);
secondRow.scrollIntoViewIfNeeded();
await expect(secondRow).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow })
).toHaveCount(3);
thirdRow.scrollIntoViewIfNeeded();
await expect(thirdRow).toBeVisible();
await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: thirdRow })
).toHaveCount(3);
});
test('can group and ungroup new panels into tab with row', async ({ dashboardPage, selectors, page }) => {
@@ -10,6 +10,10 @@ test.use({
},
});
test.use({
viewport: { width: 1920, height: 1080 },
});
const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output';
const DASHBOARD_NAME = 'Test variable output';
@@ -55,7 +59,7 @@ test.describe(
const firstPreviewOption = dashboardPage
.getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption)
.first();
await expect(firstPreviewOption).toBeVisible();
await expect(firstPreviewOption).toBeVisible({ timeout: 15_000 });
const previewOptionText = await firstPreviewOption.textContent();
const previewOption = previewOptionText?.trim() || '';
@@ -12,6 +12,10 @@ test.use({
},
});
test.use({
viewport: { width: 1920, height: 1080 },
});
test.describe(
'Dashboard Panel Layouts',
{
@@ -171,6 +175,10 @@ test.describe(
test('can change max columns in auto grid layout', async ({ dashboardPage, selectors, page }) => {
await importTestDashboard(page, selectors, 'Set max columns');
await await expect(
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first()
).toBeVisible();
await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click();
await expect(
@@ -384,6 +392,11 @@ async function importTestDashboard(page: Page, selectors: E2ESelectorGroups, tit
await page.getByTestId(selectors.components.DataSourcePicker.inputV2).click();
await page.locator('div[data-testid="data-source-card"]').first().click();
await page.getByTestId(selectors.components.ImportDashboardForm.submit).click();
const undockMenuButton = page.locator('[aria-label="Undock menu"]');
const undockMenuVisible = await undockMenuButton.isVisible();
if (undockMenuVisible) {
undockMenuButton.click();
}
}
async function saveDashboard(dashboardPage: DashboardPage, selectors: E2ESelectorGroups) {
@@ -10,6 +10,10 @@ test.use({
const PAGE_UNDER_TEST = 'edediimbjhdz4b/a-tall-dashboard';
test.use({
viewport: { width: 1920, height: 1080 },
});
test.describe(
'Dashboard panels',
{
+47 -37
View File
@@ -2,32 +2,27 @@
"apiVersion": "dashboard.grafana.app/v2beta1",
"kind": "Dashboard",
"metadata": {
"name": "fa400625-2a44-4add-a369-e6c972eb4bd6",
"generation": 1,
"creationTimestamp": "2025-05-27T11:40:22Z",
"labels": {},
"annotations": {}
"name": "addfpww",
"namespace": "default",
"uid": "AvXN09JdxuVNDqODs5IYU2iStlk5ntizuPGIfY1ywZgX",
"resourceVersion": "1",
"generation": 2,
"creationTimestamp": "2025-07-31T13:37:11Z",
"labels": {
"grafana.app/deprecatedInternalID": "6844"
},
"annotations": {
"grafana.app/createdBy": "user:cejvsh18uudxcf",
"grafana.app/updatedBy": "user:cejvsh18uudxcf",
"grafana.app/updatedTimestamp": "2025-07-31T13:37:11Z",
"grafana.app/folder": "",
"grafana.app/saved-from-ui": "Grafana v12.2.0-pre (69d1226c9a)"
}
},
"spec": {
"annotations": [
{
"kind": "AnnotationQuery",
"spec": {
"builtIn": true,
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"query": {
"group": "grafana",
"kind": "DataQuery",
"spec": {},
"version": "v0"
}
}
}
],
"annotations": [],
"cursorSync": "Off",
"description": "",
"editable": true,
"elements": {
"panel-1": {
@@ -42,6 +37,9 @@
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "PD8C576611E62080A"
},
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
@@ -60,7 +58,8 @@
"links": [],
"title": "New panel",
"vizConfig": {
"kind": "timeseries",
"group": "timeseries",
"kind": "VizConfig",
"spec": {
"fieldConfig": {
"defaults": {
@@ -128,9 +127,9 @@
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
}
}
},
"version": "12.2.0-pre"
}
}
},
@@ -146,9 +145,15 @@
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "PD8C576611E62080A"
},
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"spec": {
"scenarioId": "random_walk",
"seriesCount": 1
},
"version": "v0"
},
"refId": "A"
@@ -164,7 +169,8 @@
"links": [],
"title": "New panel",
"vizConfig": {
"kind": "timeseries",
"group": "timeseries",
"kind": "VizConfig",
"spec": {
"fieldConfig": {
"defaults": {
@@ -232,9 +238,9 @@
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
}
}
},
"version": "12.2.0-pre"
}
}
},
@@ -250,6 +256,9 @@
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "PD8C576611E62080A"
},
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
@@ -268,7 +277,8 @@
"links": [],
"title": "New panel",
"vizConfig": {
"kind": "timeseries",
"group": "timeseries",
"kind": "VizConfig",
"spec": {
"fieldConfig": {
"defaults": {
@@ -336,9 +346,9 @@
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
}
}
},
"version": "12.2.0-pre"
}
}
}
@@ -402,7 +412,7 @@
"timezone": "browser",
"to": "now"
},
"title": "Test V2 Dashboard",
"title": "TEST!!!!",
"variables": []
},
"status": {}