New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ActionDispatch::Testing::TestResponse#parsed_body
parse HTML with Nokogiri
#47144
ActionDispatch::Testing::TestResponse#parsed_body
parse HTML with Nokogiri
#47144
Conversation
get "/posts" | ||
response.content_type # => "text/html; charset=utf-8" | ||
response.parsed_body.class # => Nokogiri::HTML5::Document | ||
response.parsed_body.to_html # => "<!DOCTYPE html>\n<html>\n..." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that people that were expecting strings will have to rewrite their tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it would be a breaking change.
people that were expecting strings will have to rewrite their tests?
I wasn't sure about this. Since response.parsed_body
and response.body
return the same type (String
), would they be motivated to use response.parsed_body
?
Would upgrading from 7.0 to 7.1 be an appropriate time to introduce a breaking change? Would a breaking change require introducing a configuration? Something like action_dispatch.html_parsed_body_as_document = true
that <= 7.0
applications would set to false
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is fine to just explicitly document that the return type of that method is going to change.
250c6d4
to
3bc7d1d
Compare
@@ -35,6 +35,7 @@ Gem::Specification.new do |s| | |||
|
|||
s.add_dependency "activesupport", version | |||
|
|||
s.add_dependency "nokogiri", ">= 1.8.5" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This version was copied from actiontext/actiontext.gemspec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted in my inline comment, let's please not assume Nokogiri::HTML5
exists, and check for it so we can fall back to Nokogiri::HTML
for platforms and versions that don't support it.
@@ -50,6 +52,7 @@ def self.register_encoder(mime_name, param_encoder: nil, response_parser: nil) | |||
@encoders[mime_name] = new(mime_name, param_encoder, response_parser) | |||
end | |||
|
|||
register_encoder :html, response_parser: -> body { Nokogiri::HTML5.parse(body) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a note that the Nokogiri::HTML5
module/namespace will not exist for Nokogiri < 1.12.0
or for any JRuby user (see sparklemotion/nokogiri#2227).
I think we should take care to gracefully fall back to Nokogiri::HTML.parse(body)
unless defined?(::Nokogiri::HTML5)
3bc7d1d
to
8b3835e
Compare
8b3835e
to
180fe3e
Compare
…okogiri Prior to this commit, the only out-of-the-box parsing that `ActionDispatch::Testing::TestResponse#parsed_body` supported was for `application/json` requests. This meant that `response.body == response.parsed_body` for HTML requests. ```ruby get "/posts" response.content_type # => "text/html; charset=utf-8" response.parsed_body.class # => Nokogiri::HTML5::Document response.parsed_body.to_html # => "<!DOCTYPE html>\n<html>\n..." ``` Using `parsed_body` for JSON requests supports `Hash#fetch`, `Hash#dig`, and Ruby 3.2 destructuring assignment and pattern matching. The introduction of [Nokogiri support for pattern matching][nokogiri-pattern-matching] poses an opportunity to make assertions about the structure of the HTML response. On top of that, there is ongoing work to [introduce pattern matching support in MiniTest][minitest-pattern-matching]. [nokogiri-pattern-matching]: sparklemotion/nokogiri#2523 [minitest-pattern-matching]: minitest/minitest#936
180fe3e
to
ad79ed0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for making those changes!
Use the helpers introduced in rails-dom-testing 2.2.0 instead of managing the HTML parsers as was done in rails#48523. See also related rails#47144 / ad79ed0
Add notes for [rails#47144][] to the 7.1 Release Notes. Additionally, in the time since that was merged, both Nokogiri and Minitest have merged the PRs mentioned to integrate support for Ruby's Pattern matching (sparklemotion/nokogiri#2523 and minitest/minitest#936, respectively). This commit adds coverage for those new assertions, and incorporates guidance into the release notes. [rails#47144]: rails#47144
Use the helpers introduced in rails-dom-testing 2.2.0 instead of managing the HTML parsers as was done in rails#48523. See also related rails#47144 / ad79ed0
Add notes for [rails#47144][] to the 7.1 Release Notes. Additionally, in the time since that was merged, both Nokogiri and Minitest have merged the PRs mentioned to integrate support for Ruby's Pattern matching (sparklemotion/nokogiri#2523 and minitest/minitest#936, respectively). This commit adds coverage for those new assertions, and incorporates guidance into the release notes. [rails#47144]: rails#47144
As of [rails#47144][], `response.parsed_body` supports parsing both `format: :json` and `format: :html` responses. This commit updates the documentation to reflect that. Additionally, it cribs the `ActionDispatch::IntegrationTest` documentation that mentions `register_encoder`, and copies it to the method definition so that the documentation entry for that method has descriptive information. [rails#47144]: rails#47144
As of [rails#47144][], `response.parsed_body` supports parsing both `format: :json` and `format: :html` responses. This commit updates the documentation to reflect that. Additionally, it cribs the `ActionDispatch::IntegrationTest` documentation that mentions `register_encoder`, and copies it to the method definition so that the documentation entry for that method has descriptive information. [rails#47144]: rails#47144
As of [rails#47144][], `response.parsed_body` supports parsing both `format: :json` and `format: :html` responses. This commit updates the documentation to reflect that. Additionally, it cribs the `ActionDispatch::IntegrationTest` documentation that mentions `register_encoder`, and copies it to the method definition so that the documentation entry for that method has descriptive information. [rails#47144]: rails#47144
As of [rails#47144][], `response.parsed_body` supports parsing both `format: :json` and `format: :html` responses. This commit updates the documentation to reflect that. Additionally, it cribs the `ActionDispatch::IntegrationTest` documentation that mentions `register_encoder`, and copies it to the method definition so that the documentation entry for that method has descriptive information. [rails#47144]: rails#47144
As of [rails#47144][], `response.parsed_body` supports parsing both `format: :json` and `format: :html` responses. This commit updates the documentation to reflect that. Additionally, it cribs the `ActionDispatch::IntegrationTest` documentation that mentions `register_encoder`, and copies it to the method definition so that the documentation entry for that method has descriptive information. [rails#47144]: rails#47144
As of [rails#47144][], `response.parsed_body` supports parsing both `format: :json` and `format: :html` responses. This commit updates the documentation to reflect that. Additionally, it cribs the `ActionDispatch::IntegrationTest` documentation that mentions `register_encoder`, and copies it to the method definition so that the documentation entry for that method has descriptive information. [rails#47144]: rails#47144
As of [rails#47144][], `response.parsed_body` supports parsing both `format: :json` and `format: :html` responses. This commit updates the documentation to reflect that. Additionally, it cribs the `ActionDispatch::IntegrationTest` documentation that mentions `register_encoder`, and copies it to the method definition so that the documentation entry for that method has descriptive information. [rails#47144]: rails#47144
Motivation / Background
Prior to this commit, the only out-of-the-box parsing that
ActionDispatch::Testing::TestResponse#parsed_body
supported was forapplication/json
requests. This meant thatresponse.body == response.parsed_body
for HTML requests.Using
parsed_body
for JSON requests supportsHash#fetch
,Hash#dig
, and Ruby 3.2 destructuring assignment and pattern matching.Detail
The introduction of Nokogiri support for pattern
matching poses an opportunity to make assertions about the structure of the HTML response.
On top of that, there is ongoing work to introduce pattern matching support in MiniTest.
Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]