Updated: Capybara: Running tests with headless Chrome

Posted . Visible to the public. Auto-destruct in 52 days

Chrome is now kept from opening PDF downloads. It will stay on the current page.

Changes

  • [Headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome) is a way to run the Chrome browser without a visible window.
  • Configuring Capybara
  • ====================
  • Configure the Capybara driver like this:
  • ```ruby
  • Capybara.register_driver :selenium do |app|
  • options = Selenium::WebDriver::Chrome::Options.new
  • options.add_argument('--disable-infobars')
  • options.add_emulation(device_metrics: { width: 1280, height: 960, touch: false })
  • unless ENV.key?('NO_HEADLESS')
  • options.add_argument('--headless')
  • options.add_argument('--disable-gpu')
  • end
  • if ENV.key?('CI') # Also when in Docker
  • options.add_argument('--no-sandbox')
  • options.add_argument('--disable-dev-shm-usage')
  • end
  • if ENV.key?('REMOTE_DEBUGGING')
  • options.add_argument('--remote-debugging-port=9223')
  • end
  • + # Prevent opening PDFs (i.e. leaving the current page on download)
  • + options.add_preference('plugins.always_open_pdf_externally', true)
  • +
  • Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
  • end
  • Selenium::WebDriver.logger.level = :error
  • ```
  • ## Headless Chrome in legacy Capybara 1 projects
  • If you're working on a legacy project with Capybara version 1.x, the code below should do:
  • ```ruby
  • Capybara.register_driver :selenium do |app|
  • args = []
  • args << '--headless' unless ENV.key?('NO_HEADLESS')
  • args << '--disable-infobars'
  • args << '--window-size=1280,960'
  • Capybara::Selenium::Driver.new(app, browser: :chrome, args: args)
  • end
  • ```
  • Looking at the hidden browser
  • =============================
  • Option 1: Run without headless
  • -------------------------------
  • You can call your tests with `NO_HEADLESS=1 bundle exec cucumber` to see the Chrome window for this test run. (This will not work when your Chrome is running inside Docker – in that case see option 2.)
  • You might want to define a bash alias `alias nh='NO_HEADLESS=1'` to shorten this command to `nh bundle exec cucumber`.
  • Option 2: Remote debugging
  • --------------------------
  • With remote debugging, you can access a Docker Chrome from the host system.
  • Here is an example for a Docker container started with `docker-compose`:
  • 1. Start the Docker container: `docker-compose run --publish 9222:9222 $service bash` (mapping the local port 9222 into that container, and starting a shell)
  • -2. Capybara will instruct its instance of Chrome to open the remote debugging port. Unfortunately, Chrome will only listen on localhost. You need to make the debugging port available to the (Docker) network: `socat TCP4-LISTEN:9222,fork TCP4:127.0.0.1:9223` (if missing, install with `sudo apt install socat`)
  • +2. Capybara will instruct its instance of Chrome to open the remote debugging port. Unfortunately, Chrome will only listen on localhost. You need to make the debugging port available to the (Docker) network: `socat TCP4-LISTEN:9222,fork TCP4:127.0.0.1:9223` (if missing, install the `socat` package)
  • 2. Start you integration test e.g. `REMOTE_DEBUGGING=1 bundle exec rspec spec/system/some_spec.rb` with a debugger set
  • 0. Open <chrome://inspect/>. It should list the test Chrome under "Remote target". (Ensure "Discover network targets" is enabled and "localhost:9222" is registered behind the "Configure…" button.)
  • > [NOTE]
  • > Remote debugging does not work well if you change your selenium driver between features (e.g. from a mobile device emulation back to a desktop browser). Therefore it makes more sense to run only single features / specs with REMOTE_DEBUGGING enabled.
  • ![Image](/makandra/492109/attachments/31439)
Dominik Schöler
License
Source code in this card is licensed under the MIT License.
Posted by Dominik Schöler to makandra dev (2025-01-10 06:57)