Test an HTTPS (SSL) request in RSpec Rails

10,296

Solution 1

To instruct RSpec to make SSL requests in a controller spec use:

request.env['HTTPS'] = 'on'

In your example this looks like:

describe "GET 'index'" do
  it "renders the Start page" do
    request.env['HTTPS'] = 'on'
    get :index
    response.should render_template 'index'
  end
end

Solution 2

For rspec 3 syntax, https://stackoverflow.com/a/28361428/1107433

get :index, protocol: 'https://'

There may be a slight different version that above code doesn't work. So use code below:

get :index, protocol: :https

Solution 3

For reference I'm currently running Rails 5.2.4 and RSpec 4.

The best solution as given in this answer is to change from using the _path helper to using the _url helper.

Then you can pass the protocol param to generate the HTTPS URL:

get login_url(protocol: :https)

Note that you cannot pass protocol to the _path helper:

# NOTE: THIS IS WRONG. Doesn't work with the `_path` helper:
# get login_path(protocol: :https)

An alternative option given in carp's comment above is to pass the "HTTPS" header with the fake request.

So if you're using strings/symbols or the _path helper for the request path:

get login_path, headers: {"HTTPS" => "on"}

get '/login', headers: {"HTTPS" => "on"}

Here is carp's full comment:

For actual request specs (as opposed to the now deprecated controller specs), it works like this: get "/path", headers: { "HTTPS" => "on" }. The HTTPS header will be picked up by Rack::Request, telling everything down the line to consider the request to be an SSL/TLS one.

Share:
10,296
naudster
Author by

naudster

Updated on June 16, 2022

Comments

  • naudster
    naudster almost 2 years

    I'd like to take advantage of the force_ssl feature in rails 3.1rc4.

    class ApplicationController < ActionController::Base
      force_ssl
    end
    

    Problem is this breaks most/all of my existing RSpec controller specs. For example, this fails:

    describe "GET 'index'" do
      it "renders the Start page" do
        get :index
        response.should render_template 'index'
      end
    end
    

    Instead of rendering the page the response is a 301 redirect to https://test.host/.

    How can I change my specs to simulate an HTTPS GET/POST?

    And do I have to change each test manually or is there an easier way? (I realise I could invoke force_ssl only in production, but that's not ideal. Really, I should be testing that force_ssl does indeed redirect to https:// when expected.)