当在Rspec请求规范中使用Capybara时,设置自定义请求头的最佳方法是什么?

7

我正在使用猴子补丁来修改Capybara::Session,增加一个名为set_headers的方法,它将分配给Capybara::RackTest::Browser的options属性(我将其从attr_reader更改为attr_accessor)。

修改内容如下:

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

在我的请求规范中,我正在执行以下操作:

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

这样做是可行的,但我想知道是否有更好的方法,仅仅为了设置请求的自定义remote_ip/remote_addr,似乎有点过度。你有什么想法吗?

3个回答

1
如果您希望在所有请求中全局设置标头,可以使用类似以下的代码:
Capybara.register_driver :custom_headers_driver do |app|
  Capybara::RackTest::Driver.new(app, :headers => {'HTTP_FOO' => 'foobar'})
end

请参考Capybara 1.1.2中的rack_test_driver_spec.rb以及Capybara问题#320,设置HTTP标头


1
我发现当使用默认的Capybara::RackTest驱动程序时,可以修改标题的能力。
有一个方法Capybara::RackTest::Browser#process,该方法在最终发送请求之前准备请求(https://www.rubydoc.info/gems/capybara/Capybara%2FRackTest%2FBrowser:process)。从代码中可以看到,请求头是由options[:headers]构建的。实际上,options指的是driver.options属性。因此,您可以通过修改此哈希表来设置任何标题。
以下是我的特性规范示例,其中包含自定义标头:

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

测试环境:

  • capybara: 3.13.2 (RackTest驱动程序)
  • rspec: 3.8
  • rails: 5.2.2

P.S. 尚未使用selenium驱动程序进行测试。 但可能以类似的方式工作。


1
你是否需要在rspec中使用capybara为特定请求添加自定义标头?我在验收测试中使用了这种方法。对于我来说,这是使用带有特定标头数据的get方法的最佳方式。您可以评估响应页面上的特定元素。请参见下面的示例:
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']")

我希望它能有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接