Testing views with will_paginate Gem using Capybara/Rspec

别来无恙 提交于 2019-12-10 10:47:50

问题


Doing Michael Hartl's Rails Tutorial, on chapter 10, section 5, exercise 2. I am - very simply - trying to write tests to ensure that a pagination div appears on a couple pages using the will_paginate gem (this seems to be Hartl's preferred method of testing whether pagination works), but when I add the following code..

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

..it returns..

  1) UserPages profile page 
     Failure/Error: it { should have_selector('div.pagination') }
       expected css "div.pagination" to return something

This is especially odd because in this particular _spec file, this same Rspec code is passing in some tests and failing in others (I'll highlight this below). Also the pagination div is present in the source code in my browser, and of course it's working fine.

Because it fails in some places and not others, I got to assuming that this is somehow a "scope"- or assignment-type issue related to will_paginate - you see, for the failed tests, the content being paginated is actually part of a "Microposts" controller, but the pages/views being tested are handled by the "Users" controller. For the passing tests, the view and controller are both "Users".

Could that be the problem? It's also possible that my FactoryGirl setup/invocation is broken and not triggering the pagination code in test for some reason. I'm a Rails n00b - and actually totally new to programming - so thanks ya'll. :)

(also, p.s., how do I make my code colorful and pretty on SO?)

/spec/requests/user_pages_spec.rb

require 'spec_helper' # Omitted from below - I don't think this is relevant.

describe "UserPages" do

  subject { page }

  describe "index" do # This is the block where it is PASSING..

    let(:user) { FactoryGirl.create(:user) } # I'll include my /spec/factories.rb file below

    before(:all)  { 30.times { FactoryGirl.create(:user) } }
    after(:all)   { User.delete_all } # I'll omit my /app/models/user.rb file - I don't think it's relevant to the problem

    before do
      valid_signin user # References /spec/support/utilities.rb to sign in as a valid user, but I will omit this since this is part of the working tests
      visit users_path # This is /app/views/users/index.html.erb - this is where SUCCESSFUL pagination testing occurs
    end

    describe "pagination" do

      it { should have_selector('div.pagination') } #PASS!! As I would expect
  .
  .
  .
  end

  describe "profile page" do
    let(:user) { FactoryGirl.create(:user) }
    let!(:m1) { FactoryGirl.create(:micropost, user: user, content: "Awesome")} # Used for other tests
    let!(:m2) { FactoryGirl.create(:micropost, user: user, content: "Sauce") } # Used for other tests

    before(:all)  { 30.times { FactoryGirl.create(:micropost) } } # Is this constructed properly? Perhaps the posts are not created, and that's why the failure to render the paginate code in test.
    after(:all)   { user.microposts.delete_all } # I have tested with and without this line of code - it fails both ways.

    before { visit user_path(user) } # /app/views/users/show.html.erb

    it { should have_selector('div.pagination') } # FAIL!!! This is the line in question that generates the error above.
    .
   .
  .
 .
end

/app/views/users/index.html.erb (pagination working on site, test working also)

<%= provide(:title, 'All users') %>
<h1>All users</h1>

<%= will_paginate %>

<ul class="users">
  <%= render @users %>
</ul>

<%= will_paginate %>

/app/views/users/show.html.erb (pagination working on site, test failing)

<% provide(:title, @user.name) %>
<div class="row">
.
.
.
  <div class="span8">
    <% if @user.microposts.any? %>
      <h3>Microposts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %> # Here is where I declare that pagination should occur on @microposts, NOT @users
    <% end %>
  </div>
</div>

/spec/requests/factories.rb

FactoryGirl.define do
  factory :user do
    sequence(:name)   { |n| "Person #{n}" }
    sequence(:email)  { |n| "person_#{n}@example.com" }
    password  "secret"
    password_confirmation "secret"

    factory :admin do
      admin true
    end
  end

  factory :micropost do
    content "Lorem ipsum"
    user
  end
end

/Gemfile

source 'https://rubygems.org'

gem 'rails', '3.2.3'
gem 'pg', '0.12.2'
gem 'bootstrap-sass', '2.0.0'
gem 'bcrypt-ruby', '3.0.1'
gem 'faker', '1.0.1'
gem 'will_paginate', '3.0.3'
gem 'bootstrap-will_paginate', '0.0.6'

group :development do
    gem 'guard-rspec', '0.5.5'
    gem 'annotate', '~> 2.4.1.beta'
end

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '3.2.4'
  gem 'coffee-rails', '3.2.2'
  gem 'uglifier', '1.2.3'
end

gem 'jquery-rails', '2.0.0'

group :test, :development do
  gem 'rspec-rails', '2.9.0'
end

group :test do
    gem 'capybara', '1.1.2'
    gem 'rb-fsevent', '0.4.3.1', :require => false
    gem 'growl', '1.0.3'
    gem 'guard-spork', '0.3.2'
    gem 'spork', '0.9.0'
    gem 'factory_girl_rails', '1.4.0'
end

edit: found this article related to will_paginate and view testing, but don't understand it honestly (probably due to the syntax).. could it be somehow related?


回答1:


When you use:

before(:all)  { 30.times { FactoryGirl.create(:user) } }

You already have an user created so the total count goes up to 31 and so it paginates (pagination with will_paginate shows 30 records per page by default).

Try creating 31 microposts instead of 30, it should pass.

before(:each) { 31.times { FactoryGirl.create(:micropost, user: user) } }

Edit: I forgot to pass the :user to the micropost Factory, it should work now (is the code I have on my tests and it passes)




回答2:


According to http://thewebfellas.com/blog/2008/8/3/roll-your-own-pagination-links-with-will_paginate

"<%= will_paginate %>" produces a div tag with class = pagination, but I didn't see anything that would imply making testing for 'div.pagination' pass.

I changed the test to

it { should have_selector('div', class: 'pagination') }

and that should basically test the same thing, and this passes for me. Hope this helps!




回答3:


<%= provide (:title, 'All users') %>
<h1>All users</h1>

<div class="pagination">
<%=will_paginate%>
</div>

<ul class="users">
<%=render @users%>
</ul> 

<div class="pagination">
<%= will_paginate %>
</div>


来源:https://stackoverflow.com/questions/10762896/testing-views-with-will-paginate-gem-using-capybara-rspec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!