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)
Related
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.
My rspec tests are failing when I try to use .reload to test the Update method.
The error
Admin::CompaniesController PUT update valid attributes changes #company's attributes
Failure/Error: #company.reload
TypeError:
no implicit conversion of nil into Hash
# ./spec/controllers/admin/admin_companies_controller_spec.rb:81:in `block (4 levels) in <top (required)>'
The spec
# spec/controllers/admin_companies_controller_spec.rb
describe 'PUT update' do
before :each do
#company = create(:company, name: "Rockstars", phone: "3035551212")
end
context "valid attributes" do
it "changes #company's attributes" do
put :update, id: #company, company: attributes_for(:company, name: "Fishstars")
#company.reload #line 81
expect( #company.name ).to eq("Fishstars")
end
end
end
I have also tried (1) using let!(), (same error)
describe 'PUT update' do
let!(:company) { create(:company, name: "Rockstars", phone: "303555121d") }
context "valid attributes" do
it "changes company's attributes" do
put :update, id: company, company: attributes_for(:company, name: "Fishstars")
company.reload #line 81
expect( company.name ).to eq("Fishstars")
end
end
end
I have also tried (2) (same error)
before :each do
#company = create(:company, name: "Rockstars", phone: "3035551212")
end
it "changes #company's attributes" do
#attr = { name: "Fishstars" }
put :update, id: #company.id, :company => #attr
#company.reload
expect( #company.name ).to eq("Fishstars")
end
My first thought was that the variable #company was nil, but if I comment out line 81 (indicated) the test fails as expected.
Update
inserting 'byebug' just before line 81 allows me to see what #company looks like:
(byebug) #company
#<Company id: 1, name: "Rockstars", hq_address: "MyString", hq_city: "MyString", hq_state: "MyString", country: "MyString", description: "Description 1", phone: "3035551212", email: "Example2email#gmail.com", owner_id: 2, contact_name: "MyString", created_at: "2014-07-11 19:02:24", updated_at: "2014-07-11 19:02:24", active: true, logo_file_name: nil, logo_content_type: nil, logo_file_size: nil, logo_updated_at: nil, slug: "rockstars", refund_policy: "Refund policy">
(byebug) #company.reload
TypeError Exception: no implicit conversion of nil into Hash
nil
I wasn't able to figure out why .reload wasn't working, but I replaced it with a find_by_id call and my tests are working properly now:
# new code - effectively tests the update method
#company = Company.find_by_id(#company)
# original code - causes errors
#company.reload #line 81
I'm testing 'get' method and getting error:
expected:
[{\"user_id\":11,\"user_first_name\":\"bob\",\"user_last_name\":\"marley\",\"user_picture\":\"/images/missing.png\",\"id\":2,\"text\":\"my
third review\",\"date\":\"2013-12-27T09:08:06.364Z\"}]
got:
[{\"user_id\":11,\"user_first_name\":\"bob\",\"user_last_name\":\"marley\",\"user_picture\":\"/images/missing.png\",\"id\":2,\"text\":\"my
third review\",\"date\":\"2013-12-27T09:08:06.000Z\"}]
what the hell? Why last numbers are different while all other fields are equal?
it "should return reviews for user" do
review = Review.create(reviewer_id: #user.id, user_id: #user2.id, text: 'my third review')
get 'get_reviews_for_user', user_id: #user2.id
expect(response).to be_success
json = JSON.parse(response.body)
expect(json['reviews'].to_json).to eq([{user_id: #user.id,
user_first_name: #user.first_name,
user_last_name: #user.last_name,
user_picture: #user.picture.url(:thumb),
id: review.id,
text: review.text,
date: review.created_at
}].to_json)
end
In controller:
def get_reviews_for_user
user = User.where(id: params[:user_id]).first
return render json: {success: false} if user.nil?
reviews = []
Review.where(user_id: user.id).each do |review|
reviewer = review.reviewer
reviews << {user_id: reviewer.id,
user_first_name: reviewer.first_name,
user_last_name: reviewer.last_name,
user_picture: reviewer.picture.url(:thumb),
id: review.id,
text: review.text,
date: review.created_at}
end
render json: { success: true, reviews: reviews }
end
The times are different because the milliseconds are truncated when the time is translated into JSON.
You can use Timecop to freeze the time to a give value like this : Timecop.freeze(Time.now).
You can also use a stub like this (in you test) :
allow(Review).to receive(:where).with(user_id: #user.id).and_return([review])
allow(review).to receive(:created_at).and_return(Time.now)
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
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.