问题
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