teamcapybara / capybara

Acceptance test framework for web applications

Home Page:http://teamcapybara.github.io/capybara/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Capybara Headless Chrome Raising Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT

Meowcenary opened this issue · comments

Meta

Capybara Version: 2.17
Ruby 2.5.9
Rails 5.2.8

Driver Information (and browser if relevant):
chrome (114.0.5735.90)
selenium-webdriver (3.6.0)
webdrivers (3.9.4)

Expected Behavior

visit root_path will visit the root path of the website without error.

Actual Behavior

Only tests marked with js: true have this issue. If js: true is removed visit root_path will work. Capybara.javascript_driver is set to headless chrome too so it's not clear why it only raises this error on javascript tests.

     Failure/Error: visit root_path

     Encoding::CompatibilityError:
       incompatible character encodings: UTF-8 and ASCII-8BIT
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/net-protocol-0.1.2/lib/net/protocol.rb:160:in `read'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/http_logger-0.5.1/lib/http_logger.rb:198:in `block in request'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/http_logger-0.5.1/lib/http_logger.rb:58:in `perform'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/http_logger-0.5.1/lib/http_logger.rb:45:in `perform'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/http_logger-0.5.1/lib/http_logger.rb:197:in `request'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webmock-3.1.0/lib/webmock/http_lib_adapters/net_http.rb:97:in `block in request'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webmock-3.1.0/lib/webmock/http_lib_adapters/net_http.rb:105:in `block in request'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webmock-3.1.0/lib/webmock/http_lib_adapters/net_http.rb:137:in `start_with_connect_without_finish'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webmock-3.1.0/lib/webmock/http_lib_adapters/net_http.rb:104:in `request'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webmock-3.1.0/lib/webmock/http_lib_adapters/net_http.rb:123:in `start_without_connect'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webmock-3.1.0/lib/webmock/http_lib_adapters/net_http.rb:150:in `start'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webdrivers-3.9.4/lib/webdrivers/network.rb:31:in `get_response'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webdrivers-3.9.4/lib/webdrivers/network.rb:12:in `get'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webdrivers-3.9.4/lib/webdrivers/system.rb:65:in `block (2 levels) in download_file'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webdrivers-3.9.4/lib/webdrivers/system.rb:64:in `block in download_file'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webdrivers-3.9.4/lib/webdrivers/system.rb:63:in `chdir'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webdrivers-3.9.4/lib/webdrivers/system.rb:63:in `download_file'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webdrivers-3.9.4/lib/webdrivers/system.rb:54:in `download'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webdrivers-3.9.4/lib/webdrivers/common.rb:100:in `update'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/webdrivers-3.9.4/lib/webdrivers/chromedriver.rb:184:in `driver_path'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/selenium-webdriver-3.6.0/lib/selenium/webdriver/chrome/driver.rb:38:in `initialize'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/selenium-webdriver-3.6.0/lib/selenium/webdriver/common/driver.rb:46:in `new'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/selenium-webdriver-3.6.0/lib/selenium/webdriver/common/driver.rb:46:in `for'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/selenium-webdriver-3.6.0/lib/selenium/webdriver.rb:86:in `for'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/capybara-2.17.0/lib/capybara/selenium/driver.rb:23:in `browser'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/capybara-2.17.0/lib/capybara/selenium/driver.rb:49:in `visit'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/capybara-2.17.0/lib/capybara/session.rb:274:in `visit'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/capybara-2.17.0/lib/capybara/dsl.rb:50:in `block (2 levels) in <module:DSL>'
     # ./spec/features/mobile_menu_spec.rb:27:in `block (3 levels) in <main>'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:123:in `block in run'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `loop'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `run'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/rspec-retry-0.6.1/lib/rspec_ext/rspec_ext.rb:12:in `run_with_retry'
     # /Users/esn2981/.rvm/gems/ruby-2.5.9@galter-website/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:37:in `block (2 levels) in setup'

Steps to reproduce

"Gemfile"

gem 'capybara'
gem 'webdrivers'

config.encoding = "utf-8" is set in "config/application.rb"

"spec/rails_helper.rb" , "encoding: UTF-8" was added as an attempt to fix this issue.

# encoding: UTF-8
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'capybara/rspec'
require 'webdrivers'

Capybara.default_max_wait_time = 2

Webdrivers::Chromedriver.required_version = "114.0.5735.90"

