UNPKG

e2ed

Version:

E2E testing framework over Playwright

113 lines (112 loc) 5.95 kB
"use strict"; /* eslint-disable no-labels */ Object.defineProperty(exports, "__esModule", { value: true }); exports.waitForInterfaceStabilization = void 0; const createClientFunction_1 = require("../../createClientFunction"); const config_1 = require("../../utils/config"); const getDurationWithUnits_1 = require("../../utils/getDurationWithUnits"); const log_1 = require("../../utils/log"); /** * This function in a universal way waits for the end of the movements and redrawing * of the page interface. The function takes on the duration of an interval during * which the interface must not change to be considered stable. * Then, every 250ms, a snapshot of the state of the interface is taken. * If the state does not change within the specified period, the function successfully * resolves the returned promise. * The state of the interface is the size of the window, scrolling in the entire window, * as well as the classes, sizes and positions of some DOM elements on the page. * Elements from different points on the page are taken as checked elements. */ const clientWaitForInterfaceStabilization = (0, createClientFunction_1.createClientFunction)((stabilizationInterval, timeout) => { const isPointInsideRectangle = (x, y, { left, top, width, height }) => x >= left && x <= left + width && y >= top && y <= top + height; const keyOfIgnoredElements = Symbol.for('e2ed:PageElementsIgnoredOnInterfaceStabilization'); const global = globalThis; const ignoredElementsSelectors = global[keyOfIgnoredElements] ?? []; const CHECK_INTERVAL_IN_MS = 250; const COUNT_OF_POINTED_NODES = 8; const startTimeInMs = Date.now(); const getInterfaceState = () => { const ignoredElements = []; for (const selector of ignoredElementsSelectors) { for (const element of document.querySelectorAll(selector)) { if (!ignoredElements.includes(element)) { ignoredElements.push(element); } } } const ignoredRectangles = ignoredElements.map((element) => element.getBoundingClientRect()); const { innerWidth, innerHeight } = window; const elements = [document.documentElement]; const deltaX = innerWidth / (COUNT_OF_POINTED_NODES + 1); const deltaY = innerHeight / (COUNT_OF_POINTED_NODES + 1); for (let xIndex = 1; xIndex <= COUNT_OF_POINTED_NODES; xIndex += 1) { Points: for (let yIndex = 1; yIndex <= COUNT_OF_POINTED_NODES; yIndex += 1) { const x = deltaX * xIndex; const y = deltaY * yIndex; for (const rectangle of ignoredRectangles) { // eslint-disable-next-line max-depth if (isPointInsideRectangle(x, y, rectangle)) { continue Points; } } const element = document.elementFromPoint(x, y); if (element && !elements.includes(element)) { elements.push(element); } } } const attributes = elements.map((element) => [ element.className, element.getBoundingClientRect(), element.scrollLeft, element.scrollTop, ]); return JSON.stringify([attributes, innerHeight, innerWidth]); }; let interfaceState = getInterfaceState(); let stabilizationIntervalStart = startTimeInMs; const promise = new Promise((resolve) => { const intervalId = setInterval(() => { const newInterfaceState = getInterfaceState(); if (newInterfaceState !== interfaceState) { stabilizationIntervalStart = Date.now(); } interfaceState = newInterfaceState; if (Date.now() - stabilizationIntervalStart >= stabilizationInterval) { clearInterval(intervalId); resolve(undefined); return; } if (Date.now() - startTimeInMs > timeout) { clearInterval(intervalId); resolve(`Time was out in waitForInterfaceStabilization (${timeout}ms)`); } }, CHECK_INTERVAL_IN_MS); }); return promise; }, { name: 'waitForInterfaceStabilization' }); /** * Waits until the page interface stabilizes (in particular, the page will stop scrolling). */ const waitForInterfaceStabilization = async (stabilizationInterval, timeout) => { if (stabilizationInterval === undefined || timeout === undefined) { const { waitForInterfaceStabilization: config } = (0, config_1.getFullPackConfig)(); const { stabilizationInterval: stabilizationIntervalFromConfig, timeout: timeoutFromConfig } = config; // eslint-disable-next-line no-param-reassign stabilizationInterval ??= stabilizationIntervalFromConfig; // eslint-disable-next-line no-param-reassign timeout ??= timeoutFromConfig; } if (!(stabilizationInterval > 0) || !(timeout > 0)) { return; } const startTimeInMs = Date.now(); const maybeErrorReason = await clientWaitForInterfaceStabilization(stabilizationInterval, timeout); const waitInMs = Date.now() - startTimeInMs; const startDateTimeInIso = new Date(startTimeInMs).toISOString(); const stabilizationIntervalWithUnits = (0, getDurationWithUnits_1.getDurationWithUnits)(stabilizationInterval); const timeoutWithUnits = (0, getDurationWithUnits_1.getDurationWithUnits)(timeout); const waitWithUnits = (0, getDurationWithUnits_1.getDurationWithUnits)(waitInMs); (0, log_1.log)(`Have waited for interface stabilization for ${waitWithUnits} with stabilization interval ${stabilizationIntervalWithUnits}`, { error: maybeErrorReason, startDateTimeInIso, timeout: timeoutWithUnits }, 7 /* LogEventType.InternalCore */); }; exports.waitForInterfaceStabilization = waitForInterfaceStabilization;