I am going through Aaron Sumner's Everyday Rails Testing with RSpec (3) book, and can't get passed the following step:
I am trying to spec out a users#show action with:
users_controller_spec:
...
describe 'GET #show' do
it "assigns the requested contact to #user" do
user = create(:user)
get :show, id: user.id
expect(assigns(:user)).to eq user
end
it "renders the :show template" do
user = create(:user)
get :show, id: user.id
expect(response).to render_template :show
end
end
...
users_controller:
class UsersController < ApplicationController
before_action :authenticate
before_action :set_user, only: [:show]
### Read:
def show
...
end
private
def set_user
#user = User.find(params[:id])
end
end
application_controller helpers:
def authenticate
redirect_to home_path, alert: 'Please log in first' if current_user.nil?
end
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
Errors:
Failures:
1) UsersController GET #show assigns the requested user to #user
Failure/Error: expect(assigns(:user)).to eq user
expected: #<User id: 1, ...">
got: nil
(compared using ==)
# ./spec/controllers/users_controller_spec.rb:10:in `block (3 levels) in <top (required)>'
2) UsersController GET #show renders the :show template
Failure/Error: expect(response).to render_template :show
expecting <"show"> but rendering with <[]>
# ./spec/controllers/users_controller_spec.rb:17:in `block (3 levels) in <top (required)>'
Your issue comes from before_action :authenticate either you need to set yourself as authenticated in the specs or you need to skip authentication for the show action.
You would normally test like:
context 'when logged in' do
before(:each) do
set_as_logged_in
end
# your specs
end
where the set_as_logged_in method would differ based on the way you are authenticating. Then you could also have a 'when not logged in' context to verify the action behaves as expected when you are not logged in.
Related
I am trying to write spec code for my controller it gets failed. And i am not sure where it gets failed.
Controller Code
def index
#users = User.all
end
def update
authorize! :update, #user
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to user_index_path }
else
format.html { render :index }
end
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.permit(:active)
end
Spec Code for the above controller
RSpec.describe UserController, type: :controller do
describe 'GET #index' do
let(:user) {User.create!(name: "hari")}
context 'with user details'do
it 'loads correct user details' do
get :index
expect(response).to permit(:user)
end
end
context 'without user details' do
it 'doesnot loads correct user details' do
get :index
expect(response).not_to permit(:user)
end
end
end
describe 'Patch #update' do
context 'when valid params' do
let(:attr) do
{active: 'true'}
end
before(:each) do
#user = subject.current_user
put :update, params: { user: attr }
#user.reload
end
it 'redirects to user_index_path ' do
expect(response).redirect_to(user_index_path)
end
it 'sets active state' do
expect(#user.active?('true')).to be true
end
end
context 'when invalid param' do
let(:attr) do
{active: 'nil'}
end
before(:each) do
#user = subject.current_user
put :update, params: { user: attr }
#user.reload
end
it 'render index' do
expect(respone.status).to eq(200)
end
it 'doesnot change active state' do
expect(#user.active?(nil)).to be true
end
end
end
end
I am just a beginner and tried the spec code for my controller by checking https://relishapp.com/rspec/rspec-rails/docs/gettingstarted. Can you help me where my spec goes wrong or could anyone give me a few test examples for these methods or could redirect me to an rspec guide? the index method is getting failed
and my
terminal log is
1) UserController GET #index with user details loads correct user details
Failure/Error: expect(response).to permit(:user)
NoMethodError:
undefined method `permit' for #<RSpec::ExampleGroups::UserController::GETIndex::WithUserDetails:0x00005614152406b0>
Did you mean? print
# ./spec/controllers/user_controller_spec.rb:10:in `block (4 levels) in <top (required)>'
Im testing my Session Controller but Im getting this error, the log in feature works, I tested it on the browser but Im new to testing on Rspec and can't get this to work
Failure/Error: expect(response.session[:user_id]).to eq(#user_attr.id)
NoMethodError:
undefined method `session' for #<ActionController::TestResponse:0xd30df10>
# ./spec/controllers/sessions_controller_spec.rb:20:in `block (3 levels) in <top (required)>'
This is the code of my controller:
def new
#user = User.new
end
def create
#user = User.find_by(username: params[:user][:username])
if #user && #user.authenticate(params[:user][:password])
session[:user_id] = #user.id
redirect_to root_path
else
render :new
end
end
Rspec code:
require 'rails_helper'
RSpec.describe SessionsController, type: :controller do
describe "get Login page" do
it "returns http status" do
get :new
expect(response).to have_http_status(:success)
end
end
describe "session" do
before(:each) do
#user = FactoryGirl.create(:user)
#user_attr = FactoryGirl.attributes_for(:user)
end
it "gives session" do
request.session[:user_id] = nil
post :create, user: #user_attr
expect(response.session[:user_id]).to eq(#user_attr.id)
end
end
end
session is a variable that is available without the request/response context as shown in your example. If you want to manipulate it or check the values it contains, you can simply do something like this:
it "gives session" do
session[:user_id] = nil
post :create, user: #user_attr
expect(session[:user_id]).to eq(#user_attr.id)
end
I have a test I'm trying to pass but I can't get it to pass, I am new to this.
Here's a link to my git repository https://github.com/FrankWiebe/nameofapp
The failure message comes up like so:
1) UsersController GET #show No user is logged in redirects to login
Failure/Error: expect(response).to redirect_to(root_path)
Expected response to be a <redirect>, but was <200>
# ./spec/controllers/users_controller_spec.rb:24:in `block (4 levels) in <top (required)>'
This is the code:
require 'rails_helper'
describe UsersController, :type => :controller do
before do
#user = User.create(email: "doe#example.com", password: "1234567890")
end
describe "GET #show" do
context "User is logged in" do
before do
sign_in #user
end
it "loads correct user details" do
get :show, id: #user.id
expect(response).to have_http_status(200)
expect(assigns(:user)).to eq #user
end
end
context "No user is logged in" do
it "redirects to login" do
get :show, id: #user.id
expect(response).to redirect_to(root_path)
end
end
end
end
Perhaps #user is carried on as being logged in from one test to the next, so the 2nd show succeeds. Try to sign off the user whithin the first test.
As this is not the case, check your config/routes.rb.
Resources requiring login should be wrapped within a do...end
authenticate(:user) do
resources :user
...other stuff
end
I have this integration test that controls that a logged in user can't edit another user's data.
The code is mostly from Hartl's RoR tutorial.
Those 2 tests fail but when I test myself, the application is behaving as expected (I can't open the edit page of another user)
When I run rake, I get (lines 31 & 38 are assert flash.empty?):
FAIL["test_should_redirect_edit_when_logged_in_as_wrong_user", UsersControllerTest, 2015-07-24 12:15:07 +0800]
test_should_redirect_edit_when_logged_in_as_wrong_user#UsersControllerTest (1437711307.70s)
Failed assertion, no message given.
test/controllers/users_controller_test.rb:31:in `block in <class:UsersControllerTest>'
FAIL["test_should_redirect_update_when_logged_in_as_wrong_user", UsersControllerTest, 2015-07-24 12:15:07 +0800]
test_should_redirect_update_when_logged_in_as_wrong_user#UsersControllerTest (1437711307.71s)
Failed assertion, no message given.
test/controllers/users_controller_test.rb:38:in `block in <class:UsersControllerTest>'
Then, if I comment out assert flash.empty?, I get this (lines 32 & 39 are assert_redirected_to root_url):
FAIL["test_should_redirect_update_when_logged_in_as_wrong_user", UsersControllerTest, 2015-07-24 12:15:08 +0800]
test_should_redirect_update_when_logged_in_as_wrong_user#UsersControllerTest (1437711308.02s)
Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/login>.
Expected "http://test.host/" to be === "http://test.host/login".
test/controllers/users_controller_test.rb:39:in `block in <class:UsersControllerTest>'
FAIL["test_should_redirect_edit_when_logged_in_as_wrong_user", UsersControllerTest, 2015-07-24 12:15:08 +0800]
test_should_redirect_edit_when_logged_in_as_wrong_user#UsersControllerTest (1437711308.03s)
Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/login>.
Expected "http://test.host/" to be === "http://test.host/login".
test/controllers/users_controller_test.rb:32:in `block in <class:UsersControllerTest>'
users_controller_test.rb
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:guillaume)
#other_user = users(:peter)
end
## other tests ##
test "should redirect edit when logged in as wrong user" do
log_in_as(#other_user)
get :edit, id: #user
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect update when logged in as wrong user" do
log_in_as(#other_user)
patch :update, id: #user, user: {name: #user.name, email: #user.email}
assert flash.empty?
assert_redirected_to root_url
end
the lines that fail are the assert and assert_redirect lines
test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/reporters'
Minitest::Reporters.use!
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Returns true if a test user is logged in
def is_logged_in?
!session[:user_id].nil?
end
# Logs in a test user
def log_in_as(user, options = {})
password = options[:password] || 'password'
if integration_test?
post login_path, session: {email: user.email,
password: password}
else
session[:user] = user.id
end
end
private
# Return true inside an integration test
def integration_test?
defined?(post_via_redirect)
end
end
users_controller.rb
class UsersController < ApplicationController
before_action :logged_in_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
## new and create methods here ##
def edit
#user = User.find(params[:id])
end
def update
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name,
:email,
:club_id,
:access_key,
:password,
:password_confirmation)
end
## Before filters ##
# Confirms a logged-in user
def logged_in_user
unless logged_in?
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms a correct user
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
end
users.yml
guillaume:
name: Guillaume
email: guillaume#example.com
password_digest: <%= User.digest('password') %>
peter:
name: Peter
email: peter#example.com
password_digest: <%= User.digest('password') %>
I went though the code several times but I can't find what's missing.
This is also the first app I'm trying to develop on my own, so for this part, I'm working from Hartl's rails tutorial material.
Hi everyone I'm testing my app controllers and I have a problem. I have tests for update action which fails:
describe "PUT #update" do
before :each do
#car_service = create(:car_service)
end
it "locates the requested #message" do
put :update, id: #car_service, car_addition: attributes_for(:car_service)
assigns(:car_addition).should eq(#car_service)
end
context "valid attributes" do
it "changes #car_service's attributes" do
put :update, id: #car_service, car_addition: attributes_for(:car_service, name: "Test")
#car_service.reload
#car_service.name.should eq("Test")
end
it "redirects to the updated message" do
put :update, id: #car_service, car_addition: attributes_for(:car_service)
should redirect_to admin_car_additions_url
end
end
context "invalid attributes" do
it "does not change #car_addition's attributes" do
put :update, id: #car_service, car_addition: attributes_for(:car_service, name: nil)
#car_service.reload
#car_service.name.should_not be_nil
end
it "re-renders the edit method" do
put :update, id: #car_service, car_addition: attributes_for(:car_addition)
should render_template :edit
end
end
end
when i run this tests only one test not pass("re-renders the edit method") and throw out following error:
Failure/Error: should render_template('edit')
expecting <"edit"> but rendering with <[]>
# ./spec/controllers/admin/car_additions_controller_spec.rb:100:in `block (4 levels) in <top (required)>
My controller looks like this:
module Admin
class CarAdditionsController < ApplicationController
include Admin::BaseController
load_and_authorize_resource
add_breadcrumb I18n.t('car_additions.car_addition.home'), :admin_root_path
add_breadcrumb I18n.t('car_additions.car_additions'), :admin_car_additions_path
def index
end
def new
add_breadcrumb t('car_additions.car_addition.new')
end
def edit
add_breadcrumb t('car_additions.car_addition.edit')
end
def create
if #car_addition.save
flash[:notice] = t("car_additions.created")
redirect_to action: :index
else
add_breadcrumb t('car_additions.car_addition.new')
render :new
end
end
def update
if #car_addition.update(car_addition_params)
flash[:notice] = t("car_additions.updated")
redirect_to action: :index
else
render :edit
end
end
def destroy
#car_additon.destroy
flash[:error] = t("car_additions.destroy")
redirect_to action: :index
end
private
def car_addition_params
params.require(:car_addition).permit(:name, :type, :image,
:image_cache, :remove_image)
end
end
end
I'm using devise and CanCan for authorization. Please help.
I'm pass attributes_for(:car_addition) because this is not valid attributes. When I changed this to:
attributes_for(:car_addition, name: nil) it's still not working...
You should use render_views method in order to have your views rendered in specs:
describe "PUT #update" do
render_views
# ...
end