Reputation: 66244
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.
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:
have_tag('body')
have_tag('h2')
have_tag('LOLBBQ')
What am I missing? How can I test for the presence of correctly implemented <html>
and <body>
tags?
Upvotes: 1
Views: 999
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