How can I test ssl is enforced using minitest?

237 views Asked by At

My initial naive approach gave me a bunch of misleading errors, saying that routes don't exist that do exist.

camdennarzt@SECUR-T:~/Developer/Ruby/m2 [master L|✚ 1] $ rake test test/integration/application_test.rb
Run options: --seed 55863

# Running:

EEEEEEEEE

Fabulous run in 0.224684s, 44.5070 runs/s, 8.9014 assertions/s.

  1) Error:
ApplicationTest#test_enforces_ssl_for_SubscriptionsController#new_path:
ActionController::UrlGenerationError: No route matches {:action=>"new", :controller=>"SubscriptionsController"}
    test/integration/application_test.rb:16:in `block (3 levels) in <class:ApplicationTest>'


  2) Error:
ApplicationTest#test_enforces_ssl_for_WelcomeController#index_path:
ActionController::UrlGenerationError: No route matches {:action=>"index", :controller=>"WelcomeController"}
    test/integration/application_test.rb:16:in `block (3 levels) in <class:ApplicationTest>'


  3) Error:
ApplicationTest#test_enforces_ssl_for_SubscriptionsController#update_path:
ActionController::UrlGenerationError: No route matches {:action=>"update", :controller=>"SubscriptionsController"}
    test/integration/application_test.rb:16:in `block (3 levels) in <class:ApplicationTest>'


  4) Error:
ApplicationTest#test_enforces_ssl_for_SubscriptionsController#confirm_path:
ActionController::UrlGenerationError: No route matches {:action=>"confirm", :controller=>"SubscriptionsController"}
    test/integration/application_test.rb:16:in `block (3 levels) in <class:ApplicationTest>'


  5) Error:
ApplicationTest#test_enforces_ssl_for_SubscriptionsController#destroy_path:
ActionController::UrlGenerationError: No route matches {:action=>"destroy", :controller=>"SubscriptionsController"}
    test/integration/application_test.rb:16:in `block (3 levels) in <class:ApplicationTest>'


  6) Error:
ApplicationTest#test_enforces_ssl_for_SubscriptionsController#index_path:
ActionController::UrlGenerationError: No route matches {:action=>"index", :controller=>"SubscriptionsController"}
    test/integration/application_test.rb:16:in `block (3 levels) in <class:ApplicationTest>'


  7) Error:
ApplicationTest#test_enforces_ssl_for_SubscriptionsController#show_path:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"SubscriptionsController"}
    test/integration/application_test.rb:16:in `block (3 levels) in <class:ApplicationTest>'


  8) Error:
ApplicationTest#test_enforces_ssl_for_SubscriptionsController#edit_path:
ActionController::UrlGenerationError: No route matches {:action=>"edit", :controller=>"SubscriptionsController"}
    test/integration/application_test.rb:16:in `block (3 levels) in <class:ApplicationTest>'


  9) Error:
ApplicationTest#test_enforces_ssl_for_SubscriptionsController#create_path:
ActionController::UrlGenerationError: No route matches {:action=>"create", :controller=>"SubscriptionsController"}
    test/integration/application_test.rb:16:in `block (3 levels) in <class:ApplicationTest>'

9 runs, 0 assertions, 0 failures, 9 errors, 0 skips

camdennarzt@SECUR-T:~/Developer/Ruby/m2 [master L|✚ 1] $ rake routes
                     Prefix Verb   URI Pattern                            Controller#Action
              subscriptions GET    /subscriptions(.:format)               subscriptions#index
                            POST   /subscriptions(.:format)               subscriptions#create
           new_subscription GET    /subscriptions/new(.:format)           subscriptions#new
          edit_subscription GET    /subscriptions/:id/edit(.:format)      subscriptions#edit
               subscription GET    /subscriptions/:id(.:format)           subscriptions#show
                            PATCH  /subscriptions/:id(.:format)           subscriptions#update
                            PUT    /subscriptions/:id(.:format)           subscriptions#update
                            DELETE /subscriptions/:id(.:format)           subscriptions#destroy
       confirm_subscription GET    /subscriptions/confirm/:id(.:format)   subscriptions#confirm
           new_user_session GET    /users/sign_in(.:format)               devise/sessions#new
               user_session POST   /users/sign_in(.:format)               devise/sessions#create
       destroy_user_session DELETE /users/sign_out(.:format)              devise/sessions#destroy
              user_password POST   /users/password(.:format)              devise/passwords#create
          new_user_password GET    /users/password/new(.:format)          devise/passwords#new
         edit_user_password GET    /users/password/edit(.:format)         devise/passwords#edit
                            PATCH  /users/password(.:format)              devise/passwords#update
                            PUT    /users/password(.:format)              devise/passwords#update
   cancel_user_registration GET    /users/cancel(.:format)                devise/registrations#cancel
          user_registration POST   /users(.:format)                       devise/registrations#create
      new_user_registration GET    /users/sign_up(.:format)               devise/registrations#new
     edit_user_registration GET    /users/edit(.:format)                  devise/registrations#edit
                            PATCH  /users(.:format)                       devise/registrations#update
                            PUT    /users(.:format)                       devise/registrations#update
                            DELETE /users(.:format)                       devise/registrations#destroy
          user_confirmation POST   /users/confirmation(.:format)          devise/confirmations#create
      new_user_confirmation GET    /users/confirmation/new(.:format)      devise/confirmations#new
                            GET    /users/confirmation(.:format)          devise/confirmations#show
                user_unlock POST   /users/unlock(.:format)                devise/unlocks#create
            new_user_unlock GET    /users/unlock/new(.:format)            devise/unlocks#new
                            GET    /users/unlock(.:format)                devise/unlocks#show
                       root GET    /                                      welcome#index
             metahealthzone GET    /metahealthzone(.:format)              welcome#metahealthzone
                 contact_us GET    /contact_us(.:format)                  welcome#contact_us
              customer_care GET    /customer-care(.:format)               customer_care/welcome#customer_care
customer_care_metabolistics GET    /customer-care/metabolistics(.:format) customer_care/welcome#metabolistics
     customer_care_glossary GET    /customer-care/glossary(.:format)      customer_care/welcome#glossary
     customer_care_research GET    /customer-care/research(.:format)      customer_care/welcome#research
                       info GET    /info(.:format)                        info/welcome#info
              info_patients GET    /info/patients(.:format)               info/welcome#patients
         info_professionals GET    /info/professionals(.:format)          info/welcome#professionals
          info_distributors GET    /info/distributors(.:format)           info/welcome#distributors

My test implementation:

require 'test_helper'

class ApplicationTest < ActionDispatch::IntegrationTest
  Rails.application.eager_load!
  ApplicationController.descendants.each do |c|
    c.action_methods.each do |a|
      test "enforces ssl for #{c}\##{a} path" do
        get url_for(controller: c, action: a)
        assert_response :success
        assert https?, 'not https'
        assert_empty response.body.split('"').select {|e| e.include? 'http:'}
      end
    end
  end
end

How can I fix this so that a) it runs, and b) it tests that ssl is enforced. (I know about making a test request use ssl w/ https! but I want to see an http call respond with https or redirect)

1

There are 1 answers

0
Foton On

I think, You can use this as test body:

# http request
get url_for(controller: c, action: a)
refute https?, 'is https!'
assert_response :redirect
assert_equal request.url.gsub("http://","https://"), response.headers['Location']

follow_redirect!
assert https?, 'not https'