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
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.