WebDriverError: перехвачен щелчок элемента: другой элемент получит обнаружение щелчка - PullRequest
0 голосов
/ 07 мая 2019

Я хотел бы определить, является ли элемент кликабельным , прежде чем пытаться щелкнуть по нему. В моем конкретном случае использования элемент скрывается другим элементом поверх него во время обработки, и когда это сделано, наложение удаляется, и элемент можно щелкнуть. К сожалению, условие elementIsVisible не считает элемент скрытым другим элементом, равно как и метод WebElement.isDisplayed элемента.

// find an element that is hidden behind some overlay
const hiddenElement = await driver.findElement(By.id('hiddenElement'));

// wait for element returns the "hidden" element
const await visibleElement = driver.wait(webdriver.until.elementIsVisible(hiddenElement));

// "isDisplayed" reports the "hidden" element as visible
const visible = await hiddenElement.isDisplayed();

Я мог бы четко использовать оверлейный элемент, чтобы определить, скрыт ли этот элемент, но это нужно будет настроить для каждого отдельного типа оверлея, и я на самом деле ищу более общий способ определения, является ли элемент на самом деле кликабельно .

1 Ответ

0 голосов
/ 08 мая 2019

Я действительно нашел решение, которое работает, как я ожидал, и может быть искажено следующим образом:

Функция 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;
            }
        }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...