Capybara-webkit fails to trigger click event on element, possibly due to presence of ontouchstart

2382 views
Skip to first unread message

Peter Philips

unread,
Oct 31, 2012, 2:14:45 AM10/31/12
to capybar...@googlegroups.com
Hey all,

I'm not really a front end developer, so I'm not too clear on what exactly is going on here, but I"ll explain whats going on.

I had a suite of tests that worked fine testing a highly javascript based app.  Our front end developer switch event handling around to something he called "touch events" because they were 300ms faster on mobile devices.  This is when the tests started failing.

Basically, I have a link "#submitName", that is responsible for moving elements on the page around.  The javascript that is bound to it is as follows: 
$(document.body).on(R.touchEvent, "#submitName", this.submitName.bind(this));

where there is a function submitName() that does the heavy lifting.

I asked the front end dev, and he asked me if "window.ontouchstart" was supported in the testing driver, and if it was, that might cause problems.

So I stuck a debugger in my tests prior to the error and ran: 
page.evaluate_script("typeof(window.ontouchstart)")
=> "object"

I checked in the console of actual Chrome browser:
"undefined"

And I checked in Selenium and Chrome-Selenium webdrivers:
"undefined"

All my tests pass in Selenium and Chrome-Selenium drivers.

I'm running:
capybara (1.1.2)
capybara-webkit (0.12.1)

Any advice on what's going on here?

Thanks!
Pete


Joe Ferris

unread,
Oct 31, 2012, 10:45:27 AM10/31/12
to capybar...@googlegroups.com
Hey,

I'm new to this as I haven't had to deal with touch events before, but it seems like an odd choice in QtWebKit, which we rely on to simulate the browser: https://bugs.webkit.org/show_bug.cgi?id=56012

Looks like the official way to fix this right now is for you to recompile Qt without it: http://lists.webkit.org/pipermail/webkit-qt/2010-November/000974.html - which would be a huge pain.

I'll see if there's a way to make touch support configurable or something, but for now you could either compile Qt without touch support or trigger touch events instead of click events. Feel free to file a bug report on GitHub issues: https://github.com/thoughtbot/capybara-webkit/issues?sort=created&state=closed

-Joe

Alex Grande

unread,
Oct 31, 2012, 1:57:15 PM10/31/12
to capybar...@googlegroups.com
Hi Joe,

I work with Peter and I'm the front end developer.

We do a simple check for touch. Is ontouchstart in window? 

Literally:

var hasTouch = 'ontouchstart' in window;

If so, we use jQuery Mobile's touch library to enable "fast touch."

Fast touch is using touch events rather than click.

On touch-enabled devices, "click" is triggered 300ms after touchend.

Thus, for our human interaction, we use "tap" instead of "click" whenever touch is enabled to create a real mobile app experience for our mobile web users.

So this QtWebKit is using touch events now. This doesn't seem to work for some reason.

Ideally my code doesn't end up looking like this:

var hasTouch = 'ontouchstart' in window && navigator.userAgent.indexOf("capybara"); 

Joe Ferris

unread,
Oct 31, 2012, 2:03:47 PM10/31/12
to capybar...@googlegroups.com
Hey Alex,

Here's what I think is happening:

* QtWebKit supports touch events (the library can be used on mobile devices), so window.ontouchstart is defined and works.
* Your application detects whether or not touch events are supported, and if they are, it listens for touch events instead of click events.
* capybara is built around the idea of clicks, so when you tell it to do things like follow links and press buttons, it sends click events and not touch events, so your event listeners don't fire.

There are two possible workarounds on the testing side:

* Remove support for touch events. This can be done by recompiling Qt, but it's time-consuming and inconvenient to do so.
* Change the tests to send touch events instead of click events. Capybara supports sending whatever events you want, so instead of using the normal helpers, you can find link elements and send touch events.

When I have time, I'll look for a way to make touch event support configurable so that you can just disable it for your tests, but in the mean time, the best workaround might be to just the user agent.

-Joe

Peter Philips

unread,
Oct 31, 2012, 3:59:02 PM10/31/12
to capybar...@googlegroups.com
Hey Joe,

Thanks very much for your reply.

The second workaround is definitely viable for us.  How would one send a touch event via capybara?

something like: page.find("#submitName").touch() ?

Also, I saw some recent(~2 months ago) commits regarding this.  Should I pull latest from master or is this functionality in the latest official gems?

Thanks!
~pete

Joe Ferris

unread,
Oct 31, 2012, 4:03:48 PM10/31/12
to capybar...@googlegroups.com
Hey Peter,

You can use capybara's #trigger method to send events to nodes:

    page.find('#submitName').trigger('touchstart')

The #trigger method is in the released version of capybara, so you can use whatever is most stable for you.

-Joe

Peter Philips

unread,
Oct 31, 2012, 9:13:55 PM10/31/12
to capybar...@googlegroups.com
awesome! thanks Joe!

Peter Philips

unread,
Nov 1, 2012, 4:51:50 AM11/1/12
to capybar...@googlegroups.com
So, I realized we are using 'tap' events instead of touchstart to fire the behavior I need to test.  However, using trigger('tap') on a capybara element/node still did not work.

The only thing that seems to work for me is directly triggering the tap event via jquery: 
page.execute_script(%Q($("#submitName").trigger('tap')))

This keeps us moving with a green test suite :)  

Thanks again for your help in figuring this out, and looking forward to when tap support is configurable :)

Cheers,
Pete
Reply all
Reply to author
Forward
0 new messages