Aaron Brager
Aaron Brager

Reputation: 66244

rspec-html-matchers finds html and body tags in HTML without them

I have a very simple directory with an index.html file that I'm testing with rspec-html-matchers.

I've configured it in spec_helper.rb like so:

require "rspec-html-matchers"

RSpec.configure do |config|
  config.include RSpecHtmlMatchers

  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end

  config.shared_context_metadata_behavior = :apply_to_host_groups
end

The tests are mostly working as expected, but now I'm testing for the presence of <html> and <body> tags and getting (what I think is) an incorrect result.

Example

Here's a really simple test that I think should fail:

describe "index" do
  it "does something weird" do
    expect("<h1>just a header</h1>").to have_tag('html')
  end
end

The string clearly does not contain an <html> tag, so it should fail.

This test:

What am I missing? How can I test for the presence of correctly implemented <html> and <body> tags?

Upvotes: 1

Views: 999

Answers (1)

Dave Schweisguth
Dave Schweisguth

Reputation: 37607

rspec-html-matchers' have_tag parses the document with Nokogiri's HTML parser, which adds the missing tags that are required by the HTML standard. You can see this in irb:

irb(main):001:0> require 'nokogiri'
irb(main):002:0> Nokogiri::HTML '<p>Hi</p>'
=> #<Nokogiri::HTML::Document:0x3fedb1935a60 name="document" children=[
     #<Nokogiri::XML::DTD:0x3fedb19353f8 name="html">,
     #<Nokogiri::XML::Element:0x3fedb1934f84 name="html" children=[
       #<Nokogiri::XML::Element:0x3fedb1934a70 name="body" children=[
         #<Nokogiri::XML::Element:0x3fedb1934804 name="p" children=[
           #<Nokogiri::XML::Text:0x3fedb19344bc "Hi">]>]>]>]>

Capybara's have_selector matcher also uses Nokogiri::HTML and has the same effect.

If your HTML is XHTML, you can test for html and body tags with Nokogiri's XML parser in strict mode:

it "has html and body tags" do
  string = "<html><body><p>Hi</p></body></html>"
  # The following raises an error if the string contains unbalanced tags
  xml = Nokogiri::XML(string) { |config| config.options = Nokogiri::XML::ParseOptions::STRICT }
  htmls = xml.children.select { |child| child.name == 'html' }
  expect(htmls.length).to eq(1)
  bodys = htmls.first.children.select { |child| child.name == 'body' }
  expect(bodys.length).to eq(1)
end

Upvotes: 2

Related Questions