5

The webpage that I'm testing is using knockout. On other pages on our site that are not currently using knockout I'm not having the same problem. The scenario I have is where the page opens, I enter in various required fields and click the save button. At some point between when it enters a value in the last text field and when it clicks the save button the fields that previously had values become cleared out, and thus the script can't continue. Here is an example of the code that I'm running:

driver.findElement(By.id("sku")).clear();
driver.findElement(By.id("sku")).sendKeys(itemNo);
driver.findElement(By.id("desktopThankYouPage")).clear();
driver.findElement(By.id("desktopThankYouPage")).sendKeys(downloadUrl);
driver.findElement(By.id("mobileThankYouPage")).clear();
driver.findElement(By.id("mobileThankYouPage")).sendKeys(mobileDownloadUrl);
driver.findElement(By.id("initialPrice")).clear();
driver.findElement(By.id("initialPrice")).sendKeys(initialPrice);
driver.findElement(By.id("submitSiteChanges")).click();

Like I said, between the time it enters text in the last field and the time it clicks save the fields that previously had text in them get cleared out, and thus my test fails. The problem is it doesn't always happen. Sometimes the test runs fine, other times it doesn't.

I've tried putting Thread.sleep(x); all over the place to see if pausing at certain points would fix the problem. I also have tried using javascript to wait in the background for any ajax that might be running. Also have the implicit wait of driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS). None of it seemingly has made any difference.

I'm running version 2.13 of selenium server and all my tests run on Firefox 8.

Any help on this would be greatly appreciated!

Geoff Ziebold
  • 51
  • 1
  • 1
  • 2
  • How have you confirmed that the values being set are actually set. What happens in your KO code after you click submit? Are the dom elements bound to KO rendered as part of a template? – madcapnmckay Feb 29 '12 at 23:50
  • Yes, I have verified that the values are present in the fields before clicking the submit button. In fact sometimes the test passes. The submit button takes our bound object and converts it to JSON and sends it via ajax to our API. It appears that before we create the JSON, the web driver is clearing out several fields. – Geoff Ziebold Mar 01 '12 at 15:47
  • I would doubt that web driver is clearing the fields. A more likely possibility is that the page itself is clearing the fields due to a timing issue, or potentially a bug in event handler code, however you mentioned adding sleeps did not seem to fix the problem. Did you add a very long sleep (30 seconds) before entering text in any of the fields to completely rule out a timing issue? Did you add a couple second delay in between entering text in each field to rule out a timing issue? – Sam Woods Mar 01 '12 at 18:50
  • Yeah, I put a long sleep in on the load of the page, and then also had sleeps inbetween entering text in a field and moving on to the next. – Geoff Ziebold Mar 02 '12 at 23:20

3 Answers3

5

Firefox has a bug which prevents some events from being executed while the browser window is out of focus. This could be an issue when you're running your automation tests - which might be typing even if the window is out of focus.

The point is that knockout model updates are triggered (by default) with the change event. If it's not being executed, it's underlying model won't be up-to-date.

To fix this issue I triggered the change event "manually", injecting javascript into my tests.:

//suppose "element" is an input field
element.sendKeys("value");
JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
jsExecutor.executeScript("$(arguments[0]).change();", element);

As you might have noticed, I'm using jQuery to trigger the change event. If you're not using jQuery on your app, you can check here how to trigger it using vanilla javascript.

Hope that helps somebody.

Community
  • 1
  • 1
Marlon Bernardes
  • 13,265
  • 7
  • 37
  • 44
  • It certainly helped me! and FWIW, in C# it is `var jsExecutor = (IJavaScriptExecutor)driver; jsExecutor.ExecuteScript("$(arguments[0]).change();", element);` – LosManos Feb 13 '17 at 10:10
1

I had the exact same problem. I would guess also that your code works fine in Chrome but not firefox, and that it always works when you do it manually?

Anyway, the problem is likely to be that Selenium doesn't really behave the same way as a real user, and doesnt trigger the same events. When you "submit" the form, it sometimes won't have executed the "change" event on a text area, meaning that it won't have changed.

I had the same problem testing Backbone.modelbinding, which uses the "change" event to update the model from the form. Knockout also uses the "change" event, but fortunately it can also use the "keyup" event. See valueUpdate in the docs:

<input data-bind="value: someValue, valueUpdate: 'keyup'" />

Anyway, that reproducibly solved it for me, and didnt need any sleeps once I had that done. The downside is that you'd be running the event more than is necessary in production, in order to make tests work. Another downside is that you if you want to run some code when a value changes, you'll now get one event per keypress instead of one per field change, which sucks sometimes.

There is another solution, which is to make Selenium fire the change event yourself, for example: Selenium IE change event not fired. It's also suboptimal, but what can you do.

You could also try putting the focus on a button before you click it. Don't know if that will work, I haven't tried it.

Community
  • 1
  • 1
Paul Biggar
  • 27,579
  • 21
  • 99
  • 152
0

I was facing the same issue, while using JavaScriptExecutor for sending keys to text fields.

Using below code in IE (same code is working with chrome):

(JavascriptExecutor) driver.executeScript("arguments[0].value = '" + value + "';", element);

After updating the code to simple "sendKeys()" method, it resolved my issue:

element.sendKeys("some text");
Pramod Kajla
  • 113
  • 1
  • 10