capybara-webkit cannot simulate click on (non link/button) element

rigyt picture rigyt · Apr 19, 2013 · Viewed 7.4k times · Source

In an rspec feature scenario I have:

scenario 'shows things', js: true do

    page.find('#my_div').trigger(:click)

This doesn't seem to fire the jQuery handler that's on the click event of this element. In the debugger this call returns an empty string "".

Should capybara-webkit be able to simulate mouse events with jQuery handlers triggering ajax requests that update the dom? If so, any suggestions for this case? I switched from selenium-webdriver because the capybara #trigger method isn't supported.

And trying to trigger the jQuery event directly throws an error:

page.execute_script "$('#masthead .fclass').trigger('click')"

gives

Capybara::Webkit::InvalidResponseError:
       Javascript failed to execute

My gemfile has

group :test do
  gem 'capybara'
  gem "database_cleaner", "~> 0.9.1"
  gem 'capybara-webkit', git: 'git://github.com/thoughtbot/capybara-webkit.git'
  gem 'launchy'
end

I'm using 'edge' capybara-webkit as I hit a bug with an xpath error otherwise (v2.04?).

I haven't been able to get a log of the javascript error, though I tried adding rack exceptions in spec/spec_helper.rb:

ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rspec'
require 'rack/utils'
Capybara.app = Rack::ShowExceptions.new(MyApp::Application)

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  #...

  Capybara.javascript_driver = :webkit

  config.before (scope = :suite) do
    %x[bundle exec rake assets:precompile]
  end

  config.use_transactional_fixtures = false

  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.before(:each) do
    DatabaseCleaner.clean
  end

  config.infer_base_class_for_anonymous_controllers = false
end

Update: I replaced capybara-webkit with

gem 'poltergeist' 

And in spec/spec_helper.rb:

    require 'capybara/poltergeist'
    ...
    Capybara.register_driver :poltergeist do |app|
      Capybara::Poltergeist::Driver.new(app, { debug: true })
    end
    Capybara.javascript_driver = :poltergeist
    Capybara.current_driver = :poltergeist

I get these error messages in the console from page("#my_id").trigger('click'):

...
{"name"=>"click", "args"=>[3, 2]}
poltergeist [1366370900594] state default -> mouse_event
poltergeist [1366370900596] state mouse_event -> loading
Not allowed to load local resource: file:///home/me/rails/my_app/public/assets_test/application.css
...
Not allowed to load local resource: file:///home/me/rails/my_app/public/assets_test/application.js

I tried to chmod the poltergeist gem permissions but same outcome.

And trying to run page.execute_script(%Q($("my_id").trigger('click'))) gives a jQuery undefined type error:

 ReferenceError: Can't find variable: $
           at phantomjs://webpage.evaluate():1
           at phantomjs://webpage.evaluate():1
           at phantomjs://webpage.evaluate():1
           at phantomjs://webpage.evaluate():1

Answer

rigyt picture rigyt · Apr 26, 2013

The problems I had and solutions:

1) Capybara trigger() method isn't supported with selenium-webdriver or capybara-webkit.

  • a solution: trigger the jquery event directly from javascript: page.execute_script(%Q($("#... although this isn't as useful as it could fire the event on an element that isn't visible to the user.

2) save_and_open_page doesn't use the asset pipeline, so is fairly useless if you have hidden clickable elements. The poltergeist driver has save_screenshot, which works, but it's not as useful as having a real browser page with the assets loaded

  • a solution: precompile assets in test, although I couldn't get jQuery to load with any driver ($ is undefined) and poltergiest/phantomjs doesn't allow access to local compiled files (passing command line options to the driver has no effect)

  • better solution: use unreleased Capybara 2.1+ gem 'capybara', git: 'git://github.com/jnicklas/capybara.git', add Capybara.asset_host = "http://localhost:3000" to spec_helper.rb and leave dev server running

3) capybara-webkit Error undefined method find_xpath for #<Capybara::Webkit::Driver When using Capybara.javascript_driver = :webkit

  • solution: use master branch gem 'capybara-webkit', git: 'git://github.com/thoughtbot/capybara-webkit.git'

My set up in the end was Poltergeist (supports trigger method) + Capybara beta with assets served from dev server (not precompiled) so save_and_open_page works.