24

I have a view spec that was passing but is broken now that pagination (via Kaminari gem) has been added to the view. I'm still trying to get my head around RSpec's syntax...so looking for help in getting this to pass as the page works fine in the browser. I'm aware that many people frown on view specs for being brittle (probably for reasons like this) but I still would like to keep this one passing

I am assigning some stubbed posts to the @posts array. But arrays don't respond to current_page. So how should I handle this in RSpec?

Failures:

  1) posts/index.html.haml renders a list of posts
     Failure/Error: render
     ActionView::Template::Error:
       undefined method `current_page' for #<Array:0x000001028ab4e0>
     # ./app/views/posts/index.html.haml:31:in `_app_views_posts_index_html_haml__291454070937541541_2193463480'
     # ./spec/views/posts/index.html.haml_spec.rb:39:in `block (2 levels) in <top (required)>'

spec/views/posts/index.html.haml_spec.rb:

require 'spec_helper'

describe "posts/index.html.haml" do
  before(:each) do
    ...
    assign(:posts, [
      Factory.stub(:post),
      Factory.stub(:post)
    ])    
    view.should_receive(:date_as_string).twice.and_return("June 17, 2011")
    ...
  end

  it "renders a list of posts" do
    render
    rendered.should have_content("June 17, 2011")
    ...
  end
end
Meltemi
  • 37,979
  • 50
  • 195
  • 293
  • 1
    I know you already accepted another answer, but I'm concerned that by doing the stubbing you did that you just stubbed out a bug in your code. The error above implies that you're calling @posts.current_page in your controller. I can see @ posts.first.current_page or controller.current_page being valid, but @ posts.current_page probably isn't. – Luke Cowell Aug 16 '11 at 15:51
  • good point! so, should I, perhaps be stubbing out the controller? I'm not entirely sure what Kaminari expects to call `current_page` on?!? I only know the spec *was* failing because the posts array doesn't respond to it...but, you're right, that does seem odd? *I'll leave this open for a bit to see if a better answer presents itself.* – Meltemi Aug 16 '11 at 19:30
  • Can you also post the relevant controller code ? – Luke Cowell Aug 17 '11 at 14:07

2 Answers2

47

You can also do something like below:

assign(:posts, Kaminari.paginate_array([
        Factory.stub(:post),
        Factory.stub(:post)
      ]).page(1))
manojlds
  • 290,304
  • 63
  • 469
  • 417
  • 2
    This method fits the Rails scaffolded code nicely. Just wrap the generated stub_model array with the Kaminari.paginate_array(...).page(1) and Viola! Working specs. – scarver2 Apr 08 '13 at 16:01
  • 1
    `Kaminari.paginate_array(...).page(1)` works in my case as well – Amit Patel Nov 21 '14 at 07:44
17

You should stub the behavior, try this:

before(:each) do
  ...
  posts = [Factory.stub(:post), Factory.stub(:post)]
  posts.stub!(:current_page).and_return(1)
  posts.stub!(:total_pages).and_return(2)
  assign(:posts, posts)    
  view.should_receive(:date_as_string).twice.and_return("June 17, 2011")
  ...
end
apneadiving
  • 114,565
  • 26
  • 219
  • 213
  • 3
    Brilliant! Thanks! For anyone else watching I also had to stub out two other methods `:num_pages` and `:limit_value` in the same fashion as `:current_value` is above...and the value I'm returning for each of them is an integer `(1)`. Specs passing swimmingly...thanks! – Meltemi Aug 16 '11 at 15:36
  • 1
    I also had to stub `total_pages`. Thanks! – Matt Connolly Sep 26 '12 at 01:38
  • With Rspec 3.1 doing **posts.stub!(:current_page).and_return(1)** thrown error **Undefined method stub! for Array**. However @manojlds answer http://stackoverflow.com/a/8885026/936494 worked for me. – Jignesh Gohel Nov 21 '14 at 07:21
  • @Jignesh I guess you have to replace `stub!` with `stub`. Anyway, the other answer is better :) – apneadiving Nov 21 '14 at 07:59