Search code examples
ruby-on-railsrspec2rspec-rails

not sure why changing to before all breaks this test


Working through the exercise of Chapter 10 of the Rails Tutorial which pertains to testing pagination of micro posts, I cannot figure out why my tests break when I do them with before(:all) and after(:all) as below. Even just changing it to before(:each), it works, so it's not the instance variable. (although I can also get it to work not using the instance, and building up the user provided by let)

I am just trying to do this the proper way. Doing it once (i.e., :all) seems right for this. What am I missing?

I've tried stop_and_open_page - it shows no microposts when I use :all, only otherwise (with :each). However, by inspecting either my instance variable or user (when trying it that way with the let) with binding.pry in the console - it has the microposts all times, even when I do specify :all.

I am thinking it's something to do with not loading the association when I use :all, but I can't think of a reason, since it works otherwise in the sample site and in the tests when not using :all.

Any ideas?

P.S. I have a side question - I have the relation set up in my User model like has_many :microposts, dependent: :destroy, yet when I do these tests with the instance variable method below, I have to explicitly call delete_all on micro posts, otherwise they remain in the test db after the run (even though user gets deleted). Am I missing something obvious there or does the cascading destroy not work when user is created via Factory Girl?

UPDATE: Thanks to @Jesper I caught the reason why the after(:all) wasn't removing associated microposts. Code updated to reflect that.

subject { page }

let(:user) { FactoryGirl.create(:user) }
before { valid_signin user }

...

describe "micropost pagination" do

  before(:all) do
    @user_with_many_posts = FactoryGirl.create(:user, email: "[email protected]")
    @user_with_many_posts.save
    31.times { FactoryGirl.create(:micropost, user: @user_with_many_posts) }
    valid_signin @user_with_many_posts
    visit root_path
  end

  after(:all) do
    @user_with_many_posts.destroy
  end

  it { should have_selector('div.pagination') }

  it "should list each micropost" do
    @user_with_many_posts.microposts.paginate(page: 1).each do |mp|
      expect(page).to have_selector('li', text: mp.content)
    end
  end
end

Solution

  • Capybara resets the session between each example run, see this answer: https://stackoverflow.com/a/9789326/648392

    Most probably, your models are set up as expected, but the test fails because the session has been reset.

    In other words, you can set up any models needed in your spec in the before(:all) block, but you have to move session-related stuff, like valid_session and visit root_path to a before(:each) block.