expecting <"index"> but render with <[]> - ruby-on-rails

I'm having problems to pass a test in rails with rspec. This is what console tells me when I ran the tests.
The fail is ControlsController GET index logged in renders the index template
Failure/Error: expect(response). to render_template(:index)
expecting <"index"> but rendering with <[]>
And this is my code
require "rails_helper"
RSpec.describe ControlsController, :type => :controller do
render_views
describe "GET index" do
let(:user) {
FactoryGirl.create(:user)
}
let(:control) {
FactoryGirl.create(:control, user: user)
}
context "logged in" do
before :each do
sign_in :user, user
end
it "loads all controls into #controls" do
get :index, { user_id: user.id}
expect(assigns(:controls)).to eq([control])
end
it "assigns a new control to #control" do
get :index, { user_id: user.id}
expect(assigns(:control)).to be_a_new(Control)
end
it "renders the index template" do
get :index, { user_id: user.id}
expect(response). to render_template(:index)
end
it "a user can't see the controls from other user" do
new_user = User.create(name: "Juan",
email: "juan#gmail.com",
password: "123456789",
password_confirmation: "123456789")
get :index, { user_id: new_user.id}
expect(response).to redirect_to root_path
end
class ControlsController < ApplicationController
before_action :authenticate_user!
def index
#user= current_user
#control= Control.new
# #control_last = Control.lastcontrol (current_user.id)
# #controls_average = Control.controls_average (current_user.id)
# #controls_average_day = Control.controls_day_average (current_user.id)
#controls = Control.all
if params[:user_id] != current_user.id
redirect_to root_path
end
end

The answer is to make a private method and redirect_to user_controls_path current_user.name
This is the new code of the controller
controlsController.rb
class ControlsController < ApplicationController
before_action :authenticate_user!
before_action :redirect_if_not_current_user, only: :index
private
def control_params
params.require(:control).permit(:level, :period, :day)
end
def redirect_if_not_current_user
if params[:user_id] != current_user.name
redirect_to user_controls_path current_user.name
end
end

Related

NoMethodError:undefined method `employee' for nil:NilClass for RSPEC test Rails

I want to run the rspec of Tickets controllers, I Have used scaffold and I have made some changes according to my project.
but I am getting some errors. I also have a login (using Devise).
How do I go ahead?
This is the controller-
class TicketsController < ApplicationController
before_action :set_ticket, only: %i[ show edit update destroy assign]
before_action :set_assign_ticket, only: %i[assignid]
# shows the landing page of employee
def landing
#tickets = current_user.employee.tickets.order('tstatus_id, id desc')
end
# Service engineer index showing the tickets which are assinged to him
def slanding
#tickets = Ticket.where(service_id: current_user.employee.service_id).order('tstatus_id, id desc')
end
# Showing tickets list based on the user type
def index
#tickets = if current_user.employee.designation.role == "ADMIN"
Ticket.all.order('tstatus_id ,id desc ')
else
Ticket.where(employee: current_user.employee)
end
end
def show
#tickets = Ticket.all
end
def new
#ticket = Ticket.new
end
#creating a new ticket
def create
#ticket = Ticket.new(ticket_params)
#ticket.employee = current_user.employee
respond_to do |format|
if #ticket.save
format.html { redirect_to landing_path}
else
format.html { render :new, status: :unprocessable_entity }
end
end
end
# updating a ticket
def update
respond_to do |format|
if #ticket.update(ticket_params)
if current_user.employee.designation.role == "ADMIN"
format.html { redirect_to tickets_url }
else
format.html { redirect_to slanding_path }
end
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end
private
def set_ticket
#ticket = Ticket.where(id: params[:id]).first
end
def ticket_params
params.require(:ticket).permit(:kind, :description, :dev_id, :service_id,:tstatus_id)
end
def set_assign_ticket
#ticket = Ticket.find(params[:id])
end
end
This is the model -
class Ticket < ApplicationRecord
belongs_to :service, optional: true
belongs_to :employee
belongs_to :tstatus
before_validation(on: :create) do
self.service_id = 4 # this will assign the service engineer to NONE
self.tstatus_id = 1 # this will assign the status to logged
end
validates :description, presence: true
end
My test cases are:
require 'rails_helper'
describe TicketsController, type: :controller do
# describe 'GET show' do
it 'gets show based on ID' do
#ticket = Ticket.new(id: 1,kind: "Example Ticket", description: "Ticket#example.com", service_id: 1, employee_id: 1,tstatus_id:1)
get :show, params: { id: #ticket.id }
expect(response.status).to eq(200)
end
# describe 'GET edit' do
it 'has 200 status code' do
get :new
expect(response.status).to eq(200)
end
describe 'POST create' do
it 'has 200 status code' do
mock = double('Employee')
expect(mock).to receive(:employee_id)
post :create, params: {
ticket: {
id: 1,kind: "Example Ticket", description: "Ticket#example.com", service_id: 1, employee_id: 1,tstatus_id:1
}
}
expect(response.status).to eq 302
end
end
end
I am a newbie to rails,
Can someone tell me how to write test cases for the controller above?

NameError: undefined local variable or method `user'

