diff --git a/tests/ui-testing/playwright-tests/Dashboards/crossLinkMultiStream.spec.js b/tests/ui-testing/playwright-tests/Dashboards/crossLinkMultiStream.spec.js index 5d4f7dff7f..5e704225d5 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/crossLinkMultiStream.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/crossLinkMultiStream.spec.js @@ -336,6 +336,9 @@ test.describe("Cross-Linking Multi-Stream testcases", () => { await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("table"); await pm.chartTypeSelector.selectStream(STREAM_A); + // Add Panel auto-seeds y_axis_1 = count(_timestamp); remove it to keep + // the original single-column table shape (x-axis only). + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); await pm.dashboardPanelActions.addPanelName("CrossLink Single Stream Panel"); await pm.dashboardPanelActions.applyDashboardBtn(); diff --git a/tests/ui-testing/playwright-tests/Dashboards/crossLinking.spec.js b/tests/ui-testing/playwright-tests/Dashboards/crossLinking.spec.js index 00f5c73fef..0cb1b92d26 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/crossLinking.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/crossLinking.spec.js @@ -569,6 +569,9 @@ test.describe("Cross-Linking testcases", () => { await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("table"); await pm.chartTypeSelector.selectStream(STREAM_NAME); + // Remove the auto-seeded histogram(_timestamp) x so kubernetes_container_name + // is the first column — the cross-link drilldown clicks the first cell. + await pm.chartTypeSelector.removeField("x_axis_1", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); await pm.dashboardPanelActions.addPanelName("CrossLink Table Panel"); await pm.dashboardPanelActions.savePanel(); @@ -1414,6 +1417,9 @@ test.describe("Cross-Linking testcases", () => { await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("table"); await pm.chartTypeSelector.selectStream(STREAM_NAME); + // Remove the auto-seeded histogram(_timestamp) x so kubernetes_container_name + // is the first column — the cross-link drilldown clicks the first cell. + await pm.chartTypeSelector.removeField("x_axis_1", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); await pm.dashboardPanelActions.addPanelName("Org CrossLink Table Panel"); await pm.dashboardPanelActions.savePanel(); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-filter.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-filter.spec.js index 4791496e2a..171faf9057 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-filter.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-filter.spec.js @@ -69,8 +69,6 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); - await waitForDateTimeButtonToBeEnabled(page); await pm.dashboardTimeRefresh.setRelative("30", "m"); @@ -198,8 +196,6 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); - await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_name", "filter" @@ -286,8 +282,6 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); - await waitForDateTimeButtonToBeEnabled(page); await pm.dashboardTimeRefresh.setRelative("30", "m"); @@ -392,6 +386,7 @@ test.describe("dashboard filter testcases", () => { "kubernetes_container_name", "x" ); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_image", "y" @@ -470,7 +465,6 @@ test.describe("dashboard filter testcases", () => { await pm.dashboardPanelActions.addPanelName(panelName); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -535,7 +529,6 @@ test.describe("dashboard filter testcases", () => { // Select stream and add Y field await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); @@ -624,7 +617,6 @@ test.describe("dashboard filter testcases", () => { // Select stream and add fields await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_name", "b" @@ -731,6 +723,7 @@ test.describe("dashboard filter testcases", () => { // Select stream and add fields await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_name", "y" @@ -831,8 +824,6 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); - await waitForDateTimeButtonToBeEnabled(page); await pm.dashboardTimeRefresh.setRelative("30", "m"); @@ -950,9 +941,6 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - // Add Y-axis field - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); - await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); @@ -1051,6 +1039,7 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add Y-axis field + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -1147,9 +1136,6 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - // Add Y-axis field - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); - await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); @@ -1245,6 +1231,7 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add Y-axis field + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -1342,6 +1329,7 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add Y-axis field + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -1437,6 +1425,7 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add Y-axis field + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -1532,6 +1521,7 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add Y-axis field + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -1629,6 +1619,7 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add Y-axis field + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -1726,6 +1717,7 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add Y-axis field + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -1823,6 +1815,7 @@ test.describe("dashboard filter testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add Y-axis field + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-join.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-join.spec.js index 482f04785a..a6fc589f19 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-join.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-join.spec.js @@ -235,6 +235,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { await verifyJoinChipIsVisible(page, STREAMS.APP_USERS); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.chartTypeSelector.searchAndAddField("name", "y"); @@ -262,6 +263,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { await verifyJoinChipIsVisible(page, STREAMS.APP_USERS); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.chartTypeSelector.searchAndAddField("name", "y"); @@ -289,6 +291,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { await verifyJoinChipIsVisible(page, STREAMS.APP_USERS); await pm.chartTypeSelector.searchAndAddField("name", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("email", "y"); await pm.chartTypeSelector.searchAndAddField("plan", "y"); @@ -346,6 +349,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { await verifyJoinChipIsVisible(page, STREAMS.SESSIONS); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("device", "y"); await pm.chartTypeSelector.searchAndAddField("browser", "y"); @@ -380,6 +384,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { await verifyJoinChipIsVisible(page, STREAMS.SESSIONS, 1); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.chartTypeSelector.searchAndAddField("status", "y"); @@ -407,6 +412,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { await verifyJoinChipIsVisible(page, STREAMS.SESSIONS); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("device", "y"); await pm.chartTypeSelector.searchAndAddField("browser", "y"); await pm.chartTypeSelector.searchAndAddField("os", "y"); @@ -464,6 +470,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.chartTypeSelector.searchAndAddField("name", "y"); await pm.chartTypeSelector.searchAndAddField("plan", "y"); @@ -491,6 +498,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("plan", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("bytes", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -516,6 +524,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("plan", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("response_time_ms", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -541,6 +550,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("name", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("response_time_ms", "y"); await pm.chartTypeSelector.searchAndAddField("bytes", "y"); @@ -597,6 +607,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("response_time_ms", "y"); await pm.chartTypeSelector.searchAndAddField("name", "y"); @@ -620,6 +631,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("country", "y"); await pm.chartTypeSelector.searchAndAddField("name", "y"); @@ -643,6 +655,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("bytes", "y"); await pm.chartTypeSelector.searchAndAddField("plan", "y"); @@ -666,6 +679,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("name", "y"); await pm.chartTypeSelector.searchAndAddField("email", "y"); @@ -722,6 +736,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.chartTypeSelector.searchAndAddField("name", "y"); await pm.chartTypeSelector.searchAndAddField("plan", "y"); @@ -750,6 +765,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.chartTypeSelector.searchAndAddField("name", "y"); await pm.chartTypeSelector.searchAndAddField("email", "y"); @@ -778,6 +794,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("duration_mins", "y"); await pm.chartTypeSelector.searchAndAddField("device", "y"); @@ -804,6 +821,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -829,6 +847,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("status", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -854,6 +873,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -1002,6 +1022,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { ]); await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -1103,6 +1124,7 @@ test.describe("Dashboard Joins Feature Tests (Consolidated)", () => { // Add fields and apply - should work without any joins await pm.chartTypeSelector.searchAndAddField("request_id", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("path", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-metric-camelcase.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-metric-camelcase.spec.js index f692dde6ad..d64721588c 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-metric-camelcase.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-metric-camelcase.spec.js @@ -84,6 +84,7 @@ test.describe("Dashboard Metric Chart CamelCase Alias", () => { // Builder mode: select stream and add Y-axis field (auto-generated alias y_axis_1) await pm.chartTypeSelector.selectStream(STREAM_NAME); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); // Apply with time range and verify @@ -118,6 +119,8 @@ test.describe("Dashboard Metric Chart CamelCase Alias", () => { `SELECT count(*) AS totalcount FROM "${STREAM_NAME}"` ); + // Remove the default seeded Y (count) before adding ours — metric allows one Y. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); // Add the lowercase alias as Y-axis field (metric chart requires Y-axis to render) await pm.chartTypeSelector.searchAndAddField("totalcount", "y"); testLogger.info("Custom SQL with lowercase alias entered"); @@ -154,6 +157,8 @@ test.describe("Dashboard Metric Chart CamelCase Alias", () => { `SELECT count(*) AS metricValue FROM "${STREAM_NAME}" WHERE kubernetes_container_name = 'nonexistent_container_xyz_99999'` ); + // Remove the default seeded Y (count) before adding ours — metric allows one Y. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); // Add Y-axis field (metric chart requires Y-axis to render) await pm.chartTypeSelector.searchAndAddField("metricValue", "y"); testLogger.info("Custom SQL with non-existent filter entered"); @@ -214,6 +219,8 @@ test.describe("Dashboard Metric Chart CamelCase Alias", () => { `SELECT count(*) AS countRecords FROM "${STREAM_NAME}"` ); + // Remove the default seeded Y (count) before adding ours — metric allows one Y. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); // Add the camelCase alias as Y-axis field (metric chart requires Y-axis to render) await pm.chartTypeSelector.searchAndAddField("countRecords", "y"); testLogger.info("Custom SQL with camelCase alias entered"); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-multi-sql.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-multi-sql.spec.js index 7aa6f565b3..d3a1c222c3 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-multi-sql.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-multi-sql.spec.js @@ -47,6 +47,9 @@ async function buildPanel( if (xField) { await pm.chartTypeSelector.searchAndAddField(xField, "x"); } + // Add Panel now auto-seeds y_axis_1 = count(_timestamp). Remove it before + // adding this tab's own y-field. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField(yField, "y"); if (breakdownField) { const breakdownTarget = chartType === "table" ? "p" : "b"; @@ -66,9 +69,13 @@ async function addAndConfigureSecondQuery(pm, { yField = "kubernetes_namespace_n await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + // A new tab auto-seeds x_axis_1 = histogram(_timestamp) and y_axis_1 = count(_timestamp). + // Always remove the seeded field, then add this tab's own x/y. if (xField) { + await pm.chartTypeSelector.removeField("x_axis_1", "x"); await pm.chartTypeSelector.searchAndAddField(xField, "x"); } + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField(yField, "y"); } @@ -221,13 +228,13 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "y"); await msql.addQueryTab(2); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); // Switching tabs must surface that query's own Y-axis field. @@ -459,9 +466,8 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "y"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); - await msql.switchToQueryTab(0); await msql.configLegend(0).waitFor({ state: "visible", timeout: 10000 }); await msql.configLegend(0).clear(); @@ -743,8 +749,12 @@ test.describe("Multi-SQL Query Support", () => { // Q1: valid bar chart with y-field configured await buildPanel(page, pm, dashboardName, { chartType: "bar" }); - // Add Q2 and intentionally leave it empty (no stream, no fields) + // Add Q2 and intentionally make it invalid. New tabs now auto-seed + // histogram x + count y, so strip both fields to leave Q2 unconfigured — + // an empty query is what surfaces the execution error under test. await msql.addQueryTab(1); + await pm.chartTypeSelector.removeField("x_axis_1", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); // Switch back to Q1 — error from Q2 should surface regardless of active tab await msql.switchToQueryTab(0); @@ -998,8 +1008,9 @@ test.describe("Multi-SQL Query Support", () => { // NOTE: When addPanel() is called, the panel editor auto-populates // histogram(_timestamp) into Q1's x-axis. So buildPanel() must NOT pass - // xField — Q1 already has the histogram x-field. New query tabs (Q2+) - // always start empty, so addField calls on those work normally. + // xField — Q1 already has the histogram x-field. New query tabs (Q2+) now + // also auto-seed x_axis_1 = histogram(_timestamp) + y_axis_1 = count(_timestamp), + // so tests remove the seeded field before adding a different x/y of their own. test( "no warning with a single query using histogram x-alias", @@ -1037,11 +1048,11 @@ test.describe("Multi-SQL Query Support", () => { yField: "kubernetes_container_hash", }); - // Add Q2 also with _timestamp (histogram) — Q2 starts empty so +X works + // Q2 keeps its auto-seeded histogram(_timestamp) x await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1071,11 +1082,15 @@ test.describe("Multi-SQL Query Support", () => { await removeFirstXField(page); // removes auto _timestamp await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "x"); - // Add Q2 also with non-histogram x — Q2 starts empty so +X works + // Add Q2 with non-histogram x (replaces the seeded histogram x) await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + // New tab seeds histogram(_timestamp) x; replace it with this tab's + // non-histogram x-field. + await pm.chartTypeSelector.removeField("x_axis_1", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1104,11 +1119,15 @@ test.describe("Multi-SQL Query Support", () => { yField: "kubernetes_container_hash", }); - // Q2: non-histogram x (kubernetes_host) — Q2 starts empty so +X works + // Q2: non-histogram x (kubernetes_host), replacing the seeded histogram x await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + // New tab seeds histogram(_timestamp) x; replace it with this tab's + // non-histogram x-field. + await pm.chartTypeSelector.removeField("x_axis_1", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1139,11 +1158,11 @@ test.describe("Multi-SQL Query Support", () => { await removeFirstXField(page); // removes auto _timestamp await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "x"); - // Q2: histogram(_timestamp) — Q2 starts empty so +X works + // Q2 keeps its auto-seeded histogram(_timestamp) x await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1174,7 +1193,11 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + // New tab seeds histogram(_timestamp) x; replace it with this tab's + // non-histogram x-field. + await pm.chartTypeSelector.removeField("x_axis_1", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1211,10 +1234,12 @@ test.describe("Multi-SQL Query Support", () => { yField: "kubernetes_container_hash", }); - // Q2 with ONLY a y-field — no x-field added + // Q2 with ONLY a y-field — remove both auto-seeded fields, add only y await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("x_axis_1", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1247,7 +1272,11 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + // New tab seeds histogram(_timestamp) x; replace it with this tab's + // non-histogram x-field. + await pm.chartTypeSelector.removeField("x_axis_1", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1284,7 +1313,11 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + // New tab seeds histogram(_timestamp) x; replace it with this tab's + // non-histogram x-field. + await pm.chartTypeSelector.removeField("x_axis_1", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1363,8 +1396,8 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - // Q2 starts with empty x-axis; add _timestamp so the bar chart renders - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + // Q2 keeps its auto-seeded histogram(_timestamp) x; swap the seeded y. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1402,7 +1435,7 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1483,7 +1516,7 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1525,8 +1558,8 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - // Q2 starts with empty x-axis; add _timestamp so save validates cleanly - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + // Q2 keeps its auto-seeded histogram(_timestamp) x; swap the seeded y. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1592,7 +1625,7 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1681,8 +1714,8 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream(streamB); - // Q2 needs x-field so the bar chart renders and the panel saves cleanly - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + // Q2 keeps its auto-seeded histogram(_timestamp) x; swap the seeded y. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1746,8 +1779,8 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream(streamB); - // Q2 needs x-field so the bar chart renders and the panel saves cleanly - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + // Q2 keeps its auto-seeded histogram(_timestamp) x; swap the seeded y. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1806,8 +1839,8 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream(streamB); - // Q2 needs x-field so the bar chart renders and the panel saves cleanly - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + // Q2 keeps its auto-seeded histogram(_timestamp) x; swap the seeded y. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -1858,8 +1891,8 @@ test.describe("Multi-SQL Query Support", () => { await msql.addQueryTab(1); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream(streamB); - // Q2 needs x-field so the bar chart renders and the panel saves cleanly - await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + // Q2 keeps its auto-seeded histogram(_timestamp) x; swap the seeded y. + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-multi-y-axis.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-multi-y-axis.spec.js index 89182a5748..189c72c77c 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-multi-y-axis.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-multi-y-axis.spec.js @@ -48,6 +48,7 @@ test.describe("dashboard multi y axis testcases", () => { await pm.chartTypeSelector.selectChartType("stacked"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" @@ -111,6 +112,7 @@ test.describe("dashboard multi y axis testcases", () => { await pm.chartTypeSelector.selectChartType("stacked"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_namespace_name", "y" diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-mustache-variables.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-mustache-variables.spec.js index b2566fb8a0..0d88d0947f 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-mustache-variables.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-mustache-variables.spec.js @@ -515,6 +515,7 @@ test.describe( await pm.chartTypeSelector.selectChartType("table"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_hash", "y" diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-nested-functions.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-nested-functions.spec.js index 06d71ca834..95bd4f9ad1 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-nested-functions.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-nested-functions.spec.js @@ -199,6 +199,7 @@ test.describe("Dashboard Functions", () => { await selectStreamAndChartType(page, pm, STREAM_NAME, "table"); await pm.chartTypeSelector.searchAndAddField("user_name", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("score", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -221,6 +222,7 @@ test.describe("Dashboard Functions", () => { await selectStreamAndChartType(page, pm, STREAM_NAME, "table"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("user_name", "y"); // UI shows "Distinct" for COUNT-DISTINCT function; label displays as "count" @@ -242,6 +244,7 @@ test.describe("Dashboard Functions", () => { await selectStreamAndChartType(page, pm, STREAM_NAME, "table"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("score", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "avg"); @@ -262,6 +265,7 @@ test.describe("Dashboard Functions", () => { await selectStreamAndChartType(page, pm, STREAM_NAME, "table"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("score", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "sum"); @@ -314,6 +318,7 @@ test.describe("Dashboard Functions", () => { await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); // Add first Y-axis with COUNT + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("user_name", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -345,6 +350,7 @@ test.describe("Dashboard Functions", () => { await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); // Add Y-axis with MIN + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("score", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "min"); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-pie-donut.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-pie-donut.spec.js index eb9549f043..7b7468d4aa 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-pie-donut.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-pie-donut.spec.js @@ -155,6 +155,7 @@ test.describe("Pie & Donut Chart — E2E Tests (SQL Builder / Logs Stream)", () await pm.chartTypeSelector.selectChartType("pie"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.dashboardPanelActions.addPanelName("Pie Aggregations"); @@ -214,6 +215,7 @@ test.describe("Pie & Donut Chart — E2E Tests (SQL Builder / Logs Stream)", () await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_hash", "y"); await pm.dashboardPanelActions.addPanelName("Line To Pie"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -318,6 +320,7 @@ test.describe("Pie & Donut Chart — E2E Tests (SQL Builder / Logs Stream)", () await pm.chartTypeSelector.selectStream("e2e_automate"); // Add Y field, then switch to raw and enter custom SQL + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_hash", "y"); // Open Y-axis function popup and switch to raw tab @@ -375,6 +378,7 @@ test.describe("Pie & Donut Chart — E2E Tests (SQL Builder / Logs Stream)", () await pm.chartTypeSelector.selectChartType("pie"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_hash", "y"); // Configure Y-axis with raw count query @@ -408,6 +412,7 @@ test.describe("Pie & Donut Chart — E2E Tests (SQL Builder / Logs Stream)", () await pm.chartTypeSelector.selectStream("e2e_automate"); // Y-axis: kubernetes_container_name with count aggregation (cross-field) + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.chartTypeSelector.configureYAxisRawQuery( "y_axis_1", diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-pivot-table.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-pivot-table.spec.js index 40b08b7a95..aafcdc88b9 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-pivot-table.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-pivot-table.spec.js @@ -140,7 +140,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); // Add Y field (Value field) with count aggregation - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); // Apply and wait for render @@ -203,7 +202,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { "kubernetes_container_name", "x" ); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -273,7 +271,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { "kubernetes_container_name", "x" ); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -357,7 +354,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { "kubernetes_container_name", "x" ); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); // Check for "First Column" label (non-pivot mode) @@ -419,7 +415,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { "x" ); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); const streamPromise = waitForStreamComplete(page); @@ -533,7 +528,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { "x" ); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -679,7 +673,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { "x" ); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -767,7 +760,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { "x" ); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -841,7 +833,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { "x" ); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -928,7 +919,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { // Add only Pivot (breakdown) + Y fields (no X) await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -987,6 +977,9 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { ); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); + // Remove the default seeded Y field (count) so this truly tests the no-Y case + await pm.chartTypeSelector.removeField("y_axis_1", "y"); + await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); @@ -1040,7 +1033,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); // Multiple Y fields to create hierarchy - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); await pm.chartTypeSelector.searchAndAddField("log", "y"); @@ -1098,7 +1090,6 @@ test.describe("Dashboard Table Chart - Pivot Table Feature", () => { await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); // Y field - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); const streamPromise = waitForStreamComplete(page); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-raw-query.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-raw-query.spec.js index 1850aa06b8..59fcb957e8 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-raw-query.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-raw-query.spec.js @@ -46,6 +46,7 @@ test.describe("Dashboard Raw Query testcases", () => { panelName = pm.dashboardPanelActions.generateUniquePanelName("raw-query-test"); await pm.dashboardPanelActions.addPanelName(panelName); await pm.chartTypeSelector.selectStream(STREAM_NAME); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); // Open Y-axis popup and verify tabs @@ -79,6 +80,7 @@ test.describe("Dashboard Raw Query testcases", () => { panelName = pm.dashboardPanelActions.generateUniquePanelName("raw-query-test"); await pm.dashboardPanelActions.addPanelName(panelName); await pm.chartTypeSelector.selectStream(STREAM_NAME); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); // Open popup, switch to Raw tab, enter query @@ -117,6 +119,7 @@ test.describe("Dashboard Raw Query testcases", () => { panelName = pm.dashboardPanelActions.generateUniquePanelName("raw-query-test"); await pm.dashboardPanelActions.addPanelName(panelName); await pm.chartTypeSelector.selectStream(STREAM_NAME); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); // Configure raw query on Y-axis @@ -181,6 +184,7 @@ test.describe("Dashboard Raw Query testcases", () => { panelName = pm.dashboardPanelActions.generateUniquePanelName("raw-query-test"); await pm.dashboardPanelActions.addPanelName(panelName); await pm.chartTypeSelector.selectStream(STREAM_NAME); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.chartTypeSelector.configureYAxisRawQuery(Y_AXIS_ALIAS, RAW_QUERY); @@ -241,6 +245,7 @@ test.describe("Dashboard Raw Query testcases", () => { panelName = pm.dashboardPanelActions.generateUniquePanelName("raw-query-test"); await pm.dashboardPanelActions.addPanelName(panelName); await pm.chartTypeSelector.selectStream(STREAM_NAME); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); // Open popup @@ -297,6 +302,7 @@ test.describe("Dashboard Raw Query testcases", () => { panelName = pm.dashboardPanelActions.generateUniquePanelName("raw-query-test"); await pm.dashboardPanelActions.addPanelName(panelName); await pm.chartTypeSelector.selectStream(STREAM_NAME); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); // Configure raw query diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-series-color-multiwindow.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-series-color-multiwindow.spec.js index 220085c169..90179ea36b 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-series-color-multiwindow.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-series-color-multiwindow.spec.js @@ -86,6 +86,7 @@ test.describe("Dashboard series color with multi-window (time shift)", () => { await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("area"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); // Step 3: Apply the query to render the chart initially @@ -223,6 +224,7 @@ test.describe("Dashboard series color with multi-window (time shift)", () => { await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); // Step 2: Apply initial query diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-chart.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-chart.spec.js index 01a96d32ad..679f0ec5b3 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-chart.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-chart.spec.js @@ -167,6 +167,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_hash", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); @@ -201,7 +202,6 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); const streamPromise = waitForStreamComplete(page); @@ -293,6 +293,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); // Enable VRL function toggle and add a VRL function that creates a new field @@ -368,6 +369,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -410,6 +412,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -448,6 +451,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -492,6 +496,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -530,6 +535,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_hash", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -573,6 +579,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_hash", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "filter"); @@ -646,6 +653,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_hash", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -741,6 +749,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -797,6 +806,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { // Add X field — shows in "First Column" area await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); // Add Y field — shows in "Other Columns" area + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); // Verify layout labels @@ -837,6 +847,7 @@ test.describe("Dashboard Table Chart - Core Features", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); // Test with "sum" aggregation diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-copy-cell.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-copy-cell.spec.js index 8c0725107e..26909a5959 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-copy-cell.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-table-copy-cell.spec.js @@ -65,6 +65,7 @@ test.describe("Dashboard Table Chart - Copy Cell Timestamp Formatting", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -103,6 +104,7 @@ test.describe("Dashboard Table Chart - Copy Cell Timestamp Formatting", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -153,6 +155,7 @@ test.describe("Dashboard Table Chart - Copy Cell Timestamp Formatting", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -201,6 +204,7 @@ test.describe("Dashboard Table Chart - Copy Cell Timestamp Formatting", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); await pm.chartTypeSelector.searchAndAddField("_timestamp", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("code", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); @@ -256,7 +260,6 @@ test.describe("Dashboard Table Chart - Copy Cell Timestamp Formatting", () => { // X: row field, P: pivot/breakdown field, Y: value field await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); const streamPromise = waitForStreamComplete(page); @@ -293,7 +296,6 @@ test.describe("Dashboard Table Chart - Copy Cell Timestamp Formatting", () => { await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); const streamPromise = waitForStreamComplete(page); @@ -339,7 +341,6 @@ test.describe("Dashboard Table Chart - Copy Cell Timestamp Formatting", () => { await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "x"); await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "p"); - await pm.chartTypeSelector.searchAndAddField("_timestamp", "y"); await pm.chartTypeSelector.configureYAxisFunction("y_axis_1", "count"); const streamPromise = waitForStreamComplete(page); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-transpose.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-transpose.spec.js index fbab65f22d..4d597330da 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-transpose.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-transpose.spec.js @@ -43,6 +43,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectChartType("table"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_name", "y" @@ -84,6 +85,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectChartType("table"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_name", "y" @@ -237,6 +239,7 @@ test.describe("dashboard UI testcases", () => { "kubernetes_container_name", "x" ); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); // Open the configuration panel and enable dynamic columns @@ -288,6 +291,7 @@ test.describe("dashboard UI testcases", () => { "kubernetes_container_name", "x" ); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); // Open the configuration panel and enable both the Transpose and Dynamic Column toggle buttons diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-creation-scopes.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-creation-scopes.spec.js index d6ee384328..4eae5ef644 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-creation-scopes.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-creation-scopes.spec.js @@ -95,6 +95,7 @@ test.describe("Dashboard Variables - Creation & Scope Restrictions", { tag: ['@d await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); // Add X and Y axis fields (required for saving panel) + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -347,6 +348,7 @@ test.describe("Dashboard Variables - Creation & Scope Restrictions", { tag: ['@d await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); // Add X and Y axis fields (required for saving panel) + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -457,6 +459,7 @@ test.describe("Dashboard Variables - Creation & Scope Restrictions", { tag: ['@d await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -465,6 +468,7 @@ test.describe("Dashboard Variables - Creation & Scope Restrictions", { tag: ['@d await pm.dashboardCreate.addPanelToExistingDashboard(); await pm.chartTypeSelector.selectChartType("bar"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel2"); await pm.dashboardPanelActions.savePanel(); @@ -637,6 +641,7 @@ test.describe("Dashboard Variables - Creation & Scope Restrictions", { tag: ['@d await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -644,6 +649,7 @@ test.describe("Dashboard Variables - Creation & Scope Restrictions", { tag: ['@d await pm.dashboardCreate.addPanelToExistingDashboard(); await pm.chartTypeSelector.selectChartType("bar"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel2"); await pm.dashboardPanelActions.savePanel(); @@ -802,6 +808,7 @@ test.describe("Dashboard Variables - Creation & Scope Restrictions", { tag: ['@d // Save panel await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -882,6 +889,7 @@ test.describe("Dashboard Variables - Creation & Scope Restrictions", { tag: ['@d // Save the panel to avoid the discard confirmation dialog await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-dependency.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-dependency.spec.js index db30e89ccc..605cc56a9f 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-dependency.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-dependency.spec.js @@ -991,6 +991,7 @@ test.describe("Dashboard Variables - Dependency Loading", { tag: ['@dashboards', await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "filter"); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-panel-level.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-panel-level.spec.js index bb1b70c030..f27688cf92 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-panel-level.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-panel-level.spec.js @@ -44,6 +44,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -85,6 +86,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanelToExistingDashboard(); await pm.chartTypeSelector.selectChartType("bar"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel2"); await pm.dashboardPanelActions.savePanel(); @@ -127,6 +129,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash } await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName(`DummyPanel${i + 1}`); await pm.dashboardPanelActions.savePanel(); @@ -138,6 +141,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanelToExistingDashboard(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -283,6 +287,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -344,6 +349,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -356,6 +362,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanelToExistingDashboard(); await pm.chartTypeSelector.selectChartType("bar"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel2"); await pm.dashboardPanelActions.savePanel(); @@ -468,6 +475,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -546,6 +554,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -651,6 +660,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -663,6 +673,7 @@ test.describe("Dashboard Variables - Panel Level", { tag: ['@dashboards', '@dash await pm.dashboardCreate.addPanelToExistingDashboard(); await pm.chartTypeSelector.selectChartType("bar"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel2"); await pm.dashboardPanelActions.savePanel(); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-refresh.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-refresh.spec.js index 24e52a629b..863e03ec53 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-refresh.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-refresh.spec.js @@ -140,6 +140,7 @@ test.describe("Dashboard Variables - Refresh Indicators & Panel Reload", { tag: await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "filter"); // Add filter using varB @@ -219,6 +220,7 @@ test.describe("Dashboard Variables - Refresh Indicators & Panel Reload", { tag: await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); @@ -230,6 +232,7 @@ test.describe("Dashboard Variables - Refresh Indicators & Panel Reload", { tag: await pm.dashboardCreate.addPanelToExistingDashboard(); await pm.chartTypeSelector.selectChartType("bar"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel2"); await pm.dashboardPanelActions.savePanel(); @@ -294,6 +297,7 @@ test.describe("Dashboard Variables - Refresh Indicators & Panel Reload", { tag: await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "filter"); // Add filter using the variable @@ -320,6 +324,7 @@ test.describe("Dashboard Variables - Refresh Indicators & Panel Reload", { tag: await pm.dashboardCreate.addPanelToExistingDashboard(); await pm.chartTypeSelector.selectChartType("bar"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel2"); await pm.dashboardPanelActions.savePanel(); @@ -399,6 +404,7 @@ test.describe("Dashboard Variables - Refresh Indicators & Panel Reload", { tag: await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "filter"); // Add filter using the variable @@ -597,6 +603,7 @@ test.describe("Dashboard Variables - Refresh Indicators & Panel Reload", { tag: await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "filter"); // Add filter using the variable @@ -674,6 +681,7 @@ test.describe("Dashboard Variables - Refresh Indicators & Panel Reload", { tag: await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "filter"); // Add filter using the variable @@ -699,6 +707,7 @@ test.describe("Dashboard Variables - Refresh Indicators & Panel Reload", { tag: await pm.dashboardCreate.addPanelToExistingDashboard(); await pm.chartTypeSelector.selectChartType("bar"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "filter"); // Add filter using the variable diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-url-sync.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-url-sync.spec.js index 4225d84a68..0a24b99d28 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-url-sync.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-variables-url-sync.spec.js @@ -158,6 +158,7 @@ test.describe("Dashboard Variables - URL Sync & Drilldown", { tag: ['@dashboards await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType("line"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); @@ -527,6 +528,7 @@ test.describe("Dashboard Variables - URL Sync & Drilldown", { tag: ['@dashboards // This would typically be in panel settings // For now, verify the concept + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_pod_name", "y"); await pm.dashboardPanelActions.addPanelName("Panel1"); await pm.dashboardPanelActions.savePanel(); diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard.spec.js index f4c5e0bcbf..25dd00c494 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard.spec.js @@ -106,6 +106,7 @@ test.describe("dashboard UI testcases", () => { // Select stream and breakdown fields await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_hash", "y" @@ -149,6 +150,7 @@ test.describe("dashboard UI testcases", () => { // Configure the chart await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_hash", "y" @@ -231,6 +233,7 @@ test.describe("dashboard UI testcases", () => { // Select stream and add fields to chart await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_hash", "y" @@ -273,6 +276,7 @@ test.describe("dashboard UI testcases", () => { // Select chart type and stream await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_labels_app_kubernetes_io_component", "b" @@ -332,6 +336,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectChartType("bar"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_annotations_kubernetes_io_psp", "y" @@ -398,6 +403,7 @@ test.describe("dashboard UI testcases", () => { // Select a stream await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_annotations_kubernetes_io_psp", "y" @@ -450,6 +456,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_annotations_kubernetes_io_psp", "y" @@ -518,6 +525,7 @@ test.describe("dashboard UI testcases", () => { // Add a panel name and save again await pm.dashboardPanelActions.addPanelName(panelName); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_annotations_kubernetes_io_psp", "y" @@ -550,6 +558,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectChartType("area"); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); // Add fields to chart await pm.chartTypeSelector.searchAndAddField( @@ -621,6 +630,7 @@ test.describe("dashboard UI testcases", () => { await pm.dashboardPanelActions.addPanelName(panelName); await pm.chartTypeSelector.selectChartType("area"); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); // Add a non-required field (B-axis), but skip Y-axis await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "b"); @@ -661,6 +671,7 @@ test.describe("dashboard UI testcases", () => { await pm.dashboardCreate.addPanel(); await pm.dashboardPanelActions.addPanelName(panelName); await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_annotations_kubernetes_io_psp", "y" @@ -699,8 +710,11 @@ test.describe("dashboard UI testcases", () => { await pm.dashboardCreate.addPanel(); await pm.dashboardPanelActions.addPanelName(panelName); - // Configure table chart with custom SQL using camelCase aliases + // Configure table chart with custom SQL using camelCase aliases. + // Remove both auto-seeded builder fields — this test supplies its own + // xAxis1/yAxis1 columns, and a stale y_axis_1 would add an empty column. await pm.chartTypeSelector.removeField("x_axis_1", "x"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.selectChartType("table"); await pm.chartTypeSelector.setCustomSQL( diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard2.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard2.spec.js index 77f41b19f1..484e4737e7 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard2.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard2.spec.js @@ -41,6 +41,7 @@ test.describe("dashboard UI testcases", () => { // Select stream and fields await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_annotations_kubernetes_io_psp", "y" @@ -89,6 +90,7 @@ test.describe("dashboard UI testcases", () => { // Select stream and fields await pm.chartTypeSelector.selectStream("e2e_automate"); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_image", "y" @@ -141,6 +143,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add fields to the chart + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_annotations_kubernetes_io_psp", "y" @@ -207,6 +210,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add fields to the chart + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_annotations_kubernetes_io_psp", "y" @@ -252,6 +256,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add fields to the chart + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_name", "y" @@ -294,6 +299,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add fields to the chart + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_hash", "y" @@ -346,6 +352,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add fields to the chart + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_image", "b" @@ -380,6 +387,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add fields to the chart + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_container_hash", "y" @@ -423,6 +431,7 @@ test.describe("dashboard UI testcases", () => { await pm.chartTypeSelector.selectStream("e2e_automate"); // Add fields to the chart + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField( "kubernetes_annotations_kubectl_kubernetes_io_default_container", "y" diff --git a/tests/ui-testing/playwright-tests/Dashboards/maxquery.spec.js b/tests/ui-testing/playwright-tests/Dashboards/maxquery.spec.js index 6eaa52fefd..0a91941649 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/maxquery.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/maxquery.spec.js @@ -41,6 +41,7 @@ async function buildPanelWithWideRange(page, pm, panelName, chartType = "area") await pm.chartTypeSelector.selectChartType(chartType); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream(MAX_QUERY_STREAM); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_labels_name", "b"); @@ -203,6 +204,7 @@ test.describe("Dashboard Max Query Range", () => { await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream(MAX_QUERY_STREAM); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "y"); await pm.dashboardPanelActions.applyDashboardBtn(); @@ -252,6 +254,7 @@ test.describe("Dashboard Max Query Range", () => { await pm.chartTypeSelector.selectChartType(chartType); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream(MAX_QUERY_STREAM); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "y"); await waitForDateTimeButtonToBeEnabled(page); @@ -392,6 +395,7 @@ test.describe("Dashboard Max Query Range", () => { // First query tab await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream(MAX_QUERY_STREAM); + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "y"); // Second query tab diff --git a/tests/ui-testing/playwright-tests/Dashboards/utils/configPanelHelpers.js b/tests/ui-testing/playwright-tests/Dashboards/utils/configPanelHelpers.js index de9d8295ba..297f11d5b0 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/utils/configPanelHelpers.js +++ b/tests/ui-testing/playwright-tests/Dashboards/utils/configPanelHelpers.js @@ -69,6 +69,8 @@ async function buildPanel(page, pm, dashboardName, { await pm.chartTypeSelector.selectChartType(chartType); await pm.chartTypeSelector.selectStreamType("logs"); await pm.chartTypeSelector.selectStream("e2e_automate"); + // remove the auto-seeded default y-axis before adding this panel's measure + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField(yField, "y"); if (breakdownField) { await pm.chartTypeSelector.searchAndAddField(breakdownField, "b"); diff --git a/tests/ui-testing/playwright-tests/Dashboards/utils/dashCreation.js b/tests/ui-testing/playwright-tests/Dashboards/utils/dashCreation.js index 1ea4ea7fbe..366f5de819 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/utils/dashCreation.js +++ b/tests/ui-testing/playwright-tests/Dashboards/utils/dashCreation.js @@ -299,6 +299,8 @@ export async function addSimplePanel(pm, panelName, options = {}) { await pm.dashboardCreate.addPanel(); await pm.chartTypeSelector.selectChartType(chartType); await pm.chartTypeSelector.selectStream(streamName); + // remove the auto-seeded default y-axis before adding this panel's measure + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField(yAxisField, "y"); // Add filter fields if specified diff --git a/tests/ui-testing/playwright-tests/Dashboards/utils/panelTimeSetup.js b/tests/ui-testing/playwright-tests/Dashboards/utils/panelTimeSetup.js index 20517764b2..e346b8b11d 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/utils/panelTimeSetup.js +++ b/tests/ui-testing/playwright-tests/Dashboards/utils/panelTimeSetup.js @@ -59,6 +59,8 @@ export async function startPanelCreation(page, pm, config) { await pm.chartTypeSelector.selectStream(stream); // Add fields for proper chart configuration + // remove the auto-seeded default y-axis before adding this panel's measure + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "b"); @@ -179,6 +181,8 @@ export async function addPanelWithPanelTime(page, pm, config) { await pm.chartTypeSelector.selectStream(stream); // Add fields to Y and breakdown axes for proper chart configuration + // remove the auto-seeded default y-axis before adding this panel's measure + await pm.chartTypeSelector.removeField("y_axis_1", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_container_name", "y"); await pm.chartTypeSelector.searchAndAddField("kubernetes_namespace_name", "b"); diff --git a/web/src/components/dashboards/PanelEditor/PanelEditor.vue b/web/src/components/dashboards/PanelEditor/PanelEditor.vue index 7605b05fc6..4c1d7be30b 100644 --- a/web/src/components/dashboards/PanelEditor/PanelEditor.vue +++ b/web/src/components/dashboards/PanelEditor/PanelEditor.vue @@ -1140,6 +1140,9 @@ watch( () => [ dashboardPanelData.data.queries[dashboardPanelData.layout.currentQueryIndex] ?.fields?.stream, + // Rebuild the auto query once the stream schema loads (makeAutoSQLQuery bails + // out while groupedFields is empty). + dashboardPanelData.meta?.streamFields?.groupedFields?.length, dashboardPanelData.data.queries[dashboardPanelData.layout.currentQueryIndex] ?.fields?.x, dashboardPanelData.data.queries[dashboardPanelData.layout.currentQueryIndex] diff --git a/web/src/components/dashboards/addPanel/DashboardQueryEditor.vue b/web/src/components/dashboards/addPanel/DashboardQueryEditor.vue index 7a416f0be5..12e83d7864 100644 --- a/web/src/components/dashboards/addPanel/DashboardQueryEditor.vue +++ b/web/src/components/dashboards/addPanel/DashboardQueryEditor.vue @@ -520,24 +520,11 @@ export default defineComponent({ }); const addTab = () => { + // addQuery() seeds the new query's default builder fields (and PromQL + // sample query) synchronously, so the tab is ready the moment it activates. addQuery(); dashboardPanelData.layout.currentQueryIndex = dashboardPanelData.data.queries.length - 1; - // For metrics page: when switching from custom to builder in PromQL, set sample query - if ( - dashboardPanelData.data.queryType === "promql" && - dashboardPanelData.data.queries[ - dashboardPanelData.layout.currentQueryIndex - ].fields.stream - ) { - const streamName = - dashboardPanelData.data.queries[ - dashboardPanelData.layout.currentQueryIndex - ].fields.stream; - dashboardPanelData.data.queries[ - dashboardPanelData.layout.currentQueryIndex - ].query = `${streamName}{}`; - } }; const updatePromQLQuery = async (value, event) => { diff --git a/web/src/components/dashboards/addPanel/PanelFieldList.vue b/web/src/components/dashboards/addPanel/PanelFieldList.vue index 16989beb6d..c16ac08d9c 100644 --- a/web/src/components/dashboards/addPanel/PanelFieldList.vue +++ b/web/src/components/dashboards/addPanel/PanelFieldList.vue @@ -680,7 +680,19 @@ watch( .fields.stream_type === dashboardPanelData.meta.stream.streamResultsType ) { try { - if (promqlMode.value && dashboardPanelDataPageKey === "metrics") { + // On stream change in PromQL mode, reset the query to `${stream}{}`. + // Metrics: custom + builder. Add Panel: PromQL custom only (builder + // regenerates via DashboardQueryBuilder; SQL is excluded — promql-only block). + const promqlQuery = + dashboardPanelData.data.queries[ + dashboardPanelData.layout.currentQueryIndex + ]; + const shouldResetPromqlQuery = + promqlMode.value && + (dashboardPanelDataPageKey === "metrics" || + (dashboardPanelDataPageKey === "dashboard" && + promqlQuery?.customQuery)); + if (shouldResetPromqlQuery) { let parsedQuery = null; try { parsedQuery = parsePromQlQuery( diff --git a/web/src/components/dashboards/addPanel/QueryTypeSelector.spec.ts b/web/src/components/dashboards/addPanel/QueryTypeSelector.spec.ts index e011771252..912fac18df 100644 --- a/web/src/components/dashboards/addPanel/QueryTypeSelector.spec.ts +++ b/web/src/components/dashboards/addPanel/QueryTypeSelector.spec.ts @@ -86,6 +86,15 @@ vi.mock("../../../composables/dashboard/useDashboardPanel", () => ({ }), })); +// Mock useDefaultPanelFields — the selector only needs applyDefaultPanelFields to +// be callable on the Builder toggle; its seeding internals are covered by its own spec. +const mockApplyDefaultPanelFields = vi.fn(); +vi.mock("@/composables/dashboard/useDefaultPanelFields", () => ({ + default: () => ({ + applyDefaultPanelFields: mockApplyDefaultPanelFields, + }), +})); + // Mock ConfirmDialog component const ConfirmDialogStub = { template: ` diff --git a/web/src/components/dashboards/addPanel/QueryTypeSelector.vue b/web/src/components/dashboards/addPanel/QueryTypeSelector.vue index 7aab3e0458..0431dd94f7 100644 --- a/web/src/components/dashboards/addPanel/QueryTypeSelector.vue +++ b/web/src/components/dashboards/addPanel/QueryTypeSelector.vue @@ -92,6 +92,7 @@ import { import { useI18n } from "vue-i18n"; import { useRouter } from "vue-router"; import useDashboardPanelData from "../../../composables/dashboard/useDashboardPanel"; +import useDefaultPanelFields from "@/composables/dashboard/useDefaultPanelFields"; import ConfirmDialog from "../../ConfirmDialog.vue"; import { useStore } from "vuex"; import OToggleGroup from "@/lib/core/ToggleGroup/OToggleGroup.vue"; @@ -121,6 +122,12 @@ export default defineComponent({ removeXYFilters, updateXYFieldsForCustomQueryMode, } = useDashboardPanelData(dashboardPanelDataPageKey); + const { applyDefaultPanelFields } = useDefaultPanelFields( + dashboardPanelDataPageKey, + ); + // Pages that re-seed default builder fields on the in-page Builder toggle. + // (Entering a builder surface parses on mount, not via this handler.) + const SEED_ON_TOGGLE_PAGES = ["dashboard", "metrics", "build", "logs"]; const confirmQueryModeChangeDialog = ref(false); const confirmDialogMessage = ref( "Are you sure you want to change the query mode? The data saved for X-Axis, Y-Axis and Filters will be wiped off.", @@ -267,7 +274,9 @@ export default defineComponent({ "Are you sure you want to change the query mode? The data saved for X-Axis, Y-Axis and Filters will be wiped off."; } - dashboardPanelData.data.queries[0].query != "" + dashboardPanelData.data.queries[ + dashboardPanelData.layout.currentQueryIndex + ].query != "" ? (confirmQueryModeChangeDialog.value = true) : changeToggle(); } @@ -279,9 +288,6 @@ export default defineComponent({ popupSelectedButtonType.value === "promql" || popupSelectedButtonType.value === "sql"; - const isSwitchingToBuilder = - !isQueryTypeChange && popupSelectedButtonType.value === "builder"; - if (isQueryTypeChange) { selectedButtonQueryType.value = popupSelectedButtonType.value; } else { @@ -304,22 +310,16 @@ export default defineComponent({ } - // For metrics page: when switching from custom to builder in PromQL, set sample query - if ( - dashboardPanelDataPageKey === "metrics" && - isSwitchingToBuilder && - dashboardPanelData.data.queryType === "promql" && - dashboardPanelData.data.queries[ - dashboardPanelData.layout.currentQueryIndex - ]?.fields?.stream - ) { - const streamName = - dashboardPanelData.data.queries[ - dashboardPanelData.layout.currentQueryIndex - ].fields.stream; - dashboardPanelData.data.queries[ - dashboardPanelData.layout.currentQueryIndex - ].query = `${streamName}{}`; + // removeXYFilters() above wiped the builder fields; re-seed defaults when + // the resulting mode is a builder. + const seedQueryIdx = dashboardPanelData.layout.currentQueryIndex; + const seedQuery = dashboardPanelData.data.queries[seedQueryIdx]; + const resultingBuilderMode = !seedQuery?.customQuery; + const shouldSeedDefaults = + resultingBuilderMode && + SEED_ON_TOGGLE_PAGES.includes(dashboardPanelDataPageKey); + if (shouldSeedDefaults) { + await applyDefaultPanelFields(); } // empty the errors diff --git a/web/src/composables/dashboard/useDashboardPanel.spec.ts b/web/src/composables/dashboard/useDashboardPanel.spec.ts index 1d03b93496..2f933478e2 100644 --- a/web/src/composables/dashboard/useDashboardPanel.spec.ts +++ b/web/src/composables/dashboard/useDashboardPanel.spec.ts @@ -140,16 +140,26 @@ describe("useDashboardPanel", () => { panel.addQuery(); expect(panel.dashboardPanelData.data.queries).toHaveLength(2); expect(panel.dashboardPanelData.data.queries[1].fields.stream).toBe("stream-a"); + // New query is seeded synchronously with default builder fields so the tab + // is ready the moment it activates (no async race with stream selection). + expect(panel.dashboardPanelData.data.queries[1].fields.y).toHaveLength(1); + expect(panel.dashboardPanelData.data.queries[1].fields.y[0].functionName).toBe( + "count", + ); panel.removeQuery(1); expect(panel.dashboardPanelData.data.queries).toHaveLength(1); }); - it("resets panel data and adds default timestamp field", () => { + it("resets panel data and seeds default histogram x + count y fields", () => { const panel = useDashboardPanelData("dashboard-panel-test-2"); panel.resetDashboardPanelDataAndAddTimeField(); - expect(addXAxisItemMock).toHaveBeenCalledWith({ name: "_ts" }); + const fields = panel.dashboardPanelData.data.queries[0].fields; + expect(fields.x).toHaveLength(1); + expect(fields.x[0].functionName).toBe("histogram"); + expect(fields.y).toHaveLength(1); + expect(fields.y[0].functionName).toBe("count"); }); it("turns off VRL toggle when query type changes to promql", async () => { diff --git a/web/src/composables/dashboard/useDashboardPanel.ts b/web/src/composables/dashboard/useDashboardPanel.ts index 645cbbd6a4..d91ec72058 100644 --- a/web/src/composables/dashboard/useDashboardPanel.ts +++ b/web/src/composables/dashboard/useDashboardPanel.ts @@ -33,6 +33,11 @@ import { } from "@/utils/dashboard/dashboardAutoQueryBuilder"; import { usePanelFields } from "@/composables/dashboard/usePanelFields"; import { usePanelAggregation } from "@/composables/dashboard/usePanelAggregation"; +import { + DEFAULT_SQL_X_FIELD, + DEFAULT_SQL_Y_FIELD_COUNT, + buildDefaultBuilderFields, +} from "@/utils/dashboard/defaultFields"; import { getDefaultDashboardPanelData, getDefaultCustomChartText, @@ -161,6 +166,25 @@ const useDashboardPanelData = (pageKey: string = "dashboard") => { weight_fixed: 1, }, }; + // Seed the new query's default builder fields synchronously (mirrors the + // first query) so the tab is fully configured the moment it becomes active — + // an async seed would race with the user/test selecting a stream next. + // PromQL gets the `${stream}{}` sample query; SQL gets chart-type-aware x/y. + if (dashboardPanelData.data.queryType === "promql") { + if (newQuery.fields.stream) { + newQuery.query = `${newQuery.fields.stream}{}`; + } + } else { + const { x, y } = buildDefaultBuilderFields( + dashboardPanelData.data.type, + newQuery.fields.stream_type, + dashboardPanelData.meta?.streamFields?.groupedFields ?? [], + newQuery.fields.stream, + ); + newQuery.fields.x = x; + newQuery.fields.y = y; + } + dashboardPanelData.data.queries.push(newQuery); // Initialize per-query field cache in meta getQueryFields(dashboardPanelData.data.queries.length - 1); @@ -195,10 +219,16 @@ const useDashboardPanelData = (pageKey: string = "dashboard") => { const resetDashboardPanelDataAndAddTimeField = () => { resetDashboardPanelData(); - // add _timestamp field in x axis as default - addXAxisItem({ - name: store.state.zoConfig.timestamp_column ?? "_timestamp", - }); + // Seed default x (histogram(_timestamp)) and y (count(_timestamp)) from the + // shared default-fields builder so a bar chart renders on open — the same + // fields applyDefaultPanelFields seeds on stream/builder changes. + const currentQueryIndex = dashboardPanelData.layout.currentQueryIndex; + dashboardPanelData.data.queries[currentQueryIndex].fields.x = [ + DEFAULT_SQL_X_FIELD(), + ]; + dashboardPanelData.data.queries[currentQueryIndex].fields.y = [ + DEFAULT_SQL_Y_FIELD_COUNT(), + ]; }; // Watch queryType and toggle off VRL functions when switching to PromQL diff --git a/web/src/composables/dashboard/useDefaultPanelFields.spec.ts b/web/src/composables/dashboard/useDefaultPanelFields.spec.ts new file mode 100644 index 0000000000..805f9ce6ca --- /dev/null +++ b/web/src/composables/dashboard/useDefaultPanelFields.spec.ts @@ -0,0 +1,246 @@ +// Copyright 2026 OpenObserve Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import { describe, it, expect, beforeEach, vi } from "vitest"; + +const { mockUpdateGroupedFields, mockMakeAutoSQLQuery, state } = vi.hoisted( + () => ({ + mockUpdateGroupedFields: vi.fn(), + mockMakeAutoSQLQuery: vi.fn(), + state: { panel: null as any }, + }), +); + +vi.mock("@/composables/dashboard/useDashboardPanel", () => ({ + default: () => ({ + dashboardPanelData: state.panel, + updateGroupedFields: mockUpdateGroupedFields, + makeAutoSQLQuery: mockMakeAutoSQLQuery, + // Mirror the real chart-type axis rules: metric/gauge disallow an x-axis. + isAddXAxisNotAllowed: { + get value() { + const t = state.panel?.data?.type; + const xlen = + state.panel?.data?.queries?.[0]?.fields?.x?.length ?? 0; + if (t === "metric") return xlen >= 0; // metric: x never allowed + if (t === "gauge" || t === "pie" || t === "donut") return xlen >= 1; + if (t === "table") return false; + return xlen >= 1; // bar/line/area/etc. + }, + }, + isAddYAxisNotAllowed: { + get value() { + const ylen = + state.panel?.data?.queries?.[0]?.fields?.y?.length ?? 0; + const t = state.panel?.data?.type; + if (["pie", "donut", "gauge", "metric"].includes(t)) return ylen >= 1; + return false; + }, + }, + }), +})); + +import useDefaultPanelFields from "./useDefaultPanelFields"; + +function setPanel({ + type = "bar", + queryType = "sql", + stream = "s1", + streamType = "logs", + query = "", + customQuery = true, + groupedFields = [] as any[], +} = {}) { + state.panel = { + data: { + type, + queryType, + queries: [ + { + customQuery, + query, + fields: { + stream, + stream_type: streamType, + x: [], + y: [], + breakdown: [], + filter: {}, + }, + }, + ], + }, + layout: { currentQueryIndex: 0 }, + meta: { streamFields: { groupedFields } }, + }; +} + +const currentQuery = () => state.panel.data.queries[0]; + +describe("useDefaultPanelFields", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe("PromQL", () => { + it("seeds `${stream}{}` and sets builder mode, without touching x/y", async () => { + setPanel({ queryType: "promql", stream: "mystream", customQuery: true }); + const { applyDefaultPanelFields } = useDefaultPanelFields("metrics"); + await applyDefaultPanelFields(); + + expect(currentQuery().query).toBe("mystream{}"); + expect(currentQuery().customQuery).toBe(false); + expect(currentQuery().fields.x).toEqual([]); + expect(mockUpdateGroupedFields).not.toHaveBeenCalled(); + expect(mockMakeAutoSQLQuery).not.toHaveBeenCalled(); + }); + + it("leaves the query empty when no stream is selected", async () => { + setPanel({ queryType: "promql", stream: "" }); + const { applyDefaultPanelFields } = useDefaultPanelFields("metrics"); + await applyDefaultPanelFields(); + + expect(currentQuery().query).toBe(""); + expect(currentQuery().customQuery).toBe(false); + }); + }); + + describe("SQL", () => { + it("logs stream: seeds histogram + count, resets breakdown/filter, regenerates", async () => { + setPanel({ + queryType: "sql", + stream: "logs1", + streamType: "logs", + groupedFields: [{ name: "logs1", schema: [{ name: "_timestamp" }] }], + }); + const { applyDefaultPanelFields } = useDefaultPanelFields("dashboard"); + await applyDefaultPanelFields(); + + expect(mockUpdateGroupedFields).toHaveBeenCalledTimes(1); + expect(currentQuery().fields.x[0].functionName).toBe("histogram"); + expect(currentQuery().fields.y[0].functionName).toBe("count"); + expect(currentQuery().fields.breakdown).toEqual([]); + expect(currentQuery().fields.filter).toMatchObject({ + filterType: "group", + logicalOperator: "AND", + conditions: [], + }); + expect(currentQuery().customQuery).toBe(false); + expect(mockMakeAutoSQLQuery).toHaveBeenCalledTimes(1); + }); + + it("metrics stream with a value column: seeds avg(value)", async () => { + setPanel({ + queryType: "sql", + stream: "m1", + streamType: "metrics", + groupedFields: [{ name: "m1", schema: [{ name: "value" }] }], + }); + const { applyDefaultPanelFields } = useDefaultPanelFields("metrics"); + await applyDefaultPanelFields(); + + expect(currentQuery().fields.y[0].functionName).toBe("avg"); + }); + + it("metric chart: seeds y but NOT x (x-axis not allowed for metric)", async () => { + setPanel({ + type: "metric", + queryType: "sql", + stream: "logs1", + streamType: "logs", + groupedFields: [{ name: "logs1", schema: [{ name: "_timestamp" }] }], + }); + const { applyDefaultPanelFields } = useDefaultPanelFields("dashboard"); + await applyDefaultPanelFields(); + + expect(currentQuery().fields.x).toEqual([]); + expect(currentQuery().fields.y[0].functionName).toBe("count"); + }); + + it("gauge chart: seeds x and y (gauge allows one x when empty)", async () => { + setPanel({ + type: "gauge", + queryType: "sql", + stream: "logs1", + streamType: "logs", + groupedFields: [{ name: "logs1", schema: [{ name: "_timestamp" }] }], + }); + const { applyDefaultPanelFields } = useDefaultPanelFields("dashboard"); + await applyDefaultPanelFields(); + + expect(currentQuery().fields.x[0].functionName).toBe("histogram"); + expect(currentQuery().fields.y[0].functionName).toBe("count"); + }); + + it("no stream: seeds x/y but skips schema load and query regeneration", async () => { + setPanel({ queryType: "sql", stream: "", streamType: "logs" }); + const { applyDefaultPanelFields } = useDefaultPanelFields("dashboard"); + await applyDefaultPanelFields(); + + expect(mockUpdateGroupedFields).not.toHaveBeenCalled(); + expect(mockMakeAutoSQLQuery).not.toHaveBeenCalled(); + expect(currentQuery().fields.x[0].functionName).toBe("histogram"); + expect(currentQuery().fields.y[0].functionName).toBe("count"); + }); + + it("does not reject when updateGroupedFields throws, and falls back to count", async () => { + const errSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + // empty groupedFields = no schema for the current stream (failed/stale load) + setPanel({ + queryType: "sql", + stream: "m1", + streamType: "metrics", + groupedFields: [], + }); + mockUpdateGroupedFields.mockRejectedValueOnce(new Error("network")); + const { applyDefaultPanelFields } = useDefaultPanelFields("dashboard"); + + await expect(applyDefaultPanelFields()).resolves.toBeUndefined(); + expect(currentQuery().fields.y[0].functionName).toBe("count"); + expect(mockMakeAutoSQLQuery).toHaveBeenCalledTimes(1); + errSpy.mockRestore(); + }); + }); + + describe("guards", () => { + it("is a no-op for non-cartesian / custom chart types", async () => { + setPanel({ type: "custom_chart", customQuery: true }); + const { applyDefaultPanelFields } = useDefaultPanelFields("dashboard"); + await applyDefaultPanelFields(); + + expect(currentQuery().customQuery).toBe(true); // returned before any mutation + expect(mockMakeAutoSQLQuery).not.toHaveBeenCalled(); + }); + + it("is a no-op for heatmap (measure lives on Z; Y disallows aggregation)", async () => { + setPanel({ type: "heatmap", customQuery: true }); + const { applyDefaultPanelFields } = useDefaultPanelFields("dashboard"); + await applyDefaultPanelFields(); + + expect(currentQuery().customQuery).toBe(true); // returned before any mutation + expect(currentQuery().fields.x).toEqual([]); + expect(currentQuery().fields.y).toEqual([]); + expect(mockMakeAutoSQLQuery).not.toHaveBeenCalled(); + }); + + it("returns early (no throw) when the current query is missing", async () => { + setPanel(); + state.panel.data.queries = []; + const { applyDefaultPanelFields } = useDefaultPanelFields("dashboard"); + + await expect(applyDefaultPanelFields()).resolves.toBeUndefined(); + }); + }); +}); diff --git a/web/src/composables/dashboard/useDefaultPanelFields.ts b/web/src/composables/dashboard/useDefaultPanelFields.ts new file mode 100644 index 0000000000..72ead43082 --- /dev/null +++ b/web/src/composables/dashboard/useDefaultPanelFields.ts @@ -0,0 +1,90 @@ +// Copyright 2026 OpenObserve Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import useDashboardPanelData from "@/composables/dashboard/useDashboardPanel"; +import { + buildDefaultSqlFields, + SKIP_SEED_TYPES, +} from "@/utils/dashboard/defaultFields"; + +/** + * Shared default-field seeding for the Add Panel and Metrics pages (both render + * the same PanelEditor). Seeds the current query based on queryType + stream_type: + * PromQL -> `${stream}{}`; SQL logs/traces -> count(_timestamp); SQL metrics -> + * avg(value) if the stream has a "value" column, else count(_timestamp). + */ +const useDefaultPanelFields = (pageKey: string = "dashboard") => { + const { + dashboardPanelData, + updateGroupedFields, + makeAutoSQLQuery, + isAddXAxisNotAllowed, + isAddYAxisNotAllowed, + } = useDashboardPanelData(pageKey); + + const applyDefaultPanelFields = async () => { + const idx = dashboardPanelData.layout.currentQueryIndex; + const query = dashboardPanelData.data.queries[idx]; + if (!query) return; + if (SKIP_SEED_TYPES.includes(dashboardPanelData.data.type)) return; + + const queryType = dashboardPanelData.data.queryType; + const stream = query.fields?.stream; + const streamType = query.fields?.stream_type; + + query.customQuery = false; + + if (queryType === "promql") { + if (stream) query.query = `${stream}{}`; + return; + } + + if (stream) { + // updateGroupedFields has no catch of its own; swallow so a failed schema + // load can't reject the toggle/watcher. + try { + await updateGroupedFields(); + } catch (e) { + console.error("useDefaultPanelFields: updateGroupedFields failed", e); + } + } + + // hasValueColumn is scoped to `stream`, so a missing/stale schema (incl. join + // streams) falls back to count(_timestamp). + const { x, y } = buildDefaultSqlFields( + streamType, + dashboardPanelData.meta?.streamFields?.groupedFields ?? [], + stream, + ); + + // Respect chart-type axis rules: metric/gauge etc. don't allow an x-axis, so + // only seed x/y where the current chart type permits it (computed from the + // now-empty field state after removeXYFilters). + query.fields.x = isAddXAxisNotAllowed.value ? [] : x; + query.fields.y = isAddYAxisNotAllowed.value ? [] : y; + query.fields.breakdown = []; + query.fields.filter = { + filterType: "group", + logicalOperator: "AND", + conditions: [], + }; + + if (stream) await makeAutoSQLQuery(); + }; + + return { applyDefaultPanelFields }; +}; + +export default useDefaultPanelFields; diff --git a/web/src/plugins/metrics/Index.vue b/web/src/plugins/metrics/Index.vue index 9f66b71216..c783191e72 100644 --- a/web/src/plugins/metrics/Index.vue +++ b/web/src/plugins/metrics/Index.vue @@ -148,11 +148,7 @@ import AutoRefreshInterval from "@/components/AutoRefreshInterval.vue"; import { checkIfConfigChangeRequiredApiCallOrNot } from "@/utils/dashboard/checkConfigChangeApiCall"; import { PanelEditor } from "@/components/dashboards/PanelEditor"; import { saveMetricsStream, restoreMetricsStream } from "@/utils/streamPersist"; -import { - DEFAULT_METRICS_X_FIELD, - DEFAULT_METRICS_Y_FIELD, - DEFAULT_METRICS_Y_FIELD_COUNT, -} from "@/utils/metrics/constants"; +import useDefaultPanelFields from "@/composables/dashboard/useDefaultPanelFields"; const AddToDashboard = defineAsyncComponent(() => { return import("./../metrics/AddToDashboard.vue"); @@ -189,9 +185,8 @@ export default defineComponent({ resetDashboardPanelData, resetAggregationFunction, validatePanel, - updateGroupedFields, - makeAutoSQLQuery, } = useDashboardPanelData("metrics"); + const { applyDefaultPanelFields } = useDefaultPanelFields("metrics"); const editMode = ref(false); const selectedDate: any = ref({ valueType: "relative", @@ -227,33 +222,6 @@ export default defineComponent({ // already resets and re-initialises the state correctly. }); - /** Apply default SQL builder fields for metrics. - * Uses avg(value) if the stream has a "value" field, otherwise count(_timestamp). */ - const applyMetricsDefaults = () => { - const query = dashboardPanelData.data.queries[0]; - query.customQuery = false; - query.fields.x = [DEFAULT_METRICS_X_FIELD()]; - - // Check if the current stream has a "value" field - const streamFields = - dashboardPanelData.meta?.streamFields?.groupedFields ?? []; - const hasValueField = streamFields.some((stream: any) => - stream?.schema?.some((field: any) => field?.name === "value"), - ); - - query.fields.y = [ - hasValueField - ? DEFAULT_METRICS_Y_FIELD() - : DEFAULT_METRICS_Y_FIELD_COUNT(), - ]; - query.fields.breakdown = []; - query.fields.filter = { - filterType: "group", - logicalOperator: "AND", - conditions: [], - }; - }; - // Initialize state before any child components mount so FieldList.vue sees // stream_type = "metrics" from the start, preventing a spurious // streams?type=logs request and the double stream-list fetch that results @@ -294,6 +262,17 @@ export default defineComponent({ // let it call the watchers and then mark the panel config watcher as activated await nextTick(); isPanelConfigWatcherActivated = true; + + // Seed the default builder query on initial load (the PromQL builder only + // rebuilds on label/operation change, so the bar would otherwise be empty). + const initialQuery = dashboardPanelData.data.queries[0]; + if ( + initialQuery?.fields?.stream && + !initialQuery.customQuery && + !initialQuery.query + ) { + await applyDefaultPanelFields(); + } }); watch( @@ -326,84 +305,17 @@ export default defineComponent({ ); } - // When stream changes while in SQL builder mode and query is empty, - // apply defaults and regenerate query. Skip for custom mode. + // Seed the default query when a stream becomes available in builder mode + // with an empty query (the !query guard avoids overwriting an existing one). const query = dashboardPanelData.data.queries[0]; if ( isPanelConfigWatcherActivated && stream && - oldStream && stream !== oldStream && - dashboardPanelData.data.queryType === "sql" && !query?.customQuery && !query?.query ) { - await updateGroupedFields(); - applyMetricsDefaults(); - await makeAutoSQLQuery(); - } - }, - ); - - // Handle query type switches on metrics page. - // We use nextTick() to ensure this runs AFTER changeToggle's removeXYFilters() - // has completed, so the defaults we apply here don't get immediately cleared. - // Only applies for builder mode (not custom mode). - watch( - () => dashboardPanelData.data.queryType, - async (newType: string, oldType: string) => { - if (!isPanelConfigWatcherActivated) return; - - const query = dashboardPanelData.data.queries[0]; - const stream = query?.fields?.stream; - const isCustomMode = query?.customQuery; - - if (newType === "sql" && oldType === "promql" && !isCustomMode) { - // Switching to SQL builder: load stream fields first so applyMetricsDefaults - // can check whether the current stream has a "value" field - await nextTick(); - if (stream) { - await updateGroupedFields(); - } - applyMetricsDefaults(); - - if (stream) { - await makeAutoSQLQuery(); - } - } else if (newType === "promql" && oldType === "sql" && !isCustomMode) { - // Switching to PromQL builder: set default builder query (streamName{}) - await nextTick(); - if (stream) { - query.query = `${stream}{}`; - } - } - }, - ); - - // When switching from custom to builder mode, apply defaults. - // changeToggle's removeXYFilters() wipes the builder fields, so we - // always need to re-apply defaults regardless of whether query text is empty. - watch( - () => dashboardPanelData.data.queries[0]?.customQuery, - async (isCustom: boolean, wasCustom: boolean) => { - if (!isPanelConfigWatcherActivated) return; - // Only act when switching from custom (true) to builder (false) - if (wasCustom && !isCustom) { - await nextTick(); - const query = dashboardPanelData.data.queries[0]; - const stream = query?.fields?.stream; - - if (dashboardPanelData.data.queryType === "sql") { - if (stream) { - await updateGroupedFields(); - } - applyMetricsDefaults(); - if (stream) { - await makeAutoSQLQuery(); - } - } else if (dashboardPanelData.data.queryType === "promql" && stream) { - query.query = `${stream}{}`; - } + await applyDefaultPanelFields(); } }, ); diff --git a/web/src/utils/dashboard/defaultFields.spec.ts b/web/src/utils/dashboard/defaultFields.spec.ts new file mode 100644 index 0000000000..4c1dcf60a4 --- /dev/null +++ b/web/src/utils/dashboard/defaultFields.spec.ts @@ -0,0 +1,172 @@ +// Copyright 2026 OpenObserve Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import { describe, it, expect } from "vitest"; +import { + DEFAULT_SQL_X_FIELD, + DEFAULT_SQL_Y_FIELD_COUNT, + DEFAULT_SQL_Y_FIELD_VALUE, + hasValueColumn, + buildDefaultSqlFields, + buildDefaultBuilderFields, + SKIP_SEED_TYPES, +} from "./defaultFields"; + +describe("defaultFields", () => { + describe("field factories", () => { + it("DEFAULT_SQL_X_FIELD is histogram(_timestamp) on x_axis_1", () => { + const x = DEFAULT_SQL_X_FIELD(); + expect(x).toMatchObject({ + alias: "x_axis_1", + column: "_timestamp", + functionName: "histogram", + type: "build", + sortBy: "ASC", + }); + expect(x.args[0]).toEqual({ + type: "field", + value: { field: "_timestamp" }, + }); + }); + + it("DEFAULT_SQL_Y_FIELD_COUNT is count(_timestamp) on y_axis_1", () => { + const y = DEFAULT_SQL_Y_FIELD_COUNT(); + expect(y).toMatchObject({ + alias: "y_axis_1", + column: "_timestamp", + functionName: "count", + }); + }); + + it("DEFAULT_SQL_Y_FIELD_VALUE is avg(value) on y_axis_1", () => { + const y = DEFAULT_SQL_Y_FIELD_VALUE(); + expect(y).toMatchObject({ + alias: "y_axis_1", + column: "value", + functionName: "avg", + }); + }); + + it("returns a fresh object each call (factory, not shared ref)", () => { + const a = DEFAULT_SQL_X_FIELD(); + const b = DEFAULT_SQL_X_FIELD(); + expect(a).not.toBe(b); + expect(a.args).not.toBe(b.args); + }); + }); + + describe("hasValueColumn", () => { + const withValue = { name: "m1", schema: [{ name: "value" }, { name: "le" }] }; + const noValue = { name: "logs", schema: [{ name: "_timestamp" }] }; + + it("returns false for empty / nullish input", () => { + expect(hasValueColumn([])).toBe(false); + expect(hasValueColumn(undefined as any)).toBe(false); + }); + + it("returns true when any stream has a value column (no streamName)", () => { + expect(hasValueColumn([noValue, withValue])).toBe(true); + }); + + it("returns false when no stream has a value column", () => { + expect(hasValueColumn([noValue])).toBe(false); + }); + + it("scopes the check to the named stream only", () => { + // join: main stream has no value, joined stream does + const grouped = [noValue, withValue]; + expect(hasValueColumn(grouped, "logs")).toBe(false); + expect(hasValueColumn(grouped, "m1")).toBe(true); + }); + + it("returns false when the named stream is absent", () => { + expect(hasValueColumn([withValue], "missing")).toBe(false); + }); + }); + + describe("buildDefaultSqlFields", () => { + const metricWithValue = [{ name: "m1", schema: [{ name: "value" }] }]; + const logsSchema = [{ name: "logs", schema: [{ name: "_timestamp" }] }]; + + it("logs -> histogram(_timestamp) + count(_timestamp)", () => { + const { x, y } = buildDefaultSqlFields("logs", logsSchema, "logs"); + expect(x[0].functionName).toBe("histogram"); + expect(y[0].functionName).toBe("count"); + }); + + it("traces -> count(_timestamp) even if a value column exists", () => { + const traces = [{ name: "t1", schema: [{ name: "value" }] }]; + const { y } = buildDefaultSqlFields("traces", traces, "t1"); + expect(y[0].functionName).toBe("count"); + }); + + it("metrics with value column -> avg(value)", () => { + const { y } = buildDefaultSqlFields("metrics", metricWithValue, "m1"); + expect(y[0].functionName).toBe("avg"); + expect(y[0].column).toBe("value"); + }); + + it("metrics without value column -> count(_timestamp)", () => { + const { y } = buildDefaultSqlFields("metrics", logsSchema, "logs"); + expect(y[0].functionName).toBe("count"); + }); + + it("metrics: value column on a different (join) stream -> count for the main stream", () => { + const grouped = [ + { name: "main", schema: [{ name: "_timestamp" }] }, + { name: "joined", schema: [{ name: "value" }] }, + ]; + const { y } = buildDefaultSqlFields("metrics", grouped, "main"); + expect(y[0].functionName).toBe("count"); + }); + + it("always seeds exactly one x and one y field", () => { + const { x, y } = buildDefaultSqlFields("logs", logsSchema, "logs"); + expect(x).toHaveLength(1); + expect(y).toHaveLength(1); + }); + }); + + describe("buildDefaultBuilderFields", () => { + const logsSchema = [{ name: "logs", schema: [{ name: "_timestamp" }] }]; + + it("cartesian chart (bar): seeds histogram x + count y", () => { + const { x, y } = buildDefaultBuilderFields("bar", "logs", logsSchema, "logs"); + expect(x).toHaveLength(1); + expect(x[0].functionName).toBe("histogram"); + expect(y).toHaveLength(1); + expect(y[0].functionName).toBe("count"); + }); + + it("metric: seeds y only (no x-axis)", () => { + const { x, y } = buildDefaultBuilderFields("metric", "logs", logsSchema, "logs"); + expect(x).toHaveLength(0); + expect(y).toHaveLength(1); + expect(y[0].functionName).toBe("count"); + }); + + it.each(SKIP_SEED_TYPES)("%s: seeds nothing (self-driven builder)", (type) => { + const { x, y } = buildDefaultBuilderFields(type, "logs", logsSchema, "logs"); + expect(x).toHaveLength(0); + expect(y).toHaveLength(0); + }); + + it("metrics stream with value column: seeds avg(value) y", () => { + const grouped = [{ name: "m1", schema: [{ name: "value" }] }]; + const { y } = buildDefaultBuilderFields("bar", "metrics", grouped, "m1"); + expect(y[0].functionName).toBe("avg"); + }); + }); +}); diff --git a/web/src/utils/dashboard/defaultFields.ts b/web/src/utils/dashboard/defaultFields.ts new file mode 100644 index 0000000000..fc99e01295 --- /dev/null +++ b/web/src/utils/dashboard/defaultFields.ts @@ -0,0 +1,124 @@ +// Copyright 2026 OpenObserve Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Default builder fields shared by the Add Panel and Metrics pages. + +/** Default x-axis: histogram(_timestamp). */ +export const DEFAULT_SQL_X_FIELD = () => ({ + label: "_timestamp", + alias: "x_axis_1", + column: "_timestamp", + color: null, + type: "build", + functionName: "histogram", + args: [ + { type: "field", value: { field: "_timestamp" } }, + { type: "histogramInterval", value: null }, + ], + sortBy: "ASC", + isDerived: false, + havingConditions: [], +}); + +/** Default y-axis for logs/traces (and metrics without a "value" column): count(_timestamp). */ +export const DEFAULT_SQL_Y_FIELD_COUNT = () => ({ + label: "_timestamp", + alias: "y_axis_1", + column: "_timestamp", + color: "#5960b2", + type: "build", + functionName: "count", + args: [{ type: "field", value: { field: "_timestamp" } }], + sortBy: null, + isDerived: false, + havingConditions: [], +}); + +/** Metrics-only y-axis when the stream has a "value" column: avg(value). */ +export const DEFAULT_SQL_Y_FIELD_VALUE = () => ({ + label: "value", + alias: "y_axis_1", + column: "value", + color: "#5960b2", + type: "build", + functionName: "avg", + args: [{ type: "field", value: { field: "value" } }], + sortBy: null, + isDerived: false, + havingConditions: [], +}); + +/** + * True if a stream exposes a "value" column. When `streamName` is given, only + * that stream is checked (groupedFields also holds joined streams for SQL joins). + */ +export const hasValueColumn = ( + groupedFields: any[], + streamName?: string, +): boolean => { + const streams = streamName + ? (groupedFields ?? []).filter((stream: any) => stream?.name === streamName) + : (groupedFields ?? []); + return streams.some((stream: any) => + stream?.schema?.some((field: any) => field?.name === "value"), + ); +}; + +/** Default x/y for SQL builder mode; `streamName` scopes the value-column check. */ +export const buildDefaultSqlFields = ( + streamType: string, + groupedFields: any[], + streamName?: string, +): { x: any[]; y: any[] } => { + const useValueMeasure = + streamType === "metrics" && hasValueColumn(groupedFields, streamName); + + return { + x: [DEFAULT_SQL_X_FIELD()], + y: [useValueMeasure ? DEFAULT_SQL_Y_FIELD_VALUE() : DEFAULT_SQL_Y_FIELD_COUNT()], + }; +}; + +// Chart types that drive their own builder and must not get the cartesian x/y seed. +// heatmap is included because its measure lives on the Z/value axis — its Y axis is +// a dimension that disallows aggregation, so a count(_timestamp) Y seed is invalid. +export const SKIP_SEED_TYPES = [ + "geomap", + "sankey", + "maps", + "custom_chart", + "html", + "markdown", + "heatmap", +]; + +/** + * Chart-type-aware default builder fields, computed synchronously from the + * already-loaded stream schema (no network). Mirrors applyDefaultPanelFields' + * axis rules: self-driven builders get nothing, metric gets a measure (y) but no + * x-axis, everything else gets the cartesian histogram-x + count/avg-y seed. + */ +export const buildDefaultBuilderFields = ( + chartType: string, + streamType: string, + groupedFields: any[], + streamName?: string, +): { x: any[]; y: any[] } => { + if (SKIP_SEED_TYPES.includes(chartType)) return { x: [], y: [] }; + const { x, y } = buildDefaultSqlFields(streamType, groupedFields, streamName); + // metric has no x-axis — it renders a single measure. + if (chartType === "metric") return { x: [], y }; + return { x, y }; +}; diff --git a/web/src/utils/metrics/constants.ts b/web/src/utils/metrics/constants.ts deleted file mode 100644 index cddefcb3dc..0000000000 --- a/web/src/utils/metrics/constants.ts +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2026 OpenObserve Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -/** Default x-axis field for metrics builder: histogram(_timestamp) */ -export const DEFAULT_METRICS_X_FIELD = () => ({ - label: "_timestamp", - alias: "x_axis_1", - column: "_timestamp", - color: null, - type: "build", - functionName: "histogram", - args: [ - { type: "field", value: { field: "_timestamp" } }, - { type: "histogramInterval", value: null }, - ], - sortBy: "ASC", - isDerived: false, - havingConditions: [], -}); - -/** Default y-axis field for metrics builder: avg(value) */ -export const DEFAULT_METRICS_Y_FIELD = () => ({ - label: "value", - alias: "y_axis_1", - column: "value", - color: "#5960b2", - type: "build", - functionName: "avg", - args: [{ type: "field", value: { field: "value" } }], - sortBy: null, - isDerived: false, - havingConditions: [], -}); - -/** Fallback y-axis field for streams without a "value" column: count(_timestamp) */ -export const DEFAULT_METRICS_Y_FIELD_COUNT = () => ({ - label: "_timestamp", - alias: "y_axis_1", - column: "_timestamp", - color: "#5960b2", - type: "build", - functionName: "count", - args: [{ type: "field", value: { field: "_timestamp" } }], - sortBy: null, - isDerived: false, - havingConditions: [], -});