mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-03 16:10:21 +00:00
80 lines
3.2 KiB
JavaScript
80 lines
3.2 KiB
JavaScript
/**
|
|
* Waiting primitives shared by the on-call page objects.
|
|
*
|
|
* These exist to replace fixed `waitForTimeout` settles. A fixed sleep is a
|
|
* guess in both directions — too short and the read lands mid-repaint, too long
|
|
* and every call pays for the worst case — and it is silent either way.
|
|
*
|
|
* Two DIFFERENT needs, deliberately kept apart:
|
|
* - `settleRows` waits for something that must happen, and FAILS loudly if it
|
|
* never does.
|
|
* - `observeUntil` waits for something that may legitimately never happen and
|
|
* REPORTS which, because "it did not" is one of the answers its callers
|
|
* return rather than an error.
|
|
*/
|
|
|
|
const { expect } = require('@playwright/test');
|
|
|
|
/** OTable's own row hook. Index-based, so it restarts at 0 on every page. */
|
|
const TABLE_ROWS = '[data-test^="o2-table-row-"]';
|
|
|
|
/**
|
|
* A fingerprint of the rows currently drawn.
|
|
*
|
|
* The row index restarts at 0 on each page, so two different pages share the
|
|
* same `data-test` set — the text has to be part of the fingerprint or a page
|
|
* change is indistinguishable from no change at all. One round trip rather than
|
|
* one per row, because this is sampled repeatedly while waiting.
|
|
*/
|
|
async function rowSignature(page, rowSelector = TABLE_ROWS) {
|
|
return await page
|
|
.locator(rowSelector)
|
|
.evaluateAll((els) =>
|
|
els.map((el) => `${el.getAttribute('data-test')}:${(el.textContent || '').trim().slice(0, 80)}`).join('|'));
|
|
}
|
|
|
|
/**
|
|
* Wait until the table has stopped repainting.
|
|
*
|
|
* Requires several IDENTICAL consecutive samples rather than one pair: a single
|
|
* pair taken before the repaint has even begun looks perfectly stable, which is
|
|
* how this kind of wait passes for a fixed sleep with extra steps. Throws if the
|
|
* list never settles, so a genuinely stuck screen is reported and not absorbed.
|
|
*/
|
|
async function settleRows(page, { rowSelector = TABLE_ROWS, samples = 3, intervalMs = 150, timeout = 20000 } = {}) {
|
|
let previous = null;
|
|
let repeats = 0;
|
|
await expect
|
|
.poll(async () => {
|
|
const current = await rowSignature(page, rowSelector);
|
|
repeats = current === previous ? repeats + 1 : 0;
|
|
previous = current;
|
|
return repeats;
|
|
}, {
|
|
timeout,
|
|
intervals: [intervalMs],
|
|
message: 'the list never stopped repainting, so anything read off it would be a mid-refetch snapshot',
|
|
})
|
|
.toBeGreaterThanOrEqual(samples);
|
|
}
|
|
|
|
/**
|
|
* Poll `predicate` until it holds or the window closes, and report which.
|
|
*
|
|
* Deliberately NOT an assertion. Callers use this where "it never happened" is
|
|
* a result they return to the spec — a control that issues no request, a row
|
|
* that neither expands nor navigates — so throwing here would destroy the very
|
|
* observation the caller exists to make. Returns as soon as the predicate holds,
|
|
* so the full window is only ever paid when the answer really is "no".
|
|
*/
|
|
async function observeUntil(page, predicate, { timeout = 1200, intervalMs = 100 } = {}) {
|
|
const deadline = Date.now() + timeout;
|
|
for (;;) {
|
|
if (await predicate()) return true;
|
|
if (Date.now() >= deadline) return false;
|
|
await page.waitForTimeout(intervalMs);
|
|
}
|
|
}
|
|
|
|
module.exports = { TABLE_ROWS, rowSignature, settleRows, observeUntil };
|