I came a cross the question, how I could wait for a JavaScript Event in Capybara using the Selenium Webdriver.
This is what I came up with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
So, what is going on?
Capybara does not provide the feature to execute asynchronous JavaScript. So I get the selenium driver in and grab the private Selenium bridge. The bridge gives me access to this API: JavascriptExecutor
I set the script timeout to the timeout I set in Capybara. I found, that otherwise there is a timeout of 2ms, which was not enough for me.
Then I execute asynchronous javascript. This Javascript will get a callback as last parameter of arguments injected, which I need to call, once I’m finished with waiting for the event.
Inside the JavaScript, I set up a listener for the event I’m interested in. When I get the event I’ll immediately return true - so the event propagation goes on and I don’t change anything in the actual website.
A millisecond later, I execute the callback. Why later? Because without it, the execution of the normal JavaScript in the browser stopped. I guess, but haven’t verified, that otherwise the Ruby code will directly come back - therefore the JavaScript in the browser is in a weird state.
Is there a better solution?
I don’t know. I googled a bit and found none - so I came up with this solution. If there is a better one, I would be really glad. The code is not really obvious, has a lot of technical details and is tied quite strongly to the selenium bridge. I cannot switch to another driver, say poltergeist.
Do you have a better solution? Tell me!
Why do we need to do that at all?
When looking for solutions, I found a lot of people who asked how you actually can wait for events in Capybara. The answers were mostly around changing something in the websites JavaScript itself, e.g. showing a hidden element.
That’s not possible for us. We are building a smoke test. The event is coming from a different system, which is not under our control. In theory, I could try to get the other guys to change something in their page. But that’s not something to be done easily and fast.