Files
redux-scraper/spec/support/matchers/html_matchers.rb
2025-01-01 03:29:53 +00:00

55 lines
1.7 KiB
Ruby

# typed: false
normalize_html = lambda { |html| Nokogiri::HTML5.fragment(html.to_s) }
nodes_equal =
lambda do |a, b|
return true if a == b
return false unless a.name == b.name
stype = a.node_type
otype = b.node_type
return false unless stype == otype
sa = a.attributes
oa = b.attributes
return false unless sa.length == oa.length
sa = sa.sort.map { |n, a| [n, a.value, a.namespace && a.namespace.href] }
oa = oa.sort.map { |n, a| [n, a.value, a.namespace && a.namespace.href] }
return false unless sa == oa
skids = a.children
okids = b.children
return false unless skids.length == okids.length
if stype == Nokogiri::XML::Node::TEXT_NODE &&
(a.content.strip != b.content.strip)
return false
end
skids.to_enum.with_index.all? { |ski, i| nodes_equal.call(ski, okids[i]) }
end
RSpec::Matchers.define :eq_html do |expected|
match do |actual|
nodes_equal.call(normalize_html.call(expected), normalize_html.call(actual))
end
failure_message do |actual|
"expected HTML to match.\nExpected: #{normalize_html.call(expected)}\nGot: #{normalize_html.call(actual)}"
end
end
RSpec::Matchers.define :include_html do |expected|
match do |actual|
actual = normalize_html.call(actual)
expected = normalize_html.call(expected).children.first
node_or_children_equal =
lambda do |node|
nodes_equal.call(node, expected) ||
node.children.any? { |child| node_or_children_equal.call(child) }
end
node_or_children_equal.call(actual)
end
failure_message do |actual|
"expected HTML to include fragment.\nExpected fragment:\n#{normalize_html.call(expected)}\nIn:\n#{normalize_html.call(actual)}"
end
end