Да, я сталкивался с этой проблемой много раз при использовании Selenium. Есть 2 способа обойти эту проблему. Во-первых, вы можете изменить неявное время ожидания. Например, учитывая этот кусок кода:
Actions builder = new Actions( driver );
builder.click( driver.findElement( By.className("lala") ) ).perform();
Этот код вызовет исключение, если в точке его вызова нет элементов, которые могли бы найти класс, соответствующий классу "lala". Вы можете изменить это неявное время ожидания с помощью:
driver.manage().timeouts().implicitlyWait( 5, TimeUnit.SECONDS );
Это заставляет водителя опрашивать в течение 5 секунд, а не сразу. Если элемент все еще не может быть найден через 5 секунд, действие завершится неудачно. Конечно, вы можете изменить эту настройку. Я обнаружил, что этот метод работает нормально большую часть времени. Большую часть времени вы не заботитесь о загрузке всей страницы, только об определенной ее части.
Я также написал еще одну функцию - GetElementByClassAndText, которая будет выполнять то же самое, что и неявное ожидание элемента, за исключением того, что он также проверяет содержащий текст, чтобы обеспечить более детальную детализацию того, что вы хотите:
public static void waitAndClick( WebDriver driver, By by, String text ) {
WebDriverWait wait = new WebDriverWait( driver, 10000 );
Function<WebDriver, Boolean> waitForElement = new waitForElement( by );
wait.until( waitForElement );
for( WebElement e : driver.findElements( by ) ) {
if( e.getText().equals( text ) ) {
Actions builder = new Actions( driver );
builder.click( e ).perform();
return;
}
}
}
И соответствующая функция, которую он использует:
public class waitForElement implements Function<WebDriver, Boolean> {
private final By by;
private String text = null;
public waitForElement( By by ) {
this.by = by;
}
public waitForElement( By by, String text ) {
this.by = by;
this.text = text;
}
@Override
public Boolean apply( WebDriver from ) {
if( this.text != null ) {
for( WebElement e : from.findElements( this.by ) ) {
if( e.getText().equals( this.text ) ) {
return Boolean.TRUE;
}
}
return Boolean.FALSE;
} else {
try {
from.findElement( this.by );
} catch( Exception e ) {
return Boolean.FALSE;
}
return Boolean.TRUE;
}
}
}
Я понимаю, что вы используете Selenium в Ruby, но, надеюсь, часть моего кода (по крайней мере, концептуально) может быть передана и полезна для вас.