Tests for updating avatar in RSpec - ruby-on-rails

I want to test this update action:
def update
#player = Player.find(params[:id])
begin
#player.update_attributes(player_params_avatar)
flash[:success] = "Avatar updated"
redirect_to player_path(#player)
rescue ActionController::ParameterMissing => e
flash[:danger] = "First choose avatar file"
redirect_to :back
end
end
def player_params_avatar
params.require(:player).permit(:avatar)
end
I'm thinking about something like:
describe "PUT #update" do
let!(:player1) { FactoryGirl.create :player }
context "when data is valid" do
it "update avatar" do
avatar = File.new(Rails.root + 'spec/factories/images/1.png')
put :update, player: { id: player1.id, avatar: avatar }
expect(flash[:success]).to be_present
end
end
But in RSpec console I get the error:
Failure/Error: put :update, player: { id: player1.id, avatar: avatar }
ActionController::UrlGenerationError:
No route matches {:action=>"update", :controller=>"players", :player=>{:id=>"1", :avatar=>"#<File:0xaed5b84>"}}
Why this code rises this error? There is specific player id so should be also correct url eg.
http://localhost:3000/players/1/edit
EDIT: I'm using paperclip gem for avatars.
My routes file:
Rails.application.routes.draw do
get 'pages/about'
get 'matches/new'
root 'pages#home'
resources :players
resources :matches
get '*path' => redirect('/')
end

I resolved the problem myself.
The tricky line was:
put :update, player: { id: player1.id, avatar: avatar }
I changed it to:
put :update, id: player1.id, player: { avatar: file }
And test passes.

Related

RubySpec to test a redirect in Ruby controller

I'm trying to code a spec for a method who redirect to a specific path when the user access to provider/plans and provider/prospects
I was trying with many path combinations in the before group, i was trying with this.
before { get :provider_plans_index_path }
before { get :provider_index_plans_path}
before { get :provider_plans_path}
before { get :provider_index_path}
before { get :provider_plans_path}
before { get :provider_planes_path}
base_controller.rb
class Provider::BaseController < ActionController::Base
layout 'provider'
before_action :allowed_pages
def allowed_pages
redirect_to financial_dashboard_path if !requested_action?(params[:controller])
end
def requested_action?(data)
regexp = %r{
^(provider/plans)|
(provider/prospects)$
}x
data.match?(regexp)
end
end
base_controller_spec.rb
require 'rails_helper'
describe Provider::BaseController, type: :controller do
let(:provider) { create(:provider) }
let(:financial) { create(:financial, provider: provider) }
let(:user) { provider.user }
before { login_user user }
describe 'GET plans' do
context 'with not allowed url' do
before { get :provider_planes_path}
it { should redirect_to financial_dashboard_path}
end
end
end
routes.rb
namespace :provider do
get '', to: 'dashboard#index'
get 'dashboard', to: 'dashboard#index'
resources :plans, only: [:index, :create, :update], path: 'planes'
resources :prospects, only: [:index, :show, :create, :update], path: 'prospectos' do
get 'diagnostico', to: 'prospects#show', on: :member, as: :general
patch 'diagnostico', to: 'prospects#update', on: :member
get 'configuracion', to: 'prospects#configuration', on: :member, as: :configuration
end
end
I'm getting this error with all the combinations
ActionController::UrlGenerationError:
No route matches
For me the solution was call the action in spec via another controller
context 'with not allowed url' do
before do
#controller = Provider::PlansController.new
get :index
end
it { should redirect_to financial_dashboard_path }
end

(LikesController#create) expected #count to have changed by 1, but was changed by 0 ,Please teach me a hint

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.

ActionController::UrlGenerationError: No route matches (Rspec)

I am getting the following error while testing my CommentsController with RSpec:
ActionController::UrlGenerationError:
No route matches {:action=>"create", :comment=>{:comment=>"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, :controller=>"comments"}
spec/models/comment_spec.rb
RSpec.describe CommentsController, type: :controller do
let!(:user) { create(:user) }
let!(:post1) { create(:post, user: user) }
let!(:comment) { create(:comment, user_id: user.id, post_id: post1.id) }
let!(:comment_attributes) { attributes_for(:comment) }
describe "#create" do
before do
sign_in user
end
it 'save post' do
expect do
post :create, params: { comment: comment_attributes }, session: {}
end.to change(Comment, :count).by(1)
end
it 'if post saves, redirect_to posts page' do
post :create, params: { post: comment_attributes }, session: {}
expect(response).to redirect_to(posts_path)
end
end
end
You have to update your routes.rb file every time you create a new resource (that you want to access via link), otherwise Rails don't know which controller to use with a given URL. Adding a resources :comments line in routes.rb should do it for you.

ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"demographic_detail", :id=>nil}

I'm new to programming and sorry if this is a stupid question. I'm writing a test for controllers in Ruby on Rails. The test is expecting a parameter but I'm not sure how to do that. When I run the test with rspec I get the error you see in the title.
This is PART of the controller's code:
class DemographicDetailController < ApplicationController
#before_filter :authorize
include ::Demographic
def show
#cinema_id = params[:cinema_id]
#cinema = Cinema.find(#cinema_id)
#cinema_name = #cinema.name
#cinmea_address = #cinema.address.full_street_address
#cinema_authority_id = #cinema.address.post_code.local_authority_id
#c_working_age = Population.where(:local_authority_id => #cinema_authority_id , :year => Population.maximum("year")).first
#c_working_age = #c_working_age.working_age_16_to_64
#c_total_population = totalpopulation(#cinema_authority_id)
#c_average_income = latestaverageincome(#cinema_authority_id)
#all_cinemas = Cinema.all
(...)
end
and this is the test I wrote for show method:
describe "Demographic" do
context "when testing the DemographicDetail controller" do
#let(:params) { { disabled: false } }
let(:cinema_id) { create(:cinema) }
it "should show demoraphic details successfully" do
get :show, params: { id: #cinema_id }
assert_response :success
end
end
This is the route:
controller :demographic_detail do
get '/demographic_detail/show/:cinema_id' => :show
end
Try this
modify the route as
get '/demographic_detail/show' => 'demographic_detail#show'
Try this:
get '/demographic_details/:cinema_id' => 'demographic_detail#show'
or
controller :demographic_detail do
get '/demographic_detail/:cinema_id' => :show
end

rspec expects all :resources to equal resource

I'm new to RSpec, I wonder why I didn't pass this test
before(:each) { get :index }
it "assigns all favorites as #favorites" do
favorite = FactoryGirl.create(:favorite)
expect(assigns(:favorites)).to eq([favorite])
end
It says
1) FavoritesController GET index assigns all favorites as #favorites
Failure/Error: expect(assigns(:favorites)).to eq([favorite])
expected: [#<Favorite id: 1, patient_id: 6, doctor_id: 5>]
got: #<ActiveRecord::Relation []>
(compared using ==)
Diff:
## -1,2 +1,2
-[#<Favorite:0x000000058a5ca0 id: 1, patient_id: 6, doctor_id: 5>]
+[]
It seems assigns(:favorites) got empty. I have tried another approach as well
def valid_attributes
doctor = FactoryGirl.create(:doctor)
patient = FactoryGirl.create(:patient)
FactoryGirl.attributes_for(:favorite, doctor_id: doctor.id, patient_id: patient.id)
end
it "assigns all favorites as #favorites" do
favorite = Favorite.create! valid_attributes
expect(assigns(:favorites)).to eq([favorite])
end
And it got the same error. Any inputs would be helpful for me and I'd like to ask if there is any way to simplify it.
Update
app/controllers/favorite_controller.rb
class FavoritesController < ApplicationController
before_action :set_favorite, only: [:destroy]
before_action :authenticate_user!
def index
#favorites = Favorite.where(:patient_id => current_user.id).order(id: :asc)
end
end
spec/controllers/favorite_controller_spec.rb
require 'spec_helper'
describe FavoritesController, type: :controller do
login_patient
describe "GET index" do
let!(:favorite) { FactoryGirl.create(:favorite) }
before { get :index }
it { expect(response).to render_template(:index) }
it { expect(response).to be_success }
it { expect(response).to have_http_status(200) }
it "blocks unauthenticated access", :skip_before do
expect(response).to redirect_to(new_user_session_path)
end
it "assigns all favorites as #favorites" do
expect(assigns(:favorites).to_a).to eq([favorite])
end
end
end
spec/support/controller_helpers.rb
module ControllerHelpers
def login_patient
before :each do |example|
unless example.metadata[:skip_before]
#request.env["devise.mapping"] = Devise.mappings[:user]
#patient = FactoryGirl.create(:patient)
sign_in :user, #patient
end
end
end
end
You are creating the records after you send the request so by the time the request finishes, the record you just created isn't included in the list of favorites. Change your test code to the following
let!(:favorite) { FactoryGirl.create(:favorite) }
before { get :index }
it "assigns all favorites as #favorites" do
expect(assigns(:favorites)).to eq([favorite])
end
This will probably still fail because assigns(:favorites) is an ActiveRecord::Relation object so you have to call to_a
expect(assigns(:favorites).to_a).to eq([favorite])
UPDATE:
Since the favorite is being filtered by patient, you have to make sure that the created favorite in the test belongs to the patient. You can do that by changing the favorite to
let!(:favorite) { FactoryGirl.create(:favorite, patient: #patient)
Try to create the records before the request:
let!(:favorite) { FactoryGirl.create(:favorite) }
before(:each) { get :index }
it "assigns all favorites as #favorites" do
expect(assigns(:favorites).to_a).to eq([favorite])
end

Resources