Testing layouts with RSpec on Rails

Hey guys,

Does anyone have any wisdom to share on the subject of speccing Rails
layouts?

Most of it’s plain old view specs stuff, but are there sensible ways
to verify things like the yield call? (Mocking doesn’t catch that)

Thanks,

Matt


Matt P. | Design & Code
| http://www.reprocessed.org/

I’m not sure you want to test that the yield call works, but merely
that it is being called because you will end up creating an
integration test otherwise. I would suggest just stubbing out the
yield call. I’m pretty sure you can just do template.stub!(:yield) ?

or if you want to test that it is being called… you could do
template.should_receive(:yield).and_return(’’)

2007/10/9, Lance C. [email protected]:

or if you want to test that it is being called… you could do
template.should_receive(:yield).and_return(’’)

I’m missing a point… how can you expect to receive a :yield message
since yield is a Ruby keyword ?

– Jean-François.

It is a ruby keyword, but isn’t also just a method being called in the
view?

Also maybe instead of and_return… you would do and_yield(’’)

On Tue, 09 Oct 2007 21:12:09 +0100, Matt P. wrote:

Matt
Was there ever any resolution on this? This would be a very beneficial
capability to have for making sure views work as expected.

Thanks,
Steve

On 9 Oct 2007, at 19:55, Jean-François Trân wrote:

2007/10/9, Lance C. [email protected]:

or if you want to test that it is being called… you could do
template.should_receive(:yield).and_return(’’)

I’m missing a point… how can you expect to receive a :yield message
since yield is a Ruby keyword ?

That was kind of my original point…

It occured to me that it would be nice to have a spec that would barf
if I ever nuked the layout’s yield (or, indeed, one of its
content_for yields), mainly because they’re the integration point
between layouts and views, and we’re primarily testing them in
isolation (a good thing…)

I was mainly wondering if anyone had some great practices in testing
those integration points, and layout stuff in general, that I could
learn from…

Matt


Matt P. | Design & Code
| http://www.reprocessed.org/

On 10/21/07, Steve [email protected] wrote:

learn from…

Matt

Was there ever any resolution on this? This would be a very beneficial
capability to have for making sure views work as expected.

It would be awesome if you could just do this:

$yielded = false
render “/layouts/application.html.erb” do
$yielded = true
end
$yielded.should be_true

However, it doesn’t work :frowning:

Basically, someone with more time on his/her hands than I needs to
figure out how to observe the yield call and verify that it happened
after the fact (as opposed to using a message expectation).

Patches welcome!

On 10/22/07, David C. [email protected] wrote:

those integration points, and layout stuff in general, that I could
render “/layouts/application.html.erb” do
Patches welcome!
Actually, it turns out that you can do this in a view spec:

render “/path/to/my/file.html.erb”, :layout => “application”

and it will render with the layout. So you could (in theory, I
haven’t done this yet) do something like this:

spec/resources/views/layout_example.html.erb

yielded from layout

spec/views/layouts/application.html.erb_spec.rb

require File.dirname(FILE) + ‘/…/…/spec_helper’

describe “/layouts/application” do

it “should yield” do
render “/…/…/spec/resources/views/layout_example.html.erb”,
:layout => “application”
response.should have_tag(‘div’,‘yielded from layout’)
end

it “should have title” do
render “/…/…/spec/resources/views/layout_example.html.erb”,
:layout => “application”
response.should have_tag(“div.idbar”,“My Killer App”)
end

end

On 10/22/07, David C. [email protected] wrote:

Actually, it turns out that you can do this in a view spec:

render “/path/to/my/file.html.erb”, :layout => “application”

and it will render with the layout. So you could (in theory, I
haven’t done this yet) do something like this:

Actually - I had tried this before I sent the email - I just forgot to
edit this part :slight_smile:

It does work. It’s not perfect, but it does work.

On 10/22/2007 5:25 AM, David C. wrote:

$yielded = false

::Cough:: I believe the past tense is “yelt”.

Jay

On Oct 22, 2007, at 12:18 AM, Steve wrote:

learn from…


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

I’m not sure if this is what you’re after but I’ve created this
custom matcher to my spec_helper.rb, then in my controller spec I can
say

it “should use application layout” do
do_it
response.should use_layout(“application”)
end

custom matchers

#---------------------
class UseLayout
def initialize(expected)
@expected = ‘layouts/’ + expected
end
def matches?(controller)
@actual = controller.layout
#@actual.equal?(@expected)
@actual == @expected
end
def failure_message
return “use_layout expected #{@expected.inspect}, got #
{@actual.inspect}”, @expected, @actual
end
def negeative_failure_message
return “use_layout expected #{@expected.inspect} not to equal #
{@actual.inspect}”, @expected, @actual
end
end

def use_layout(expected)
UseLayout.new(expected)
end

On Mon, 22 Oct 2007 10:40:45 -0400, Jonathan L. wrote:

def matches?(controller)
{@actual.inspect}", @expected, @actual
end
end

def use_layout(expected)
UseLayout.new(expected)
end

This looked promising, but when I try calling controller.layout, I get
“undefined method ‘layout’” on otherwise working controller specs. I
didn’t think ActionController exposed a layout property. If this
something
you exposed yourself?

Thanks,
Steve

On Mon, 22 Oct 2007 04:49:50 -0500, David C. wrote:

On 10/22/07, David C. [email protected] wrote:
Actually, it turns out that you can do this in a view spec:

render “/path/to/my/file.html.erb”, :layout => “application”

and it will render with the layout. So you could (in theory, I
haven’t done this yet) do something like this:

It would feel even less hackish if “render” supported :text like
rails render does. So you could do this:

render :text => ‘

yielded
’, :layout => ‘application’
response.should have_tag(‘div’, ‘yielded’)

Steve

On 10/22/07, Steve [email protected] wrote:

It would feel even less hackish if “render” supported :text like
rails render does. So you could do this:

render :text => ‘

yielded
’, :layout => ‘application’
response.should have_tag(‘div’, ‘yielded’)

Good idea. Feature request please.

On Mon, 22 Oct 2007 10:40:45 -0400, Jonathan L. wrote:

def matches?(controller)
{@actual.inspect}", @expected, @actual
end
end

def use_layout(expected)
UseLayout.new(expected)
end

I didn’t think ActionController exposed a “layout” property. When I went
to try calling controller.layout on some existing specs I got an
undefined
method ‘layout’ exception. Did you modify ActionController to expose
that
property?

Steve

On Mon, 22 Oct 2007 10:40:45 -0400, Jonathan L. wrote:

def matches?(controller)
{@actual.inspect}", @expected, @actual
end
end

def use_layout(expected)
UseLayout.new(expected)
end

This looked promising, but when I try calling controller.layout, I get
“undefined method ‘layout’” on otherwise working controller specs. I
didn’t think ActionController exposed a layout property. If this
something
you exposed yourself?

Thanks,
Steve

On Tue, 23 Oct 2007 00:55:40 +0000, Steve wrote:

This looked promising, but when I try calling controller.layout, I get
“undefined method ‘layout’” on otherwise working controller specs. I
didn’t think ActionController exposed a layout property. If this something
you exposed yourself?

Thanks,
Steve

My apologies for the multiple postings. My newsreader reported the
messages had not been sent, when they apparently were.

Steve

On Mon, 22 Oct 2007 20:06:50 -0500, David C. wrote:

It would feel even less hackish if “render” supported :text like
rails render does. So you could do this:

render :text => ‘

yielded
’, :layout => ‘application’
response.should have_tag(‘div’, ‘yielded’)

Good idea. Feature request please.

Submitted as issue #14969.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs