Как заставить Selenium WebDriver щелкнуть элемент, который в настоящее время не отображается?

99

Я использую Java API Selenium 2 с FirefoxDriver. Когда я заполняю форму, на страницу добавляются флажки в зависимости от входных данных формы.

Я хотел бы смоделировать щелчок по этим флажкам с помощью Selenium. Элемент виден и может использоваться в обычном браузере, но селен утверждает, что элементы не видны.

"Element is not currently visible and so may not be interacted with"

Могу ли я заставить селен игнорировать невидимое состояние элементов? Как заставить Selenium взаимодействовать с невидимым элементом?

джондал
источник
Какой браузер вы используете? Вы не можете взаимодействовать с элементами, которые отключены или невидимы, потому что конечный пользователь не сможет взаимодействовать с ними. Вам нужно будет предоставить свой тестовый код и исходный код страницы, если вы хотите, чтобы я попытался диагностировать проблему.
Ardesco

Ответы:

102

Selenium определяет, является ли элемент видимым или нет, по следующим критериям (используйте инспектор DOM, чтобы определить, какой CSS применяется к вашему элементу, убедитесь, что вы смотрите на вычисленный стиль):

  • видимость! = скрыто
  • display! = none (также проверяется по каждому родительскому элементу)
  • непрозрачность! = 0 (при щелчке по элементу не проверяется)
  • высота и ширина> 0
  • для входа тип атрибута! = hidden

Ваш элемент соответствует одному из этих критериев. Если у вас нет возможности изменить стиль элемента, вот как вы можете принудительно сделать это с помощью javascript (предполагается, что WebDriver, поскольку вы сказали Selenium2 API):

((JavascriptExecutor)driver).executeScript("arguments[0].checked = true;", inputElement);

Но это не вызовет событие javascript, если вы зависите от события изменения для этого ввода, вам также придется запустить его (много способов сделать это, проще всего использовать любую библиотеку javascript, загруженную на этой странице).

Источник проверки видимости -

https://github.com/SeleniumHQ/selenium/blob/master/javascript/atoms/dom.js#L577

Спецификация WebDriver, которая определяет это -

https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html#widl-WebElement-isDisplayed-boolean

Lukeis
источник
1
У вас есть источник (или каноническая ссылка) для списка условий?
mjs
2
Если вы умеете читать Javascript, видимость определяется методом bot.dom.isShown: code.google.com/p/selenium/source/browse/trunk/javascript/atoms/…
Люкис
что здесь inputElement. Я запускаю приведенный ниже код WebElement inputElement = driver.findElement (By.xpath (PASSWORD_PATH)); ((Драйвер JavascriptExecutor)) .executeScript ("arguments [0] .checked = true;", inputElement); Но нет справки inputElement.sendKeys (пароль);
Deepak Goel
2
@NIleshSharma python имеет метод execute_script непосредственно в самом объекте драйвера: driver.execute_script (...)
Люкис,
1
Ссылка на источник, размещенная @TunaBum, изменилась на code.google.com/p/selenium/source/browse/javascript/atoms/…
Shepmaster
27

Иногда это означает, что на странице есть несколько элементов с одним и тем же свойством, по которому вы пытаетесь выполнить поиск, и вы «говорите не с тем».

Если ваш элемент не может быть однозначно идентифицирован по: id или: name (или: class), это может быть сложно.

Иногда поиск элемента по: xpath помогает, а в некоторых случаях даже это непрактично.

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

Я использую Selenium / Watir из приложения Ruby on Rails, поэтому в моем случае пример будет следующим:

browser = Watir::Browser.new(:firefox, :profile => "default")       
browser.goto("http://www.google.com/analytics")
# login
browser.divs(:text, "+ New Property").last.click

Надеюсь это поможет.

ranktrackerpro
источник
добавление идентификатора к элементу dom исправило это для меня
naoru
У меня была такая же проблема, и настройка XPath, чтобы он мог различать уникальный элемент, помогала.
JohnL
У меня такая же проблема. Изменен вызов findElements () для подсчета совпадений, и появился еще один соответствующий элемент. Спасибо!
Овен
Так много для меня. ВСЕГДА убедитесь, что ваши критерии выбора достаточно конкретны для элемента, с которым, по вашему мнению, вы взаимодействуете. Много раз у меня было два элемента в игре, и один был скрыт и выдает эту ошибку.
Крис
14

У меня была аналогичная проблема, но она была связана с тем, что элемент не отображался в окне просмотра. Я сделал снимок экрана и понял, что окно браузера слишком узкое и элемент не виден. Я сделал одно из них, и это сработало:

driver.maximize_window()

См .: WebDriver.maximize_window ()

mynameistechno
источник
7

Или вы можете использовать Selenium Action Class для имитации взаимодействия с пользователем - например

    WebDriver = new FirefoxDriver();

    WebElement menu = driver.findElement(By.xpath("")); // the triger event element

    Actions build = new Actions(driver); // heare you state ActionBuider
    build.moveToElement(menu).build().perform(); // Here you perform hover mouse over the needed elemnt to triger the visibility of the hidden
    WebElement m2m= driver.findElement(By.xpath(""));//the previous non visible element
    m2m.click();
Фил Михайлов
источник
7

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

  • Когда элемент преобразован в CSS
  • Когда родительский элемент элемента преобразован в CSS

Чтобы проверить, преобразован ли элемент, с которым вы не хотите взаимодействовать, CSS, в CHROME сделайте следующее:

  1. открытый инспектор
  2. Найдите интересный элемент (или, что более вероятно, его родительский элемент, предположительно элемент div)
  3. Выберите вкладку "Рассчитанные"
  4. если есть параметр: webkit-transform: matrix (...), это означает, что элемент преобразован в CSS и не может быть распознан селеном 2 как видимый элемент
justnpT
источник
5

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

См., Например, вопрос о разрешении WebDriver ждать, пока не появится элемент .

Avandeursen
источник
2

У меня была такая же проблема с селеном 2 в Internet Explorer 9, но мое исправление действительно странное. Мне не удалось щелкнуть входные данные внутри моей формы -> повторения селена, их не видно.

Это произошло, когда у моей формы были изогнутые тени -> http://www.paulund.co.uk/creating-different-css3-box-shadows-effects : в конкретном "Эффекте № 2"

Я понятия не имею, почему и как это решение псевдоэлементов остановило тесты на селен, но у меня это работает.

Агореддах
источник
2

Вы не можете принудительно получить доступ / изменить элемент, к которому пользователь обычно не имеет доступа, поскольку Selenium предназначен для имитации взаимодействия с пользователем.

Если возникает эта ошибка, проверьте:

  • элемент виден в вашем окне просмотра, попробуйте развернуть текущее окно, которое использует webdriver (например, maximize()в node.js , maximize_window()в Python),
  • ваш элемент не появляется дважды (под одним и тем же селектором), и вы выбираете не тот,
  • если ваш элемент скрыт, подумайте о том, чтобы сделать его видимым,
  • если вы хотите , чтобы значение доступа / изменения скрытого элемента , несмотря на ограничения, а затем использовать Javascript для этого (например , executeScript()в Node.js , execute_script()в Python).
Kenorb
источник
1
Я понятия не имел, что Selenium разработан так строго. Похоже, что это не совсем инструмент автоматизации в общем смысле, скорее инструмент автоматизированного взаимодействия с пользователем. Думаю, в этом есть смысл. Спасибо за разъяснение!
Daniel Lidström
1

Я просто решил эту ошибку при использовании capybara в проекте ror, добавив:

Capybara.ignore_elements = true

к features/support/env.rb.

Zernel
источник
1

Я просто решаю эту ошибку, ожидая свойства отображения элемента

waitFor() { element.displayed }
Суат Кескин
источник
Из всех ответов на этой странице именно это устранило мою проблему с модальным диалоговым окном Bootstrap. Спасибо, @Suat Keskin!
alastairs
1

Я попадаю в исключение ElementNotVisibleException, используя селен для функциональных тестов на сайте django с начальными глификонами в виде ссылок в шаблонах:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger"></span></a>

Во время моих функциональных тестов стиль начальной загрузки не загружается, поэтому попытка щелкнуть по таким ссылкам вызовет исключение ElementNotVisibleException. Мне удается сделать их интерактивными, просто добавив пробел в тег, например:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger">&nbsp;</span></a>
Жан Пьер Юарт
источник
1

На этой странице есть много хороших ответов.

  1. Обычно я начинаю с maximize.window (), на самом деле я делаю это в Driver Factory или там, где вы инициализируете свой драйвер. Это делается по умолчанию - всегда.
  2. Обычно это ожидание элемента из-за некоторой задержки javascript.

Оба обсуждаются в различных деталях выше. Ответа, которого я не видел, был ScrollToElement. Похоже, вы обрабатываете список элементов, а во время обработки вы создаете больше элементов, флажков. Это может привести к тому, что элементы в вашем списке переместятся с видимой страницы. Иногда элемент можно увидеть невооруженным глазом, но щелкнуть по нему просто невозможно. При обработке списков иногда приходится вставлять прокрутку.

  • Установите точку останова и проверьте, находится ли используемый вами элемент на краю окна, вверху / внизу справа / слева. Иногда, когда это так, вы не можете добраться до него через селен, но вы можете вручную щелкнуть мышью.

Поскольку я наткнулся на это, я создал PageScroll.java и поместил туда свои сценарии прокрутки. Вот несколько методов из этого класса:

public static void scrollToTop(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0,0)");
    }

    public static void scrollToBottom(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0, document.body.scrollHeight)");
    }

    public static void scrollToElementTop(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(true);", element);
    }

    public static void scrollToElementBottom(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(false);", element);
    }

см. « Прокрутить элемент в представление с помощью Selenium» для получения дополнительных примеров

Mancocapac
источник
0

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

function getStyles(element){
	
	computedStyle = window.getComputedStyle(element);

	if(computedStyle.opacity === 0
	|| computedStyle.display === "none"
	|| computedStyle.visibility === "hidden"
	|| (computedStyle.height < 0 && computedStyle.height < 0)
	|| element.type === "hidden") {
		console.log("Found an element that Selenium will consider to not be visible")
		console.log(element);
		console.log("opacity: " + computedStyle.opacity);
		console.log("display: " + computedStyle.display);
		console.log("visibility: " + computedStyle.visibility);
		console.log("height: " + computedStyle.height);
		console.log("width: " + computedStyle.width);
	}

	if(element.parentElement){
		getStyles(element.parentElement);
	}
}

getStyles(document.getElementById('REPLACE WITH THE ID OF THE ELEMENT YOU THINK IS VISIBLE BUT SELENIUM CAN NOT FIND'));

стармер
источник
0

Чтобы добавить сюда свою песчинку: если элемент находится за фиксированным div, он будет считаться невидимым, и вы не сможете щелкнуть по нему; это случилось со мной недавно, и я решил, что он выполнил сценарий, как рекомендовано выше, который:

document.evaluate("<xpath locator for element to be clicked>", document, null, XPathResult.ANY_TYPE, null).iterateNext().click()", locator);
Фернандо Габриэли
источник
Что здесь за локатор?
Анджана