Peter Marklund's Home |
Rails Testing: Making assert_select XML safe
I've been using the new assert_select command extensively in my tests lately and it's a wonderfully powerful tool - a huge improvement over assert_tag. The only annoyance has been the warning messages "ignoring attempt to close form with link" that have been polluting my test output. The other day I decided to track the source of the messages and I discovered that others had already complained about them. I found that the root cause of the problem lies in the HTML::Document and the HTML::Tag classes that ship with Rails. More specifically the problem is in the HTML::Tag#childless? method that auto-closes HTML tags such as img, br, and hr.
What do I mean by auto-closing. Well, in XML you have to close all tags, either with a trailing slash, or with a closing tag. In HTML however, we use tags such as <br> and <link>, usually without a trailing slash. The HTML::Tag class takes those special tags into account and understands that they are auto-closing (childless) without the trailing slash. This becomes a problem if you have an XML document that contains <link>some content</link> since the parser will think the first tag is self-closing and the second tag will be a mismatch. Not only does this cause warning or error messages, but it breaks assert_select for those specific tags.
I have submitted a patch that makes HTML::Document enter XML mode if the document has an <?xml declaration. Jamis has posted about his approach which he calls assert_xml_select. However, since all my documents are XML (XHTML or VoiceXML in my current project) I chose the following approach instead which allows me to use assert_select:
if RAILS_ENV == 'test' module ActionController #:nodoc: module TestProcess # Work around Rails ticket http://dev.rubyonrails.org/ticket/1937 def html_document @html_document ||= HTML::Document.new(@response.body, true, true) end end end end
Setting the first boolean argument to true makes the parser error out if there is an unclosed or mis-matched tag. I want my documents to be valid and I like to fail early.