Rails Clearance, Unit Test Controller - ruby-on-rails

I'm having trouble getting the Clearance authentication to work with Rails controller unit testing. I've followed the instructions at https://github.com/thoughtbot/clearance "Controller Test Helpers". How do you unit test controllers that require authentication?
I get the following error:
GoalsControllerTest#test_should_get_index:
NoMethodError: undefined method `sign_in_as' for #<GoalsControllerTest:0x007f8c41c6b9c8>
test/controllers/goals_controller_test.rb:7:in `block in <class:GoalsControllerTest>'
test/test_helper.rb
require 'clearance/test_unit'
test/controller/goals_controller_test.rb
require 'test_helper'
class GoalsControllerTest < ActionDispatch::IntegrationTest
setup do
user = User.new(fname: "Test", lname: "User", email: "testuser#test.com", password: "password")
sign_in_as(user)
#goal = goals(:one)
end

i've same problem with you, but now fixed by this answer https://github.com/thoughtbot/clearance/issues/695
Enable the Middleware in Test:
# config/environments/test.rb
MyRailsApp::Application.configure do
# ...
config.middleware.use Clearance::BackDoor
# ...
end
In my test/test_helper.rb file, I wrote this following code.
class ActionDispatch::IntegrationTest
def manual_sign_in_as(user)
post session_url, params: {
session: {
email: user.email,
password: user.password
}
}
end
end
Rails 5 subclasses controller tests from ActionDispatch::IntegrationTest by default, so I only had to follow the instructions on the readme from here https://github.com/thoughtbot/clearance.
class PostsControllerTest < ActionDispatch::IntegrationTest
test "user visits index page while logged in"
user = User.create!(email: "example#example.com", password: "letmein")
get links_url(as: user)
# and
post links_url(as: user), params: { post: { title: "hi" } }
end
end

Are you using Rails 5? Rails 5 unified integration and controller tests behind ActionDispatch::IntegrationTest. When you require clearance/test_unit, Clearance is only adding it's helpers to ActionController::TestCase.
I think you could do:
class ActionDispatch::IntegrationTest
include Clearance::Testing::ControllerHelpers
end
in your test_helper.rb file in order to get access to the helpers in those tests. However, I'm not certain the helpers themselves will work in that context.
If you could give that a try, it'd be helpful. This should be fixed in Clearance as well. Since I don't use TestUnit/MiniTest myself I sometimes miss things like this.

Related

Rails 6 Devise test helpers without RSpec

Devise test helpers with Rails 6 without Rspec doesn't seem to work. Here is the code, any idea why it might be getting errors?
Controller:
class VehiclesController < ApplicationController
before_action :authenticate_user!, only: [:new]
def index
#vehicles = Vehicle.all
end
def new
#vehicle = Vehicle.new
end
end
test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require_relative "../config/environment"
require "rails/test_help"
class ActiveSupport::TestCase
# Run tests in parallel with specified workers
parallelize(workers: :number_of_processors)
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
include Devise::Test::IntegrationHelpers
end
user fixture:
valid_user:
first_name: "Toseef"
last_name: "zafar"
email: "exampleuser#gmail.com"
encrypted_password: <%= Devise::Encryptor.digest(User, '12345678') %>
controller test:
require "test_helper"
class VehiclesControllerTest < ActionDispatch::IntegrationTest
test "should be able to get to new form page" do
sign_in users(:valid_user)
get new_vehicles_url
assert_response :success
end
end
and this is the error I get:
Failure:
VehiclesControllerTest#test_should_be_able_to_get_to_new_form_page [/test/controllers/vehicles_controller_test.rb:12]:
Expected response to be a <2XX: success>, but was a <302: Found> redirect to <http://www.example.com/users/sign_in>
Response body: <html><body>You are being redirected.</body></html>
rails test test/controllers/vehicles_controller_test.rb:9
Also, I don't know why it would point to http://www.example.com
The devise user model has got confirmable hence when we do sign_in users(:valid_user) devise creates a user but because the user is not confirmed (i.e. no confirmation email link clicking is involved) when we go to a secured URL it takes us back to login because user hasn't confirmed through clicking on the link from the email.
The solution to this is to set confirmed_at value to Time.now before sign_in
e.g.
#user = users(:valid_user)
#user.confirmed_at = Time.now
sign_in #user
after doing that the tests passed! :)

How can I login a user for my Rails tests using Omniauth gem?

I've made an application with the omniauth-facebook gem. All of my rails test were passing, but after adding in code to check for an authenticated user for access to certain actions - some of my tests fail. How can I go about adding code to my tests to log in a "test" user so that I can simulate an authenticated user? Most of the google results showed examples for Rspec or Devise examples, but I've been using the default testing suite for Rails 5, so it's been difficult for me to find some examples of how to properly do this. Please let me know if you'd like me to provide any specific samples of my current tests. Nothing relevant came to mind to include since I'm not sure where to start with this.
So after reading through documentation here, and trying various things here's what I came up with...
test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
OmniAuth.config.test_mode = true
OmniAuth.config.add_mock(:facebook, {:uid => '123456', info: { email: 'email_address_of_user_in_fixtures#gmail.com' }})
def sign_in_admin
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:facebook]
get auth_facebook_callback_path
end
end
test/controllers/restaurants_controller_test.rb
require 'test_helper'
class RestaurantsControllerTest < ActionDispatch::IntegrationTest
setup do
# I sign in an admin user, and proceed
sign_in_admin
#restaurant = restaurants(:mcdonalds)
end
# other test methods for actions ...
end
config/routes.rb
Rails.application.routes.draw do
#...
get 'auth/facebook/callback', to: 'sessions#create'
#...
end

