Selenium file_detector 无法找到要上传到 selenium 网格的文件

Selenium file_detector unable to find file to upload to selenium grid

使用 selenium webdriver 3.12 和 运行在 saucelabs(selenium 网格)上进行文件上传测试作为 Win 10 chrome 66。我尝试实现文件检测器并将密钥发送到我的代码,以便系统可以从我的本地计算机上获取文件并在 saucelabs 中使用它,但是 运行 遇到错误:

Selenium::WebDriver::Error::ExpectedError:
       invalid argument: File not found : /Users/john.doe/Work/project/spec/support/apps/files/suggested_content/valid_sc.csv
         (Session info: chrome=66.0.3359.117)
         (Driver info: chromedriver=2.38.551601 (edb21f07fc70e9027c746edd3201443e011a61ed),platform=Windows NT 10.0.10586 x86_64)

我实现这个的方法是添加文件检测器作为我的规范助手的一部分,然后在我的规范文件的顶部需要规范助手,然后使用 sendkeys 发送文件上传路径。类似于 Saucelabs best practices here

我的规范助手中的一个片段...我已经实例化了驱动程序并添加了文件检测器的代码(这与 sauce 和 ruby​​doc 的使用略有不同,因为它使用的是当前会话驱动程序而不仅仅是驱动程序) :

       Capybara::Selenium::Driver.new(app,
                                       browser: :remote,
                                       url: url,
                                       desired_capabilities: capabilities)
        end

Capybara.current_session.driver.browser.file_detector = lambda do |args|
            str = args.first.to_s
            str if File.exist?(str)
          end

以及调用什么来上传文件:

    def add_file(file_name = 'valid_sc.csv')
      path = './spec/support/apps/files/suggested_content/'
      expose_file_upload
      page.find('input[id*=content--add-file')
          .send_keys(File.expand_path(path + file_name))
    end

该文件肯定在该路径中,并且当我 运行 在本地进行测试时工作正常。我在这里错过了什么?

假设错误消息是来自远程驱动程序的响应(堆栈跟踪将有助于确认)错误消息包含原始文件名(而不是临时文件名)的事实告诉您文件检测器是'正在使用。从您的代码中不清楚当您的规范帮助程序代码为 运行 时 Capybara.current_session 是什么,因此可能的原因是当您添加文件检测器时当前会话不正确。尝试在驱动程序注册块中设置它

Capybara.register_driver(...) do
  ...
  Capybara::Selenium::Driver.new(app,
                                   browser: :remote,
                                   url: url,
                                   desired_capabilities: capabilities).tap do |driver|
    driver.browser.file_detector = lambda do |args|
      str = args.first.to_s
      str if File.exist?(str)
    end
  end
end

selenium-webdriver 3.14 版本中也有一些解决 file_detector 的问题,因此您可能也想尝试升级。

在单独的注释中,您是否尝试过将水豚 attach_filemake_visible 选项一起使用,而不是自己滚动 expose_file_upload

page.attach_file(File.expand_path(path + file_name), make_visible: true)

在 saucelabs 上使用水豚测试文件上传有点棘手。 我前段时间遇到过类似的问题。

尝试不使用文件检测器并使用水豚的 attach_file 方法。

概览:

而 运行 如果您使用 attach_file 水豚函数上传文件,这将验证本地计算机上的文件存在路径,请参阅下面的 attach_file 来自 ruby​​docs 的方法源代码

    def attach_file(locator = nil, path, make_visible: nil, **options)
      Array(path).each do |p|
        raise Capybara::FileNotFound, "cannot attach file, #{p} does not exist" unless File.exist?(p.to_s)
      end
      # Allow user to update the CSS style of the file input since they are so often hidden on a page
      if make_visible
        ff = find(:file_field, locator, options.merge(visible: :all))
        while_visible(ff, make_visible) { |el| el.set(path) }
      else
        find(:file_field, locator, options).set(path)
      end
    end

但是在执行时它会在 saucelabs 机器上搜索相同的路径,如果文件在 saucelabs 机器上不存在,这可能会出错。

因此对于简单的解决方案,您可以创建一个自定义的 attach_file 方法而不进行路径验证,如下所示:

    def attach_file_new(locator, path, options={})
      find(:file_field, locator, options).set(path)
    end

您可以通过执行javascript或jquery方法来检查和设置元素可见性,并向此方法提供实际saucelabs机器的文件路径。

所以它的作用是不会验证本地机器上的路径,而是直接从 saucelabs 机器上选择文件。

更多信息: 在 saucelabs 上执行测试时,它会在执行时创建机器,因此您之前不能将文件放在该机器上。

所以更好的方法是在实际文件上传步骤之前添加一些设置步骤,在这些步骤中您打开浏览器并点击直接下载文件 url 例如一些保管箱文件 url 或 google drive direct file download url,它会在saucelabs机器上为你下载文件并且下载总是在下载目录中所以你可以提供那个目录的路径和文件名给attach_file方法。

希望对您有所帮助。

这对我来说已经解决了。注册远程驱动程序后,我将此代码段的底部添加到我的 spec_helper.rb

Capybara.register_driver :selenium do |app|
  # ...

  Capybara::Selenium::Driver.new(app,
                                 browser: :remote,
                                 url: url,
                                 desired_capabilities: capabilities)
end

# Add file upload capability on remote driver
page.driver.browser.file_detector = lambda do |args|
  str = args.first.to_s
  str if File.exist?(str)
end

确保仅在使用远程驱动程序时执行此操作,否则常规的本地 selenium 驱动程序将不知道如何处理 file_detector 方法。

我偶然发现了这个线程的另一个错误,但发现这个问题的上下文很有用。将其添加到此处以防有人卡在这个问题上:

NoMethodError:
           undefined method `file_detector=' for #<Selenium::WebDriver::Chrome::Driver:0x00007ff8edf60020>

我的版本设置如下:

  • Chrome 驱动程序 83.0.4103.39
  • selenium-webdriver 3.14

解决这个问题:

  1. 我按照 Thomas 的建议将 driver.browser.file_detector 放入用于远程驱动程序的驱动程序注册中,如他的回答所示
  2. 我将 selenium-webdriver gem 从 3.14 升级到 3.142.7