WebDriver: изменение события не срабатывает

У меня есть приложение, которое использует KnockoutJS, и я пытаюсь написать некоторые тесты, которые тестируют форму. Если вы не знаете KnockoutJS, рассказ для него заключается в том, что он предоставляет привязки с моего взгляда к моей модели данных. Это означает, что при вводе значения в поле ввода, мой базовый объект автоматически обновляется с этим значением полей ввода. Это делается через событие change по умолчанию.

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

Я сделал все, что мог найти в интернете, чтобы сделать эту работу. Я:

  1. послал клавишу tab
  2. щелкнул прочь от поля формы
  3. отправить код JavaScript для запуска событий фокусировки и размытия (проверка происходит при размытии)
  4. щелкните поле формы перед набрав
  5. set waits просто incase это была проблема времени
  6. изменен KnockoutJS для обновления поля ввода на afterkeydown

ни один из них не работал для меня. Мне нужна помощь.

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

для решения, которое я ищу, это тот, который работает для всех драйверов браузера (... на наименее основные из них, например IE, FF, Chrome, Safari) и не требуют использования jQuery.

любая помощь была бы весьма признательна.

здесь относительный код, который я использую для ввода значений в поле:

// find element
WebElement input = this.element.findElement(By.className("controls"))
                               .findElement(By.tagName("input"));

// to set focus?
input.click();

// erase any existing value (because clear does not send any events
for (int i = 0; i < input.getAttribute("value").length(); i++) {
    input.sendKeys(Keys.BACK_SPACE);
}

// type in value
input.sendKeys(text);

// to fire change & blur? (doesnt fire change)
//input.sendKeys(Keys.TAB);

// to fire change & blur? (doesnt fire change)
driver.findElement(By.tagName("body")).click();

2 ответов


поэтому я считаю, что я узнал свою проблему. Я полностью признать, что это был PEBKAC. Я забыл, что у WebDriver есть проблемы, если окно браузера не находится в активном фокусе на машине (что все еще странно для меня). Когда я отлаживал проблему, я использовал свой редактор, чтобы пройти через код. При обычном запуске кода и без удаления фокуса из браузера события запускаются, как и ожидалось, с использованием всех трех решений (tab, click-away и javascript).

У меня есть пример проекта, показывающий все три метода, однако я крупный noob с git и github и испытываю проблемы с доставкой проекта. Как только я это выясню, я поделюсь проектом со всеми вами.

редактировать: получил пример кода на GitHub (https://github.com/loesak/knockout.webdriver.change.event.test). Вы можете либо запустить проект как webapp на сервере и запустить тест вручную, либо запустить тесты через maven (mvn clean install). Я не ставил много усилий, чтобы заставить это работать надежно, поэтому предполагается, что у Вас установлен Firefox и порт 0808 8080 открыт.

редактировать: исправлен указанный номер порта


поэтому я нашел способ обойти эту проблему на данный момент, но я считаю, что это правильное решение. Это нарушает мое правило о не использовании jQuery, однако я чувствую, что это нормально для меня, поскольку KnockoutJS требует загрузки jQuery. Вероятно, есть простой способ сделать это на JavaScript. Я протестировал это с FireFox, Safari и PhantomJS. Я предполагаю, что он будет работать так же хорошо в Chrome. Я не даю никаких обещаний для Internet Explorer.

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

// find element in question
WebElement input = this.element.findElement(By.className("controls"))
                               .findElement(By.tagName("input"));

// click it to fire focus event
input.click();

// erase any existing value
for (int i = 0; i < input.getAttribute("value").length(); i++) {
    input.sendKeys(Keys.BACK_SPACE);
}

// enter in desired text
input.sendKeys(text);

// fire on change event (WebDriver SHOULD DO THIS)
((JavascriptExecutor) driver).executeScript(
        "$(arguments[0]).change(); return true;"
    , input);

// click away to fire blur event
driver.findElement(By.tagName("body")).click();