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>