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. :(
Related
I am writing test for controllers in Rails:
require 'rails_helper'
RSpec.describe GoodsController, type: :controller do
DatabaseCleaner.clean
user = User.create(password: "12345678")
user.save!
describe "GET index" do
it "renders the index template" do
sign_in user
get "index"
expect(response).to render_template("index")
end
end
DatabaseCleaner.clean
end
the GoodsController has this index action I want to test:
def index
if params[:category_id] == nil
#goods = Good.all
else
#goods = Good.where(category_id: params[:category_id])
end
end
and when I run the test, I receive this error:
1) GoodsController GET index renders the index template
Failure/Error: expect(response).to render_template("index")
expecting <"index"> but was a redirect to <http://test.host/users/sign_in>
# ./spec/controllers/goods_controller_spec.rb:12:in `block (3 levels) in <top (required)>'
I've added that sign_in user line, according to other answers in SO, but it didn't help. It still redirects to the logging page. How do I resolve this?
The user you create is not used by rspec when running the Examples (aka tests). It's just a variable inside a block that doesn't do anything useful.
When dealing with fixtures/factories you should either create them in before, let or inside the test itself (it block).
describe "GET index" do
let(:user) { User.create(password: "12345678") }
it "renders the index template" do
# OR, create it here before sign_in
sign_in user
get "index"
expect(response).to render_template("index")
end
end
Not sure if you are using factory_bot, but you should look at it. Usually DatabaseCleaner is set up inside rails_helper, check this SO post for more details.
If you are going to have multiple tests that need the user to be signed in you could also wrap the sign_in in a before hook.
describe "GET index" do
let(:user) { User.create(password: "12345678") }
before do
sign_in user
end
it "renders the index template" do
get "index"
expect(response).to render_template("index")
end
end
I'm following this tutorial for a rails API but it is a little outdated and some things don't seem to work with newer versions of rails. I'm having a hard time with the user controller specs:
user_controller_spec.rb
require 'rails_helper'
RSpec.describe Api::V1::UsersController, type: :controller do
describe "GET #show" do
before(:each) do
#user = FactoryGirl.create :user
get :show, params: {id: #user.id}
end
it "returns the information about a reporter on a hash" do
user_response = JSON.parse(response.body, symbolize_name: true)
expect(user_response[:email]).to eql #user.email
end
it { expect(response).to have_http_status(200) }
end
end
user_controller.rb
class Api::V1::UsersController < ApplicationController
def show
render json: User.find(params[:id])
end
end
user.rb factory
FactoryGirl.define do
factory :user do
email { FFaker::Internet.email }
password "12345678"
password_confirmation "12345678"
end
end
But, this isn't working, the email doesn't seem to match. Any ideas what could be wrong?
Failures:
1) Api::V1::UsersController GET #show returns the information about a reporter on a hash
Failure/Error: expect(user_response[:email]).to eql #user.email
expected: "mitzie_nikolaus#rice.com"
got: nil
(compared using eql?)
# ./spec/controllers/api/v1/users_controller_spec.rb:12:in `block (3 levels) in <top (required)>'
The code is correct, but you've made a typo in using the symbolize_names option for JSON.parse.
I assume, that because you do not copy-paste examples, but type it by your own, which is great, because it's better for learning.
To fix the test just correct this line (change symbolize_name to symbolize_names):
user_response = JSON.parse(response.body, symbolize_names: true)
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
I have following route:
GET /confirm/:token(.:format) Confirmations#confirm
Controller:
class ConfirmationsController < ApplicationController
# GET /confirm/<token>
def confirm
#user = User.find_by_email_token(params[:token])
if #user
#user.confirmed = true
#user.email_token = nil
#user.save!
sign_in #user
redirect_to root_url, flash: { success: "Welcome <#{#user.email}>, your address has been verified." }
elsif
redirect_to root_url, flash: { error: "Error: could not find matching user record." }
end
end
end
And this simple confirmations_controller_spec.rb:
require 'spec_helper'
describe ConfirmationsController do
let(:user) { FactoryGirl.create(:user, email_token: "some_token") }
describe "Get confirm" do
it "confirms user with valid email_token" do
get :confirm, token: "some_token"
assigns(:user).should eq(user)
user.reload.email_token.should be_nil
end
it "does not confirm user with invalid email_token"
end
end
but it fails:
1) ConfirmationsController Get confirm confirms user with valid email_token
Failure/Error: get :confirm, token: "some_token"
ActionController::RoutingError:
No route matches {:token=>"some_token", :controller=>"confirmations", :action=>"confirm"}
# ./spec/controllers/confirmations_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
Anyone see what (could be multiple things) I screwed up?
BTW- I'm using a get request here (as opposed to put) because it's being initiated from a text based email so we can't, to my understanding, use a put request...
In your rake routes, Confirmations should not have a capital letter.
Can you define the route like so in config/routes.rb:
match '/confirm/:token' => 'confirmations#confirm'
I have controller:
def login
if admin_logged_in?
flash[:notice]="You are already logged in"
redirect_to( "/admin/")
else
render(:layout => "admin")
end
end
my RSpec test case
require 'spec_helper'
describe "AdminController" do
before (:each) do
#admin = FactoryGirl.create(:admin)
end
describe "GET 'login'" do
it "should be successful" do
get 'login'
response.should be_success
end
end
end
when I am going execute my test case getting error:
1) AdminController GET 'login' should be successful
Failure/Error: get 'login'
RuntimeError:
#controller is nil: make sure you set it in your test's setup method.
# ./spec/controllers/admin_controller_spec.rb:10:in `block (3 levels) in <top (required)>'
Finished in 0.18799 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/controllers/admin_controller_spec.rb:9
In your test, I would replace the describe block of "AdminController" to AdminController. Your test should now look like this...
require 'spec_helper'
describe AdminController do
before (:each) do
#admin = FactoryGirl.create(:admin)
end
describe "GET 'login'" do
it "should be successful" do
get 'login'
response.should be_success
end
end
end
Explanation: Because you wrote AdminController in parenthesis, rspec was not able to tell which controller you were testing.