无法使用Ruby 中的 gem 上传文件selenium-webdriver (3.142.6)
技术堆栈:
硒网络驱动程序 (3.142.6(
铬版本 : 77
铬驱动程序:77
错误信息:
Selenium::WebDriver::Error::UnknownCommandError: unknown command: unknown command: session/xxxsession_idXXX/se/file
Backtrace:
Ordinal0 [0x00FDEB13+1501971]
Ordinal0 [0x00F5F6D1+980689]
Ordinal0 [0x00EE765F+489055]
Ordinal0 [0x00E9618E+156046]
Ordinal0 [0x00E95FF4+155636]
Ordinal0 [0x00E7220E+8718]
Ordinal0 [0x00E72626+9766]
Ordinal0 [0x00E72C10+11280]
Ordinal0 [0x00F78F37+1085239]
GetHandleVerifier [0x0107D7ED+503293]
GetHandleVerifier [0x0107D580+502672]
GetHandleVerifier [0x010846AC+531644]
GetHandleVerifier [0x0107DFFA+505354]
Ordinal0 [0x00F70606+1050118]
Ordinal0 [0x00F7047F+1049727]
Ordinal0 [0x00E7204B+8267]
Ordinal0 [0x00E71D7C+7548]
GetHandleVerifier [0x013CD83C+3976780]
BaseThreadInitThunk [0x755738F4+36]
RtlUnicodeStringToInteger [0x77375E13+595]
RtlUnicodeStringToInteger [0x77375DDE+542]
似乎是这个版本的 gem 的上传被破坏了。
用于上传文件的代码(watir with cheezy(
@browser.file_field(xpath: "//*[contains(text(), 'Upload')]/input[@type='file']").set(complete_path_to_file)
根本原因:w3c
浏览器功能状态
说明:当w3c:true
硒网络驱动程序抛出此错误时。这可能是因为Selenium 3并不完全支持w3c实现。
解决方案1:如果您没有任何基于w3c
功能的依赖项,则简单的解决方案将是w3c:false
。
解决方案2:如果解决方案1不起作用,则必须更新selenium-webdriver-3.142.6libseleniumwebdriverremotew3ccommands.rb
文件。 检查以下行,然后更新它。
upload_file: [:p ost, 'session/:session_id/se/file']
将此行更新为
upload_file: [:p ost, 'session/:session_id/file']
结论:在硒 4 推出之前,首选解决方案 1。如果您使用解决方案 2,则当您尝试在不推送此更改的计算机上运行它们时,可能会测试失败/文件可能会用bundle install
设置。
您可以使用方法直接使用解决方案,但我个人觉得这太多了。
将解决方案发布到SeleniumHQ,一旦得到确认,将向SeleniumHQ提交拉取请求。这样您就不会在更高版本的Selenium Ruby WebDriver中遇到此问题。
核心问题是 Chrome 的网络驱动程序使用非 W3C 标准网址来处理文件上传。 上传文件时,WebDriver 使用/se/file
URL 路径进行上传。 此路径(又名命令(受 Selenium 服务器支持。因此,Selenium 提供的 docker 镜像工作正常。 一旦我们直接使用chromedriver
,上传就会失败。 在此 GitHub 问题和其中的链接问题中查找更多信息。
为了解决这个问题,我们可以通过覆盖:upload_file
中的 键来强制 Web 驱动程序使用符合标准的Selenium::WebDriver::Remote::Bridge::COMMANDS
键。 由于加载模块时不会初始化此COMMANDS
常量,因此我们可以覆盖attach_file
方法以确保正确设置常量。这里是黑客代码:
module Capybara::Node::Actions
alias_method :original_attach_file, :attach_file
def attach_file(*args, **kwargs)
implement_hacky_fix_for_file_uploads_with_chromedriver
original_attach_file(*args, **kwargs)
end
def implement_hacky_fix_for_file_uploads_with_chromedriver
return if @hacky_fix_implemented
original_verbose, $VERBOSE = $VERBOSE, nil # ignore warnings
cmds = Selenium::WebDriver::Remote::Bridge::COMMANDS.dup
cmds[:upload_file] = [:post, "session/:session_id/file"]
Selenium::WebDriver::Remote::Bridge.const_set(:COMMANDS, cmds)
$VERBOSE = original_verbose
@hacky_fix_implemented = true
end
end
顺便说一下,找到根本原因很困难,因为当错误发生时,水豚宝石会捕获错误并尝试再次引发错误。 但是,当重新引发时,它使用不存在的错误常量。我通过在gems/capybara-3.38.0/lib/capybara/selenium/nodes/chrome_node.rb +109
中使用StandardError
来解决它。只有这样,错误搜索才能继续。也许这本身就值得一个问题。