Why does this rspec specification not update the model?

I have a query specification for interacting with a user model. I want users with the administrator role to be able to create / edit / delete users. I am having a problem right now when the "Edit" action does not update the user. Everything works correctly when I manually view the actions on the site itself, but the tests do not update the user.

Here is my specification:

it 'edits a user' do @user = FactoryGirl.create(:user) visit new_user_session_path unless current_path == new_user_session_path fill_in "Email", :with => @user.email fill_in "Password", :with => @user.password click_button "Sign In" user_to_edit = FactoryGirl.create(:user, first_name: "John", last_name: "Smith") visit edit_user_path(user_to_edit) unless current_path == edit_user_path(user_to_edit) fill_in 'user_last_name', with: "Changed" expect{ click_button "Do it" }.to change { user_to_edit.last_name }.from("Smith").to("Changed") page.should have_content "John Changed" end 

The error I get is:

 Failure/Error: expect{ result should have been changed to "Changed", but is now "Smith" 

If I changed the last few lines of the test to this:

  fill_in 'user_last_name', with: "Changed" click_button "Do it" page.should have_content "John Changed" 

Then the test succeeds. This does not seem to be correct, since the page should not display "John Changed" if user_to_edit not been updated.

The delete request specification works fine:

 it "deletes a user" do @user = FactoryGirl.create(:user) visit new_user_session_path unless current_path == new_user_session_path fill_in "Email", :with => @user.email fill_in "Password", :with => @user.password click_button "Sign In" user_to_delete = FactoryGirl.create(:user, first_name: "John", last_name: "Smith") visit users_path unless current_path == users_path expect{ within ".user_#{user_to_delete.id}" do click_link 'Delete' end }.to change(User,:count).by(-1) page.should_not have_content "John Smith" end 

I have a user model:

 class User < ActiveRecord::Base ROLES = %w[renter landlord admin] devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable attr_accessible :email, :password, :password_confirmation :first_name, :last_name, :role validates :password, :presence => true, :on => :create validates :first_name, :presence => true validates :last_name, :presence => true before_save :set_phones def set_phones self.fax = Phoner::Phone.parse(self.fax).format("%a%n") unless self.fax.blank? self.land_phone = Phoner::Phone.parse(self.land_phone).format("%a%n") unless land_phone.blank? self.mobile_phone = Phoner::Phone.parse(self.mobile_phone).format("%a%n") unless mobile_phone.blank? end end 

I have this factory:

 require 'faker' FactoryGirl.define do factory :user do |f| f.first_name { Faker::Name.first_name } f.last_name { Faker::Name.last_name } f.email {Faker::Internet.email} f.password { "oq2847hrowihgfoigq278o4r7qgo4" } f.role { "admin" } end end 

I have these actions in my user controller:

  def edit @user = User.find_by_id(params[:id]) respond_to do |format| format.html end end def update if params[:user][:password].blank? [:password,:password_confirmation].collect{|p| params[:user].delete(p) } end respond_to do |format| if @user.errors[:base].empty? and @user.update_attributes(params[:user]) flash.now[:notice] = "Your account has been updated" format.html { render :action => :show } else format.html { render :action => :edit, :status => :unprocessable_entity } end end end 

The routes.rb also matters, since I use Devise and has a user user controller:

  devise_for :users, :skip => [:sessions, :registrations] devise_scope :user do get "login" => "devise/sessions#new", :as => :new_user_session post 'login' => 'devise/sessions#create', :as => :user_session delete "logout" => "devise/sessions#destroy", :as => :destroy_user_session get "signup" => "devise/registrations#new", :as => :new_user_registration put "update-registration" => "devise/registrations#update", :as => :update_user_registration delete "delete-registration" => "devise/registrations#destroy", :as => :delete_user_registration get "edit-registration" => "devise/registrations#edit", :as => :edit_user_registration get "cancel-registration" => "devise/registrations#cancel", :as => :cancel_user_registration post "create-registration" => "devise/registrations#create", :as => :user_registration end resources :users, :controller => "users" 
+8
ruby-on-rails devise rspec-rails capybara cancan
source share
1 answer

you are being fooled by what the intelligent testing framework looks like :) of course you expect the db entry for user_to_edit change. user_to_edit is a local variable, so user_to_edit.last_name will not change no matter which buttons you click. try { user_to_edit.reload.last_name }

+18
source share

All Articles