how #user output in console? - ruby-on-rails

please help solve the problem. i use gem 'devise', gem 'rspec' and this tutorial:
Authentication with Devise in Rspec tests
.i need #user output in console.
emails_controller_spec.rb:
RSpec.describe EmailsController, type: :controller do
let(:valid_attributes) {
{
email: Faker::Internet.email,
description: Faker::Lorem.paragraph(7),
user_id: 1
}
}
describe "GET #index" do
login_user
it "assigns all emails as #emails" do
email = Email.create! valid_attributes
get :index
binding.pry
expect(assigns(:emails)).to eq([email])
#expect(assigns(#user)).to eq(#user)
end
end
end
spec/factories/users.rb:
FactoryGirl.define do
factory :user do
sequence(:email){ |i| "us#{i}#ad.ad" }
password 'qwertyui'
password_confirmation{ |u| u.password }
role :none
end
end
spec/support/controller_macros.rb:
module ControllerMacros
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryGirl.create(:user)
sign_in user
end
end
end
i user gem 'pry' for see on variables from console after run the test. but i see follow:
kalinin#kalinin ~/rails/mailer $ rspec spec/controllers
From: /home/kalinin/rails/mailer/spec/controllers/emails_controller_spec.rb # line 56 :
[1] pry(#<RSpec::ExampleGroups::EmailsController::GETIndex>)> #user
=> nil
[2] pry(#<RSpec::ExampleGroups::EmailsController::GETIndex>)> user
NameError: undefined local variable or method `user' for #<RSpec::ExampleGroups::EmailsController::GETIndex:0x00000007c4e670>
from /home/kalinin/.rvm/gems/ruby-2.0.0-p598/gems/rspec-expectations-3.3.1/lib/rspec/matchers.rb:966:in `method_missing'
[3] pry(#<RSpec::ExampleGroups::EmailsController::GETIndex>)> puts page.html
=> nil
i need displays user-object or displays html-code of page. please help

I hope you have included your ControllerMacros module somewhere. If not add that to top of your emails_controller_spec.rb file as include ControllerMacros
Add login_user in a before block -
describe "GET #index" do
before { login_user }
it "assigns all emails as #emails" do
email = Email.create! valid_attributes
get :index
binding.pry
expect(assigns(:emails)).to eq([email])
expect(assigns(#user)).to eq(#user)
end
end
Also change your ControllerMacros to:
module ControllerMacros
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
#user = FactoryGirl.create(:user)
sign_in #user
end
end
end

Related

How i run the test with rspec, using simple_token_authentication and devise

I run my test but the sign_in don't authenticate.
require 'rails_helper'
describe "get all contacts route", :type => :request do
let!(:contacts) {FactoryBot.create_list(:random_contacts, 20)}
before(:each) do
get '/api/v1/contacts'
user = FactoryBot.create(:user)
request.env["devise.mapping"] = Devise.mappings[:user]
request.headers['X-User-Email'] = "#{user.email}"
request.headers['X-User-Token'] = "#{user.authentication_token}"
sign_in user
end
it 'returns all contacts' do
expect(JSON.parse(response.body).size).to eq(20)
end
it 'returns status code 200' do
expect(response).to have_http_status(:success)
end
end
The return of the test is:
"{\"error\":\"You need to sign in or sign up before continuing.\"}"
https://github.com/andbri321/one_bit_contacts/tree/feature/test_contact
You might want to create some sign in/out helpers. Something along the lines of
module DeviseRequestSpecHelpers
include Warden::Test::Helpers
def sign_in(resource_or_scope, resource = nil)
resource ||= resource_or_scope
scope = Devise::Mapping.find_scope!(resource_or_scope)
login_as(resource, scope: scope)
end
def sign_out(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
logout(scope)
end
end
And then load them in your RSpec config like so:
RSpec.configure do |config|
config.include DeviseRequestSpecHelpers, type: :request
end
Then use these helpers before the tests are run.
Look here for more info.

rspec + Devise: current_user is nil in tests

I am using Devise for my user logins and stuff and rspec for testing. I have looked at the Devise testing guide for rspec and mixined ControllerMicros to controller specs.
And actually things are all working fine if I have tests organized like this:
describe 'GET #index' do
context 'user logged in but not admin' do
login_user
it 'should redirect to root_path for non_user' do
get :index
// I have asserted that the current_user here is not nil
expect(response).to redirect_to(root_path)
end
end
end
However, if I have 2 tests in the context and I got current_user is nil for the non-first test.
describe 'GET #index' do
context 'user logged in but not admin' do
login_user
it 'should redirect to root_path for non_user' do
get :index
// I have asserted that the current_user here is not nil
expect(response).to redirect_to(root_path)
end
it 'should do some other thing' do
get :index
// the current_user method returns nil here
expect(response).to redirect_to(root_path)
end
end
end
And the worst part is that it seems this problem is not deterministic: happens somewhat randomly--cause after several failed runs the suite just passed on my computer(but still fails on Travis my build)
Some additional information:
the ControllerMacro.rb
module ControllerMacros
def login_admin
before(:each) do
# #request.env["devise.mapping"] = Devise.mappings[:user]
user = User.find_by(email: 'default_admin#controller.spec')
user ||= FactoryGirl.create(:user, email: 'default_admin#controller.spec', uid: 'default_admin.controller.spec')
admin = Admin.find_by(user_id: user.id)
FactoryGirl.create(:admin, user: user) if not admin
sign_in user
end
end
def login_user(user = nil)
before(:each) do
# #request.env["devise.mapping"] = Devise.mappings[:user]
user ||= User.find_by(email: 'default_user#controller.spec')
user ||= FactoryGirl.create(:user, email: 'default_user#controller.spec', uid: 'default_user.controller.spec')
sign_in user
end
end
end
the rails_helper.rb
RSpec.configure do |config|
# for loading devise in test
config.include Devise::TestHelpers, :type => :controller
config.extend ControllerMacros, :type => :controller
end
Your login_user method is run when the test suite load, you should put it in a before :each block to run it once for each test.
describe "GET index" do
before do
login_user
end
it 'blabla' do
get :index
expect(response).to redirect_to(root_path)
end
end
PS : Don't know what you do in your login_user method, but Devise have some nice helpers you can include as follow
#rails_helper.rb
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
end
#then in you test
before do
sign_in user_instance
end
UPDATE from comment
If you have multiple type of user / devise login entry, maybe try to specify the devise mapping you're trying to sign in the user to , as follow :
sign_in :user, user_instance
sign_in :admin, admin_user_instance

Devise RSpec Error

I am trying to validate that the current_user's organization matches that of the organization they are trying to view.
Here's the part of the controller that's failing this test (#organization is being defined in an earlier method):
if current_user.organization != #organization
redirect_to root_path, notice: "Not authorized to edit this organization"
end
Here's the failing test:
require 'rails_helper'
RSpec.describe Admin::PagesController, :type => :controller do
describe 'GET #home' do
login_user
before do
#organization = FactoryGirl.create(:organization)
end
context "valid params" do
it "renders the home template and returns http 200" do
get :home, name: #organization.name
expect(response).to render_template("home")
expect(response.status).to eq(200)
end
end
end
Here's my factory:
factory :user do
email { Faker::Internet.email }
organization_id 1
password "foobarfoobar"
password_confirmation { |u| u.password }
end
...And here's where login_user is being defined:
module ControllerMacros
def login_user
#request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryGirl.create(:user)
sign_in user
end
end
Stacktrace:
1) Admin::PagesController GET #home valid params renders the home template and returns http 200
Failure/Error: it "renders the home template and returns http 200" do
expecting <"home"> but rendering with <[]>
# ./spec/controllers/admin/pages_controller_spec.rb:15:in `block (4 levels) in <top (required)>'
However:
[2] pry(#<RSpec::ExampleGroups::AdminPagesController::GETHome::ValidParams>)> subject.current_user.organization == #organization
=> true
Not sure what is going wrong here, seems like pretty standard stuff. Any ideas?
Turns out the issue was that I was sending in the wrong parameter - should have been sending #organization.subdomain, not #organization.name. :(

rspec fails where 'current_user' code written in controller

I have started rspec coding recently and i am new to rails framework, rspec fails where i am using 'current_user' in controller. Please check below for my controller and rspec code. Thanks in advance.
Controller code:
def task
#tasks = current_user.alerts.where(kind: "TASK")
end
rspec code:
describe "get #task" do
it "assigns a task" do
sign_in(#user)
get :task
expect(response).to have_http_status(200)
end
You can do it like this:
#request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryGirl.create(:user) # Don't forget to create a factory for user
user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the "confirmable" module
sign_in user
It is better to put it in support/devise.rb:
module ControllerMacros
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryGirl.create(:user)
user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the "confirmable" module
sign_in user
end
end
end
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.extend ControllerMacros, :type => :controller
end
you can say login_user instead of sign_in(#user)

Infamous AbstractController::ActionNotFound - Devise + Rails

So I have read how to solve this problem:
RSpec Test of Custom Devise Session Controller Fails with AbstractController::ActionNotFound
and
http://lostincode.net/blog/testing-devise-controllers
But under which file do I add these changes is my problem:
Under the rspec folder for my
registrations_controller
I tried this
before :each do
request.env['devise.mapping'] = Devise.mappings[:user]
end
require 'spec_helper'
describe RegistrationsController do
describe "GET 'edit'" do
it "should be successful" do
get 'edit'
response.should be_success
end
end
end
Which didn't work, any help with the specific files to change to make this work would be greatly appreciated.
EDIT
So I also tried -
https://github.com/plataformatec/devise/wiki/How-To:-Controllers-and-Views-tests-with-Rails-3-(and-rspec)
so I made a folder with spec/support and made a file called controllers_macros.rb
module ControllerMacros
def login_admin
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:admin]
sign_in Factory.create(:admin) # Using factory girl as an example
end
end
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
user = Factory.create(:user)
user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the confirmable module
sign_in user
end
end
end
And my registrations_controller is now this:
require 'spec_helper'
describe RegistrationsController do
describe "GET 'edit'" do
before :each do
request.env['devise.mapping'] = Devise.mappings[:user]
end
it "should be successful" do
get 'edit'
response.should be_success
end
end
end
I have other controllers in rspec do I need to change every single one? Or I'm confused on where to make the changes.
Just take the first version you tried, but move the before block inside the first describe block like this:
require 'spec_helper'
describe RegistrationsController do
before :each do
request.env['devise.mapping'] = Devise.mappings[:user]
end
describe "GET 'edit'" do
it "should be successful" do
get 'edit'
response.should be_success
end
end
end

Resources