Testing an Rspec Controller with associations - ruby-on-rails

I've got two models:
class Solution < ActiveRecord::Base
belongs_to :user
validates_attachment_presence :software
validates_presence_of :price, :language, :title
validates_uniqueness_of :software_file_name, :scope => :user_id
has_attached_file :software
end
class User < ActiveRecord::Base
acts_as_authentic
validates_presence_of :first_name, :last_name, :primary_phone_number
validates_uniqueness_of :primary_phone_number
has_many :solutions
end
with my routes looking like this:
map.resources :user, :has_many => :solutions
Now I'm trying to test my solutions controllers with the following RSpec test:
describe SolutionsController do
before(:each) do
#user = Factory.build(:user)
#solution = Factory.build(:solution, :user => #user)
end
describe "GET index" do
it "should find all of the solutions owned by a user" do
Solution.should_receive(:find_by_user_id).with(#user.id).and_return(#solutions)
get :index, :id => #user.id
end
end
end
However, this gets me the following error:
ActionController::RoutingError in 'SolutionsController GET index should find all of the solutions owned by a user'
No route matches {:id=>nil, :controller=>"solutions", :action=>"index"}
Can anybody point me to how I can test this, since the index should always be called within the scope of a particular user?

Factory#build builds an instance of the class, but doesn't save it, so it doesn't have an id yet.
So, #user.id is nil because #user has not been saved.
Because #user.id is nil, your route isn't activated.
try using Factory#create instead.
before(:each) do
#user = Factory.create(:user)
#solution = Factory.create(:solution, :user => #user)
end

Looks like your other problem is on this line:
get :index, :id => #user.id
You're trying to make a request to the index method, but you've provided the wrong variable name. When testing SolutionsController id implies a solution id, you need to supply the user id. This should work, or at least move you forward:
get :index, :user_id => #user.id

Related

send invitation for user rails by adding user_id and page_id in a table

I am new to rails and I have a task asking me to let a page admin to send invitations for regular users to be admins with him I implemented the part to reply to the invitations but I am stuck in an error and please tell me if I am on the right way here is my code for the invitation method
def invite
inviteUser = {"user_id" => current_user.id,"magazine_id" => params[:id]}
CollaborationInvitation.create(inviteUser)
#magazine = Magazine.find(params[:id])
redirect_to :back
end
Here is my model for the invitation:
class CollaborationInvitation < ActiveRecord::Base
belongs_to :user
belongs_to :magazine
end
Model for page:
class Magazine < ActiveRecord::Base
mount_uploader :image, ImgUploader
has_many :articles
acts_as_followable
has_and_belongs_to_many :users
errors[:image] << 'should be less than 5MB' if image.size > 5.megabytes
validates :name, presence: true
validates :image, presence: true
validate :image_size
end`
And the routes:
routes`member do
put 'follow' => 'magazines#follow'
put 'unfollow' => 'magazines#unfollow'
put 'invite' => 'magazines#invite'
end
error : No route matches [GET] "/magazines/3/invite"
and when I changed the route from put to get
I get this error: unknown attribute 'user_id' for CollaborationInvitation.
It looks like you just need to setup the routes properly as resources. Remove the routes listed above and define these instead:
resources :magazines do
member do
put :follow
put :unfollow
put :invite
end
end

How do I test with rspec a create action when my model belongs_to another model and uses devise for authentication

In my rails app I use devise for authenticating a user. I need to create rspec tests for a controller Arts which belongs_to User.
My Art model is the following:
class Art < ActiveRecord::Base
belongs_to :user
attr_accessible :description, :title, :image
has_attached_file :image, :styles => { :medium => "620x620>", :thumb => "200x200>" }
validates :title, :presence => true
validates :description, :presence => true
validates :image, :presence => true
end
In my ArtsController I have the following code:
class ArtsController < ApplicationController
before_filter :authenticate_user!
def create
#user = current_user
#art = #user.arts.create(params[:art])
end
end
I am trying to create a test to check if user is redirected to the sign in page when it tries to create an art and it is not logged in. So my test looks like this:
describe ArtsController do
describe "When user is not logged in" do
it "should be redirected to sign in page if creating new art" do
post :create
response.should redirect_to '/users/sign_in'
end
end
end
But I get the following error:
1) ArtsController When user is not logged in should be redirected to sign in page if creating new art
Failure/Error: post :create
ActionController::RoutingError:
No route matches {:controller=>"arts", :action=>"create"}
# ./spec/controllers/arts_controller_spec.rb:11:in `block (3 levels) in <top (required)>'
My routes.rb is like this:
Capuccino::Application.routes.draw do
devise_for :users
match "home" => "users#home", :as => :user_home
resources :users do
resources :arts
end
match "home/art/:id" => "arts#show", :as => :art
match "home/arts" => "arts#index", :as => :arts
end
How does my rspec test should be to perform this test?
You don't have any routes for arts#create that will take only the controller and action as parameters.
If you want to use your current nested route, you're gonna have to pass along the :user_id parameter in your request:
it "should be redirected to sign in page if creating new art" do
post :create, { :user_id => user_id }
response.should redirect_to '/users/sign_in'
end
But since you're trying to test the use case where you don't have a :user_id, you need a new non-nested route for that.

