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)
Related
I'm biginer.
I studied Rspec.
I made an implementation that allowed me to do good on my posts.
But on the browser I do the expected move, but the test does not pass.
The destroy action goes through the test, but the create action does not pass the test.
My error is
Failure/Error: expect { post :create, format: :js, params: { post_id: post1.id, id: like.id } }.to change(Like, :count).by(1)
expected #count to have changed by 1, but was changed by 0
My code is
require 'rails_helper'
RSpec.describe LikesController, type: :controller do
let!(:user) { create(:user) }
let!(:post1) { create(:post, user: user) }
let!(:like) { create(:like, user_id: user.id, post_id: post1.id) }
describe "#create" do
before do
sign_in user
end
it "response Ajex" do
post :create, format: :js, params: { post_id: post1.id, id: like.id }
expect(response.content_type).to eq 'text/javascript'
end
it "success like function" do
expect { post :create, format: :js, params: { post_id: post1.id, id: like.id } }.to change(Like, :count).by(1)
end
end
describe "#destroy" do
before do
sign_in user
end
it "response Ajex" do
delete :destroy, format: :js, params: { post_id: post1.id, user_id: user.id, id: like.id }
expect(response.content_type).to eq 'text/javascript'
end
it "delete like function" do
expect { delete :destroy, format: :js, params: { post_id: post1.id, user_id: user.id, id: like.id } }.to change(Like, :count).by(-1)
end
end
end
likes_controller.rb
class LikesController < ApplicationController
def create
#like =
current_user.likes.find_or_create_by(post_id:params[:post_id])
#likes = Like.where(post_id: params[:post_id])
#post = Post.find(params[:post_id])
end
def destroy
like = current_user.likes.find_by(post_id: params[:post_id])
like.destroy
#likes = Like.where(post_id: params[:post_id])
#post = Post.find(params[:post_id])
end
end
I cannot solove this problem.
Please teach me a hint.
You've got an error in your code somewhere, most likely, which is why the Like count fails to increment. First, I'd try and figure out why it isn't incrementing. Since you asked for a hint, here's one way you can split out the "success like function" block:
context "valid" do
before do
post :create, format: :js, params: { post_id: post1.id, id: like.id }
end
it "success" do
# You can inject a binding.pry here if needed
expect(response.status).to eq(200)
end
it "response" do
# You can inject a `binding.pry` here if needed
# You can also inspect the `response.body` with puts if needed
expect(JSON.parse(response.body)).to include(
# You would modify this to match the shape of your response
post: a_hash_including(
like: like.id
)
)
end
end
You'll want to install pry-rails and pry-byebug gems (for inspecting).
The reason behind splitting them up is it makes it easier to determine the issue (you can have a valid response code but not the expected result, for example). This comes with some caveats (it will make for slower tests) but in this example it will make it easier to determine why your post is failing.
The snippet above should help you debug the error; once you fix it you can revert back to your previous method of checking.
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 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)
Tested in browser and works fine. Test error says "expected result to have changed from 0 to 1, but did not change". Is this a factory issue or rspec issue? Why is it not changing?
Error:
Failures:
1) ShortLinksController Short links controller Clicking a short link increments the click counter by 1
Failure/Error: expect{ get :url_dispatch, { id: short_link.short_link } }.to change{short_link.click_counter}.from(0).to(1)
expected result to have changed from 0 to 1, but did not change
# ./spec/controllers/short_links_controller_spec.rb:34:in `block (4 levels) in <top (required)>'
Rspec:
it "increments the click counter by 1" do
short_link = create(:short_link)
expect{ get :url_dispatch, { id: short_link.short_link } }.to change{short_link.click_counter}.from(0).to(1)
end
Controller:
def url_dispatch
id = params[:id]
record = ShortLink.where(["short_link = ?", id]).first
if record.update(click_counter: record.click_counter + 1)
redirect_to record.redirect_to
else
render '/not_found'
end
end
Factory:
FactoryGirl.define do
factory :short_link do
redirect_to "http://google.com"
title "This is the google page"
short_link "xGh7u"
click_counter 0
owner Owner.create!(first_name: "Bob", last_name: "Diller", email: "bdiller#example.com")
end
end
per Fab's request, here is how I'm currently working around the issue.
context 'save invocations' do
before(:each) do
#org = create(:organization)
user = create(:user, organization: #org, is_admin: true)
sign_in user
end
it 'valid scenario' do
user2 = create(:user, organization: #org, is_admin: false)
put :update, id: user2, user: { is_admin: true }
user2.reload
expect(response).to have_http_status(204)
expect(user2.is_admin).to eq true
end
end
Here I'm calling user2.reload in order to get the updated attributes from the user2 factory.
I don't know why the expect{} syntax doesn't work for factories but you could refactor your code like this:
it "increments the click counter by 1" do
short_link = create(:short_link)
count = short_link.click_counter
get :url_dispatch, { id: short_link.short_link }
short_link.reload
expect(short_link.click_counter).to eq count + 1
end
Again I'm not saying this is best practice, I just couldn't find anything in the FactoryGirl documentation regarding RSpec 3 expect syntax in controllers that update attributes.
I'm new to RSpec so I'm looking for a little help on a simple test:
# controller method
def show
#group = Group.find(params[:id])
#group_members = #group.group_members.order("posts ASC")
end
# in my rspec
it "should show order correctly" do
#group = FactoryGirl.create(:group)
#user_1 = FactoryGirl.create(:user, user_name: "Gary")
#user_2 = FactoryGirl.create(:user, user_name: "Shawn")
#user_3 = FactoryGirl.create(:user, user_name: "Gus")
#user_4 = FactoryGirl.create(:user, user_name: "Jack")
#group_member_1 = FactoryGirl.create(:group_member, group_id: #group.id, user_id: #user_1.id, posts: 30)
#group_member_2 = FactoryGirl.create(:group_member, group_id: #group.id, user_id: #user_2.id, posts: 20)
#group_member_3 = FactoryGirl.create(:group_member, group_id: #group.id, user_id: #user_3.id, posts: 10)
#group_member_4 = FactoryGirl.create(:group_member, group_id: #group.id, user_id: #user_4.id, posts: 15)
visit group_path(#group)
# how do i assert the order of the array?
end
Can someone please help me with a statement to check that the array sorted correctly?
my_array.should eq expected_array
That will make sure that each item is in the exact same spot. If you want to check that an array has the same elements as another array, but the order doesn't matter, do this:
my_array.should =~ expected_array
So in your particular case, you first would need to do a get to the show action, then check the variable. That's done like this:
get :show, :id => #group.id
expected_group_members = [#group_member_3, #group_member_4, #group_member_2, #group_member_1]
assigns(:group_members).should eq expected_group_members
For more information, check out RSpec's GitHub page.