如何在chromedriver中关闭w3c以解决错误未知命令:在W3C中无法调用非W3C标准命令

Jul*_*lie 17 selenium google-chrome selenium-chromedriver selenium-webdriver webdriver-w3c-spec

在刚刚发布的Chrome版本75中,我们的测试无法正常运行。他们给出了粘贴在下面的堆栈跟踪。我们在带有rspec,selenium-webdriver 3.8.0的Rails v。5.1.6.2上使用ruby。

堆栈跟踪:

Selenium::WebDriver::Error::UnknownCommandError:
            unknown command: Cannot call non W3C standard command while in W3C mode
          # 0   chromedriver                        0x000000010c46e8e9 chromedriver + 3594473
          # 1   chromedriver                        0x000000010c3fe543 chromedriver + 3134787
          # 2   chromedriver                        0x000000010c1aa29f chromedriver + 692895
          # 3   chromedriver                        0x000000010c11a691 chromedriver + 104081
          # 4   chromedriver                        0x000000010c11b7d5 chromedriver + 108501
          # 5   chromedriver                        0x000000010c42d555 chromedriver + 3327317
          # 6   chromedriver                        0x000000010c438e60 chromedriver + 3374688
          # 7   chromedriver                        0x000000010c438bf8 chromedriver + 3374072
          # 8   chromedriver                        0x000000010c40cd39 chromedriver + 3194169
          # 9   chromedriver                        0x000000010c4396d8 chromedriver + 3376856
          # 10  chromedriver                        0x000000010c420f27 chromedriver + 3276583
          # 11  chromedriver                        0x000000010c456064 chromedriver + 3493988
          # 12  chromedriver                        0x000000010c474617 chromedriver + 3618327
          # 13  libsystem_pthread.dylib             0x00007fff7744c2eb _pthread_body + 126
          # 14  libsystem_pthread.dylib             0x00007fff7744f249 _pthread_start + 66
          # 15  libsystem_pthread.dylib             0x00007fff7744b40d thread_start + 13
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/response.rb:69:in `assert_ok'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/response.rb:32:in `initialize'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/http/common.rb:81:in `new'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/http/common.rb:81:in `create_response'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/http/default.rb:104:in `request'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/http/common.rb:59:in `call'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/bridge.rb:166:in `execute'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/oss/bridge.rb:579:in `execute'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/remote/oss/bridge.rb:526:in `element_displayed?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/selenium-webdriver-3.8.0/lib/selenium/webdriver/common/element.rb:199:in `displayed?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/selenium/node.rb:148:in `visible?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/node/element.rb:269:in `block in visible?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/node/base.rb:81:in `synchronize'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/node/element.rb:269:in `visible?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/queries/selector_query.rb:84:in `matches_filters?'
          # /Users/julie/.rvm/gems/ruby-2.5.1/gems/capybara-2.17.0/lib/capybara/result.rb:29:in `block in initialize'
Run Code Online (Sandbox Code Playgroud)

我们的驱动程序配置:

File.write(LOG_FILE_PATH, '')
Selenium::WebDriver.logger.level = :debug
Selenium::WebDriver.logger.output = LOG_FILE_PATH
Capybara.register_driver :selenium do |app|
  # from https://github.com/SeleniumHQ/selenium/issues/3738
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: {browser: 'ALL'})
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument '--disable-infobars' # hide info bar about chrome automating test
  # if we don't use this flag, every selenium test will die with the error:
  # "unknown error: Chrome failed to start: exited abnormally"
  options.add_argument '--no-sandbox'
  options.add_argument '--headless' if ENV.fetch("HEADLESS", nil).present?
  options.add_argument '--window-size=1600,2400'
  options.add_argument '-–allow-file-access-from-files' # TODO Julie - may help with file specs?
  options.add_preference('homepage', 'about:blank') # TODO is this working?
  options.add_preference('profile.default_content_settings.popups', 0)
  options.add_preference('download.default_directory', DownloadHelpers::PATH.to_s)
  Capybara::Selenium::Driver.new(
    app,
    clear_local_storage: true,
    clear_session_storage: true,
    browser: :chrome,
    options: options,
    desired_capabilities: capabilities,
  )
end
Run Code Online (Sandbox Code Playgroud)

更新:

我能够使用暂时使我们的测试工作capabilities = { "chromeOptions" => {'w3c' => false} }

更新chromedriver后,我们开始收到错误“未知错误:DevToolsActivePort文件不存在”。为了解决此问题,我们将selenium-webdriver gem升级到3.142.3,并解决了此问题,使我们可以使用w3c而无需任何其他参数。

Deb*_*anB 19

首先解决

正如John Chen [Google Chrome浏览器的WebDriver所有者]昨天承诺的那样,ChromeDriver 75.0.3770.9076.0.3809.25的新版本已经发布,现在可以在ChromeDriver下载站点上使用。这些版本包含以下针对先前版本的ChromeDriver 7576的错误修复:

  • 修复了在OSS模式下错误地拒绝主体为空的POST请求的错误
  • 添加了用于检索Chrome日志的新端点

