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 Patterson | Design & Code <matt at reprocessed org> | 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) ? On 10/9/07, Matt Patterson <matt-lists at reprocessed.org> wrote:> 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 Patterson | Design & Code > <matt at reprocessed org> | http://www.reprocessed.org/ > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
or if you want to test that it is being called.. you could do template.should_receive(:yield).and_return('''') On 10/9/07, Lance Carlson <lancecarlson at gmail.com> wrote:> 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) ? > > On 10/9/07, Matt Patterson <matt-lists at reprocessed.org> wrote: > > 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 Patterson | Design & Code > > <matt at reprocessed org> | http://www.reprocessed.org/ > > > > > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > >
Jean-François Trân
2007-Oct-09 18:55 UTC
[rspec-users] Testing layouts with RSpec on Rails
2007/10/9, Lance Carlson <lancecarlson at gmail.com>:> 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. -- Ruby ( http://www.rubyfrance.org ) on Rails ( http://www.railsfrance.org )
It is a ruby keyword, but isn''t also just a method being called in the view? On 10/9/07, Jean-Fran?ois Tr?n <jftran at rubyfrance.org> wrote:> 2007/10/9, Lance Carlson <lancecarlson at gmail.com>: > > 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. > > -- > Ruby ( http://www.rubyfrance.org ) on Rails ( http://www.railsfrance.org ) > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Also maybe instead of and_return.. you would do and_yield('''') On 10/9/07, Lance Carlson <lancecarlson at gmail.com> wrote:> It is a ruby keyword, but isn''t also just a method being called in the view? > > On 10/9/07, Jean-Fran?ois Tr?n <jftran at rubyfrance.org> wrote: > > 2007/10/9, Lance Carlson <lancecarlson at gmail.com>: > > > 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. > > > > -- > > Ruby ( http://www.rubyfrance.org ) on Rails ( http://www.railsfrance.org ) > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > >
On 9 Oct 2007, at 19:55, Jean-Fran?ois Tr?n wrote:> 2007/10/9, Lance Carlson <lancecarlson at gmail.com>: >> 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 Patterson | Design & Code <matt at reprocessed org> | http://www.reprocessed.org/
On Tue, 09 Oct 2007 21:12:09 +0100, Matt Patterson wrote:> 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... > > MattWas 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 10/21/07, Steve <vertebrate at gmail.com> wrote:> On Tue, 09 Oct 2007 21:12:09 +0100, Matt Patterson wrote: > > > 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 > > 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 :( 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 Chelimsky <dchelimsky at gmail.com> wrote:> On 10/21/07, Steve <vertebrate at gmail.com> wrote: > > On Tue, 09 Oct 2007 21:12:09 +0100, Matt Patterson wrote: > > > > > 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 > > > > 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 :( > > 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!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 <div>yielded from layout</div> # 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 Chelimsky <dchelimsky at gmail.com> 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 :) It does work. It''s not perfect, but it does work.> > # spec/resources/views/layout_example.html.erb > <div>yielded from layout</div> > > # 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 Oct 22, 2007, at 12:18 AM, Steve wrote:> On Tue, 09 Oct 2007 21:12:09 +0100, Matt Patterson wrote: > >> 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 > > 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 > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-usersI''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 10/22/2007 5:25 AM, David Chelimsky wrote:> $yielded = false::Cough:: I believe the past tense is "yelt". Jay
On Mon, 22 Oct 2007 04:49:50 -0500, David Chelimsky wrote:> On 10/22/07, David Chelimsky <dchelimsky at gmail.com> 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 => ''<div>yielded</div>'', :layout => ''application'' response.should have_tag(''div'', ''yielded'') Steve
On Mon, 22 Oct 2007 10:40:45 -0400, Jonathan Linowes wrote:> 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 > > # 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) > endThis 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 10:40:45 -0400, Jonathan Linowes wrote:> 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 > > # 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) > endThis 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 10:40:45 -0400, Jonathan Linowes wrote:> > 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 > # 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) > endI 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 10/22/07, Steve <vertebrate at gmail.com> wrote:> On Mon, 22 Oct 2007 04:49:50 -0500, David Chelimsky wrote: > > > On 10/22/07, David Chelimsky <dchelimsky at gmail.com> 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 => ''<div>yielded</div>'', :layout => ''application'' > response.should have_tag(''div'', ''yielded'')Good idea. Feature request please.
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, > SteveMy 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 Chelimsky wrote:>> It would feel even less hackish if "render" supported :text like >> rails render does. So you could do this: >> >> render :text => ''<div>yielded</div>'', :layout => ''application'' >> response.should have_tag(''div'', ''yielded'') > > Good idea. Feature request please.Submitted as issue #14969.
Its a typo (sort of). I actually call it on response rather than controller, which does have the layout it "should use application layout" do do_it response.should use_layout("application") end On Oct 22, 2007, at 8:55 PM, Steve wrote:> On Mon, 22 Oct 2007 10:40:45 -0400, Jonathan Linowes wrote: > >> 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 >> >> # 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 > > 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 > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On Tue, 23 Oct 2007 03:16:32 +0000, Steve wrote:> On Mon, 22 Oct 2007 20:06:50 -0500, David Chelimsky wrote: > >>> It would feel even less hackish if "render" supported :text like >>> rails render does. So you could do this: >>> >>> render :text => ''<div>yielded</div>'', :layout => ''application'' >>> response.should have_tag(''div'', ''yielded'') >> >> Good idea. Feature request please. > > Submitted as issue #14969.I don''t know if there are any repercussions, but just adding :text to the array in rspec_on_rails/lib/spec/rails/dsl/behaviour/view_example.rb:subject_of_render was enough to make it work. Steve
On 10/23/07, Steve <vertebrate at gmail.com> wrote:> On Tue, 23 Oct 2007 03:16:32 +0000, Steve wrote: > > > On Mon, 22 Oct 2007 20:06:50 -0500, David Chelimsky wrote: > > > >>> It would feel even less hackish if "render" supported :text like > >>> rails render does. So you could do this: > >>> > >>> render :text => ''<div>yielded</div>'', :layout => ''application'' > >>> response.should have_tag(''div'', ''yielded'') > >> > >> Good idea. Feature request please. > > > > Submitted as issue #14969. > > I don''t know if there are any repercussions, but just adding :text to the > array in > rspec_on_rails/lib/spec/rails/dsl/behaviour/view_example.rb:subject_of_render > was enough to make it work.That''s cool, but that''s not how we do things. Please submit a patch with specs. ;)
On Tue, 23 Oct 2007 17:58:45 -0500, David Chelimsky wrote:>> I don''t know if there are any repercussions, but just adding :text to the >> array in >> rspec_on_rails/lib/spec/rails/dsl/behaviour/view_example.rb:subject_of_render >> was enough to make it work. > > That''s cool, but that''s not how we do things. Please submit a patch > with specs. ;)Yeah, I know. I was just stating that that''s all that was needed. I''m not entirely sure what would be needed to verify that it doesn''t have unintended consequences.