Других методов проверки на кликабельность, кроме как перечислены выше, нет. Пробуйте что работает для вас и используйте его. А потом если будут какие-то конкретные проблемы, будем думать дальше.
Проблема у меня была в том, что слишком много слипов для ожидания возможности кликнуть по элементам.
И с этим надо было что-то делать.
Связка isDisplayed и isEnabled практически везде прокатила.
Слипы остались только в двух местах:
- После определенных действий пользователя сверху на страницу наезжала форма.
Связка isDisplayed & isEnabled у элемента на этой форме выдает клик как положено без ругани.
Проблема только в том, что клик похоже происходит еще до того как форма полностью выкатится и вне формы, т.к. форма не выехав до конца убирается обратно (так по сценарию заложено). Короче тут слип я оставил. - При обращении к БД. Необходимо просто дождаться когда до БД дойдут данные.
по п.1 - если форма ajax’овская, то возможно поможет, перед поиском элемента и совершения действий с ним, проверить “return jQuery.active == 0”
Sleep плох только тогда, когда он не оправдан. Увлекаться этим методом не стоит, потому как он сложен в поддержке (например, нужно изменить время ожидания), лучше использовать динамические способы, которые предоставляет инструмент (AjaxElementLocator, WebDriver Wait).
Но бывает, что такое решение оказывается гораздо эффективнее (результат / трудозатраты) и точечное его использование вполне нормально (когда работает стабильно).
Так что в случае с отправкой данных в БД, sleep, на мой взгляд, использовать нормально.
А с выезжающей формой нужно разобраться как определить её окончательную загрузку. Если это Ajax, то @5am вам подсказал возможное решение. Если это связано с JS-анимацией, тогда возможно стоит поискать локатор, который наверняка определяет окончательное положение формы. И после этого уже обращаться к элементу на форме
Все-таки стали попадаться загадочные ситуации, когда isDisplayed & isEnabled выдают таки эксепшн.
Переделал под вариант “кликать пока не кликнется” - все встало на свои места.
В этой области я чайник. Можно пару строчек реального кода, от которого я могу оттолкнуться?
Спасибо
Вот пример на python
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import WebDriverException
def ajax_complete(driver):
try:
return 0 == driver.execute_script("return jQuery.active")
except WebDriverException:
pass
def my_automation_test():
ff_driver = webdriver.Firefox()
ff_driver.get("http://domain.tld")
#wait for ajax items to load
WebDriverWait(ff_driver, 10).until(
ajax_complete, "Timeout waiting for page to load")
assert "ajax loaded string" in ff_driver.page_source
На java тоже не проблема найти c# - Wait for an Ajax call to complete with Selenium 2 WebDriver - Stack Overflow
public void WaitForAjax()
{
while (true) // Handle timeout somewhere
{
var ajaxIsComplete = (bool)(driver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
break;
Thread.Sleep(100);
}
}
Вроде понятно куда двигаться. Спасибо
Так это не мой код, я нашел примерочный код в интернете, чтобы @Raynor смог сориентироваться.
Но по поводу твоего вопроса. В методе until
в WebDriverWait
обычно передается callable object в виде lambda выражения, в данном случае это простая функция, которая будет вызываться. Сам класс WebDriverWait
при запуске метода until
будет передавать инстанс объекта в callable object как первый аргумент.
Обычно это выглядит где-то так
from selenium.webdriver.support.ui import WebDriverWait
element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId"))
Если посмотреть внутри реализации, то все становиться понятным http://selenium.googlecode.com/git/docs/api/py/_modules/selenium/webdriver/support/wait.html#WebDriverWait.until
Я оставил только код, который это объясняет.
class WebDriverWait(object):
def __init__(self, driver, ...):
...
self._driver = driver
...
def until(self, method, message=''):
...
while(True):
try:
value = method(self._driver)
...
except self._ignored_exceptions:
pass
....
@polusok спасибо, понял. В Ruby Wait работает капельку иначе.
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
wait = Selenium::WebDriver::Wait.new timeout: 10
driver.get 'http://example.com'
wait.until do
driver.find_element :xpath, '/html/body/div/a'
end
element = driver.find_element :xpath, '/html/body/div/a'
element.click
driver.close
Ну ты ведь в until
тоже ничего не передаешь, хотя ты просто в одном скрипте все написал без функций и классов и инстанс driver виден из метода until
или может быть я конечно не понимаю ruby (что вполне возможно )
Я написал для примера работающий путём copy/path скрипт.
Т. к. я хотел показать работу wait, то не стал перегружать скрипт ненужными в данном случае классами и методами.
И да, объект driver
виден внутри wait
.
Ну ок, что ты не хочешь усложнять, но что если инициализация драйвера и реалиализация вейтера в разных функциях, ты что явно передаешь инстанс вебрайвера?
[quote=“polusok, post:33, topic:3719, full:true”]
но что если инициализация драйвера и реалиализация вейтера в разных функциях, ты что явно передаешь инстанс вебрайвера?
[/quote]Не совсем так. driver инициализируется как public переменная и доступна из любого места теста. Я же не просто скрипт пишу, а всё внутри rspec обёртки.
Посмотри мой пример из Проверка правильности сортировки блоков c помощью WebDriver, пример на Ruby