此外,版本76.0.3809.25还包括以下更改:

  • 在W3C模式下为显示命令添加了端点

电子邮件快照

75_76


细节

在chromedriver中关闭w3c以解决该错误将违反最佳做法:

Selenium::WebDriver::Error::UnknownCommandError:
        unknown command: Cannot call non W3C standard command while in W3C mode
Run Code Online (Sandbox Code Playgroud)

因为ChromeDriver的当前实现要求向客户端发送W3C兼容会话。


然而,此错误消息意味着ChromeDriver无法调用非W3C标准的命令,而在W3C模式同时启动/产生一个新的web浏览器Chrome的浏览器会话。

主要问题是,当ChromeDriver的客户端请求符合W3C的会话时ChromeDriver的响应不符合W3C规范,并导致语言API错误。

根据W3C模式下ChromeDriver响应中的讨论不符合标准, John Chen(Google Chrome浏览器的WebDriver的所有者)提到 Simon Stewart(Creator-WebDriver)已更新:

  • w3c会话的新会话响应应类似于:

    {
      "value": {
        "sessionId": "some-uuid",
        "capabilities": {
          "browserName": "chrome",
          ...
        }
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 但首先是一个新的会话时w3c选项设置为truechromeOptions,返回的响应看起来像:

        {
          "sessionId": "af4656c27fb94485b7872e1fc616923a",
          "status": "ok",
          "value": {
            "browserName": "chrome",
            ...
          }
        }
    
    Run Code Online (Sandbox Code Playgroud)

这既不是针对JSON Wire Protocol的正确格式的响应(“状态”为整数),也不是正确格式的W3C响应,并且如果没有正确格式的响应,则不能使用w3c兼容。

修订和本提交解决了此问题。


这个用例

大概你正在使用ChromeDriver v75.x铬v75.x和情况下,你仍然看到的错误,你需要通过ExperimentalOption w3ctrue明确如下:

  • Ruby代码示例:

    capabilities = { "chromeOptions" => {'w3c' => true} }
    
    Run Code Online (Sandbox Code Playgroud)
  • Java代码示例:

    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.chrome.ChromeOptions;
    
    public class W3c {
      public static void main(String[] args) throws Exception {
        ChromeOptions opt = new ChromeOptions();
        opt.setExperimentalOption("w3c", true);
        ChromeDriver driver = new ChromeDriver(opt);
        driver.get("https://www.google.co.in");
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • Python代码示例:

    from selenium import webdriver
    
    opt = webdriver.ChromeOptions()
    opt.add_experimental_option('w3c', True)
    driver = webdriver.Chrome(chrome_options=opt)
    driver.get('https://www.google.co.in')
    
    Run Code Online (Sandbox Code Playgroud)

更新资料

直到ChromeDriver v74.xChromeChromeDriver组合默认在w3c模式下运行,但chromedriver / server / http_handler.cc中存在错误。根据goog:chromeOptions.w3c = false中的详细信息不适用于带有空主体的POST请求

方法HttpHandler::HandleCommand检查kW3CDefault常量的值而不是会话goog:chromeOptions.w3c值。结果,JSON Wire协议支持被破坏,允许带有空主体的POST请求。displayed在w3c模式下恢复端点之前,将需要JSON Wire协议。应当注意,W3C WebDriver规范不禁止使用“显示”端点,并且某些API中积极使用了此功能。

由于Is Element Displayed命令不是W3C规范的一部分,而是某些API仍在使用,因此其功能可能很难在这些API中复制。此变更列表 [ 版本提交 ]在W3C模式下重新启用此命令,以简化向W3C模式的转换。

@John已经确认我们希望明天通过修复程序对ChromeDriver v75.0进行更新。

  • @DebanjanB我可以确认76.0.3809.25正常工作。不幸的是,75.0.3770.90不在,而76仍处于beta版。是否有希望将此修补程序合并到稳定分支中? (3认同)

小智 7

完成后options = Selenium::WebDriver::Chrome::Options.new 你可以做options.add_option('w3c', false)


小智 5

对于使用Java语言的人(我专门使用WebdriverIO),请确保您使用“ goog:chromeOptions”

  capabilities: {
    browserName: 'chrome',
    'goog:chromeOptions': {
        'w3c': false
    }
  }
Run Code Online (Sandbox Code Playgroud)

否则你会得到

unknown error: Illegal key values seen in w3c capabilities: [chromeOptions]
Run Code Online (Sandbox Code Playgroud)

  • 使用 selenium-webdriver 4.0.0-alpha.4 和 chromedriver 76.0.1 这对我有用: `const driver = new Builder().withCapability({ browserName: 'chrome', chromeOptions: { w3c: false } }).. .build();` (2认同)