Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebDriver: Change event not firing

I have an application that is using KnockoutJS and I'm attempting to write some tests that test a form. If you don't know KnockoutJS, the short story for it is that it provides bindings from my view to my data model. This means that when I type a value in the an input field, my underlying object automatically gets updated with that input fields value. This is done through a change event by default.

The problem I am having is that when my WebDriver test is typing into the field, the change event is not firing so my underlying data model does not have the appropriate values. This causes my form validation to fail when it should not.

I've done everything I could find on the internet to make this work. I've:

  1. sent the tab key
  2. clicked away from the form field
  3. send JavaScript code to fire focus and blur events (validation occurs on blur)
  4. clicked the form field before typing
  5. set waits just incase it was a timing issue
  6. changed KnockoutJS to update input field on afterkeydown

None of these have worked for me.

In addition, I have verified that this is not an event bubbling issue as I removed all other events explicitly, leaving just the KnockoutJS change event.

for the solution i'm looking for is one that works for all browser drivers (... at least the main ones e.g. IE, FF, Chrome, Safari) and does not require the use of jQuery.

How do I solve the problem?

Here is the relevant code I'm using to type values into the field:

// 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();
like image 1000
loesak Avatar asked May 30 '13 20:05

loesak


1 Answers

So I have found a way to work around this issue for now, but by far do I believe this is the correct solution. This does break my rule about not using jQuery, however I feel this is okay for me as KnockoutJS requires jQuery be loaded. There's probably a plain ol' JavaScript way of doing this. I have tested this with FireFox, Safari, and PhantomJS. I assume it will work just as well in Chrome. I give no promises for Internet Explorer.

I am NOT going to mark this answer as the correct answer. The correct solution should be through WebDriver browsers firing the proper events. Only when I believe this is not possible through WebDriver will I mark this as the correct answer.

// 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();
like image 84
loesak Avatar answered Oct 02 '22 12:10

loesak