I'm setting up basic tests for a rails app, I'm wondering how the reload function works. Rails generated the basic crud tests, I adapted them to my need, but it seems like the reload function doesn't work.
I create a user with valid params, then ask to change its name, but it seems like nothing's updated (output is still name: 'Toto' instead of name: 'Tata').
Here's the code sample, I just followed the basic rspec tutorial, still, nothing gets updated. Any idea why ?
context "with valid params" do
let(:new_attributes) { {name: 'Tata'} }
it "updates the requested creator" do
creator = Creator.create! valid_attributes
puts creator.id
puts new_attributes
put :update, :id => creator.id, :creator => new_attributes
creator.reload
puts creator.name.to_yaml
expect(creator.attributes).to include( { "name" => 'Tata' } )
...
Here's the matching controller method
def update
#creator = Creator.find(params[:id])
authorize #creator
#creator.completed = true
params[:hidden] == 'false' ? #creator.hidden = false : #creator.hidden = true
#creator.update(creator_params)
if params[:user].present?
if params[:user][:picture].present?
#creator.picture = params[:user][:picture]
end
end
if #creator.save
if iban.nil? || (iban && !iban.valid?)
flash[:alert] = "Veuillez entrer un IBAN valide"
redirect_to edit_creator_path(#creator)
elsif params[:brief_id].present?
flash[:notice] = "Informations mises à jour"
redirect_to brief_path(params[:brief_id])
else
flash[:notice] = "Informations mises à jour"
redirect_to creator_path(#creator)
end
else
puts #creator.errors.full_messages
render :edit
end
end
Related
everyone.
I'm gonna test an active record object destroy failure but I've problems creating a failure situation.
I have a before_filter method called 'require_user_payment_info' which validates the #payment_info object before the delete method is called, so I can't create a 'bad' #payment_info object before the delete method is called.
Here's the require_user_payment_info method:
def require_user_payment_info
#payment_info = credit_card_model.slave.find_by_user_guid(user_guid)
if !#payment_info || #payment_info.user_guid != user_guid
redirect_to(:controller => 'store', :action => 'index') and return false
else
if((#payment_info.card_expires_year.to_i < Date.today.year) ||
((#payment_info.card_expires_month.to_i < Date.today.month) && (#payment_info.card_expires_year.to_i == Date.today.year)))
#payment_info.card_account_public = "" #clear this out so the user is forced to re-enter the credit card number
#payment_info.valid?
flash.now[:error] = t('ui_flash_errors.card_expired_error')
end
end
end
And the actual delete method:
def delete
# required to be called via a delete request
redirect_to :action => 'edit' and return if !request.delete?
if #payment_info.destroy
flash[:notice] = "Delete SUCCESSFUL"
redirect_to :action => 'new'
else
flash[:error] = "Delete failed"
redirect_to :action => 'edit'
end
Any ideas?
This is my solution:
def test_delete
payment_info = Factory.create(:payment_info, :user_guid=>#user.guid, :card_expires_month=>'04',
:card_expires_year=>(Date.today.year+2).to_s, :cardholder_city=>"test city",
:cardholder_state=>'NC', :cardholder_country=>'US', :cardholder_zip=>'27612')
PaymentInfo.any_instance.stubs(:destroy).returns(false)
delete(:delete, {}, #session)
assert_response(:redirect)
assert_equal false, assigns(:payment_info).blank?
assert_redirected_to({:controller=>'account', :action=>'edit'})
assert_equal flash[:error], "There was an error deleting your credit card information. Please try again."
end
authenticate_with_http_token do |token, options|
auth_key = AuthKey.find_by(authentication_token: token)
if auth_key.present?
if auth_key.token_valid?
auth_key.touch
sign_in(:user, auth_key.user, store: false, bypass: false) unless current_user.present?
else
render json: { message: t('invalid_otp_access'), errors: [t('token_expired')] }, status: 401 and return
end
else
render json: { message: t('invalid_access_message'), errors: [t('invalid_access')] }, status: 401 and return
end
end
i need to write spec for the above code, in my controller i am using current_user.
My controller looks like below.
def index
schedules = params[:type] == "upcoming" ? :upcoming : :past
schedules = current_user.audit_schedules.send(schedules)
if schedules.present?
paginate json: schedules, per_page:10, root: false, each_serializer: Api::V1::MyAuditSerializer
else
render json: { message: t('.no_audits_scheduled'), errors: [] }
end
end
and i am trying to test my index with passing valid token and params
context "with invalid attributes" do
it "It will return list of audits" do
request.headers["Authorization"] = "Token #{auth_key.authentication_token}"
#request.env["devise.mapping"] = Devise.mappings[:user]
get :index, { params: { type: "upcoming" } }
expect(response.body).to eq 200
end
end
the above spec returning body like
<html><body>You are being redirected.</body></html>
And in my spec helper i included devise helpers like
config.include Devise::TestHelpers, type: :controller
If i remove that helper current_user is always nil. if i add that helper it is redirecting like above, please let me know what i missed and how can i test those spec.
I think you want user_signed_in? vs. current_user.present?. This doesn't fix the problem.
You're sure user is not null? and that the user has been confirmed if you're using confirmable?
Digging through the code, I see this:
if options[:bypass]
warden.session_serializer.store(resource, scope)
elsif warden.user(scope) == resource && !options.delete(:force)
# Do nothing. User already signed in and we are not forcing it.
true
else
warden.set_user(resource, options.merge!(scope: scope))
end
source: https://github.com/hassox/warden/blob/906edf86c6c31be917a921097031b89361d022e8/lib/warden/proxy.rb
You can try adding :force which should force the setting of the user.
I am new to ror and I'm stuck with writing tests in Capybara .
What I need to do is to test the creation of a new Case
by user clicks the button . But when I check if the glasses did not see created .
require 'spec_helper'
feature "User can create new case" to
background do
# user = FactoryGirl.create (: sysadmin_user) # user.make_current
#plan = FactoryGirl.create(:plan)
# account = FactoryGirl.create (: account, plan: #plan, user: #user)
#trial = FactoryGirl.create trial (:trial, account: #account)
# trial.make_current
# trial_phase = FactoryGirl.create (: trial_phase, trial: #trial)
login (# user.email, # user.password)
end
scenario 'create new case' to
Case.where puts ("created_by =?", # user.id).count #returns 0
fill_in 'case_subject_identifier', with 'MyNewTest'
expect {click_button ('Create New Case')}.to change(Case,:count).by(1)
Case.where puts ("created_by =?", # user.id).count #returns 0
end
end
And this is controller :
POST /cases as HTML
def create`
#case = Case.where("subject_identifier = ? && trial_id = ?", params[:case]
[:subject_identifier], #current_trial.id).first
if #case || params[:case][:subject_identifier].blank?
respond_to :js
else`
params[:case][:subject_identifier]
=sanitize_value(params[:case[:subject_identifier])
if params[:case]
#case = Case.create(params[:case])``
if current_user.trial_member?(#current_trial, current_user)
#case.update_attributes(:location_id => current_user.default_location_id)
else
#case.update_attributes(:location_id => Location.find_by_name("None").id)
end
#case.update_attributes(:trial_phase_id
=>TrialPhase.find_by_name("None").id,:access
=> "None")
#redirect_to "/trial/#{#current_trial.id.to_s}/cases/#{#case.id.to_s}/case_view"
respond_to do |format|
format.js { render :js => %(window.location.pathname='#{'/trial
/'+#current_trial.id.to_s+'/cases/'+#case.id.to_s+'/case_view'}') }
end
end
end
I have used the following regex to validate the nic number in my rails app :
VALID_NIC_REGEX = /\A\d{9}[V|v|x|X]\z/i
validates :nic, presence: true, allow_blank: true, format: { with: VALID_NIC_REGEX }, uniqueness: { case_sensitive: false }
When I test it in my local machine, everything works fine. But after uploading to heroku, it give an error while trying to save the member with a value in the nic field. Both valid and invalid values give the error. If there's no value in the nic field, it saves the member. In the heroku log, I found this error :
NoMethodError (undefined method `limit' for nil:NilClass):
app/controllers/members_controller.rb:117:in `update'
So, I commented out the two validation lines and uploaded the site to Heroku. Now it works. Can some one please explain this? Thank you.
Controller update action :
def update
#source = params[:source]
#telfie = params[:telfie].to_i
#member = Member.find(params[:id])
#tel = Array.new
(1..#telfie.to_i).each do |i|
#tel << params[:tele][:"#{'tele'}#{i}"]
end
#params[:tele] = #tel
if params[:commit] == 'More Numbers'
#telfie = #telfie + 1
render 'edit'
else
if params[:commit] == 'Less Numbers'
if #telfie > 1
#telfie = #telfie - 1
render 'edit'
else
flash.now[:error] = "Can't remove all contact fields!"
render 'edit'
end
else
if #member.update_attributes(member_params)
#member.tele = #tel
#member.save
flash[:success] = "Member #{#member.name} Successfully Updated!"
if params[:commit] == 'Save Member and Add Associates'
redirect_to new_associate_url(memberid: #member.id, source: "memberv" )
else
if #source == "database"
redirect_to database_path
else
redirect_to member_url(#member)
end
end
else
render 'edit'
end
end
end
end
Basically I'm stumped as to why this particular test is failing. The page works fine when I go in and test it out by hand but the test keeps failing. First off, here's the error.
2) Setlist Pages Edit page adding a song
Failure/Error: click_button submit
ActionController::RoutingError:
No route matches {:action=>"edit", :controller=>"setlists", :id=>nil}
# ./app/controllers/allocations_controller.rb:15:in `create'
# (eval):2:in `click_button'
# ./spec/requests/setlist_pages_spec.rb:79:in `block (4 levels) in <top (required)>'
I realise that the id is set to nil but I know that when the test initially visits the page it renders because tests for content pass. I'm not sure why it points to the create controller when I'm testing the edit action as well? The test is shown below:
before do
#setlist = Setlist.create(date: Date.today, morning: true)
end
...
describe "Edit page" do
let(:admin) { FactoryGirl.create(:admin) }
let(:submit){ "Add Song" }
before do
#secondSong = FactoryGirl.create(:song)
sign_in admin
visit edit_setlist_path(#setlist)
end
it{ should have_content("Edit a Setlist")}
describe "adding a song" do
before do
select("#{#secondSong.title} by #{#secondSong.artist}", from: 'Songs')
click_button submit
end
it{ should have_selector('div.alert.alert-success')}
it "should create a new allocation" do
expect{click_button submit}.to change(Allocation, :count).by(1)
end
end # end adding a song
end # end edit test
Controller code as requested:
def create
#setlist = Setlist.new(params[:setlist])
if #setlist.save
#success!
flash[:success] = "Setlist saved"
##setlist.allocations.build produce invalid allocation with nil id
redirect_to setlist_path(#setlist)
else
#FAIL!
render 'new'
end
end
def edit
#songs= Song.search(params[:search])
##songs = Song.all(order: 'title')
#setlist = Setlist.find(params[:id])
#allocations = #setlist.allocations
#allocation = Allocation.new
#selections = Song.all.collect {|s| [ [s.title, s.artist].join(" by "), s.id ]}
end
def update
#setlist = Setlist.find(params[:id])
#selections = Song.all.collect {|s| [ [s.title, s.artist].join(" by "), s.id] }
#allocations = #setlist.allocations
#allocation = Allocation.new
#Allocation parameters
#allocation.song_id = params[:allocation][:song_id]
#allocation.setlist_id = #setlist.id
#allocation.songPosition = #setlist.songs.count + 1
if #setlist.update_attributes(params[:setlist])
if #allocation.save
flash[:success] = "SETLIST SAVED!"
redirect_to edit_setlist_path(#setlist)
else
flash[:fail] = "Sorry there was an error adding songs to the setlist"
render 'edit'
end
else
flash[:fail] = "Invalid Set"
render 'edit'
end
end
Any pointers would be much appreciated!