SeleniumHQ / selenium

A browser automation framework and ecosystem.
https://selenium.dev
Apache License 2.0
30.56k stars 8.17k forks source link

Network conditions cannot modified for remote chrome browser with capybara #7174

Closed nikriek closed 5 years ago

nikriek commented 5 years ago

πŸ› Bug Report

We use a combination of docker-compose, rails and selenium to perform integration/system testing. The Capybara/rspec environment is supposed to send commands to a remote chrome container:

chrome:
    image: selenium/standalone-chrome
    volumes:
      - ./spec/fixtures/files:/app/spec/fixtures/files

This is how we setup the driver:

Capybara.register_driver :headless_chrome do |app|
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
      chromeOptions: {
          args: %W[no-sandbox
                   disable-dev-shm-usage
                   no-default-browser-check
                   start-maximized
                   headless
                   disable-gpu]}
  )
  Capybara::Selenium::Driver.new(app,
                                 url: "http://#{ENV['SELENIUM_HOST']}/wd/hub",
                                 browser: :chrome,
                                 desired_capabilities: capabilities)
end

This setup works completely fine. Capybara connects to the hub and successfully runs our integration tests.

In order to enhance our tests, we need to make use of the network_conditions selenium endpoint to test the application in an offline setup. This seems not to be officially documented, but it can be achieved using this call:

page.driver.browser.network_conditions = {offline: false}

Instead of returning a success, the call throws an exception:

*** Selenium::WebDriver::Error::WebDriverError Exception: unexpected response, code=404, content-type="text/html"
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" type="text/css" href="/assets/displayhelpservlet.css" media="all"/>
  <link href="/assets/favicon.ico" rel="icon" type="image/x-icon" />
  <script src="/assets/jquery-3.1.1.min.js" type="text/javascript"></script>
  <script src="/assets/displayhelpservlet.js" type="text/javascript"></script>
  <script type="text/javascript">
    var json = Object.freeze('{"consoleLink": "\u002fwd\u002fhub","type": "Standalone","class": "org.openqa.grid.web.servlet.DisplayHelpHandler$DisplayHelpServletConfig","version": "3.141.59"}');
  </script>
</head>
<body>

<div id="content">
  <div id="help-heading">
    <h1><span id="logo"></span></h1>
    <h2>Selenium <span class="se-type"></span>&nbsp;v.<span class="se-version"></span></h2>
  </div>

  <div id="content-body">
    <p>
      Whoops! The URL specified routes to this help page.
    </p>
    <p>
      For more information about Selenium <span class="se-type"></span> please see the
      <a class="se-docs">docs</a> and/or visit the <a class="se-wiki">wiki</a>.
      <span id="console-item">
        Or perhaps you are looking for the Selenium <span class="se-type"></span> <a class="se-console">console</a>.
      </span>
    </p>
    <p>
      Happy Testing!
    </p>
  </div>

To Reproduce

You can reproduce the issue by using a custom remote host in the Rails application.

Expected behavior

The expected behavior is a successful call for

page.driver.browser.network_conditions = {offline: false}

The call expects a json response from POST http://<HOST>:4444/wd/hub/session/e1fa22b0aaac7e5207d7bbe497673f57/chromium/network_conditions

{
  sessionId: "e1fa22b0aaac7e5207d7bbe497673f57",
  status: 13,
  value: {
    message: "unknown error: network conditions must be set before it can be retrieved (Session info: chrome=74.0.3729.108) (Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}),platform=Linux 4.9.125-linuxkit x86_64)"
  }
}

I suspect the issue to be a problem of absolute and relative url paths in the chrome bride: https://github.com/SeleniumHQ/selenium/blob/master/rb/lib/selenium/webdriver/chrome/bridge.rb#L27

Other calls to the api (like for creating a new session) do not have a / appended. It seems that the call is going to POST http://<HOST>:4444/session/e1fa22b0aaac7e5207d7bbe497673f57/chromium/network_conditions

Test script or set of commands reproducing this issue

See above

Environment

OS: Linux 4.9.125-linuxkit / Docker Browser: chrome Browser version: chromedriver=74.0.3729.6 Browser Driver version: Language Bindings version: Ruby 2.5.2

nikriek commented 5 years ago

Switching to browser: :remote is also working for the current setup. However, when calling the network_conditions, it returns

*** NoMethodError Exception: undefined method `network_conditions' for #<Selenium::WebDriver::Remote::Driver:0x00005599f4e652b0>
nikriek commented 5 years ago

To prove my point I patched the paths. This makes it work:

module Selenium
  module WebDriver
    module Chrome
      module Bridge
        PATCHED_COMMANDS = {
            get_network_conditions: [:get, 'session/:session_id/chromium/network_conditions'],
            set_network_conditions: [:post, 'session/:session_id/chromium/network_conditions'],
            send_command: [:post, 'session/:session_id/goog/cdp/execute']
        }.freeze

        def commands(command)
          PATCHED_COMMANDS[command] || super
        end
      end
    end
  end
end
p0deje commented 5 years ago

Thank you for a great bug report and a provided fix. I've committed and it will be released in the next 4.0 alpha.

p0deje commented 5 years ago

This is also released in 3.142.2.