I'm writing an app using RoR, using gem Devise for user authentication. I'm trying to test user behaviour when he signed in the app and have next error:
User::TransactionsController when logged in when its own record GET #show assigns the requested instance as #instance
Failure/Error: let(:transaction) { FactoryGirl.create(:transaction, user_id: user.id) }
NameError:
undefined local variable or method `user' for #<RSpec::ExampleGroups::UserTransactionsController::WhenLoggedIn::WhenItsOwnRecord::GETShow:0x00000004d77220>
My tests start with:
RSpec.describe User::TransactionsController, type: :controller do
render_views
before { sign_in FactoryGirl.create :user }
let(:transaction_category) { FactoryGirl.create(:transaction_category) }
let(:transaction) { FactoryGirl.create(:transaction, user_id: user.id) }
......
end
My factory:
FactoryGirl.define do
factory :transaction do
date '2016-01-08'
comment 'MyString'
amount 1
transaction_category
trait :invalid do
amount nil
end
end
end
My TransactionsController looks like:
class User::TransactionsController < ApplicationController
before_action :authenticate_user!
before_action :find_transaction, only: [:show, :edit, :destroy, :update]
def new
#transaction = current_user.transactions.build
end
def show
end
def create
#transaction = current_user.transactions.build(transaction_params)
if #transaction.save
redirect_to user_transaction_url(#transaction)
else
render :new
end
end
def index
#transactions = current_user.transactions
end
def edit
end
def destroy
#transaction.destroy
redirect_to user_transactions_url
end
def update
if #transaction.update(transaction_params)
redirect_to user_transaction_url
else
render :edit
end
end
private
def transaction_params
params.require(:transaction).permit(:amount, :date, :comment,
:transaction_category_id)
end
def find_transaction
#transaction = current_user.transactions.find(params[:id])
end
end
Thanks!
You need to define user
RSpec.describe User::TransactionsController, type: :controller do
render_views
user = FactoryGirl.create( :user )
before { sign_in( user ) }
let(:transaction_category) { FactoryGirl.create(:transaction_category) }
let(:transaction) { FactoryGirl.create(:transaction, user_id: user.id) }
......
end

Why does my rspec test fail?

I have problem with my "POST create" action. Test passed successfully, when attributes are valid, but when they are invalid, player is also saved. It's strange because, only :invalid_player, can be saved with invalid attributes. If I change for example, wins to -1 or "string", player with attributes :invalid_player is saved. But if I change attributes for :player, like wins = -1, validators prevent player, from being saved.
Console output with error message:
Failures:
1) PlayersController user is signed in POST create with invalid attributes does not save the new player
Failure/Error:
expect{
post :create, { tournament_id: #tournament, player: FactoryGirl.attributes_for(:invalid_player) }
}.to_not change(Player, :count)
expected #count not to have changed, but did change from 1 to 2
# ./spec/controllers/players_controller_spec.rb:111:in `block (5 levels) in <top (required)>'
This is my Player model:
class Player < ActiveRecord::Base
belongs_to :user
belongs_to :tournament
validates :wins, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :loses, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :draws, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
end
Factory file for players:
FactoryGirl.define do
factory :player do
wins 0
loses 0
draws 0
end
factory :invalid_player, parent: :player do
wins -1
loses 0
draws 0
end
end
Spec test:
context "user is signed in" do
before do
#tournament = create(:tournament)
#player = create(:player)
#user = create(:user)
#request.env["devise.mapping"] = Devise.mappings[:user]
sign_in(#user)
controller.stub(:current_user).and_return(#user)
end
describe "GET new" do
end
describe "GET index" do
it "renders the :index view" do
get :index, tournament_id: #tournament
expect(response).to render_template :index
end
end
describe "GET show" do
it "renders the :show view" do
get :show, { id: #player, tournament_id: #tournament }
expect(response).to render_template :show
end
end
describe "POST create" do
context "with valid attributes" do
it "creates a new player" do
expect{
post :create, { tournament_id: #tournament, player: FactoryGirl.attributes_for(:player) }
}.to change(Player,:count).by(1)
end
it "redirects to the tournament" do
post :create, { tournament_id: #tournament, player: FactoryGirl.attributes_for(:player) }
expect(response).to redirect_to #tournament
end
end
context "with invalid attributes" do
it "does not save the new player" do
expect{
post :create, { tournament_id: #tournament, player: FactoryGirl.attributes_for(:invalid_player) }
}.to_not change(Player, :count)
end
it 're-renders the new method' do
post :create, { tournament_id: #tournament, player: FactoryGirl.attributes_for(:invalid_player) }
response.should render_template :new
end
end
end
end
Controller:
class PlayersController < ApplicationController
before_action :set_tournament
before_action :set_admin, only: [:edit, :update, :destroy]
before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
def index
#players = #tournament.players.all
end
def show
#player = Player.find(params[:id])
end
def new
#player = #tournament.players.new
end
def create
if current_user.player.nil? == false
flash[:error] = "You're already in tournament."
redirect_to tournaments_url
else
#player = #tournament.players.new
#player.user_id = current_user.id
if #player.save
redirect_to #tournament
else
render 'new'
end
end
end
def edit
if current_user == #admin
#player = #tournament.players.find(params[:id])
else
redirect_to tournaments_url
end
end
def update
if current_user == #admin
#player = #tournament.players.find(params[:id])
if #player.update_attributes(game_params)
flash[:success] = "Player was updated successful"
redirect_to #tournament
end
else
redirect_to tournaments_url
end
end
def destroy
#player = Player.find(params[:id])
flash[:success] = "Player deleted"
redirect_to #tournament
end
private
def set_tournament
#tournament = Tournament.find(params[:tournament_id])
end
def set_admin
#tournament = Tournament.find(params[:tournament_id])
#admin = #tournament.user
end
end
You are not assigning any attributes to your model in your create method. You need to do the following (I assume it's rails 4):
#player = #tournament.players.new(player_params)
#...
private
def player_params
params.require(:player).permit(:wins, :loses, :draws)
end
Without any assignment you most likely falling back onto database default value of zero, which is valid.

Rspec test controller with chain methods

How can I test this code in my controller? My problem is with the wizard_incompleted? method
class ApplicantsController < ApplicationController
def index
#applicant = current_user.applicant
#application = #applicant.applications.last
if #application.wizard_incompleted?
# some redirect
end
end
end
describe "GET #index" do
let(:application) { double('application')}
it "redirect to wizard if it is incompleted" do
get :index
allow_any_instance_of(application).to receive(:wizard_incompleted?).and_return(true)
expect(response).to redirect_to(new_applicants_application_path)
end
end
You can controller test this
# app/controllers/applicants_controller.rb
class ApplicantsController < ApplicationController
def index
#applicant = current_user.applicant
#application = #applicant.applications.last
redirect_to "/" if #application.wizard_incompleted?
end
end
Like this
# spec/controllers/applicants_controller_spec.rb
require "spec_helper"
describe ApplicantsController, type: :controller do
it "#index" do
last_application = double(:last_application, wizard_incompleted?: true)
applications = double(:applications, last: last_application)
applicant = double(:applicant, applications: applications)
current_user = double(:current_user, applicant: applicant)
expect(controller).to receive(:current_user).and_return(current_user)
expect(current_user).to receive(:applicant).and_return(applicant)
expect(applicant).to receive(:applications).and_return(applications)
expect(applications).to receive(:last).and_return(last_application)
expect(last_application).to receive(:wizard_incompleted?).and_return(true)
get :index
expect(assigns(:applicant)).to eq applicant
expect(assigns(:application)).to eq last_application
expect(response).to redirect_to "/"
end
end

Rspec param is missing or the value is empty: user

Hello i'm testing the Update action the User Controller using Rspec.
I get this error
1) UsersController POST #update user updated
Failure/Error: patch :update, {id: user.id }, { user_id: user.id }, user: user_params
ActionController::ParameterMissing:
param is missing or the value is empty: user
# /Users/joseph/.rvm/gems/ruby-2.1.2/gems/actionpack-4.2.0/lib/action_controller/metal/strong_parameters.rb:249:in `require'
# ./app/controllers/users_controller.rb:60:in `user_params'
# ./app/controllers/users_controller.rb:39:in `update'
Weird thing is i used a binding.pry to test whats going on. There is a user and there are user_params. So i don't understand why i receive the above error.
Please see below for the user and user params.
From: /Users/joseph/Documents/Safsy/Website/Safsy/Safsy/spec/controllers/users_controller_spec.rb # line 76 :
71: end
72: end
73:
74: describe "POST #update" do
75: it "user updated" do
=> 76: binding.pry
77: patch :update, {id: user.id }, { user_id: user.id }, user: user_params
78: expect(response).to redirect_to(assigns(:user))
79: expect(assigns(:user)).to eq(user)
80: end
81: end
[1] pry(#<RSpec::ExampleGroups::UsersController::POSTUpdate>)> patch :update, {id: user.id }, { user_id: user.id }, user: user_params
ActionController::ParameterMissing: param is missing or the value is empty: user
from /Users/joseph/.rvm/gems/ruby-2.1.2/gems/actionpack-4.2.0/lib/action_controller/metal/strong_parameters.rb:249:in `require'
[2] pry(#<RSpec::ExampleGroups::UsersController::POSTUpdate>)> user
=> #<User:0x007fd91fe40458
id: 2,
username: "username2",
email: "user2#factory.com",
created_at: Thu, 08 Oct 2015 11:09:54 UTC +00:00,
updated_at: Thu, 08 Oct 2015 11:09:54 UTC +00:00,
password_digest: "$2a$04$YsvGZ05kdqMoa5fhJlkh1Oa9ISN6wuO7TBCT23vVDS.UO1k.vKTA2",
remember_digest: nil,
admin: false,
activation_digest: "$2a$04$GzFp9Otdlo7l1JBPOTeiQu7NUZELLQSIkLZUd7df1h2p4XpqNXLMm",
activated: true,
activated_at: nil,
reset_digest: nil,
>: nil,
reset_sent_at: nil,
avatar_file_name: nil,
avatar_content_type: nil,
avatar_file_size: nil,
avatar_updated_at: nil,
description: "Corporis odio magni repellendus.",
header_image_file_name: nil,
header_image_content_type: nil,
header_image_file_size: nil,
header_image_updated_at: nil>
[3] pry(#<RSpec::ExampleGroups::UsersController::POSTUpdate>)> user_params
=> {:username=>"username512",
:email=>"user463#factory.com",
:password=>"Password123",
:password_confirmation=>"Password123",
:admin=>false,
:description=>"Nihil eligendi ab debitis iure."}
[4] pry(#<RSpec::ExampleGroups::UsersController::POSTUpdate>)>
here is the User controller
def update
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(
:username,
:email,
:password,
:password_confirmation,
:avatar,
:header_image,
:description
)
end
Here is the complete test
require "rails_helper"
RSpec.describe UsersController, type: :controller do
let!(:admin) { create(:user, password: "Password123", admin: true) }
let!(:user) { create(:user, password: "Password456", admin: false) }
let!(:users) do
[admin, user] + 3.times.map { create(:user) }
end
let!(:user_params) { user_params = { username: "username#{rand(1000)}",
email: "user#{rand(1000)}#factory.com",
password: "Password123",
password_confirmation: "Password123",
admin: false,
description: "Nihil eligendi ab debitis iure.",
} }
let!(:category) { create(:category, name: "Shirt") }
let!(:category1) { create(:category, name: "Short") }
describe "GET #index" do
it "admin user renders template and shows users" do
get :index, {}, { user_id: admin.id }
expect(response).to render_template(:index)
expect(response).to have_http_status(:success)
expect(assigns(:users).map(&:id)).to eq users.map(&:id)
end
it "user renders template and shows users" do
get :index, {}, { user_id: user.id }
expect(response).to redirect_to(root_path)
end
it "redirects visitor" do
get :index
expect(response).to redirect_to(root_path)
end
end
describe "GET #show" do
it "user renders template and shows user" do
get :show, id: user.id
expect(response).to render_template(:show)
expect(response).to have_http_status(:success)
expect(assigns(:user)).to eq(user)
end
end
describe "GET #new" do
it "renders template" do
get :new
expect(response).to render_template(:new)
expect(response).to have_http_status(:success)
end
end
describe "POST #create" do
it "user created" do
post :create, user: user_params
expect(assigns(:user)).to be_persisted
end
end
describe "GET #edit" do
it "user edit" do
get :edit, {id: user.id }, { user_id: user.id }
expect(response).to render_template(:edit)
expect(response).to have_http_status(:success)
expect(assigns(:user)).to eq(user)
end
end
describe "POST #update" do
it "user updated" do
patch :update, {id: user.id }, { user_id: user.id }, user: user_params
expect(response).to redirect_to(assigns(:user))
expect(assigns(:user)).to eq(user)
end
end
describe "DELETE #destroy" do
it "user destroy" do
delete :destroy, {id: user.id }, { user_id: user.id }, user: user_params
expect(response).to redirect_to(users_path)
end
end
end
User controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :update, :edit]
before_action :logged_in_user, only: [:edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: [:destroy, :index]
def index
#users = User.paginate(page: params[:page])
end
def new
#user = User.new
end
def show
#items = #user.items.paginate(page: params[:page])
end
def show_user_items
#user = User.find(current_user)
#items = #user.items.paginate(page: params[:page])
end
def create
#user = User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
def edit
end
def update
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_path
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(
:username,
:email,
:password,
:password_confirmation,
:avatar,
:header_image,
:description
)
end
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.try(:admin?)
end
end
Here is my log_in method
def log_in(user)
session[:user_id] = user.id
end
def logged_in?
!current_user.nil?
end
def current_user
if (user_id = session[:user_id])
#current_user ||= User.find_by(id: user_id)
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user && user.authenticated?(:remember, cookies[:remember_token])
log_in user
#current_user = user
end
end
end
Change this:
patch :update, {id: user.id }, { user_id: user.id }, user: user_params
to this:
patch :update, id: user.id, user: user_params, { user_id: user.id }

Resources