options = %w(headless disable-gpu ignore-certificate-errors disable-web-security)
Capybara.register_driver :headless_chrome do |app|
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(chromeOptions: {args: options})
  Capybara::Selenium::Driver.new app, browser: :chrome, desired_capabilities: capabilities
end

Capybara.javascript_driver = :headless_chrome

"spec/features/mobile_menu_spec.rb"

RSpec.feature 'User navigation menu on mobile screen', type: :feature do
  let(:user) { FactoryBot.create(:user) }
  let(:mobile_nav) { page.find('#masthead') }
  let!(:fpe_top) {
    FactoryBot.create(:front_page_element,
                      element_type: 'top_row_nav',
                      heading_large: 'Prism',
                      link_destination: 'https://prism.northwestern.edu',
                      published: true) }
  let!(:fpe_bottom) {
    FactoryBot.create(:front_page_element,
                      element_type: 'bottom_row_nav',
                      heading_large: 'Search Tools',
                      html: '<ul><li><a href="/search">Search</a></li></ul>',
                      nav_bar_list: 'Find, Borrow, Request',
                      published: true) }
  let!(:unpublished_fpe) {
    FactoryBot.create(:front_page_element,
                      element_type: 'bottom_row_nav',
                      heading_large: 'Get In Touch',
                      html: '<li><a href="/contact">Contact</a></li>',
                      nav_bar_list: 'About',
                      published: false) }

  describe "Navigation links", js: true do
    before do
      visit root_path
      resize_window_to_mobile
    end

    it 'does not reveal links on page load' do
      expect(mobile_nav).to_not have_link('More')
      expect(mobile_nav).to_not have_link('Home', href: '/')
      expect(mobile_nav).to_not have_link('Prism', href: 'https://prism.northwestern.edu')
      expect(mobile_nav).to_not have_link('Ask Us', href: '/request-services-and-materials/ask-a-librarian')
      expect(mobile_nav).to_not have_link('Site Preferences', href: '/site_preferences')
      expect(mobile_nav).to_not have_link('My Galter', href: '/signin')
    end
end

"app/views/layouts/application.html.erb" notice <meta charset="UTF-8">

<!DOCTYPE html>
<html lang="en">
<head>
  <title><%= full_title(yield(:title)) %></title>
  <%= tag('meta', name: 'robots', content: 'noindex') if !Rails.env.production? %>
  <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
  <meta name='viewport' content='width=device-width, initial-scale=1.0'/>
  <meta name='description' content="<%= yield(:meta_description) %>"/>
  <meta name='keywords' content="<%= yield(:meta_keywords) %>"/>
  <meta charset="UTF-8">
  <%= render 'layouts/favicons' %>

  <%= stylesheet_link_tag    'application', :media => 'all' %>

  <%= javascript_include_tag 'application' %>
  <!--[if lt IE 9]>
    <script src='/js/respond.js'></script>
  <![endif]-->
  <!--[if IE]>
    <script>
      $(function() {
        $('.home-res').matchHeight();
      });
    </script>
  <![endif]-->
  <%= csrf_meta_tags %>
  <%= render 'layouts/google_analytics' if Rails.env.production? %>
  <%= render 'layouts/matomo_analytics' if Rails.env.production? %>
  <%= render 'layouts/libchat' %>
  <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,700" rel="stylesheet" type="text/css">

  <%= render 'layouts/sinon' %>
  <!-- <link rel="manifest" href="/manifest.json" /> -->
  <meta name="apple-mobile-web-app-capable" content="yes">
</head>
<body>
  <div id='wrapper'>
    <div id='page-positioner' class='fluid-container'>
      <div class='layout-stretch'>
        <%= render 'layouts/header' %>
      </div>
      <%= render 'layouts/alerts' %>
      <div id='mainContent' class='row'>
        <%= yield %>
      </div>
      <div class='layout-stretch'>
        <%= render 'layouts/footer' %>
      </div>
    </div> <!-- /container/page-positioner -->
  </div> <!-- /wrapper -->

  <script>
    $(function() {
      <% if use_proxy? %>
        augment_remote_links();
      <% end %>
    });
  </script>
</body>
</html>

I've been tinkering with this for quite awhile now and I can't find what is causing this issue. Previously the tests were driven by Poltergeist and I was following along with several guides explaining the process of switching to headless chrome. Again, visit root_path works fine when not running with javascript i.e js: true is not set. That feels like a significant clue to what is going on here.

Sorry for opening this. I'm realizing now that it's actually an issue with webdrivers downloading the chromedriver and it just so happens to trigger from a visit root_path call.