Я действительно нашел решение, которое работает, как я ожидал, и может быть искажено следующим образом:
Функция isElementClickable
, которая отвечает за проверку, кликабелен ли элемент:
function isElementClickable(element) {
const SCRIPT = `
const element = arguments[0];
// is element visible by styles
const styles = window.getComputedStyle(element);
if (!(styles.visibility !== 'hidden' && styles.display !== 'none')) {
return false;
}
// is the element behind another element
const boundingRect = element.getBoundingClientRect();
// adjust coordinates to get more accurate results
const left = boundingRect.left + 1;
const right = boundingRect.right - 1;
const top = boundingRect.top + 1;
const bottom = boundingRect.bottom - 1;
if (document.elementFromPoint(left, top) !== element ||
document.elementFromPoint(right, top) !== element ||
document.elementFromPoint(left, bottom) !== element ||
document.elementFromPoint(right, bottom) !== element) {
return false;
}
return true;
`;
return element.getDriver().executeScript(SCRIPT, element);
}
Функция 'elementIsClickableCondition', которую можно использовать вместо условия вместо webdriver.until.elementIsVisible
:
function elementIsClickableCondition(locator) {
return new webdriver.WebElementCondition('until element is visible', async function (driver) {
try {
// find the element(s)
const elements = await driver.findElements(locator);
if (elements.length > 1) {
throw new Error(`elementIsClickableCondition: the locator "${locator.toString()} identifies "${elements.length} instead of 1 element`);
} else if (elements.length < 1) {
return null;
}
const element = elements[0];
// basic check if the element is visible using the build-in functionality
if (!await element.isDisplayed()) {
return null;
}
// really check if the element is visible
const visible = await isElementClickable(element);
return visible ? element : null;
} catch (err) {
if (err instanceof webdriver.error.StaleElementReferenceError) {
return null;
} else {
throw err;
}
}
});
}