What's the best way to set custom request headers when using Capybara in RSpec request specs?

大憨熊 提交于 2019-12-21 04:26:18

问题


I'm monkey patching Capybara::Session with a set_headers method that assigns to Capybara::RackTest::Browser's options attribute (which I've changed from an attr_reader to an attr_accessor).

The patches:

class Capybara::RackTest::Browser
  attr_accessor :options
end

class Capybara::Session
  def set_headers(headers)
    if driver.browser.respond_to?(:options=) #because we've monkey patched it above
      options = driver.browser.options
      if options.nil? || options[:headers].nil?
        options ||= {}
        options[:headers] = headers
      else
        options[:headers].merge!(headers)
      end
    else
      raise Capybara::NotSupportedByDriverError
    end
  end
end

In my request spec, I'm doing:

page.set_headers("REMOTE_ADDR" => "1.2.3.4")
visit root_path

This works, but I'm wondering if there's a better way, it seems a bit overkill to just be able to set a custom remote_ip/remote_addr on a request. Any thoughts?


回答1:


If you want the headers to be globally set on all requests, you can use something like:

Capybara.register_driver :custom_headers_driver do |app|
  Capybara::RackTest::Driver.new(app, :headers => {'HTTP_FOO' => 'foobar'})
end

See the rack_test_driver_spec.rb in Capybara 1.1.2 and Capybara's issue #320, Setting up HTTP headers.




回答2:


Do you need to add custom header into one specific request in rspec using capybara? I used this in acceptance tests. It was the best way for me to use get method with specific header data. You can assess specific element on response page. See my example below:

get user_registration_path, { :invite => invite_token }, { 'X_GEOIP_COUNTRY_CODE' => 'US' } 
expect(assigns(:ip_country)).to eq('US')
response.body.should have_selector("input#currency_usd[checked='checked']")

I hope it helps.




回答3:


I've discovered an ability to modify headers when using the default Capybara::RackTest driver.

There's a method Capybara::RackTest::Browser#process which prepares a request before finaly being sent (https://www.rubydoc.info/gems/capybara/Capybara%2FRackTest%2FBrowser:process). As you can see there in the code the request headers are built from the options[:headers]. The options actually refers to the driver.options attribute. So you can set any headers by modifying this hash.

Here's an example of my feature spec with custom headers:


let(:headers) do
  {
    "YOUR_CUSTOM_HEADER_1" => "foo",
    "YOUR_CUSTOM_HEADER_2" => "bar",
    ...
  }
end 

before(:each) do
  @origin_headers = page.driver.options[:headers]
  page.driver.options[:headers] ||= {}
  page.driver.options[:headers].merge!(headers)
end

after(:each) do
  page.driver.options[:headers] = @origin_headers
end

Tested with:

  • capybara: 3.13.2 (RackTest driver)
  • rspec: 3.8
  • rails: 5.2.2

P.S. Haven't tested it with selenium driver yet. But probably it works in a similar way.



来源:https://stackoverflow.com/questions/7062129/whats-the-best-way-to-set-custom-request-headers-when-using-capybara-in-rspec-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!