RSpec test failed find user - ruby-on-rails

My Controller (User Controller)
def reset_password
#user = User.find_by_reset_code(params[:reset_code]) unless params[:reset_code].nil?
if request.post?
if #user && #user.update_attributes(:password => params[:user][:password], :password_confirmation => params[:user][:password_confirmation])
self.current_user = #user
#user.delete_reset_code
flash[:success] = t('helpers.password_reset_successful')
render :template => "sessions/new"
else
flash[:error] = t('helpers.password_reset_error')
redirect_to root_path
end
end
end
I would like test it and I do...
it "POST 'reset password with reset code page'" do
#user.reset_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
User.should_receive(:find_by_reset_code).with(#user.reset_code)
post :reset_password, :user => {"id" => #user.id}
end
But I've exception in Rspec -
Failure/Error: User.should_receive(:find_by_reset_code).with(#user.reset_code)
(<User(id: integer, name: string, email: string, encrypted_password: string, salt: string, created_at: datetime, updated_at: datetime, admin: boolean, reset_code: string) (class)>).find_by_reset_code("acd8a322d9554fbde375f5c39446276188a41678")
expected: 1 time
received: 0 times
What's wrong?

There is no reset_code param in your request.
Replace with:
post :reset_password, :reset_code => #user.reset_code
And you'd rather do:
User.should_receive(:find_by_reset_code).with(#user.reset_code).and_return #user

Related

Issue with apipie gem and rspec in rails 4

i'm writing the code to get my Rspec tests to pass on my api. I'm using the apipie gem to generate documentation and it seems that my tests are failing because thy are expecting a number and it's funny because this is exactly what I want to test.
The page fails when the :bpm parameter is not a number. is there any way of going around this ?
context "when is not created" do
before(:each) do
user = FactoryGirl.create :user
#invalid_lesson_attributes = { title: "California Dreamin",
bpm: "Hello"
}
request.headers['Authorization'] = user.auth_token
post :create, { user_id: user.id, lesson: #invalid_lesson_attributes }
end
it "renders an errors json" do
lesson_response = json_response
expect(lesson_response).to have_key(:errors)
end
it "renders the json errors on why the user could not be created" do
lesson_response = json_response
expect(lesson_response[:errors][:bpm]).to include "is not a number"
end
it { should respond_with 422 }
end
end
Update spec:
context "when is not updated" do
before(:each) do
patch :update, { user_id: #user.id, id: #lesson.id,
lesson: { bpm: "ten" }, format: :json }
end
it "renders an errors json" do
lesson_response = json_response
expect(lesson_response).to have_key(:errors)
end
it "renders the json errors on why the user could not be updated" do
lesson_response = json_response
expect(lesson_response[:errors][:bpm]).to include "is not a number"
end
it { should respond_with 422 }
end
in my users_controller:
api :POST, '/teachers/:user_id/lessons/', "Create lesson"
param :lesson, Hash, desc: 'Lesson information', :required => true do
param :title, String, desc: 'Title of the lesson', :required => true
param :bpm, :number, desc: 'tempo of the lesson (beats per second)', :required => true
end
error :code => 422, :desc => "Unprocessable Entity"
my error when I run my rspec tests :
Apipie::ParamInvalid: Invalid parameter 'bpm' value "Hello": Must be a number.
Adds format json to post request
post :create, { user_id: user.id, lesson: #invalid_lesson_attributes, format: :json }
That worked for me.

Rspec controller spec resulting in failure

My RSpec for ResidenceInformations Controller is resulting in failure when I run 'rake spec'. My Controller code is as follows
class ResidenceInformationsController < ApplicationController
def index
end
def show
render partial: 'subregion_select'
end
def new
#residence_info = ResidenceInformation.new
#saved_residence_info = ResidenceInformation.where('applicant_id=?', current_applicant.id)
end
def create
#residence_info = ResidenceInformation.new(residence_informations_params)
#residence_info.state = params[:order][:state]
#residence_info.applicant_id = current_applicant.id
##residence_info.residence_type_id = params[:residence_type][:residence_type_id]
#residence_info.save!
if cookies[:residence_next] == 'true' && cookies[:add_another] == 'false'
redirect_to new_employment_information_path
elsif cookies[:residence_next] == 'false' && cookies[:add_another] == 'true'
#cookies[:add_another] = 'false'
redirect_to request.referer
elsif cookies[:residence_next] == 'false' && cookies[:add_another] == 'false'
redirect_to request.referer
end
end
def edit
#residence_info = ResidenceInformation.find(params[:id])
end
def update
end
def destroy
end
def subregion_options
render partial: 'subregion_select'
end
private
def residence_informations_params
params.require(:residence_information).permit(:address1, :address2, :country, :state, :city, :zip, :reason_for_moving, :resident_since, :resident_upto, :was_notice_given, :monthly_rent, :residence_type_id, :applicant_id)
end
end
And This is my spec file for the above mentioned controller
require 'rails_helper'
RSpec.describe ResidenceInformationsController, :type => :controller do
describe 'GET #new' do
login_applicant
it 'should have a current_applicant' do
subject.current_applicant.should_not be_nil
end
it 'assigns a new ResidenceInformation to #residenceinfo' do
#residenceinfo = FactoryGirl.create(:residence_information, address1: 'dsada', country: 'india', state: 'wb', city: 'kolkata', zip: '700091', reason_for_moving: 'none', resident_since: '2015-01-05', was_notice_given: 'true', residence_type_id: 1, applicant_id: 13)
#puts"****************#{residenceinfo.inspect}***********************"
get :new
assigns(:residenceinfo).should be_a_new(ResidenceInformation)
end
it 'renders the :new template' do
get :new
response.should render_template :new
end
end
describe 'POST create' do
login_applicant
context 'with valid attributes' do
it 'should have a current_applicant' do
subject.current_applicant.should_not be_nil
end
it 'create a new ResidenceInformation' do
expect{
post :create, residenceinformation: FactoryGirl.create(:residence_information, address1: 'dsada', country: 'india', state: 'wb', city: 'kolkata', zip: '700091', reason_for_moving: 'none', resident_since: '2015-01-05', was_notice_given: 'true', residence_type_id: 1, applicant_id: 13)
}.to change(ResidenceInformation, :count).by(1)
end
end
end
end
I am getting the following error when running this spec file
Failure/Error: assigns(:residenceinfo).should be_a_new(ResidenceInformation)
expected nil to be a new ResidenceInformation(id: integer, address1: string, address2: string, country: string, state: string, city: string, zip: string, monthly_rent: integer, reason_for_moving: string, resident_since: date, resident_upto: date, was_notice_given: boolean, created_at: datetime, updated_at: datetime, residence_type_id: integer, applicant_id: integer)
# ./spec/controllers/residence_informations_controller_spec.rb:17:in `block (3 levels) in <top (required)>'
As I am completely new to RSpec , so I would appreciate any kind of help I get from you people. Thanks in advance
EDIT
Sorry , I had given the wrong spec file. now given the right one
Your instance variable is named #residence_info and you are checking :residenceinfo. Try it with the underscore:
assigns(:residence_info).should be_a_new(ResidenceInformation)

Rails scope policy not accepting additional criteria

So in my wiki model I have an attribute for private. If private is true then the wiki should not be viewable to users who are not assign to the wiki_ids via a HABTM relationship.
wiki.rb:
class Wiki
include Mongoid::Document
include Mongoid::Timestamps
has_and_belongs_to_many :users
field :title, type: String
field :body, type: String
field :private, type: Boolean, default: false
scope :visible_to, ->(user) {
user.present? || user.blank? ?
where(:private => false) : where(:private => false).or(:id => user.wiki_ids)
}
def public?
!self.private?
end
end
WikisController:
def index
##wikis = policy_scope(Wiki)
##wikis = Wiki.all
#wikis = Wiki.visible_to(current_user)
authorize #wikis
end
def show
#wiki = Wiki.find(params[:id])
end
def new
#wiki = Wiki.new
authorize #wiki
end
def create
#wiki = current_user.wikis.build(params.require(:wiki).permit(:title, :body, :private, :user))
authorize #wiki
if #wiki.save
flash[:notice] = "Wiki was saved."
redirect_to #wiki
# report success
else
flash[:error] = "There was an error saving your wiki. Please try again."
render :new
end
I'm pretty confident its the scope that needs to be modified in the model, because if i comment out the scope in the model and replace the index in the controler to Wiki.all. I see all the wikis.
As of right now as somebody who created the wiki plus flagged it private and I am logged in I do not see that wiki nor does anybody that I add as a user to the wiki.
I tried adding other conditions to the end such as user.present? ? where(:id => user.wiki_ids) and user.present? && where(:id => user.wiki_ids) but just get errors thrown back at me.
DB entry for User:
User_id: 547eb8867261691268000000, wiki_ids: [BSON::ObjectId('54807226726 1690be0260000'),
BSON::ObjectId('5480735c7261690bae000000'), BSON::ObjectId('548
136e57261690aef000000'), BSON::ObjectId('5489af337261690d95000000'),
BSON::Objec tId('5489b57e7261690d95010000'),
BSON::ObjectId('548f9f607261690bb5060000'), BSO
N::ObjectId('54908f127261690be8000000'),
BSON::ObjectId('54908f207261690be801000 0')], name: "Carey VonRueden",
email: "admin#email.com", encrypted_password: "$2a
$10$NrlQ2XH64UucOPcI1aje9.57eoSO74676264YrIjfGvncyGcpGWy",
reset_password_token : nil, reset_password_sent_at: nil,
remember_created_at: nil, sign_in_count: 7, current_sign_in_at:
2014-12-17 18:51:15 UTC, last_sign_in_at: 2014-12-16 02:38:5 8 UTC,
current_sign_in_ip: "10.0.2.2", last_sign_in_ip: "10.0.2.2",
confirmation
_token: nil, confirmed_at: 2014-12-03 07:15:18 UTC, confirmation_sent_at: nil, u nconfirmed_email: nil, role: "admin">
DB entry for Wiki:
Wiki _id: 54908f207261690be8010000, created_at: 2014-12-16 19:59:28 UTC, updated_at: 2014-12-16 19:59:28 UTC, user_ids:
[BSON::ObjectId('547eb886726169126 8000000')], title: "Private", body:
"Private", private: true>
your scope condition is wrong
user.present? || user.blank? -> this will be true always. if user is present or user is blank, it will always return only the public wikis
Change your scope to something like below.(assuming you want all public wiki's if user is not signed in. If user is signed in, you want public + the wikis created by user)
scope :visible_to, ->(user) {
user.nil? ? where(:private => false) : where(:private => false).or(:id => user.wiki_ids)
}
If you are still not getting what you are expecting, check if user.wiki_ids is returning the right values

Ruby error NoMethodError for nil:NilClass

I'm following the Treebook tutorial on teamtreehouse.com (making a facebook clone) using rails. I have created a userfriendships controller and am getting this error when trying to reference a friend's full name in my index.html page of the friendships view: undefined method `full_name' for nil:NilClass. The problem occurs on line 4 here, (this is /views/user_friendships/index.html)
<div class="page-header">
<h1>Friends</h1>
</div>
<hr />
<% if #user_friendships.empty? %>
<em>No <%= params[:list] %> friends yet!</em>
<% end %>
<% #user_friendships.each do |friendship| %>
<% friend = friendship.friend %>
<div id="<%= dom_id(friendship) %>" class="friend panel">
<div class="panel-heading">
<span class="pull-right label>"><%= "#{friendship.state}".upcase %></span>
<h3 class="panel-title"><%= friend.full_name %></h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-1">Put gravatar url here</div>
<div class="col-md-11">
<em>Friends since time_ago_in_words ago</em>
</div>
</div>
</div>
<div class="panel-footer clearfix">
<%= link_to "Update friendship", edit_user_friendship_path( friend.profile_name), class: 'btn btn-primary pull-right' %>
</div>
</div>
<% end %>
Here's the User Friendships Controller:
class UserFriendshipsController < ApplicationController
before_filter :authenticate_user!
def index
#user_friendships = current_user.user_friendships.all
end
def new
if params[:friend_id]
#friend = User.where(profile_name: params[:friend_id]).first
raise ActiveRecord::RecordNotFound if #friend.nil?
#user_friendship = current_user.user_friendships.new(friend: #friend)
else
flash[:error] = "Friend required"
end
rescue ActiveRecord::RecordNotFound
render file: 'public/404', status: :not_found
end
def create
if params[:user_friendship] && params[:user_friendship].has_key?(:friend_id)
#friend = User.where(profile_name: params[:user_friendship][:friend_id]).first
#user_friendship = UserFriendship.request(current_user, #friend)
respond_to do |format|
if #user_friendship.new_record?
format.html do
flash[:error] = "There was a problem creating that friend request."
redirect_to profile_path(#friend)
end
format.json { render json: #user_friendship.to_json, status: :precondition_failed }
else
format.html do
flash[:success] = "Friend request sent to #{#friend.full_name}."
redirect_to profile_path(#friend.profile_name)
end
format.json { render json: #user_friendship.to_json }
end
end
else
flash[:error] = "Friend required"
redirect_to root_path
end
end
def edit
#friend = User.where(profile_name: params[:id]).first
#user_friendship = current_user.user_friendships.find(params[:id])
end
def destroy
#user_friendship = current_user.user_friendships.find(params[:id])
if #user_friendship.destroy
flash[:success] = "Friendship destroyed."
end
redirect_to user_friendships_path
end
def accept
#user_friendship = current_user.user_friendships.find(params[:id])
if #user_friendship.accept!
flash[:success] = "You are now friend with #{#user_friendship.friend.full_name}"
else
flash[:error] = "That friendship could not be accepted."
end
redirect_to user_friendships_path
end
def block
#user_friendship = current_user.user_friendships.find(params[:id])
if #user_friendship.block!
flash[:success] = "You have blocked #{#user_friendship.friend.full_name}."
else
flash[:error] = "That friendship could not be blocked."
end
redirect_to user_friendships_path
end
private
def friendship_association
case params[:list]
when nil
current_user.user_friendships
when 'blocked'
current_user.blocked_user_friendships
when 'pending'
current_user.pending_user_friendships
when 'requested'
current_user.requested_user_friendships
when 'accepted'
current_user.accepted_user_friendships
end
end
private
def user_friendship_attributes
params.require(:user_friendship).permit(:user, :friend, :user_id, :friend_id, :state)
end
end
Lastly, I will include the user friendships model:
class UserFriendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, class_name: 'User', foreign_key: 'friend_id'
state_machine :state, initial: :pending do
after_transition on: :accept, do: :send_acceptance_email
state :requested
event :accept do
transition any => :accepted
end
end
def self.request(user1, user2)
transaction do
friendship1 = create(user: user1, friend: user2, state: 'pending')
friendship2 = create(user: user2, friend: user1, state: 'requested')
friendship1.send_request_email
friendship1
end
end
def send_request_email
UserNotifier.friend_requested(id).deliver
end
def send_acceptance_email
UserNotifier.friend_request_accepted(id).deliver
end
def mutual_friendship
self.class.where({user_id: friend_id, friend_id: user_id}).first
end
# Manually updating the state to avoid callbacks and infinite loops
def accept_mutual_friendship
mutual_friendship.update_attribute(:state, 'accepted')
end
end
I'm aware that I must have to change this somehow, but am at a loss as to how to do that. I would like this page to display all of the friends that a user has, either in an accepted or pending state. Can anyone see what I need to do?
Thanks!
EDIT: If I change the views/user_friendships/index.html to friend.full_name instead of #friend.full_name I still get the same error. I can verify that the users currently in the db all have a valid first and last name (so the full name method should work).
Another EDIT: Here is a rails console entry showing that I do have userfriendships in the database:
2.1.2 :003 > UserFriendship.all
UserFriendship Load (0.3ms) SELECT "user_friendships".* FROM "user_friendships"
=> #<ActiveRecord::Relation [#<UserFriendship id: 1, user_id: 6, friend_id: nil, created_at: "2014-10-04 14:20:42", updated_at: "2014-10-04 14:20:42", state: nil>, #<UserFriendship id: 2, user_id: 6, friend_id: nil, created_at: "2014-10-04 14:21:32", updated_at: "2014-10-04 14:21:32", state: nil>, #<UserFriendship id: 3, user_id: 6, friend_id: 3, created_at: "2014-10-04 14:21:50", updated_at: "2014-10-04 14:21:50", state: nil>, #<UserFriendship id: 4, user_id: 6, friend_id: 6, created_at: "2014-10-04 14:23:58", updated_at: "2014-10-04 14:23:58", state: nil>, #<UserFriendship id: 5, user_id: 6, friend_id: 6, created_at: "2014-10-04 14:25:05", updated_at: "2014-10-04 14:25:05", state: nil>, #<UserFriendship id: 6, user_id: 6, friend_id: 4, created_at: "2014-10-04 14:25:15", updated_at: "2014-10-04 14:25:15", state: nil>, #<UserFriendship id: 7, user_id: 6, friend_id: 6, created_at: "2014-10-04 20:42:40", updated_at: "2014-10-04 20:42:40", state: nil>, #<UserFriendship id: 8, user_id: 6, friend_id: 6, created_at: "2014-10-04 20:45:44", updated_at: "2014-10-04 20:45:44", state: nil>, #<UserFriendship id: 9, user_id: 6, friend_id: 6, created_at: "2014-10-04 21:38:17", updated_at: "2014-10-04 21:38:17", state: nil>, #<UserFriendship id: 10, user_id: 6, friend_id: 6, created_at: "2014-10-09 16:53:44", updated_at: "2014-10-09 16:53:44", state: "pending">, ...]>
2.1.2 :004 >
Another Edit: Here is the user model models/user.rb:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :first_name, presence: true
validates :last_name, presence: true
validates :profile_name, presence: true,
uniqueness: true,
format: {
with: /\A.+\z/,
message: "must be formatted correctly"
}
has_many :statuses
has_many :user_friendships
has_many :friends, -> { where user_friendships: { state: 'accepted'} }, through: :user_friendships
has_many :pending_user_friendships, -> { where state: 'pending' },
class_name: 'UserFriendship',
foreign_key: :user_id
has_many :pending_friends, through: :pending_user_friendships, source: :friend
def full_name
first_name + " " + last_name
end
def gravatar_url
stripped_email = email.strip
downcased_email = stripped_email.downcase
hash = Digest::MD5.hexdigest(downcased_email)
"http://gravatar.com/avatar/#{hash}"
end
end
instead of #friend.full_name use friend.full_name
You have define it here <% friend = friendship.friend %>
So I am pretty sure what happened was that some of my database tables were dropped during a rake db:migrate that I ran. I did it because I was looking at a similar rails app that was building a social network site and switching my database back and forth between the two. Not sure how or why migrate deleted something ( i believe it deleted first and last name which is why full_name would be an nil error). I am going to revert to a previous commit where everything was working and try to rebuild from there.
Thanks for the posts!
tl;dr: dont run db:migrate without knowing what you're doing

Ruby/Rails/Rspec - ActiveRecord::AssociationTypeMismatch:

OK, here's my rspec code ...
before(:each) do
#attr = { :greeting => "Lorem ipsum", :recipient => #recipient }
end
it "should redirect to the home page" do
puts "spec: #attr = #{#attr}"
puts "spec: recipient = #{#attr[:recipient]}"
post :create, :card => #attr
response.should redirect_to(root_path)
end
Now the output from this is:
spec: #attr = {:greeting=>"Lorem ipsum", :recipient=>#<User id: 2, first_name: "Example", last_name: "User", email: "recipient#example.com", created_at: "2011-12-22 04:01:02", updated_at: "2011-12-22 04:01:02", encrypted_password: "2d1323ad5eb21fb5ae5e87dfa78a63b521c56833189cc049ee2...", salt: "2679fcc29a30e939541cb98cb65d1d508035fea0eff1136037a...", admin: false>}
spec: recipient = #<User:0xac5d80c>
So we can see that recipient is a User.
On the controller side, we see have ...
def create
puts "create: Params = #{params}"
#card = current_user.sent_cards.build(params[:card])
if #card.save
flash[:success] = "Card created!"
redirect_to root_path
else
render 'pages/home'
end
end
With a display of ...
create: Params = {"card"=>{"greeting"=>"Lorem ipsum", "recipient"=>"2"}, "controller"=>"cards", "action"=>"create"}
and I see an error of ...
1) CardsController POST 'create' success should create a card
Failure/Error: post :create, :card => #attr
ActiveRecord::AssociationTypeMismatch:
User(#90303150) expected, got String(#76171330)
# ./app/controllers/cards_controller.rb:7:in `create'
# ./spec/controllers/cards_controller_spec.rb:47:in `block (5 levels) in <top (required)>'
# ./spec/controllers/cards_controller_spec.rb:44:in `block (4 levels) in <top (required)>'
So ... how did the User object get changed into its id as a string? Any ideas?
You cannot pass an entire object as a parameter. Rails replaces the object with its id if it has one or else passes a string representation of the object i.e. #<User:0xac5d80c> for your case if it doesn't find the id.
So for your case, you should rename the :recipient parameter to :recipient_id. Then
#card = current_user.sent_cards.build(params[:card])
will create your card with the associated recipient as we have passed in the recipient_id.

Resources