test: cut alpha1 querier load from e2e helpers (#15462)

This commit is contained in:
Shrinath Rao
2026-10-16 18:15:26 +00:00
committed by GitHub
parent ce1ed757d1
commit 03e5e5863f
6 changed files with 64 additions and 26 deletions
+27 -5
View File
@@ -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"]', {
@@ -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();
@@ -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();
@@ -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
@@ -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<object>} - API response
* @returns {Promise<object>} - 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 });
@@ -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;