Tests for polymorphic nested resource

I'm trying to fix the default tests for a polymorphic nested resource and running into lots of issues. I'm betting there is a simple solution that this newbie just hasn't wrapped his head around yet. Any help would be greatly appreciated as always.
My Models:
class Member < ActiveRecord::Base
has_many :names, as: :person
has_many :dependents
attr_accessible :active, :deleted
end
class Name < ActiveRecord::Base
belongs_to :person, polymorphic: true
attr_accessible :dob, :dod, :first, :gender, :last, :mi, :prefix, :relation, :suffix
end
routes.rb:
resources :dependents do
resources :names
end
resources :members do
resources :names
end
Example Test:
require 'test_helper'
class NamesControllerTest < ActionController::TestCase
setup do
#name = names(:one)
#person = members(:one)
end
test "should get edit" do
get :edit, id: #name
assert_response :success
end
end
Error I'm receiving:
3) Error:
test_should_get_edit(NamesControllerTest):
ActionController::RoutingError: No route matches {:id=>"980190962", :person_id=>"980190962", :controller=>"names", :action=>"edit"}
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:544:in raise_routing_error'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:540:inrescue in generate'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:532:in generate'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:573:ingenerate'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:569:in generate_extras'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_dispatch/routing/route_set.rb:565:inextra_keys'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_controller/test_case.rb:153:in assign_parameters'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_controller/test_case.rb:465:inprocess'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_controller/test_case.rb:49:in process'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-3.2.13/lib/action_controller/test_case.rb:392:inget'
/Users/mkenney/hraccess/test/functional/names_controller_test.rb:43:in `block in '
If I add back in the non-nested route to names these errors run. How do I tell the test that it is a nested resource and does this have anything to do with the polymorphic relationship, or is that just noise that is throwing me off?
Thanks in advance for any help you can offer this newbie!
Mark
I needed to add the member_id to get the proper route I believe:
test "should get edit" do
get :edit, member_id: #person, id: #name
assert_response :success
end

Attribute not accessible via Rspec

Models:
class User < ActiveRecord:Base
has_many :roles
has_many :networks, :through => :roles
end
class Network < ActiveRecord:Base
has_many :roles
has_many :network, :through => :roles
end
class Role < ActiveRecord:Base
attr_accesible :user_id, :network_id, :position
belongs_to :user
belongs_to :network
end
The default for role is "member"
In the console I can type:
> #role = Role.find(1)
> #role.position
=> "member"
But in my Rspec tests, I use FactoryGirl to create a user, network, and role. And I have the test #role.should respond_to(:position) I have also tried just assigning it #role.position = "admin". And no matter what, I get an error like:
Failure/Error: #role.should respond_to(:position)
expected [#<Role id:1, user_id: 1, position: "member", created_at...updated_at...>] to respond to :position
Am I missing something very basic?
EDIT:
factories.rb
FactoryGirl.define do
factory :user do
name "Example User"
sequence(:email) {|n| "email#{n}#program.com"}
end
factory :network do
sequence(:name) {|n| "Example Network #{n}"}
location "Anywhere, USA"
description "Lorem Ipsum"
end
factory :role do
association :user
association :network
position "member"
end
end
network_controller_spec
...
before(:each) do
#user = test_sign_in(FactoryGirl.create(:user)
#network = FactoryGirl.create(:network)
#role = FactoryGirl.create(:role, :user_id => #user.id, :network_id = #network.id)
#I have also tried without using (_id) I have tried not setting the position in the factories as well.
end
it "should respond to position" do
get :show, :id => #network
# This may not be the best or even correct way to find this. But there should only be one, and this method works in the console.
#role = Role.where(:user_id => #user.id, :network_id => #network.id)
#role.should respond_to(:position)
end
Jesse is correct in his comment, hopefully he will come back and write it as an answer, in the meantime, the code should be:
#role = Role.where(:user_id => #user.id, :network_id => #network.id).first
or
#role = Role.find_by_user_id_and_network_id(#user.id, #network.id)
As an aside, it seems a little odd to be testing the role class in the network controller spec (unless this is just an exploratory test to work out why things aren't working as expected).

build_* not working despite being has_one

My intention here is just to create a corresponding contact when a user
signs up, but the said contact is never created, despite using build_*
with a has_one:
Contact model:
has_one :user
User model:
belongs_to :contact
Users Controller:
def signup
#user = User.new
end
def signup_success
#user = User.find params[:id]
contact = #user.build_contact
contact.contactable = School.first
contact.save
end
protected
routes:
map.resources :users,
:collection => {
:signup => :get
},
:member => {
:signup_success => :any
}
Any idea of what I'm doing wrong? Thanks for any suggestions.
Does it work if you pass the attributes to build?
contact = #user.build_contact(:contactable => School.first)
contact.save

Resources