Ben Aldred
2008-Jan-24 16:00 UTC
[rspec-users] Help to spec a rails helper method that uses content_for
Hi guys, I am a Rspec newbie and am having problems creating a spec for a RoR helper method. I have in fact already implemented the helper method and am trying to create retrospective specs. I know its the wrong way to do it but I am still learning Rspec. In my view I have a call to a helper method. <% body_class "users" %> which sets a CSS class declaration in the content_for block which is then used in the <body> tag in application.html.erb layout. def body_class(class_name) content_for(:body_class) { " class=\"#{class_name}\"" } end I was trying the following in my view spec: template.should_receive (:body_class).with("users").and_return('' class="users"'') render "/admin/users/index.html.erb", :layout => "application" response.should have_tag(''body.users'') I get a: Expected at least 1 element matching "body.users", found 0. <false> is not true. when I printed the response.body to screen it does not contain he CSS class declaration on the body tag, where as running mongrel and going to the page everything is fine. what am I doing wrong? I ended up doing: render "/admin/users/index.html.erb", :layout => "application" response[:body_class].should == '' class="users"'' I am interested to know why my first attempt did not work. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/rspec-users/attachments/20080124/86eb6565/attachment-0001.html
John D. Hume
2008-Jan-27 17:05 UTC
[rspec-users] Help to spec a rails helper method that uses content_for
Ben, You''re trying to test more than one thing in one spec. The gutter that''s steered you into here is that you''re looking for side-effects of a method you''ve mocked. Your spec says to make sure the template calls "body_class" and to have the call return a string, but that''s not how the body_class method works: the real method passes that string along to "content_for," which is what causes it to end up in the layout. There are really three responsibilities to specify: (1) the template is supposed to provide the right body_class, (2) the body_class method is supposed to format a string and pass it along to content_for, and (3) the layout is supposed to put that content into the body tag. For purposes of specifying the template''s responsibility, I think you''ve got all you need by saying template.should_receive(:body_class).with("users") For the helper, you can just say in your helper spec self.should_receive(:content_for).with(:body_class, " class=\"funclass\"") body_class "funclass" Note that I''m mocking the receiver of the method being tested, which is a smell, but I think it''s reasonable when dealing with app-specific helpers that rely on Rails helper methods. Also note that I''m specifying that you change your implementation to pass the content as the second argument to content_for. That''s a lot less ugly to mock than the version with the block. I don''t have a good recommendation for specifying the layout''s responsibility for plopping the "body_class" content into the body tag, but I think it ought to be pretty easy to do readably. Maybe someone with more view-spec experience could help out. -hume. On Thu, Jan 24, 2008 at 11:00 AM, Ben Aldred <benaldred at gmail.com> wrote:> Hi guys, > > I am a Rspec newbie and am having problems creating a spec for a RoR helper > method. > > I have in fact already implemented the helper method and am trying to create > retrospective specs. I know its the wrong way to do it but I am still > learning Rspec. > > In my view I have a call to a helper method. > > <% body_class "users" %> > > which sets a CSS class declaration in the content_for block which is then > used in the <body> tag in application.html.erb layout. > > def body_class(class_name) > content_for(:body_class) { " class=\"#{class_name}\"" } > end > > > I was trying the following in my view spec: > > template.should_receive (:body_class).with("users") > .and_return('' class="users"'') > render "/admin/users/index.html.erb", :layout => "application" > response.should have_tag('' body.users'') > > I get a: > > Expected at least 1 element matching "body.users", found 0. > <false> is not true. > > when I printed the response.body to screen it does not contain he CSS class > declaration on the body tag, where as running mongrel and going to the page > everything is fine. > > what am I doing wrong? I ended up doing: > > render "/admin/users/index.html.erb", :layout => "application" > response[:body_class].should == '' class="users"'' > > I am interested to know why my first attempt did not work. > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Paul P.
2011-May-25 04:34 UTC
[rspec-users] Help to spec a rails helper method that uses content_for
John, I know this is quite old, but I wanted to apply your same example in Rspec 2. I''m getting the following when I attempt to do so. application_helper.rb ==========================module ApplicationHelper # Return a title on a per-page basis. def title(page_title) content_for(:title) { page_title } end end application_helper_spec.rb ==========================require ''spec_helper'' describe ApplicationHelper do describe "#title" do it "should pass through page title to tile variable" do self.should_receive(:content_for).with(:title, "funtitle") title "funtitle" end end end Results ========================= 1) ApplicationHelper#title should pass through page title to tile variable Failure/Error: title "funtitle" #<RSpec::Core::ExampleGroup::Nested_1::Nested_1:0xb0b4fb8> received :content_for with unexpected arguments expected: (:title, "funtitle") got: (:title) # ./app/helpers/application_helper.rb:5:in `title'' # ./spec/helpers/application_helper_spec.rb:9:in `block (3 levels) in <top (required)>'' Can you see anything I''m doing wrong? Thanks, Paul -- Posted via http://www.ruby-forum.com/.
Justin Ko
2011-May-25 08:27 UTC
[rspec-users] Help to spec a rails helper method that uses content_for
On Tue, May 24, 2011 at 10:34 PM, Paul P. <lists at ruby-forum.com> wrote:> John, > > I know this is quite old, but I wanted to apply your same example in > Rspec 2. I''m getting the following when I attempt to do so. > > application_helper.rb > ==========================> module ApplicationHelper > > # Return a title on a per-page basis. > def title(page_title) > content_for(:title) { page_title } > end > > end > > application_helper_spec.rb > ==========================> require ''spec_helper'' > > describe ApplicationHelper do > > describe "#title" do > it "should pass through page title to tile variable" do > self.should_receive(:content_for).with(:title, "funtitle") > title "funtitle" > end > end > > end > > > Results > =========================> > 1) ApplicationHelper#title should pass through page title to tile > variable > Failure/Error: title "funtitle" > #<RSpec::Core::ExampleGroup::Nested_1::Nested_1:0xb0b4fb8> > received :content_for with unexpected arguments > expected: (:title, "funtitle") > got: (:title) > # ./app/helpers/application_helper.rb:5:in `title'' > # ./spec/helpers/application_helper_spec.rb:9:in `block (3 levels) > in <top (required)>'' > > Can you see anything I''m doing wrong? > > Thanks, > Paul > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >You actually want to use the "helper" method in helper specs. It is an instance of ActionView::Base with the described helper module mixed in. Try this: helper.should_receive(:content_for).with(:title, "funtitle") helper.title "funtitle" More info: http://relishapp.com/rspec/rspec-rails/v/2-6/dir/helper-specs/helper-spec -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20110525/27a051f3/attachment.html>