Forum: RSpec problems matching generated html output.

Posted by Patrick Collins (patrick99e99)
on 2011-11-03 23:51
(Received via mailing list)
So, I am writing tests for a presenter class that outputs html markup.

I have a method that does something like this:

def output

  things.map do |thing|

    content_tag :div, :id => thing[:id] do
     [content_tag :p, thing[:body_1],
     content_tag :p, thing[:body_2].join.html_safe
   end

  end.join.html_safe

end

...

Then my spec is something like this:

  it "returns markup" do

  @presenter.stubs(:things).returns({:id => "an_id", :body_1 => "hello",
   :body_2 => "goodbye"})

   @presenter.output.should == filter_for_html("

    <div id="an_id">
      <p>hello</p>
      <p>goodbye</p>
     </div>
   ")
  end

and I made this filter_for_html helper method which allows me to not 
care about
whitespace...  So that just does:

  def filter_for_html(markup)
    markup.squeeze(" ").strip.gsub(/\n\s+/, "")
  end

And this effctively strips out all the whitespace and gives me a string 
like:
"<div id="an_id"><p>hello</p><p>goodbye</p></div>"

...

-- END OF BACKGROUND EXPLANATION --

Now for my question--- I have two problems and am not sure what the best 
to
solve either one is:

1)  The match fails because content_tag apparently inserts in a few \n's 
here
and there.

2)  My background explanation was actually quite simplified, and my 
presenter
class is actually rendering some haml partials, and something like 
%ul.foo
turns into <ul class='foo'>  (note the SINGLE QUOTES)..  So my test 
fails
because my expectation code uses double classes

3)  Some of the text generated via the partials is calling things like
.humanize which capitalize text and I am not really concerned about 
those
details in my test..........


So the way I got my test passing is to do:

@presenter.output.gsub("\n", "").gsub("'", "\"").downcase.should == 
filter_for_html(' ... same content as before ... ')

Which I don't know about you, but that makes me go "ewwwwwwwwww".  And 
makes
all the RSpec readibility go out the window.  Is there something I 
should be
doing with a custom matcher or something to test for case-indifferent 
text,
ignore whitespace and \n, and be quote indifferent?

Thanks.

Patrick J. Collins
http://collinatorstudios.com
Posted by Matt Wynne (mattwynne)
on 2011-11-04 00:14
(Received via mailing list)
On 3 Nov 2011, at 22:36, Patrick J. Collins wrote:

>      content_tag :p, thing[:body_2].join.html_safe
>  it "returns markup" do
>    ")
> "<div id="an_id"><p>hello</p><p>goodbye</p></div>"
>
> So the way I got my test passing is to do:
> Patrick J. Collins
> http://collinatorstudios.com

I realise this isn't the answer you're looking for, but I'm curious: 
where did you get the idea that a presenter should know anything about 
HTML?

cheers,
Matt

--
Freelance programmer & coach
Author, http://pragprog.com/book/hwcuc/the-cucumber-book (with Aslak 
Hellesy)
Founder, http://relishapp.com
+44(0)7974430184 | http://twitter.com/mattwynne
Posted by Patrick Collins (patrick99e99)
on 2011-11-04 00:27
(Received via mailing list)
> I realise this isn't the answer you're looking for, but I'm curious: where
> did you get the idea that a presenter should know anything about HTML?

Maybe I am using the wrong terminology then.  I always thought 
presenters were
classes that output presentational content...  If you have a view with a 
lot of
dynamic content, the conditional logic ends up building to the point 
where the
view is unreadable, and if you try to refactor out into helper methods, 
you end
up having something like

module MyHelper

  def something(lol)
    modify_lol(lol)
  end

  def modify_lol(lol)
    do_something_else_with_lol(lol)
  end

  ... etc

end

A class helps to eliminate this problem by giving you a way to 
instantiate with
instance variables and cut down on having pass around the same variable 
to
multiple helpers......  I've always called that a presenter, and in this 
case
it deals with HTML.  Am I totally on crack?

Patrick J. Collins
http://collinatorstudios.com
Posted by Patrick Collins (patrick99e99)
on 2011-11-04 00:49
(Received via mailing list)
> So, I am writing tests for a presenter class that outputs html markup.
>
Actually now that I am thinking about it..  Would you guys recommend 
that I use
something like Nokogiri to parse the content and test for things like 
number of
children, classes, ids, etc, rather than just comparing the raw HTML?

Patrick J. Collins
http://collinatorstudios.com
Posted by Pat Maddox (Guest)
on 2011-11-04 03:27
(Received via mailing list)
On Nov 3, 2011, at 4:07 PM, Patrick J. Collins wrote:

>> So, I am writing tests for a presenter class that outputs html markup.
>>
> Actually now that I am thinking about it..  Would you guys recommend that I use
> something like Nokogiri to parse the content and test for things like number of
> children, classes, ids, etc, rather than just comparing the raw HTML?

Yes, definitely. Also you might be interested in 
https://github.com/nakajima/elementor although I haven't used it in a 
long time so I don't know how up to date it is.

As far as your other question goes about how to use presenters, you 
probably don't want them emitting HTML. Instead you want the presenter 
to provide a simpler interface to some commonly accessed data that you 
don't think belongs on the model. An example might be

class UserPresenter
  def initialize(user)
    @user = user
  end

  def full_name
    @user.first_name + ' ' + @user.last_name
  end
end

Ignoring whether this is an appropriate case for using a presenter, you 
can see what I'm accomplishing here. And hopefully you can imagine it 
being more useful if there are multiple models involved.

A presenter is basically the facade pattern used specifically for 
presentation logic.

Pat

http://c2.com/cgi/wiki?FacadePattern
http://blog.jayfields.com/2007/03/rails-presenter-...
Posted by Matt Wynne (mattwynne)
on 2011-11-04 10:52
(Received via mailing list)
On 3 Nov 2011, at 23:25, Patrick J. Collins wrote:

>> I realise this isn't the answer you're looking for, but I'm curious: where
>> did you get the idea that a presenter should know anything about HTML?
>
> Maybe I am using the wrong terminology then.  I always thought presenters were
> classes that output presentational content

Well, in any discussion I've seen of the pattern, that's the job of the 
view.

MVP / Passive View[1][2] is quite a well-established pattern in 
curly-bracket languages, and the presenter's job in that pattern is to 
tell the view, at a logical level, what to show. The view is then just 
left with the simple job of showing it. The idea being that you could 
use the same presenter with a view for a web app, a view for a 
rich-client GUI, or a view for a mobile app. In theory.

This makes them both much easier to test.

Steve Klabnik has been writing about their application in the Ruby / 
Rails world recently[3]

[1] http://martinfowler.com/eaaDev/PassiveScreen.html
[2] 
http://www.objectmentor.com/resources/articles/The...
[3] 
http://blog.steveklabnik.com/2011/09/06/the-secret...

cheers,
Matt

--
Freelance programmer & coach
Author, http://pragprog.com/book/hwcuc/the-cucumber-book (with Aslak 
Hellesy)
Founder, http://relishapp.com
+44(0)7974430184 | http://twitter.com/mattwynne
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.