You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多域名反向代理场景下Rails应用的Capybara测试方案问询

解决Rails跨域名Capybara端到端测试问题

咱们先拆解一下你的问题核心:Capybara默认对跨域名访问有严格限制,而你的架构需要在测试中同时模拟自定义域名(如testdomain.me)和平台域名(lvh.me)的跳转,再加上生产环境的反向代理逻辑在测试环境中需要特殊适配,这才导致之前的配置没起作用。下面给你一套可行的解决方案:

1. 先搞定本地域名解析

首先,testdomain.me默认不会指向你的本地测试服务器,所以得修改本地hosts文件,让它映射到127.0.0.1:

  • Mac/Linux:编辑 /etc/hosts,添加一行:
    127.0.0.1 testdomain.me
    
  • Windows:编辑 C:\Windows\System32\drivers\etc\hosts,同样添加上面的内容(需要管理员权限)

2. 更新Capybara & Webkit配置

去掉固定的app_host,让测试动态指定域名,同时确保Webkit驱动允许所有需要的域名及端口访问:

Capybara::Webkit.configure do |config|
  config.allow_unknown_urls
  config.ignore_ssl_errors
  config.skip_image_loading
  config.raise_javascript_errors = true
  # 允许所有测试相关的域名(包括带端口的)
  config.allow_url("lvh.me")
  config.allow_url("*.lvh.me")
  config.allow_url("testdomain.me")
  config.allow_url("lvh.me:*")
  config.allow_url("testdomain.me:*")
end

Capybara.configure do |config|
  config.always_include_port = true
  config.javascript_driver = :webkit
  config.default_max_wait_time = ENV.has_key?("CI") ? 60 : 10
  # 不要固定app_host,让测试动态指定
  config.server_host = "0.0.0.0" # 允许本地所有IP访问测试服务器
end

RSpec.configure do |config|
  config.include SubdomainHelper, type: :feature
  
  config.before(type: :request) do
    host! "lvh.me"
  end
  
  config.before(type: :feature) do
    # 只固定协议,host在测试中动态设置
    default_url_options[:protocol] = "http"
  end
end

3. 关键:确保跨域名跳转时Session不丢失

你的生产环境中,用户从自定义域名跳转到平台域名时Session是保留的,测试环境需要模拟这个逻辑。修改config/environments/test.rb中的Session配置,让Cookie的Domain绑定到平台域名:

Rails.application.config.session_store :cookie_store, 
  key: '_your_app_session',
  domain: 'lvh.me' # 不管访问哪个域名,Cookie都绑定到平台域名

这样当你访问testdomain.me时,应用设置的Cookie会被浏览器关联到lvh.me,跳转到平台域名时Session就能正常保持了。

4. 编写跨域名测试用例

直接在测试中指定完整的自定义域名URL,然后验证跳转后的平台页面:

feature "跨域名选品结算流程" do
  scenario "用户从自定义域名选品后跳转到平台域名结算" do
    # 访问自定义域名的店铺页面(带上测试服务器端口)
    visit "http://testdomain.me:#{Capybara.server_port}/shop"
    
    # 模拟选品操作(根据你的实际页面调整)
    click_link "加入购物车"
    expect(page).to have_content("购物车已添加")
    
    # 点击结算按钮,触发跨域名跳转
    click_button "去平台结算"
    
    # 验证已跳转到平台域名的结算页
    expect(current_url).to match(%r{http://lvh.me:\d+/checkout})
    expect(page).to have_content("结算信息填写")
  end
end

额外注意事项

  • CI环境适配:如果在Heroku CI等环境运行测试,需要在CI脚本中添加hosts配置(比如用echo "127.0.0.1 testdomain.me" | sudo tee -a /etc/hosts)
  • 驱动备选:如果Webkit驱动还是有问题,可以切换到selenium-chrome-headless驱动,它对跨域场景的支持更友好,配置逻辑和上面一致
  • 端口问题:Capybara默认随机分配服务器端口,always_include_port = true确保URL中会自动带上端口,不用手动固定

内容的提问来源于stack exchange,提问作者Kyle Byrne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:58:32