How can I use the devise user_signed_in? method in an integration test?

When I have assert user_signed_in? in an integration test it says the method is undefined. Is there a way I can use this method in my testing? I am using rails 4 and the latest version of devise. Here is my test file:
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
test "valid signup information" do
get new_user_registration_path
assert_difference 'User.count', 1 do
post_via_redirect user_registration_path,
user: { first_name: "Example",
last_name: "User",
email: "user#example.org",
password: "password",
password_confirmation: "password" }
end
assert_template 'activities/index'
assert user_signed_in?
end
The user_signed_in? method is included in Devise::Controllers::Helpers module which isn't available in your integration tests so you can't use it.
You have the option of either mocking this method (which won't really meet your testing needs) or testing that a user is signed in by looking for page content that will only render when the user is signed in like Logout link for example or Signed in successfully message.
For your controller tests you can use devise test helpers include Devise::TestHelpers which exposes a sign_in and sign_out methods for you, more on that in the Gem's home page https://github.com/plataformatec/devise
you can't use user_signed_in? inside integration tests as mentioned here before me, but you can write a simple helper method to help you mimic this behavior
what i did is ,inside the test_helper.rb :
def is_logged_in?
request.env['warden'].authenticated?(:user)
end
it's a pretty hacky solution but it does the trick

Simple example of Rails Testing Devise Controllers

I want the simplest example to test the validity of attributes of devise's actions for new registrations (email, password, password confirmation), sign_in and forgot_password. The internet is full of RSpec ones but I want to go native with what Rails 4.2 gives me and there is absolutely nothing.
I am stuck to the default implementation:
require 'test_helper'
class RegistrationsControllerTest < ActionController::TestCase
def setup
#controller = RegistrationsController.new
#request = ActionController::TestRequest.new
#response = ActionController::TestResponse.new
#request.env["devise.mapping"] = Devise.mappings[:user]
#user = Registrations.new(username: "John", email: "myemail#email.com")
end
end
I know this isn't too much but I am making my first steps in TDD, so please don't shoot !
How do I check for the validity of a user's attributes, for example a nil email or a password of 100 characters ?
You can check with rails in-build minitest
I have assumed you have overriding devise's registration_controller.
In tdd for controller you can write test cases for action.
Check modified code :-
require 'test_helper'
class RegistrationsControllerTest < ActionController::TestCase
include Devise::TestHelpers # for including devise's actions
def setup # this set up default settings for controller
#controller = RegistrationsController.new
#request = ActionController::TestRequest.new
#response = ActionController::TestResponse.new
#request.env["devise.mapping"] = Devise.mappings[:user]
#user = Registrations.new(username: "John", email: "myemail#email.com")
end
setup do # this used for setting global variable used in test file
#user= users(:one) # users is the fixture file of test in which you can set default data for test environment.
end
test "should create user" do # then you test cases for controller
sign_in users(:one)
post :create, users:{email:'test#test.com, password:'XXXX'...}# you can pass arguments for create method. Please check it once, i am not sure about names
assert_response :success
end
end
Rails minitest provides some assertion.

make a helper for my methods for integration testing in rails 3

I'm preparing some integration tests on my rails 3.2.16 application, I figured that, in my user scenarios, I have several calls that I repeat over many tests, so I would like to DRY them up, by placing them in a separate common module,
for example I have created /test/integration/my_test_helpers.rb:
require 'test_helper'
module MyTestHelper
def login_user(email, password, stay = 0)
login_data = {
email: email,
password: password,
remember_me: stay
}
post "/users/sign_in", user: login_data
assert_redirected_to :user_root
end
end
and tried to use it in my integration test:
require 'test_helper'
require "./my_test_helpers.rb"
class CreateCommentTest < ActionDispatch::IntegrationTest
setup do
#user = users(:user1)
end
test "create comment" do
login_user #user.email, "password", 1
end
end
I get exception:
`require': cannot load such file -- ./my_test_helpers.rb (LoadError)
How can I load the module? is it right to make MyTestHelpers a module?
You should put your helper in support folder(test/support/my_test_helpers.rb, or something) and load module in test_helper.rb:
ENV["RAILS_ENV"] ||= "test"
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require_relative "./support/my_test_helpers"
require "minitest/rails"
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
fixtures :all
# Add more helper methods to be used by all tests here...
end
Do not remember include your module:
require 'test_helper'
class CreateCommentTest < ActionDispatch::IntegrationTest
include MyTestHelper
setup do
#user = users(:user1)
end
test "create comment" do
login_user #user.email, "password", 1
end
end

Resources