From 03e5e5863fb3fac8322d0657f95fe6a4e86d5ff9 Mon Sep 17 00:00:00 2001 From: Shrinath Rao Date: Fri, 16 Oct 2026 18:15:26 +0000 Subject: [PATCH] test: cut alpha1 querier load from e2e helpers (#15462) --- tests/ui-testing/pages/logsPages/logsPage.js | 32 ++++++++++++++++--- .../Dashboards/dashboard-chartJson.spec.js | 12 +++---- .../playwright-tests/Logs/logspage.spec.js | 12 +++---- .../RegressionSet/Logs/logs-bugs.spec.js | 2 +- .../playwright-tests/utils/data-ingestion.js | 15 ++++++++- .../utils/global-setup-alpha1.js | 17 ++++++---- 6 files changed, 64 insertions(+), 26 deletions(-) diff --git a/tests/ui-testing/pages/logsPages/logsPage.js b/tests/ui-testing/pages/logsPages/logsPage.js index f69bc6633c..35ddbfcfee 100644 --- a/tests/ui-testing/pages/logsPages/logsPage.js +++ b/tests/ui-testing/pages/logsPages/logsPage.js @@ -962,10 +962,26 @@ export class LogsPage { } } + /** + * True when the current page is this org's logs page and was loaded moments ago, so it has no state to reset. + * @param {string} orgId + * @param {number} maxAgeMs + */ + async isFreshLogsPage(orgId, maxAgeMs = 15000) { + let url; + try { url = new URL(this.page.url()); } catch { return false; } + if (!url.pathname.endsWith('/web/logs') || url.searchParams.get('org_identifier') !== orgId) return false; + const ageMs = await this.page.evaluate(() => performance.now()).catch(() => Infinity); + return ageMs < maxAgeMs; + } + async selectStream(stream, maxRetries = 5, apiWaitMs = null, skipNavigation = false) { // Cloud environments need longer for streams to be indexed after ingestion const effectiveApiWaitMs = apiWaitMs ?? (isCloudEnvironment() ? 120000 : 30000); testLogger.info(`selectStream: Selecting stream: ${stream} (apiWait: ${effectiveApiWaitMs}ms, skipNavigation: ${skipNavigation})`); + const orgId = getOrgIdentifier(); + // Measured before the API wait, which takes time but leaves the UI untouched. + const freshLogsPage = !skipNavigation && await this.isFreshLogsPage(orgId); // First, wait for the stream to be available via API (skip if apiWaitMs is 0) if (effectiveApiWaitMs > 0) { @@ -982,10 +998,11 @@ export class LogsPage { // Navigate to logs page via URL to ensure fresh stream list. // skipNavigation=true bypasses page.goto when the caller is already // on the logs page and wants to avoid auto-triggering a query. - const orgId = getOrgIdentifier(); const logsUrl = `${process.env.ZO_BASE_URL}/web/logs?org_identifier=${orgId}`; - if (!skipNavigation) { + if (freshLogsPage) { + testLogger.info('selectStream: Logs page just loaded for this org — skipping reload (retries still reload if the stream is missing)'); + } else if (!skipNavigation) { testLogger.info(`selectStream: Navigating to logs page: ${logsUrl}`); await this.page.goto(logsUrl, { waitUntil: 'domcontentloaded', timeout: 30000 }).catch(() => {}); // Wait for the index-dropdown wrapper to mount instead of a hard timeout. @@ -1270,7 +1287,7 @@ export class LogsPage { // Wait for button to leave Cancel/loading state before clicking — // otherwise a click on "Cancel" aborts the in-flight query instead // of starting a fresh one. - await this.page.waitForFunction( + const settled = await this.page.waitForFunction( (sel) => { const b = document.querySelector(sel); if (!b) return false; @@ -1280,8 +1297,13 @@ export class LogsPage { }, this.queryButton, { timeout: 30000 }, - ).catch(() => {}); - await queryBtn.click(); + ).then(() => true).catch(() => false); + // A retry on a still-busy button would cancel and restart the same search; keep waiting on it instead. + if (settled || attempt === 1) { + await queryBtn.click(); + } else { + testLogger.debug(`selectRunQuery: search still running on attempt ${attempt} — waiting instead of re-clicking`); + } try { await this.page.waitForSelector('[data-test="logs-search-result-logs-table"]', { diff --git a/tests/ui-testing/playwright-tests/Dashboards/dashboard-chartJson.spec.js b/tests/ui-testing/playwright-tests/Dashboards/dashboard-chartJson.spec.js index 1e41dfbe1f..c82a602277 100644 --- a/tests/ui-testing/playwright-tests/Dashboards/dashboard-chartJson.spec.js +++ b/tests/ui-testing/playwright-tests/Dashboards/dashboard-chartJson.spec.js @@ -113,7 +113,7 @@ test.describe("dashboard UI testcases", () => { // we toggle JSON rendering on the field — mirrors test 4's pattern, // which avoids the race between the v-model toggle on // `fields.showFieldAsJson` and the first panel-schema build. - await pm.dateTimeHelper.setRelativeTimeRange("6-w"); + await pm.dateTimeHelper.setRelativeTimeRange("1-h"); await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); @@ -181,7 +181,7 @@ test.describe("dashboard custom query mode field options testcases", () => { await page.waitForTimeout(1000); // Set date-time range - await pm.dateTimeHelper.setRelativeTimeRange("6-w"); + await pm.dateTimeHelper.setRelativeTimeRange("1-h"); await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); @@ -238,7 +238,7 @@ test.describe("dashboard custom query mode field options testcases", () => { await page.waitForTimeout(1000); // Set date-time range - await pm.dateTimeHelper.setRelativeTimeRange("6-w"); + await pm.dateTimeHelper.setRelativeTimeRange("1-h"); await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); @@ -295,7 +295,7 @@ test.describe("dashboard custom query mode field options testcases", () => { await page.waitForTimeout(1000); // Set date-time range - await pm.dateTimeHelper.setRelativeTimeRange("6-w"); + await pm.dateTimeHelper.setRelativeTimeRange("1-h"); await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); @@ -354,7 +354,7 @@ test.describe("dashboard custom query mode field options testcases", () => { await page.waitForTimeout(1000); // Set date-time range - await pm.dateTimeHelper.setRelativeTimeRange("6-w"); + await pm.dateTimeHelper.setRelativeTimeRange("1-h"); await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); @@ -409,7 +409,7 @@ test.describe("dashboard custom query mode field options testcases", () => { await page.waitForTimeout(1000); // Set date-time range - await pm.dateTimeHelper.setRelativeTimeRange("6-w"); + await pm.dateTimeHelper.setRelativeTimeRange("1-h"); await pm.dashboardPanelActions.applyDashboardBtn(); await pm.dashboardPanelActions.waitForChartToRender(); diff --git a/tests/ui-testing/playwright-tests/Logs/logspage.spec.js b/tests/ui-testing/playwright-tests/Logs/logspage.spec.js index 745bfb6aea..8465a8a696 100644 --- a/tests/ui-testing/playwright-tests/Logs/logspage.spec.js +++ b/tests/ui-testing/playwright-tests/Logs/logspage.spec.js @@ -102,8 +102,7 @@ test.describe("Logs Page testcases", () => { }, async ({ page }) => { testLogger.info('Testing VRL query execution with valid text'); await pm.logsPage.clickDateTimeButton(); - await pm.logsPage.waitForRelative6WeeksButtonVisible(); - await pm.logsPage.clickRelative6WeeksButton(); + await pm.logsPage.clickRelative15MinButton(); await applyQueryButton(pm); await pm.logsPage.toggleVrlEditor(); @@ -125,7 +124,7 @@ test.describe("Logs Page testcases", () => { }, async ({ page }) => { testLogger.info('Testing field list collapse/expand functionality'); await pm.logsPage.clickDateTimeButton(); - await pm.logsPage.clickRelative6WeeksButton(); + await pm.logsPage.clickRelative15MinButton(); await pm.logsPage.clickShowQueryToggle(); await pm.logsPage.clickFieldListCollapseButton(); await page.waitForLoadState('domcontentloaded'); // Replace hard wait @@ -140,7 +139,7 @@ test.describe("Logs Page testcases", () => { }, async ({ page }) => { testLogger.info('Testing saved views name validation with special characters'); await pm.logsPage.clickDateTimeButton(); - await pm.logsPage.clickRelative6WeeksButton(); + await pm.logsPage.clickRelative15MinButton(); await pm.logsPage.clickShowQueryToggle(); await pm.logsPage.clickSavedViewsButton(); // Allowed: alphanumeric, spaces, underscores, hyphens (/^[A-Za-z0-9 _-]+$/) @@ -172,8 +171,7 @@ test.describe("Logs Page testcases", () => { }, async ({ page }) => { testLogger.info('Testing logs results display on graph'); await pm.logsPage.clickDateTimeButton(); - await pm.logsPage.waitForRelative6WeeksButtonVisible(); - await pm.logsPage.clickRelative6WeeksButton(); + await pm.logsPage.clickRelative15MinButton(); await applyQueryButton(pm); await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {}); // Replace long hard wait await pm.logsPage.expectSearchListVisible(); @@ -192,7 +190,7 @@ test.describe("Logs Page testcases", () => { testLogger.info('Testing live mode functionality with 5 second interval'); await page.route("**/logData.ValueQuery", (route) => route.continue()); await pm.logsPage.clickDateTimeButton(); - await pm.logsPage.clickRelative6WeeksButton(); + await pm.logsPage.clickRelative15MinButton(); await pm.logsPage.clickLiveModeButton(); // Wait for the 5-sec live-mode option to be enabled in the dropdown await pm.logsPage.waitForLiveMode5SecReady(); diff --git a/tests/ui-testing/playwright-tests/RegressionSet/Logs/logs-bugs.spec.js b/tests/ui-testing/playwright-tests/RegressionSet/Logs/logs-bugs.spec.js index 49092710eb..5686df3a6f 100644 --- a/tests/ui-testing/playwright-tests/RegressionSet/Logs/logs-bugs.spec.js +++ b/tests/ui-testing/playwright-tests/RegressionSet/Logs/logs-bugs.spec.js @@ -1167,7 +1167,7 @@ test.describe("Logs Regression Bug Fixes", () => { // Set wide time range to get more records await pm.logsPage.clickDateTimeButton(); await page.waitForTimeout(500); - await pm.logsPage.clickRelative6WeeksButton(); + await pm.logsPage.clickRelative15MinButton(); await page.waitForTimeout(500); // Run query diff --git a/tests/ui-testing/playwright-tests/utils/data-ingestion.js b/tests/ui-testing/playwright-tests/utils/data-ingestion.js index 92676c679a..46b440889a 100644 --- a/tests/ui-testing/playwright-tests/utils/data-ingestion.js +++ b/tests/ui-testing/playwright-tests/utils/data-ingestion.js @@ -2,11 +2,16 @@ const testLogger = require('./test-logger.js'); const logsdata = require("../../../test-data/logs_data.json"); const { getAuthHeaders, getOrgIdentifier } = require('./cloud-auth.js'); +// Rows are stamped at ingest, so a 5-min refresh keeps them inside every 15-min test window. +const SHARED_STREAM = 'e2e_automate'; +const SHARED_STREAM_REFRESH_MS = 5 * 60 * 1000; +const lastSharedIngest = new Map(); + /** * Ingest test data into a stream via API using Node.js context (secure) * @param {import('@playwright/test').Page} page - Playwright page object * @param {string} streamName - Name of the stream to ingest data into (default: "e2e_automate") - * @returns {Promise} - API response + * @returns {Promise} - API response, or `{ skipped: true }` when this worker refreshed the shared stream within the last 5 min */ async function ingestTestData(page, streamName = "e2e_automate") { const orgId = getOrgIdentifier(); @@ -15,11 +20,19 @@ async function ingestTestData(page, streamName = "e2e_automate") { ? process.env.INGESTION_URL.slice(0, -1) : process.env.INGESTION_URL; + const sharedKey = `${orgId}:${streamName}`; + const lastIngest = streamName === SHARED_STREAM ? lastSharedIngest.get(sharedKey) : undefined; + if (lastIngest && Date.now() - lastIngest < SHARED_STREAM_REFRESH_MS) { + testLogger.debug('Test data ingestion skipped — this worker refreshed the shared stream recently', { streamName, ageMs: Date.now() - lastIngest }); + return { skipped: true }; + } + try { const response = await page.request.post(`${baseUrl}/api/${orgId}/${streamName}/_json`, { headers: headers, data: logsdata }); + if (response.ok() && streamName === SHARED_STREAM) lastSharedIngest.set(sharedKey, Date.now()); const responseData = await response.json().catch(() => ({ error: 'Failed to parse JSON' })); testLogger.debug('Test data ingestion response', { response: responseData, streamName }); diff --git a/tests/ui-testing/playwright-tests/utils/global-setup-alpha1.js b/tests/ui-testing/playwright-tests/utils/global-setup-alpha1.js index 7c26346a93..df88c65810 100644 --- a/tests/ui-testing/playwright-tests/utils/global-setup-alpha1.js +++ b/tests/ui-testing/playwright-tests/utils/global-setup-alpha1.js @@ -560,16 +560,18 @@ async function performGlobalIngestion(page) { const maxWaitMs = 90000; const pollIntervalMs = 3000; const startTime = Date.now(); + let lastSeen = 'no response'; while (Date.now() - startTime < maxWaitMs) { try { const streamsResult = await page.evaluate(async ({ orgId, headers }) => { - const r = await fetch(`/api/${orgId}/streams?type=logs&page_num=0&page_size=1000`, { headers }); + const r = await fetch(`/api/${orgId}/streams?type=logs&keyword=e2e_automate`, { headers }); if (!r.ok) return { ok: false, status: r.status }; const data = await r.json(); const names = (data.list || []).map(s => s.name); - return { ok: true, names }; + return { ok: true, status: r.status, names }; }, { orgId, headers }); + lastSeen = `HTTP ${streamsResult.status}, names=[${(streamsResult.names || []).join(',')}]`; if (streamsResult.ok) { const hasE2e = streamsResult.names.includes('e2e_automate'); @@ -589,7 +591,7 @@ async function performGlobalIngestion(page) { } if (Date.now() - startTime >= maxWaitMs) { - testLogger.warn(`[alpha1] Streams not fully indexed after ${maxWaitMs}ms — tests may fail on stream selection`); + testLogger.warn(`[alpha1] Streams not fully indexed after ${maxWaitMs}ms (last: ${lastSeen}) — tests may fail on stream selection`); } } @@ -709,25 +711,28 @@ async function performGlobalIngestionWithFetch() { const maxWaitMs = 90000; const pollIntervalMs = 3000; const startTime = Date.now(); + let lastSeen = 'no response'; while (Date.now() - startTime < maxWaitMs) { try { - const r = await fetch(`${baseUrl}/api/${orgId}/streams?type=logs&page_num=0&page_size=1000`, { headers }); + const r = await fetch(`${baseUrl}/api/${orgId}/streams?type=logs&keyword=e2e_automate`, { headers }); + lastSeen = `HTTP ${r.status}`; if (r.ok) { const data = await r.json(); const names = (data.list || []).map(s => s.name); + lastSeen += `, names=[${names.join(',')}]`; if (names.includes('e2e_automate')) { testLogger.info(`[alpha1] e2e_automate indexed after ${Date.now() - startTime}ms`); return; } } } catch (e) { - testLogger.debug(`[alpha1] Error checking streams: ${e.message}`); + lastSeen = `error: ${e.message}`; } await new Promise(r => setTimeout(r, pollIntervalMs)); } - testLogger.warn(`[alpha1] Streams not fully indexed after ${maxWaitMs}ms — tests may fail on stream selection`); + testLogger.warn(`[alpha1] Streams not fully indexed after ${maxWaitMs}ms (last: ${lastSeen}) — tests may fail on stream selection`); } module.exports = globalSetup;