title: Using Cucumber/Capybara in Rails 3, how do I set a custom User-Agent string?
body: <p>In my Rails 3 app, I have different layouts for iPhone vs desktop browsers. I'm trying to test the iPhone layout using Cucumber/Capybara. So far, all my attempts at setting an iPhone User-Agent string in the request's HTTP header have failed.</p>
  
  <p>I have followed the <a href="http://aflatter.de/2010/06/testing-headers-and-ssl-with-cucumber-and-capybara/" rel="nofollow noreferrer">Testing custom headers and ssl with Cucumber and Capybara</a> tutorial but it doesn't seem to set the User-Agent string in the HTTP request.</p>
  
  <p>If I just browse to my Rails app using my iPhone, I get the right layout. I am using <a href="http://github.com/talison/rack-mobile-detect" rel="nofollow noreferrer">Rack-Mobile-Detect</a> to set the Rails request.format to :iphone.</p>
  
  <p>Any ideas on how to make this work? I'm about ready to ditch Capybara and go back to Webrat.</p>
  
  <p>Here's what I have so far:</p>
  
  <pre><code>Feature: Detect Browser
    In order to have different layouts for iPhone vs. desktop browsers
    As a developer
    I want to show different layouts for different browsers
  
  Scenario: Show home page with desktop layout 
    Given I am using "a desktop browser"
    When I go to "the home page"
    Then I should see "desktop browser"
  
  Scenario: Show home page with iPhone layout
    Given I am using "mobile safari"
    When I go to "the home page"
    Then show me the page
    Then I should see "mobile safari"
  </code></pre>
  
  <p>Detect_browser_steps.rb</p>
  
  <pre><code>Given /^(?:|I )am using (.+)$/ do |browser|
    case browser
    when "mobile safari"
      agent = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16"
      add_headers({'User-Agent' =&gt; agent})
    else
      # don't set a special User-Agent header
    end
  end
  </code></pre>
  
  <p>headers_hack.rb</p>
  
  <pre><code># http://aflatter.de/2010/06/testing-headers-and-ssl-with-cucumber-and-capybara/
  # The following solution will work only if you use the :rack_test driver.
  module RackTestMixin
  
    def self.included(mod)
      mod.class_eval do
        # This is where we save additional entries.
        def hacked_env
          @hacked_env ||= {}
        end
  
        # Alias the original method for further use.
        alias_method  :original_env, :env
  
        # Override the method to merge additional headers.
        # Plus this implicitly makes it public.
        def env
          original_env.merge(hacked_env)
        end
      end
    end
  
  end
  
  Capybara::Driver::RackTest.send :include, RackTestMixin
  
  module HeadersHackHelper
  
    def add_headers(headers)
      page.driver.hacked_env.merge!(headers)
    end
  
  end
  
  World(HeadersHackHelper)
  </code></pre>