Reputation: 34633
I'm writing a request spec, to test that will_paginate is working ok, and I've got a few problems. Firstly, here's a pruned version of my spec:
require 'spec_helper'
describe "Articles" do
subject { page }
describe "index page" do
let(:user) { FactoryGirl.create(:user) }
before { visit news_path }
describe "pagination" do
before(:all) { 31.times { FactoryGirl.create(:article, user: user) } }
after(:all) { Article.delete_all; User.delete_all }
let(:first_page) { Article.paginate(page: 1) }
let(:second_page) { Article.paginate(page: 2) }
it "should not list the second page of articles" do
second_page.each do |article|
page.should_not have_selector('li', text: article.title)
end
end
end
end
end
As you can see there is a test to ensure that the second page of articles are not shown when the user visits the articles index page. This test fails:
1) Articles index page pagination should not list the second page of articles
Failure/Error: page.should_not have_selector('li', text: article.title)
expected css "li" with text "Article number 1" not to return anything
I can't understand why this is failing. When I manually create 31 articles, in development env, and view it in the browser, pagination works fine, but when I switch to the test env, the specs fail.
Article Model:
class Article < ActiveRecord::Base
attr_accessible :body, :title
belongs_to :user
validates :user_id, presence: true
default_scope order: 'created_at DESC'
end
Article Factory looks like this:
FactoryGirl.define do
factory :article do
sequence(:title) { |n| "Article number #{n}" }
body "This is the body"
user
end
end
Upvotes: 2
Views: 720
Reputation: 34633
Quite incredibly, the solution to this was to do the following;
Change:
before(:all) { 31.times { FactoryGirl.create(:article, user: user) } }
to:
before do
31.times { FactoryGirl.create(:article, user: user) }
visit news_path
end
Two things I learned here:
before
block must not target (:all)
, otherwise tests failvisit news_path
inside the before block, after the creation of the factories, otherwise capybara's page object will not be what I expect it to beSo, to illustrate:
This won't work:
# fails because it targets (:all)
before(:all) do
31.times { FactoryGirl.create(:article, user: user) }
visit news_path
end
And neither will this:
# fails because we are visiting the news path before the objects exist
before do
visit news_path
31.times { FactoryGirl.create(:article, user: user) }
end
It needs to be this:
# not targeting (:all) and only visiting news path after creation of the objects
before do
31.times { FactoryGirl.create(:article, user: user) }
visit news_path
end
Over 20 hours to figure this out, at least I learned some new stuff etc.
Upvotes: 4