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

Rails/Capybara测试中attach_file无法适配Active Storage直传如何解决?

使用Capybara测试Rails Active Storage直传功能时文件上传失败问题

使用Capybara开展系统测试时,无法向启用了direct upload功能的文件输入框上传文件。切换到直传模式前所有测试均可正常运行,手动通过浏览器提交对应表单也完全正常,但在Capybara环境下始终无法成功上传。

相关代码

视图层输入框代码

<%= f.input :desktop_files, as: :file, input_html: { direct_upload: true, multiple: true } %>

测试用例上传代码

attach_file 'uploads_create_assets_former[desktop_files][]', "#{fixture_path}/files/image.jpg"

报错信息

运行包含上述代码的测试时,会抛出如下异常:

Selenium::WebDriver::Error::UnexpectedAlertOpenError: unexpected alert open: {Alert text : Error reading image.jpg}
  (Session info: headless chrome=94.0.4606.81)

同时Capybara启动的浏览器控制台可见FileReader相关报错。

环境信息

依赖版本

  • ruby (3.0.0)
  • rails (6.1.4.1)
  • selenium-webdriver (4.0.3)
  • capybara (3.35.3)
  • webdrivers (4.7.0)

Capybara驱动配置

Capybara.register_driver :headless_chrome do |app|
  options = Selenium::WebDriver::Chrome::Options.new(
    args: %w[headless disable-gpu no-sandbox window-size=1440x768]
  )
  options.add_preference(:download, prompt_for_download: false,
                                    default_directory: Rails.root.join('tmp/downloads').to_s)
  options.add_preference(:browser, set_download_behavior: { behavior: 'allow' })

  Capybara::Selenium::Driver.new(app, browser: :chrome, capabilities: options)
end

补充说明

已完全按照Rails官方Active Storage直传文档实现功能,文件在表单提交时触发上传。
对应表单HTML代码如下:

<form class="formtastic uploads_create_assets_former" id="new_uploads_create_assets_former" enctype="multipart/form-data" action="/admin/upload/create" accept-charset="UTF-8" method="post">
  <fieldset class="inputs">
    <ol>
      <li class="file input optional" id="uploads_create_assets_former_desktop_files_input"><label for="uploads_create_assets_former_desktop_files" class="label">Dateien (Computer)</label>
        <input id="uploads_create_assets_former_desktop_files" multiple="multiple" data-direct-upload-url="http://127.0.0.1:49538/rails/active_storage/direct_uploads" type="file" name="uploads_create_assets_former[desktop_files][]" />
      </li>
    </ol>
  </fieldset>  
  <fieldset class="actions">
    <ol>
      <li class="action input_action " id="uploads_create_assets_former_submit_action">
        <input type="submit" name="commit" value="Nächster Schritt" data-disable-with="Nächster Schritt" />
      </li>
    </ol>
  </fieldset>
</form>

排查验证

已搭建最小可复现项目验证问题,确认以下信息:

  • 文件路径正确,路径错误会直接抛出Capybara::FileNotFound异常,测试中未出现该类异常
  • 尝试过相对路径、绝对路径均无效
  • 测试文件对所有用户开放读权限,权限信息如下:
-rw-r--r--  1 martintomas  staff    26436 Oct 22 12:51 image.jpg
  • 本地环境和CI环境均可复现相同问题

临时解决方案

如果完全信任Active Storage直传的官方实现,且没有自定义直传相关JS代码,可以在系统测试中临时关闭直传功能绕过问题:

def attach_file(locator = nil, paths, make_visible: nil, **options)
  turn_off_direct_upload # Capybara does not work with direct upload
  super
end

def turn_off_direct_upload
  page.execute_script 'document.querySelectorAll("input[data-direct-upload-url]:not([data-direct-upload-url=\"\"])").forEach((input) => { delete input.dataset.directUploadUrl } )'
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 09:54:05