尝试理解显式等待的方法。
require 'rubygems'
require 'selenium-webdriver'
require 'cucumber'
$driver = Selenium::WebDriver.for :firefox
$driver.manage.timeouts.implicit_wait = 3
Then /^do search$/ do
driver = $driver
one_way = driver.find_element(:id, "search.ar.type.code.oneWay").click
sleep 5
from = driver.find_element :xpath => "//div[@class = 'origin column1']//input[@type = 'text']"
from.click
所以在单击one_way
单选按钮并更改输入表单后,我放sleep 5
给它一个时间元素出现,否则将是错误“元素不可见......”。所以我认为现在是理解显式等待的好时机,因为我需要等到元素出现。
wait = Selenium::WebDriver::Wait.new(:timeout => 40)
wait.until {from = driver.find_element(:xpath, "//div[@class = 'origin column1']//input[@type = 'text']")
from.click
}
但是得到错误“Selenium :: WebDriver :: Error :: ElementNotVisibleError:元素当前不可见,因此可能无法与之交互”。为什么这段代码不会等到元素出现并单击它?
答案 0 :(得分:4)
问题是该元素还没有在DOM中,因此你需要在那里加时间延迟。
也就是说,API doco for ruby说你应该这样做
require 'rubygems' # not required for ruby 1.9 or if you installed without gem
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
driver.get "http://somedomain/url_that_delays_loading"
wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
begin
element = wait.until { driver.find_element(:id => "some-dynamic-element") }
ensure
driver.quit
end
请注意,然后可以从wait.until方法中分配您可以.click()
的元素,而不是代码中的find_element()方法。
然而,任意延迟并不总是有效,如果网站繁忙,那么延迟可能不够长。 更好的选择是等待元素变为可点击或可见。
Java API具有ExpectedConditions convenience methods,可以像这样使用...
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
element.click();
不幸的是,我不认为Ruby有这个。您可能需要编写自己的ExpectedCondition
类或包。
我不是Ruby开发人员,但这里是Java中的一个函数的概念,可用于实现您的ExpectedCondition
public WebElement findElementInTime(WebDriver driver, By by, int timeoutInSeconds)
{
log.debug("==================+>>>>>> looking for element for "+ timeoutInSeconds + " seconds");
WebElement ret = null;
for (int second = 0; second < timeoutInSeconds; second++) {
try { if (isElementPresent(driver,by)) {
log.debug("found element :-)");
ret = driver.findElement(by);
break;
}} catch (Exception e) {
log.debug("oops... sleeping 1 sec wait for button");
}
log.debug("sleeping 1 sec wait for button");
}
return ret;
}