mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-05 16:10:43 +00:00
455 lines
19 KiB
JavaScript
455 lines
19 KiB
JavaScript
const {
|
|
test,
|
|
expect,
|
|
navigateToBase,
|
|
} = require("../utils/enhanced-baseFixtures.js");
|
|
import { ingestion } from "./utils/dashIngestion.js";
|
|
import {
|
|
waitForDashboardPage,
|
|
deleteDashboard,
|
|
} from "./utils/dashCreation.js";
|
|
import { waitForDateTimeButtonToBeEnabled } from "../../pages/dashboardPages/dashboard-time";
|
|
import { generateDashboardName } from "./utils/configPanelHelpers.js";
|
|
|
|
import PageManager from "../../pages/page-manager";
|
|
import DashboardMaxQueryRange from "../../pages/dashboardPages/dashboard-max-query-range.js";
|
|
const testLogger = require("../utils/test-logger.js");
|
|
|
|
// Use a dedicated stream for max query range tests (not e2e_automate)
|
|
const MAX_QUERY_STREAM = "e2e_max_query_range";
|
|
|
|
// Serial mode is required: all tests share the same stream
|
|
// (e2e_max_query_range) and its max_query_range setting, so in parallel one
|
|
// test's afterEach reset wipes another's restriction mid-query. This said
|
|
// "default", which under the config's fullyParallel:true means PARALLEL — the
|
|
// very thing this comment forbids. A dedicated stream per test would allow
|
|
// parallelism, but that is a larger change.
|
|
test.describe.configure({ mode: "serial" });
|
|
|
|
|
|
// ============================================================================
|
|
// Helpers
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Build a panel with a wide time range (6 weeks) in the panel editor,
|
|
* apply, name, and save. This is done BEFORE setting max query range
|
|
* so the time picker buttons are not disabled.
|
|
* Leaves the user on the dashboard view (panel saved).
|
|
*/
|
|
async function buildPanelWithWideRange(page, pm, panelName, chartType = "area") {
|
|
await pm.dashboardCreate.addPanel();
|
|
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");
|
|
|
|
// Set wide time range while no restriction is active
|
|
await waitForDateTimeButtonToBeEnabled(page);
|
|
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
|
|
|
await pm.dashboardPanelActions.applyDashboardBtn();
|
|
await pm.dashboardPanelActions.waitForChartToRender().catch(() => {});
|
|
await pm.dashboardPanelActions.addPanelName(panelName);
|
|
await pm.dashboardPanelActions.savePanel();
|
|
}
|
|
|
|
// ============================================================================
|
|
// Test suite
|
|
// ============================================================================
|
|
|
|
test.describe("Dashboard Max Query Range", () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
const pm = new PageManager(page);
|
|
await navigateToBase(page);
|
|
await ingestion(page, MAX_QUERY_STREAM);
|
|
// Poll until the stream is actually queryable instead of sleeping 2s: the
|
|
// ingest -> queryable delay scales with load, so a constant wait is both
|
|
// wasteful when the box is idle and too short when it is not.
|
|
await pm.dashboardMaxQueryRange.waitForStreamReady(MAX_QUERY_STREAM);
|
|
});
|
|
|
|
// Ensure max query range is always reset even when a test fails mid-way,
|
|
// preventing restriction state from cascading into subsequent tests.
|
|
test.afterEach(async ({ page }) => {
|
|
const pm = new PageManager(page);
|
|
await pm.dashboardMaxQueryRange.resetMaxQueryRange();
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Scenario 1: Warning icon appears when query range exceeds max limit
|
|
// --------------------------------------------------------------------------
|
|
test(
|
|
"should display max query range warning when time range exceeds the stream limit",
|
|
{ tag: ["@maxQueryRange", "@P0"] },
|
|
async ({ page }) => {
|
|
const pm = new PageManager(page);
|
|
const mqr = pm.dashboardMaxQueryRange;
|
|
const dashboardName = generateDashboardName();
|
|
|
|
// Create dashboard with wide time range (no restriction yet)
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardCreate.createDashboard(dashboardName);
|
|
await buildPanelWithWideRange(page, pm, "Max Query Panel", "area");
|
|
|
|
// Set max query range to 2 hours
|
|
await mqr.setMaxQueryRange(2);
|
|
|
|
// Navigate back and reopen dashboard with wide time range
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardList.clickOnDashboard(dashboardName);
|
|
|
|
await waitForDateTimeButtonToBeEnabled(page);
|
|
const searchDone1 = mqr.createSearchResponsePromise();
|
|
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
|
await searchDone1;
|
|
await mqr.waitForPanelsIdle();
|
|
|
|
// Assert warning icon is visible
|
|
await expect(pm.dashboardMaxQueryRange.warningIcon.first()).toBeVisible({
|
|
timeout: 15000,
|
|
});
|
|
|
|
// Verify tooltip text
|
|
const tooltipText = await mqr.getWarningTooltipText();
|
|
// Accept either backend wording — see expectRangeRestrictionTooltip.
|
|
mqr.expectRangeRestrictionTooltip(expect, tooltipText);
|
|
|
|
testLogger.info("Tooltip text verified", { tooltipText });
|
|
|
|
// Cleanup
|
|
await pm.dashboardCreate.backToDashboardList();
|
|
await deleteDashboard(page, dashboardName);
|
|
}
|
|
);
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Scenario 2: Warning disappears when time range is within the limit
|
|
// --------------------------------------------------------------------------
|
|
test(
|
|
"should hide max query range warning when time range is within the stream limit",
|
|
{ tag: ["@maxQueryRange", "@P0"] },
|
|
async ({ page }) => {
|
|
const pm = new PageManager(page);
|
|
const mqr = pm.dashboardMaxQueryRange;
|
|
const dashboardName = generateDashboardName();
|
|
|
|
// Create dashboard with wide time range, then restrict to 4 hours
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardCreate.createDashboard(dashboardName);
|
|
await buildPanelWithWideRange(page, pm, "Toggle Warning Panel", "bar");
|
|
await mqr.setMaxQueryRange(4);
|
|
|
|
// Reopen dashboard and set 6-week range (exceeds limit)
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardList.clickOnDashboard(dashboardName);
|
|
|
|
await waitForDateTimeButtonToBeEnabled(page);
|
|
const searchDone6w = mqr.createSearchResponsePromise();
|
|
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
|
await searchDone6w;
|
|
await mqr.waitForPanelsIdle();
|
|
|
|
// Warning should be visible
|
|
await expect(pm.dashboardMaxQueryRange.warningIcon.first()).toBeVisible({
|
|
timeout: 15000,
|
|
});
|
|
testLogger.info("Warning visible with 6-week range (exceeds 4h limit)");
|
|
|
|
// Set time range within the limit (2 hours)
|
|
await waitForDateTimeButtonToBeEnabled(page);
|
|
const searchDone2h = mqr.createSearchResponsePromise();
|
|
await pm.dateTimeHelper.setRelativeTimeRange("2-h");
|
|
await searchDone2h;
|
|
await mqr.waitForPanelsIdle();
|
|
|
|
// Warning should disappear
|
|
await expect(pm.dashboardMaxQueryRange.warningIcon).not.toBeVisible({
|
|
timeout: 15000,
|
|
});
|
|
testLogger.info("Warning hidden with 2-hour range (within 4h limit)");
|
|
|
|
// Cleanup
|
|
await pm.dashboardCreate.backToDashboardList();
|
|
await deleteDashboard(page, dashboardName);
|
|
}
|
|
);
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Scenario 3: Warning appears in panel editor (add_panel page) as well
|
|
// --------------------------------------------------------------------------
|
|
test(
|
|
"should display max query range warning in the panel editor when range is exceeded",
|
|
{ tag: ["@maxQueryRange", "@P1"] },
|
|
async ({ page }) => {
|
|
const pm = new PageManager(page);
|
|
const mqr = pm.dashboardMaxQueryRange;
|
|
const dashboardName = generateDashboardName();
|
|
|
|
// Create dashboard, then set restriction
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardCreate.createDashboard(dashboardName);
|
|
await mqr.setMaxQueryRange(2);
|
|
|
|
// Reopen dashboard
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardList.clickOnDashboard(dashboardName);
|
|
|
|
// Add panel — set time range BEFORE selecting stream (avoids disabled buttons)
|
|
await pm.dashboardCreate.addPanel();
|
|
await pm.chartTypeSelector.selectChartType("line");
|
|
|
|
await waitForDateTimeButtonToBeEnabled(page);
|
|
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
|
|
|
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();
|
|
await pm.dashboardPanelActions.waitForChartToRender().catch(() => {});
|
|
|
|
// Warning should be visible in editor
|
|
await expect(pm.dashboardMaxQueryRange.warningIcon.first()).toBeVisible({
|
|
timeout: 15000,
|
|
});
|
|
testLogger.info("Warning visible in panel editor when range exceeds max");
|
|
|
|
// Save and cleanup
|
|
await pm.dashboardPanelActions.addPanelName("Editor Warning Panel");
|
|
await pm.dashboardPanelActions.savePanel();
|
|
await pm.dashboardCreate.backToDashboardList();
|
|
await deleteDashboard(page, dashboardName);
|
|
}
|
|
);
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Scenario 4: Different chart types show the warning
|
|
// --------------------------------------------------------------------------
|
|
test(
|
|
"should display max query range warning across different chart types",
|
|
{ tag: ["@maxQueryRange", "@P1"] },
|
|
async ({ page }) => {
|
|
const pm = new PageManager(page);
|
|
const mqr = pm.dashboardMaxQueryRange;
|
|
const dashboardName = generateDashboardName();
|
|
|
|
// Create dashboard and add panels with wide time range (no restriction yet)
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardCreate.createDashboard(dashboardName);
|
|
|
|
const chartTypes = ["bar", "line", "area"];
|
|
|
|
for (let i = 0; i < chartTypes.length; i++) {
|
|
const chartType = chartTypes[i];
|
|
testLogger.info(`Adding panel with chart type: ${chartType}`);
|
|
|
|
if (i === 0) {
|
|
await pm.dashboardCreate.addPanel();
|
|
} else {
|
|
await pm.dashboardCreate.addPanelToExistingDashboard();
|
|
}
|
|
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);
|
|
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
|
|
|
await pm.dashboardPanelActions.applyDashboardBtn();
|
|
await pm.dashboardPanelActions.waitForChartToRender().catch(() => {});
|
|
|
|
await pm.dashboardPanelActions.addPanelName(`Panel_${chartType}`);
|
|
await pm.dashboardPanelActions.savePanel();
|
|
}
|
|
|
|
// Set restriction and reopen dashboard
|
|
await mqr.setMaxQueryRange(2);
|
|
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardList.clickOnDashboard(dashboardName);
|
|
|
|
await waitForDateTimeButtonToBeEnabled(page);
|
|
// Best-effort settle, not a gate: a panel whose range is already clamped renders the
|
|
// warning without issuing a query, so "one countable search per panel" is an assumption
|
|
// about the network layer the app does not make. Counting short is normal — failing the
|
|
// test on it reported a missing response where the behaviour under test was fine.
|
|
const allSearchesDone = mqr
|
|
.createNSearchResponsesPromise(chartTypes.length, 20000)
|
|
.catch(() => {});
|
|
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
|
await allSearchesDone;
|
|
|
|
// The real gate: poll the warning count, which is the behaviour this test exists to check.
|
|
// Budgeted for the slow-search case the wait above no longer absorbs.
|
|
await expect(pm.dashboardMaxQueryRange.warningIcon).toHaveCount(chartTypes.length, { timeout: 45000 });
|
|
testLogger.info(`All ${chartTypes.length} panels show max query range warning`);
|
|
|
|
// Cleanup
|
|
await pm.dashboardCreate.backToDashboardList();
|
|
await deleteDashboard(page, dashboardName);
|
|
}
|
|
);
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Scenario 5: Warning shows correct adjusted time range in tooltip
|
|
// --------------------------------------------------------------------------
|
|
test(
|
|
"should show the correct adjusted time range in the warning tooltip",
|
|
{ tag: ["@maxQueryRange", "@P1"] },
|
|
async ({ page }) => {
|
|
const pm = new PageManager(page);
|
|
const mqr = pm.dashboardMaxQueryRange;
|
|
const dashboardName = generateDashboardName();
|
|
|
|
// Create dashboard with wide time range, then restrict to 3 hours
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardCreate.createDashboard(dashboardName);
|
|
await buildPanelWithWideRange(page, pm, "Tooltip Range Panel", "line");
|
|
await mqr.setMaxQueryRange(3);
|
|
|
|
// Reopen dashboard with wide time range
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardList.clickOnDashboard(dashboardName);
|
|
|
|
await waitForDateTimeButtonToBeEnabled(page);
|
|
const searchDone5 = mqr.createSearchResponsePromise();
|
|
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
|
await searchDone5;
|
|
await mqr.waitForPanelsIdle();
|
|
|
|
// Verify warning is present
|
|
await expect(pm.dashboardMaxQueryRange.warningIcon.first()).toBeVisible({
|
|
timeout: 15000,
|
|
});
|
|
|
|
// Hover and verify the tooltip reports the restriction.
|
|
const tooltipText = await mqr.getWarningTooltipText();
|
|
mqr.expectRangeRestrictionTooltip(expect, tooltipText);
|
|
|
|
// Only the non-streaming backend names the limit in hours; the streaming
|
|
// path reports the cached window and never says "restriction of N hours".
|
|
// Assert the number where the message actually carries it, rather than
|
|
// pinning the whole test to one deployment mode.
|
|
if (DashboardMaxQueryRange.statesRestrictionHours(tooltipText)) {
|
|
expect(tooltipText).toContain("restriction of 3 hours");
|
|
} else {
|
|
testLogger.info(
|
|
"Streaming backend: tooltip reports the limit without naming hours",
|
|
{ tooltipText }
|
|
);
|
|
}
|
|
|
|
// Cleanup
|
|
await pm.dashboardCreate.backToDashboardList();
|
|
await deleteDashboard(page, dashboardName);
|
|
}
|
|
);
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Scenario 6: No warning when no max query range is set (default 0)
|
|
// --------------------------------------------------------------------------
|
|
test(
|
|
"should not display warning when max query range is not set on the stream",
|
|
{ tag: ["@maxQueryRange", "@P1"] },
|
|
async ({ page }) => {
|
|
const pm = new PageManager(page);
|
|
const mqr = pm.dashboardMaxQueryRange;
|
|
const dashboardName = generateDashboardName();
|
|
|
|
// Ensure no limit
|
|
await mqr.resetMaxQueryRange();
|
|
|
|
// Create dashboard with panel and wide time range
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardCreate.createDashboard(dashboardName);
|
|
await buildPanelWithWideRange(page, pm, "No Limit Panel", "area");
|
|
|
|
// Warning should NOT be visible since there is no max query range limit
|
|
await expect(pm.dashboardMaxQueryRange.warningIcon).not.toBeVisible({
|
|
timeout: 5000,
|
|
});
|
|
testLogger.info("No warning shown when max query range is not set");
|
|
|
|
// Cleanup
|
|
await pm.dashboardCreate.backToDashboardList();
|
|
await deleteDashboard(page, dashboardName);
|
|
}
|
|
);
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Scenario 7: Warning with multi-SQL queries on the same stream
|
|
// --------------------------------------------------------------------------
|
|
test.skip(
|
|
"should display max query range warning with multiple SQL queries on the same stream",
|
|
{ tag: ["@maxQueryRange", "@multiSQL", "@P2"] },
|
|
async ({ page }) => {
|
|
const pm = new PageManager(page);
|
|
const mqr = pm.dashboardMaxQueryRange;
|
|
const msql = pm.dashboardMultiSQL;
|
|
const dashboardName = generateDashboardName();
|
|
|
|
// Create dashboard and set restriction
|
|
await pm.dashboardList.menuItem("dashboards-item");
|
|
await waitForDashboardPage(page);
|
|
await pm.dashboardCreate.createDashboard(dashboardName);
|
|
await mqr.setMaxQueryRange(2);
|
|
|
|
// Add panel — set time range BEFORE selecting stream
|
|
await pm.dashboardCreate.addPanel();
|
|
await pm.chartTypeSelector.selectChartType("line");
|
|
|
|
await waitForDateTimeButtonToBeEnabled(page);
|
|
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
|
|
|
// 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
|
|
await msql.addQueryTab(1);
|
|
await pm.chartTypeSelector.selectStreamType("logs");
|
|
await pm.chartTypeSelector.selectStream(MAX_QUERY_STREAM);
|
|
await pm.chartTypeSelector.searchAndAddField("kubernetes_labels_name", "y");
|
|
|
|
// Apply and assert warning
|
|
await pm.dashboardPanelActions.applyDashboardBtn();
|
|
await pm.dashboardPanelActions.waitForChartToRender().catch(() => {});
|
|
|
|
await expect(pm.dashboardMaxQueryRange.warningIcon.first()).toBeVisible({
|
|
timeout: 15000,
|
|
});
|
|
testLogger.info("Warning visible with multi-SQL queries exceeding max range");
|
|
|
|
// Verify tooltip
|
|
const tooltipText = await mqr.getWarningTooltipText();
|
|
// Accept either backend wording — see expectRangeRestrictionTooltip.
|
|
mqr.expectRangeRestrictionTooltip(expect, tooltipText);
|
|
|
|
// Cleanup
|
|
await pm.dashboardPanelActions.addPanelName("MultiSQL Max Query Panel");
|
|
await pm.dashboardPanelActions.savePanel();
|
|
await pm.dashboardCreate.backToDashboardList();
|
|
await deleteDashboard(page, dashboardName);
|
|
}
|
|
);
|
|
});
|