3

The core part of my app makes calls to Etsy API. I'm trying to write tests using Rspec, Capybara and Selenium to test that API. After I make one successful call I'd like to stub those out.

My problem is that the Etsy auth process only works with SSL. So when I try to test with http I get error 400.

I used this tutorial to set up SSL but I keep getting this error:

  1) New connection authenticates with Etsy
     Failure/Error: res = http.get('/__identify__')

     OpenSSL::SSL::SSLError:
       SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: unknown protocol
     # ./spec/spec_helper.rb:68:in `responsive?'

Here's my spec_helper.rb:

require 'webmock/rspec'
require 'capybara/rspec'
include WebMock::API
require 'etsy'
WebMock.disable_net_connect!(allow_localhost: true)
#Capybara.current_driver = :selenium
Capybara.default_max_wait_time = 20

require 'webrick/https'
require 'rack/handler/webrick'

def run_ssl_server(app, port)

  opts = {
    :Port => port,
    :SSLEnable => true,
    :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
    :SSLPrivateKey => OpenSSL::PKey::RSA.new("./spec/support/server.key"),
    :SSLCertificate => OpenSSL::X509::Certificate.new(File.read "./spec/support/server.crt"),
    :SSLCertName => [["US", 'localhost.key']],
    :AccessLog => [],
    :Logger => WEBrick::Log::new(Rails.root.join("./log/capybara_test.log").to_s)
  }
  profile = Selenium::WebDriver::Firefox::Profile.new
  profile.assume_untrusted_certificate_issuer = false

   Capybara::Driver::Selenium.new(app, :browser=> :firefox, :profile => profile)
  Rack::Handler::WEBrick.run(app, opts)
end

Capybara.server do |app, port|
  run_ssl_server(app, port)
end

Capybara.server_port = 3001
Capybara.app_host = "https://localhost:%d" % Capybara.server_port

  Capybara.register_driver :selenium do |app|
    profile = Selenium::WebDriver::Firefox::Profile.new
    profile.assume_untrusted_certificate_issuer = false
    Capybara::Selenium::Driver.new(app, :profile => profile)
  end

module Capybara
  class Server
    def responsive?
      return false if @server_thread && @server_thread.join(0)

      http = Net::HTTP.new(host, @port)
      http.use_ssl = true
      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
      res = http.get('/__identify__')

      if res.is_a?(Net::HTTPSuccess) or res.is_a?(Net::HTTPRedirection)
        return res.body == @app.object_id.to_s
      end
    rescue SystemCallError
      return false
    end
  end
end

Thanks in advance! here's the files I generated

Maayan Naveh
  • 340
  • 3
  • 20

1 Answers1

5

You appear to have extra stuff in your run_ssl_server which doesn't make any sense

profile = Selenium::WebDriver::Firefox::Profile.new
profile.assume_untrusted_certificate_issuer = false

Capybara::Driver::Selenium.new(app, :browser=> :firefox, :profile => profile)

so I assume that was just a copy/paste error?

Moving on the error you're getting appears to be telling you that the SSLv2/SSLv3 protocols aren't known/supported by the connection. You can disable them in your WEBRick options by specifying the SSLOptions, SSLCiphers, and SSLVersion options as shown in How to harden rails+webrick+https with insecure ciphers removed on Ruby 2.2

An easier option may be to not register your own server, patch Capybara, fix the server port or set app_host, but instead switch over to using Capybara >= 3.1.0 and just configure Puma to run SSL

Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}?key=#{key_file_path}&cert=#{cert_file_path}" }

Then you can register whatever browser you're using with Selenium to allow self signed certs (if necessary)

Capybara.register_driver :insecure_selenium do |app|
  Capybara::Selenium::Driver.new(
    app,
    browser: :firefox,
    desired_capabilities: { accept_insecure_certs: true }
  )
end

Capybara.javascript_driver = :insecure_selenium # https://github.com/teamcapybara/capybara#drivers
Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
  • Thank you so much, @Thomas! That's definitely a huge improvement to what I was doing, but it still seems to me that the server is starting in regular http over https: Capybara starting Puma... * Version 3.11.4 , codename: Love Song * Min threads: 0, max threads: 4 * Listening on tcp://127.0.0.1:44047 Also the browser that opens up is using http. I'd really appreciate your help, thank you! – Maayan Naveh May 15 '18 at 17:40
  • @MaayanNaveh Sounds like you have something overriding your `Capybara.server` setting. Are you using system tests on Rails 5.1 by any chance? There was a bug in Rails 5.1 where it would override any server set by the user. It was fixed in https://github.com/rails/rails/commit/f1b4cd1ad47eab55ab7b18ae0cc167fabf72f38b#diff-cc89a43c353564685593335fa454fdbd . If you can't upgrade to Rails 5.2 you can monkeypatch ActionDispatch::SystemTestings::Server#set_server to do nothing - https://github.com/rails/rails/blob/5-1-stable/actionpack/lib/action_dispatch/system_testing/server.rb#L36 – Thomas Walpole May 15 '18 at 17:58
  • thanks for the suggestion! This is a feature test in rspec. – Maayan Naveh May 15 '18 at 18:02
  • @MaayanNaveh You're sure it's a "feature" test and not using the "system" tests now in RSpec? If it is a "feature" test then look for anywhere else `Capybara.server` is being set, and make sure your setting occurs after it in load order. Also, I am assuming you are running Capybara 3.1 and you added the location of your key and cert files to the server declaration I showed in my answer. – Thomas Walpole May 15 '18 at 18:12
  • It's definitely in the features folder, and I have inferred type by location on. I've searched through all of the project files and found no other Capybara server. I am using your suggested solution, yes. I tried downgrading from the master branch to the official release and it started the server with ssl: but when I upgraded to the master branch, same thing happens and it starts with http. When I "downgraded" it started with ssl which selenium then rejected because it's self signed, so I'm stuck on square 1 :( – Maayan Naveh May 15 '18 at 19:16
  • @MaayanNaveh On the official 3.1.0 it starts with ssl but then the browser rejects it? If that's the case then you just need to set up selenium not to reject self signed certs for whatever browser you're using by specifying the `:accept_insecure_certs` capability in your driver registration. I am curious why Capybara would not start in SSL when running the master branch though. – Thomas Walpole May 15 '18 at 19:36
  • thank you for all your help. Would you mind giving me an example of how to use :accept_insecure_certs ? I'm curious as well :) – Maayan Naveh May 15 '18 at 19:39
  • @MaayanNaveh Added to the answer -- it's just standard selenium driver configuration – Thomas Walpole May 15 '18 at 19:48
  • That did it! Thank you so much, @ThomasWalpole! I've been stuck on this for three days straight. Really appreciate it <3 – Maayan Naveh May 16 '18 at 05:16