RSpec, have_tag(), Spec::Matcher, and Nokogiri

One of my faithful readers at http://www.jbrains.ca told me that he couldn’t find an RSS feed icon in his Firefox address bar. I thought I could implement that fairly easily, so I agreed to do it. In the process, I wrote this spec:


This is a companion discussion topic for the original entry at http://blog.thecodewhisperer.com/permalink/rspec-havetag-specmatcher-and-nokogiri

Shortly after I wrote this, I learned that I could use webrat's have_selector() matchers. I will try that, and if anything exciting happens, you'll know shortly after I do.

J.B. - have_tag will be deprecated in rspec-rails-1.x and removed from rspec-rails-2.x in favor of the webrat matchers, which use Nokogiri under the hood. I still like the idea of the custom matcher for an rss feed, but have_selector or have_xpath would work well in the matcher.

Also, the matcher plumbing prefers the match block to return a boolean value rather than setting an expectation. It works fine with an expectation, but it's not necessary. So the last line of the block could read "rss_link_tag["href"] == rss_url_as_text" and it will work the same way.

The reasoning is that matchers are intended to work with both should and should_not. While the expectation might seem to make the intent of the match block more clear, it becomes more confusing when used with "response.should_not have_rss_feed_at(...)". Of course you may never want to use this particular matcher in the negative, but as you write more custom matchers I'm sure you'll see some that would work well with should_not as well as should.

Thanks, David, for your suggestions. I will try them now.

Regarding "should_not have_rss_feed_at()", I agree with you, and will have to monitor those as I go. My design style favors generalizing from very specific code, and I haven't written many matchers yet, so I don't have much evidence yet about what constitutes appropriate matcher design. I will.

Thanks so much for posting this. I love seeing quick examples of great TDD minds working on things that I can easily wrap my mind around.

One quick thing: Google Reader (on Chrome) doesn't pick up the Gists, and it took me a little while to realize that stuff was missing. I don't know if this is a known issue or not, I just figured you'd want to know if you don't already.

Anyways, thanks again! I hope you post more examples like this in the future.

http://github.com/kucaahbe/... this gem returns have_tag functionality and adds some similar matchers(like have_form, with_checkbox etc.)

give a try https://rubygems.org/gems/r... :)

I'm just going to leave this here) https://rubygems.org/gems/r...

Thank you for the suggestion. I don't need to try this again right now, but I'll remember your advice for next time!

useful stuff, JB.

where to put the Matcher and now to make RSpec see is what I'm missing.

Somehow the notification for this comment evaded my attention. :)

I think the typical approach involves putting the matcher in rspec_helper.rb and then gradually moving it to a more sensible location as rspec_helper.rb grows too big.

I'm going only by memory, but I think you must define the helper in the module that rspec_helper.rb defines, so I would add a require statement into that module in rspec_helper.rb that requires something like "spec/matchers/nokogiri_matchers.rb". Then I could create that file in my project and create that matcher without a direct reference back to the RSpec module that rspec_helper.rb creates.

Maybe by now RSpec does some magic for this. I don't know; I haven't looked for that in several years.