Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions lib/rails/dom/testing/assertions/selector_assertions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,7 @@ def assert_not_dom(*args, &block)
alias_method :refute_select, :assert_not_dom

private def dom_assertions(selector, &block)
if selector.selecting_no_body?
assert true
return
end

selector.ensure_no_assertion_on_nokogiri_body!
count, max = selector.tests.slice(:count, :maximum).values

selector.select.tap do |matches|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ def initialize(values, previous_selection = nil, refute: false, &root_fallback)
end
end

def selecting_no_body? # :nodoc:
# Nokogiri gives the document a body element. Which means we can't
# run an assertion expecting there to not be a body.
@selector == "body" && @tests[:count] == 0
def ensure_no_assertion_on_nokogiri_body! # :nodoc:
# Nokogiri gives the document a body element when missing
return unless @selector == "body" && (@tests.keys & [:text, :html]).none?
raise ArgumentError, "Assertions on body can only be for text or html"
end

def select
Expand Down
14 changes: 13 additions & 1 deletion test/selector_assertions_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,8 @@ def test_feed_item_encoded_with_html_version

def test_body_not_present_in_empty_document
render_html "<div></div>"
assert_select "body", 0
error = assert_raises(ArgumentError) { assert_select "body", 0 }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change. Why do we need it?

Copy link
Author

@3v0k4 3v0k4 Aug 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nokogiri adds a <body> (and <html>) when it's not present. In this case, the rendered html would be <html><body><div></div></body></html>.

So asserting a count (or minimum/maximum) on <body> does not make sense. Now that I think about it, we should prolly do the same thing with <html>.

assert_equal "Assertions on body can only be for text or html", error.message
end

def test_body_class_can_be_tested
Expand All @@ -490,6 +491,17 @@ def test_body_class_can_be_tested_with_html
assert_select ".foo"
end

def test_assert_not_select_on_body_with_text
render_html "<div><p>foo</p><p>bar</p></div>"
assert_failure(/Expected exactly 0 elements matching "body", found 1/) { assert_not_select "body", "foobar" }
assert_failure(/Expected exactly 0 elements matching "body", found 1/) { assert_not_select "body", /foo/ }
end

def test_assert_not_select_on_body_with_html
render_html "<div>foo</div>"
assert_failure(/Expected exactly 0 elements matching "body", found 1/) { assert_not_select "body", { html: "<div>foo</div>" } }
end

def test_assert_select_with_extra_argument
render_html "<html><head><title>Welcome</title></head><body><div></div></body></html>"

Expand Down