Guillermo Siliceo Trueba
Guillermo Siliceo Trueba

Reputation: 4609

In a capybara test a controller changes an object, expectation does not pick it up

i'm using capybara with webkit driver to do integration tests and i want to test that a user can deactivate his account overriding a devise controller, the override works as i can see with binding pry that it does change the user.

This is the relevant code on the user model

class User < ActiveRecord::Base
  [...]
  def deactivate!
    self.deactivated = true
    self.deactivated_at = Time.zone.now
    self.save!
    # binding.pry here shows that the user with id 1 changed
  end
end

And my override of the devise destroy method, this is a copy paste with just one line changed

class RegistrationsController < Devise::RegistrationsController
  def destroy
    resource.deactivate!
    # binding.pry shows that the user was actually deactivated
    Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
    set_flash_message :notice, :destroyed if is_navigational_format?
    respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
  end
end

And now the meat of the problem, the test

feature 'registration' do
  let(:user) { create(:user) }

  scenario 'user can deactivate his account' do
    # binding.pry show that the user was created with id 1
    # And now i perform steps to login the user
    visit root_url
    click_link 'Sign in'
    fill_in 'Email', with: user.email
    fill_in 'Password', with: user.password
    click_button 'Log in'
    # binding.pry shows that the user last_login_at was actually correctly updated, so the login works

    # We need rack tests driver because the webkit driver does not support custom HTTP methods
    current_driver = Capybara.current_driver
    Capybara.current_driver = :rack_test
    # Actual submit
    page.driver.submit :delete, user_registration_path, {} # this triggers the deactivate method

    Capybara.current_driver = current_driver

    # binding.pry shows that user was not touched at all!
    expect(user).to be_deactivated # so this fails :(
  end
end

Maybe i'm missing something about the rack test driver, and it rollsback the changes, looking at the tail -f log/test.log i don't see rollbacks but i do see a RELEASE SAVEPOINT active_record_1 Right after the deactivate method, any ideas?

Upvotes: 1

Views: 240

Answers (1)

infused
infused

Reputation: 24337

The problem is that the user object that is loaded in the spec was loaded before the underlying data was changed. You will need to reload the user object in order to see the changes that were made:

expect(user.reload).to be_deactivated

Upvotes: 3

Related Questions