mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 08:09:27 +00:00
test(dashboard): fix flaky tests in deployed environment (#9511)
### **User description** …riables ___ ### **PR Type** Tests, Enhancement ___ ### **Description** - Refine chart-render wait logic with class checks - Integrate values-stream helper in variable dropdown - Standardize relative time ranges to 30m - Improve streaming test with API wait loops ___ <details> <summary><h3> File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Formatting</strong></td><td><details><summary>2 files</summary><table> <tr> <td><strong>apiCleanup.js</strong><dd><code>Remove extraneous newline at EOF</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-537fe76c0d8e26e81c5f77c83bd0ee35daaa973822105c809bf83171a26b33c5">+1/-1</a> </td> </tr> <tr> <td><strong>cleanup.spec.js</strong><dd><code>Remove trailing blank line</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-c214275a512fa285a7e4f2ab61dfcb42d71a0436b0e4241f94d7b45693587983">+1/-0</a> </td> </tr> </table></details></td></tr><tr><td><strong>Enhancement</strong></td><td><details><summary>4 files</summary><table> <tr> <td><strong>dashboard-panel-actions.js</strong><dd><code>Refine waitForChartToRender class checks</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-d29713fdcc11cbc93bda29da5261da389226cd718e4292a1c2cd96629f573a80">+27/-10</a> </td> </tr> <tr> <td><strong>dashboard-variables.js</strong><dd><code>Add stream helper and input typing delay</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-67d38d39bb67f4a0cbfa473ee81ad50b1fffebc40c635417e58905f3c865a6e2">+18/-3</a> </td> </tr> <tr> <td><strong>dashboard-streaming.spec.js</strong><dd><code>Add API wait loops in streaming test</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-92f44296937f53cb448371d1c61510c8c910fbecab83b02b8e89490d5832be19">+36/-4</a> </td> </tr> <tr> <td><strong>streaming-helpers.js</strong><dd><code>Implement waitForValuesStreamComplete utility</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-ba793998d7c077815ee18543001a519b7d45a9236990b60d256124a4b30d48cb">+65/-1</a> </td> </tr> </table></details></td></tr><tr><td><strong>Tests</strong></td><td><details><summary>6 files</summary><table> <tr> <td><strong>dashboard-geoMap.spec.js</strong><dd><code>Update time range to 30m</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-6ae8394cd6b915e6d55a179cf6c7dc32992b8ebbd5d9aac177c0cbd1b9f351b3">+1/-1</a> </td> </tr> <tr> <td><strong>dashboard-html-chart.spec.js</strong><dd><code>Set html chart time to 30m</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-02c503aa87193168f5aa83c8105c376ea0c4dc45e6c7bd6f255b693bf7ebc462">+1/-1</a> </td> </tr> <tr> <td><strong>dashboard-multi-y-axis.spec.js</strong><dd><code>Update multi-y-axis time to 30m</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-e90516a105c0b17c8e04c18e2b67ac10af213dbdd208fa4414cdcb7e377e6ee5">+2/-2</a> </td> </tr> <tr> <td><strong>dashboard-transpose.spec.js</strong><dd><code>Change transpose time range to 30m</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-da631007cea76a4bc59e4acd1195b59ae4131cd5208d21a9c1f94d3913911dc4">+1/-1</a> </td> </tr> <tr> <td><strong>dashboard.spec.js</strong><dd><code>Adjust gauge and table time ranges to 15m</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-d0fa0042783dc109334b05266edce228bad97adcb568dd1e447920596238e9b4">+5/-5</a> </td> </tr> <tr> <td><strong>dashboard2.spec.js</strong><dd><code>Standardize dashboard2 time to 30m</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-8c9189e9e3950fff987c45ee8116d89f15f8fdec5baad209bef6f5858f3b3045">+7/-7</a> </td> </tr> </table></details></td></tr><tr><td><strong>Configuration changes</strong></td><td><details><summary>1 files</summary><table> <tr> <td><strong>playwright.yml</strong><dd><code>Fix typo in run_files list</code> </dd></td> <td><a href="https://github.com/openobserve/openobserve/pull/9511/files#diff-7afcd2d8f7b49bda74843f209eefb7b2da45f7e7803bf2e4bd636699b76aa2d3">+1/-0</a> </td> </tr> </table></details></td></tr></tr></tbody></table> </details> ___ --------- Co-authored-by: ktx-abhay <abhay.padamani@kiara.tech>
This commit is contained in:
@@ -168,6 +168,7 @@ jobs:
|
||||
"dashboard-folder.spec.js",
|
||||
"dashboard-import.spec.js",
|
||||
"maxquery.spec.js",
|
||||
"dashboard-chartJson.spec.js",
|
||||
]
|
||||
- testfolder: "Dashboards-Settings"
|
||||
browser: "chrome"
|
||||
|
||||
@@ -2611,4 +2611,4 @@ class APICleanup {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = APICleanup;
|
||||
module.exports = APICleanup;
|
||||
@@ -37,18 +37,35 @@ export default class DashboardactionPage {
|
||||
|
||||
async waitForChartToRender() {
|
||||
// Wait for button or parent to have light button class (render complete)
|
||||
// Supports both repo structures: button.o2-primary-button-light OR parent.o2-secondary-button-light
|
||||
// The parent div.q-btn-group has classes o2-primary-button and o2-secondary-button-light
|
||||
await this.page.waitForFunction(() => {
|
||||
const btn = document.querySelector('[data-test="dashboard-apply"]');
|
||||
return (
|
||||
btn &&
|
||||
(btn.classList.contains("o2-primary-button-light") ||
|
||||
btn.classList.contains("o2-secondary-button-light") ||
|
||||
(btn.parentElement &&
|
||||
(btn.parentElement.classList.contains("o2-primary-button-light") ||
|
||||
btn.parentElement.classList.contains("o2-secondary-button-light"))))
|
||||
);
|
||||
});
|
||||
if (!btn) return false;
|
||||
|
||||
// Check button itself
|
||||
if (btn.classList.contains("o2-primary-button-light") ||
|
||||
btn.classList.contains("o2-secondary-button-light")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check immediate parent (button group container)
|
||||
const parent = btn.parentElement;
|
||||
if (parent &&
|
||||
(parent.classList.contains("o2-primary-button-light") ||
|
||||
parent.classList.contains("o2-secondary-button-light"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if parent has both o2-primary-button AND o2-secondary-button-light
|
||||
// (which indicates the button group is in the rendered state)
|
||||
if (parent &&
|
||||
parent.classList.contains("o2-primary-button") &&
|
||||
parent.classList.contains("o2-secondary-button-light")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}, { timeout: 30000 });
|
||||
}
|
||||
|
||||
//Dashboard panel actions(Edit, Layout, Duplicate, Inspector, Move, Delete)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//methods: addDashboardVariable, selectValueFromVariableDropDown
|
||||
//addDashboardVariable params: name, streamtype, streamName, field, customValueSearch, filterConfig, showMultipleValues
|
||||
import { expect } from "@playwright/test";
|
||||
import { waitForValuesStreamComplete } from "../../playwright-tests/utils/streaming-helpers.js";
|
||||
|
||||
export default class DashboardVariables {
|
||||
constructor(page) {
|
||||
@@ -56,13 +57,11 @@ export default class DashboardVariables {
|
||||
await this.page
|
||||
.getByRole("option", { name: streamName, exact: true })
|
||||
.click();
|
||||
|
||||
// Select Field
|
||||
const fieldSelect = await this.page.locator('[data-test="dashboard-variable-field-select"]');
|
||||
await fieldSelect.click();
|
||||
await this.page.keyboard.type(field);
|
||||
await this.page.keyboard.type(field, {delay:100});
|
||||
|
||||
|
||||
// Wait for dropdown to have options available
|
||||
await this.page.waitForFunction(
|
||||
() => {
|
||||
@@ -225,9 +224,25 @@ export default class DashboardVariables {
|
||||
async selectValueFromVariableDropDown(label, value) {
|
||||
const input = this.page.getByLabel(label, { exact: true });
|
||||
await input.waitFor({ state: "visible", timeout: 10000 });
|
||||
|
||||
// Wait for _values_stream API call when clicking on the dropdown
|
||||
// Start listening before the action to ensure we capture the stream
|
||||
const valuesStreamPromise = waitForValuesStreamComplete(this.page);
|
||||
|
||||
await input.click();
|
||||
|
||||
// Wait for the values stream to complete (waits for 'data: [[DONE]]' marker)
|
||||
await valuesStreamPromise;
|
||||
|
||||
// Wait for _values_stream API call when filling/searching
|
||||
// Start listening before filling to capture the search stream
|
||||
// const searchStreamPromise = waitForValuesStreamComplete(this.page);
|
||||
|
||||
await input.fill(value);
|
||||
|
||||
// // Wait for search stream to complete (waits for 'data: [[DONE]]' marker)
|
||||
// await searchStreamPromise;
|
||||
|
||||
const option = this.page.getByRole("option", { name: value });
|
||||
await option.waitFor({ state: "visible", timeout: 10000 });
|
||||
await option.click();
|
||||
|
||||
@@ -196,3 +196,4 @@ test.describe("Pre-Test Cleanup", () => {
|
||||
testLogger.info('Pre-test cleanup completed successfully');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ test.describe("dashboard maps testcases", () => {
|
||||
);
|
||||
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
// await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
await pm.dashboardPanelActions.waitForChartToRender();
|
||||
|
||||
@@ -136,7 +136,7 @@ test.describe("HTML chart dashboard", () => {
|
||||
|
||||
await pm.chartTypeSelector.selectChartType("html");
|
||||
|
||||
await pm.dashboardTimeRefresh.setRelative("15", "m");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
|
||||
await page
|
||||
.locator('[data-test="dashboard-html-editor"]')
|
||||
|
||||
@@ -59,7 +59,7 @@ test.describe("dashboard multi y axis testcases", () => {
|
||||
await pm.chartTypeSelector.searchAndAddField("kubernetes_labels_name", "b");
|
||||
|
||||
// Set the relative time range
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("30-m");
|
||||
|
||||
// Apply the configuration and wait for the chart to render
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
@@ -122,7 +122,7 @@ test.describe("dashboard multi y axis testcases", () => {
|
||||
await pm.chartTypeSelector.searchAndAddField("kubernetes_labels_name", "b");
|
||||
|
||||
// Set the relative time range
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("30-m");
|
||||
|
||||
// Apply the configuration and wait for the chart to render
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
@@ -87,21 +87,53 @@ test.describe("dashboard streaming testcases", () => {
|
||||
);
|
||||
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
await pm.dashboardPanelActions.waitForChartToRender();
|
||||
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
|
||||
await pm.dashboardPanelActions.waitForChartToRender();
|
||||
|
||||
|
||||
const variableInput = page.getByLabel("variablename", {
|
||||
exact: true,
|
||||
});
|
||||
await variableInput.waitFor({ state: "visible", timeout: 10000 });
|
||||
|
||||
// Wait for the _values API call when clicking on the variable input
|
||||
const valuesApiPromise = page.waitForResponse(
|
||||
response => response.url().includes('_values') || response.url().includes('/values'),
|
||||
{ timeout: 15000 }
|
||||
);
|
||||
|
||||
await variableInput.click();
|
||||
|
||||
// Wait for the API response to complete
|
||||
try {
|
||||
await valuesApiPromise;
|
||||
await page.waitForTimeout(500); // Additional wait for dropdown to render
|
||||
} catch (e) {
|
||||
console.log("Warning: _values API response not detected, continuing...");
|
||||
}
|
||||
|
||||
// Type partial search terms to trigger multiple _values API calls with streaming enabled
|
||||
const searchTerms = ["zi", "zio", "ziox"];
|
||||
for (const term of searchTerms) {
|
||||
// Wait for the _values API call for each search term
|
||||
const valuesApiResponse = page.waitForResponse(
|
||||
response => response.url().includes('_values') || response.url().includes('/values'),
|
||||
{ timeout: 15000 }
|
||||
);
|
||||
|
||||
await variableInput.fill(term);
|
||||
// await page.waitForTimeout(1500);
|
||||
// await page.waitForLoadState("networkidle");
|
||||
|
||||
// Wait for the API response to complete
|
||||
try {
|
||||
await valuesApiResponse;
|
||||
await page.waitForTimeout(300); // Wait for dropdown to update with new results
|
||||
} catch (e) {
|
||||
console.log(`Warning: _values API response not detected for term "${term}", continuing...`);
|
||||
}
|
||||
}
|
||||
// Select the final value
|
||||
const option = page.getByRole("option", { name: "ziox" });
|
||||
@@ -262,7 +294,7 @@ test.describe("dashboard streaming testcases", () => {
|
||||
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
await pm.dashboardPanelActions.waitForChartToRender();
|
||||
|
||||
|
||||
|
||||
@@ -352,7 +352,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
await pm.chartTypeSelector.searchAndAddField("xAxis", "y");
|
||||
|
||||
// Set relative time range
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
|
||||
await pm.dashboardPanelActions.waitForChartToRender();
|
||||
|
||||
|
||||
@@ -419,7 +419,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
);
|
||||
|
||||
// Set date-time and timezone for gauge chart
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("6-w");
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("15-m");
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
// Verify the gauge chart is visible
|
||||
@@ -429,7 +429,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
await pm.chartTypeSelector.selectChartType("table");
|
||||
|
||||
// Set timezone for the table chart
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("1-w");
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("15-m");
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
await pm.dashboardPanelActions.waitForChartToRender();
|
||||
|
||||
@@ -471,7 +471,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
);
|
||||
|
||||
// Set date-time filter
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("5-w");
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("15-m");
|
||||
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
@@ -521,7 +521,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
|
||||
// Set date-time filter and timezone
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
// Attempt to save the panel without a name
|
||||
@@ -579,7 +579,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "filter");
|
||||
|
||||
// Set time range and apply
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("5-w");
|
||||
await pm.dateTimeHelper.setRelativeTimeRange("15-m");
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
// Apply "Is Null" filter
|
||||
|
||||
@@ -101,7 +101,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
|
||||
// Set relative time
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
// Cancel adding the breakdown field
|
||||
@@ -155,7 +155,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
|
||||
// Set the date-time range and apply changes
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
// Change chart types and verify
|
||||
@@ -220,7 +220,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
|
||||
// Set the date-time range and apply changes
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
// Save the dashboard panel
|
||||
@@ -261,7 +261,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
await pm.chartTypeSelector.searchAndAddField("kubernetes_host", "b");
|
||||
|
||||
// Set the date-time range
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
// Refresh the page
|
||||
@@ -307,7 +307,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
|
||||
// Set relative date-time and timezone
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
|
||||
// await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
|
||||
@@ -393,7 +393,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
|
||||
// Set relative date-time and timezone
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
await pm.dashboardPanelActions.applyDashboardBtn();
|
||||
await pm.dashboardPanelActions.savePanel();
|
||||
|
||||
@@ -436,7 +436,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
|
||||
// Set relative date-time
|
||||
await waitForDateTimeButtonToBeEnabled(page);
|
||||
await pm.dashboardTimeRefresh.setRelative("6", "w");
|
||||
await pm.dashboardTimeRefresh.setRelative("30", "m");
|
||||
|
||||
// Configure no value replacement
|
||||
await pm.dashboardPanelConfigs.openConfigPanel();
|
||||
|
||||
@@ -6,13 +6,18 @@ const testLogger = require('./test-logger.js');
|
||||
*
|
||||
* Usage:
|
||||
* ```javascript
|
||||
* import { waitForStreamComplete, waitForTableWithData } from '../utils/streaming-helpers.js';
|
||||
* import { waitForStreamComplete, waitForValuesStreamComplete, waitForTableWithData } from '../utils/streaming-helpers.js';
|
||||
*
|
||||
* // Wait for a streaming API to complete
|
||||
* const streamPromise = waitForStreamComplete(page);
|
||||
* await someAction();
|
||||
* await streamPromise;
|
||||
*
|
||||
* // Wait for values stream to complete
|
||||
* const valuesStreamPromise = waitForValuesStreamComplete(page);
|
||||
* await page.click('#field-dropdown');
|
||||
* await valuesStreamPromise;
|
||||
*
|
||||
* // Wait for table to have data
|
||||
* await waitForTableWithData(page);
|
||||
* ```
|
||||
@@ -81,6 +86,65 @@ export async function waitForStreamComplete(page, timeout = 15000) {
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a values stream API call to complete by listening for the 'data: [[DONE]]' marker.
|
||||
* This is specifically designed for the _values_stream endpoint.
|
||||
*
|
||||
* The function monitors the _values_stream endpoint and resolves when it receives
|
||||
* the completion marker 'data: [[DONE]]' in the response body.
|
||||
*
|
||||
* @param {import('@playwright/test').Page} page - The Playwright page object
|
||||
* @param {number} timeout - Maximum time to wait in milliseconds (default: 15000)
|
||||
* @returns {Promise<void>} Resolves when values stream completes or times out
|
||||
*
|
||||
* @example
|
||||
* // Start listening before triggering the request
|
||||
* const streamPromise = waitForValuesStreamComplete(page);
|
||||
* await page.click('#field-dropdown');
|
||||
* await streamPromise; // Wait for values streaming to finish
|
||||
*/
|
||||
export async function waitForValuesStreamComplete(page, timeout = 15000) {
|
||||
return Promise.race([
|
||||
new Promise((resolve) => {
|
||||
const responseHandler = async (response) => {
|
||||
const url = response.url();
|
||||
|
||||
// Check if this is a values stream endpoint
|
||||
if (url.includes('_values_stream')) {
|
||||
|
||||
try {
|
||||
// Read the response body as text
|
||||
const body = await response.text();
|
||||
|
||||
// Check if stream has completed with 'data: [[DONE]]' marker
|
||||
if (body.includes('data: [[DONE]]')) {
|
||||
testLogger.info(`Values stream completed for: ${url.split('/').pop()}`);
|
||||
page.off('response', responseHandler);
|
||||
resolve();
|
||||
}
|
||||
} catch (error) {
|
||||
// Response body might not be available or already consumed
|
||||
testLogger.debug(`Could not read response body: ${error.message}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
page.on('response', responseHandler);
|
||||
|
||||
// Clean up listener if it somehow doesn't resolve
|
||||
setTimeout(() => {
|
||||
page.off('response', responseHandler);
|
||||
}, timeout + 1000);
|
||||
}),
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
testLogger.warn('Values stream wait timeout - continuing anyway');
|
||||
resolve();
|
||||
}, timeout);
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the table to have data rows before proceeding.
|
||||
* This ensures the table has been populated with actual data from the stream.
|
||||
|
||||
Reference in New Issue
Block a user