« Back to Index

Variety of different Capybara configurations, tips and tricks

View original Gist on GitHub

features support env.rb

Capybara.default_wait_time = 20
Capybara.default_host = DEFAULT_HOST
Capybara.app = Capybara.app_host = DEFAULT_HOST

Capybara.configure do |config|
  config.match = :prefer_exact
  config.ignore_hidden_elements = false
end

Capybara.run_server = false
Capybara.current_driver = :mechanize

class Capybara::Mechanize::Browser < Capybara::RackTest::Browser
  def default_user_agent
    "cucumber"
  end
end

Capybara.register_driver :mechanize_with_test_user_agent do |app|
  driver = Capybara::Mechanize::Driver.new(app)
  driver.browser.agent.user_agent = "cucumber"

  driver
end

Capybara.register_driver :selenium do |app|
  Capybara::Selenium::Driver.new(app, :browser => :chrome, :args => ["--user-agent=cucumber"])
end

Capybara.register_driver :mechanize_with_test_user_agent_and_adverts do |app|
  driver = Capybara::Mechanize::Driver.new(app)
  driver.browser.agent.user_agent = "cucumber"
  driver.browser.agent.request_headers = {"X-Advert-Override" => "true"}

  driver
end

module Capybara::Poltergeist
  class Client
    private
    def redirect_stdout
      prev = STDOUT.dup
      prev.autoclose = false
      $stdout = @write_io
      STDOUT.reopen(@write_io)

      prev = STDERR.dup
      prev.autoclose = false
      $stderr = @write_io
      STDERR.reopen(@write_io)
      yield
    ensure
      STDOUT.reopen(prev)
      $stdout = STDOUT
      STDERR.reopen(prev)
      $stderr = STDERR
    end
  end
end

class WarningSuppressor
  class << self
    def write(message)
      if message =~ /QFont::setPixelSize: Pixel size <= 0/ || message =~/CoreText performance note:/ then 0 else puts(message);1;end
    end
  end
end

Capybara.register_driver :poltergeist do |app|
  driver = Capybara::Poltergeist::Driver.new(app, {
    :inspector => true,
    :timeout => 60,
    :js_errors => false,
    :phantomjs_options => ['--load-images=no'],
    :phantomjs_logger => WarningSuppressor
  })

  driver
end

Capybara.register_driver :poltergeist_images do |app|
  driver = Capybara::Poltergeist::Driver.new(app, {
    :inspector => true,
    :timeout => 60,
    :js_errors => false,
    :phantomjs_logger => WarningSuppressor
  })

  driver
end

Capybara.default_driver = :mechanize_with_test_user_agent

def setup_poltergeist(with_images = nil)
  Capybara.current_driver = with_images.nil? ? :poltergeist : :poltergeist_images

  page.driver.headers = {
    "User-Agent" => "cucumber"
  }

  # the following code is required to prevent some JS code causing cukes to fail
  # i.e. our grid overlay javascript sets up 'keyup' event bindings
  # for example if you press the 'a' key then the grid overlay visibility is toggled
  # but when Capybara/Poltergeist fills in a form field it causes the grid to toggle on,
  # and that then breaks further tests because Capybara/Poltergeist can't click on the page elements
  page.driver.set_cookie('poltergeist', 'is running')
end

Before "@javascript" do
  setup_poltergeist
end

Before "@javascript_with_images" do
  setup_poltergeist 'images'
end

Before "@device_desktop" do |scenario|
  setup_poltergeist
  set_device('desktop')
end

Before "@multi_device" do |scenario|
  setup_poltergeist
  set_device(scenario.to_hash['device'])
end

Before "@multi_device_debug" do |scenario|
  Capybara.current_driver = :selenium
  set_device(scenario.to_hash['device'])
end

def set_device(device)
  case device
  #Height is set to 800 across the board, but should be changed
  #to something more appropriate when our site reacts to it
  when "feature phone"
    Capybara.current_driver = nil
  when "smart phone portrait"
    resize_browser(320, 800)
  when "smart phone landscape"
    resize_browser(480, 800)
  when "tablet portrait"
    resize_browser(640, 800)
  when "tablet landscape"
    resize_browser(768, 800)
  when "desktop"
    resize_browser(1280, 1024)
  when "desktop no javascript"
    Capybara.current_driver = nil
  end
end

def resize_browser(w, h)
  if Capybara.current_driver == :selenium
    page.driver.browser.manage.window.resize_to(w, h)
  else
    page.driver.resize(w, h)
  end
end

Before "@debug" do
  Capybara.current_driver = :selenium
end

def destroy_poltergeist
  begin
    Capybara.drivers[:poltergeist].call().quit
  rescue
  end

  Capybara.current_driver = nil
end

After "@javascript" do
  destroy_poltergeist
end

After "@javascript_with_images" do
  destroy_poltergeist
end

After "@debug, @multi_device, @multi_device_debug" do
  Capybara.current_driver = nil
end

World(Capybara)

module Capybara
  class Session
    alias :_visit :visit

    def visit(url, opts = {})

      opts[:query_params] ||= {}

      if opts[:cache_busting] != false
        opts[:query_params]['cb'] = Time.now.to_i
        opts[:query_params]['i_hate_caching'] = rand(10000)
      end

      params = opts[:query_params].map{|k,v| [k, "=", v]}.map(&:join).join("&")

      uri = URI.parse(url)

      query = "#{uri.query}&#{params}".gsub(/^&/, '')

      url = URI::Generic.build(
        :scheme => uri.scheme,
        :host => uri.host,
        :port => uri.port,
        :path => uri.path,
        :query => query,
        :fragment => uri.fragment
      ).to_s

      _visit url
      raise "PHP #{$&} in response!" if /(?:Notice|Warning|Fatal error):/.match(body)
    end
  end
end