-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Regression in integration tests when providing as: :html #50345
Comments
The issue comes from this new line in action_dispatch/testing/request_encoder.rb + register_encoder :html, response_parser: -> body { Rails::Dom::Testing.html_document.parse(body) } Without HTML encoder, the default encoder Now that an HTML encoder has been registered, it tries to call My first thought was to register a ActionDispatch::IntegrationTest.register_encoder :html,
response_parser: ->(body) { Rails::Dom::Testing.html_document.parse(body) },
param_encoder: ->(params) { params }
EDIT: The patch suggested is working. I'll try to pull a request asap. |
Thank you very much @inkstak for the detailed explanations. I have attached a PR that implements your suggested change as well as the corresponding tests. Please let me know if there is anything you would like me to fix. |
In the case you've shared above, passing In the short-term, you might be better off omitting the In the long-term, the |
Closes [rails#50345][] First, handle the exception mentioned in [rails#50345][]: ``` BugTest#test_params_with_htm_content_type: NoMethodError: undefined method `to_html' for {:name=>"Muad'Dib"}:Hash .../actionpack/lib/action_dispatch/testing/request_encoder.rb:39:in `encode_params' .../actionpack/lib/action_dispatch/testing/integration.rb:251:in `process' ``` When an `ActionDispatch::Testing::RequestEncoder` registered through a call to `register_encoder` does not define a `:param_encoder` keyword argument **and** the params do not respond to a `to_$MIME` method, fallback to returning the `params` themselves, unchanged. This behavior is what's implemented by the private `IdentityEncoder` class, so mimic it for defined encoders. Next, special case handling requests with `as: :html`. Passing `as: :html` implies that the request parameters will come from a `POST` body encoded as `text/html`. That isn't entirely true -- browsers will encode `POST` parameters as with the `Content-Type:` header set to either [application/x-www-form-urlencoded][] or [multipart/form-data][]. This commit skips setting the `CONTENT_TYPE` Rack header when processed with `as: :html`. [rails#50345]: rails#50345 [application/x-www-form-urlencoded]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_post_method [multipart/form-data]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_enctype_attribute
@seanpdoyle I couldn't agree more. Using I used to use it as RSpec metadata to explicitly test responses to unexpected formats against API endpoints. RSpec.describe "API::ResourcesController#create" do
subject do
post "/resources", as:, headers:, params:
end
let(:as) { |e| e.metadata[:as] }
context "when requesting JSON", as: :json do
it_behaves_like "it requires authentication"
it_behaves_like "it responds successfully when signed in"
end
context "when requesting HTML", as: :html do
it_behaves_like "it responds with not acceptable"
end
end |
Closes [rails#50345][] First, handle the exception mentioned in [rails#50345][]: ``` BugTest#test_params_with_htm_content_type: NoMethodError: undefined method `to_html' for {:name=>"Muad'Dib"}:Hash .../actionpack/lib/action_dispatch/testing/request_encoder.rb:39:in `encode_params' .../actionpack/lib/action_dispatch/testing/integration.rb:251:in `process' ``` When an `ActionDispatch::Testing::RequestEncoder` registered through a call to `register_encoder` does not define a `:param_encoder` keyword argument **and** the params do not respond to a `to_$MIME` method, fallback to returning the `params` themselves, unchanged. This behavior is what's implemented by the private `IdentityEncoder` class, so mimic it for defined encoders. Next, special case handling requests with `as: :html`. Passing `as: :html` implies that the request parameters will come from a `POST` body encoded as `text/html`. That isn't entirely true -- browsers will encode `POST` parameters as with the `Content-Type:` header set to either [application/x-www-form-urlencoded][] or [multipart/form-data][]. This commit skips setting the `CONTENT_TYPE` Rack header when processed with `as: :html`. [rails#50345]: rails#50345 [application/x-www-form-urlencoded]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_post_method [multipart/form-data]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_enctype_attribute
Closes [rails#50345][] First, handle the exception mentioned in [rails#50345][]: ``` BugTest#test_params_with_htm_content_type: NoMethodError: undefined method `to_html' for {:name=>"Muad'Dib"}:Hash .../actionpack/lib/action_dispatch/testing/request_encoder.rb:39:in `encode_params' .../actionpack/lib/action_dispatch/testing/integration.rb:251:in `process' ``` Calls with `as: :html` result in a `NoMethodError` because `Hash#to_html` does not exist. Passing `as: :html` implies that the request parameters will come from a `POST` body encoded as `text/html`. That isn't entirely true -- browsers will encode `POST` parameters as with the `Content-Type:` header set to either [application/x-www-form-urlencoded][] or [multipart/form-data][]. This commit skips setting the `CONTENT_TYPE` Rack header when processed with `as: :html`. To account for that, extend the `RequestEncoder` constructor to accept a `content_type `argument to use when provided. When omitted, continue to fall back to the provided MIME type. Extend the default `:html` encoder configuration to default to submitting with `Content-Type: x-www-form-urlencoded`. [rails#50345]: rails#50345 [application/x-www-form-urlencoded]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_post_method [multipart/form-data]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_enctype_attribute
Closes [rails#50345][] First, handle the exception mentioned in [rails#50345][]: ``` BugTest#test_params_with_htm_content_type: NoMethodError: undefined method `to_html' for {:name=>"Muad'Dib"}:Hash .../actionpack/lib/action_dispatch/testing/request_encoder.rb:39:in `encode_params' .../actionpack/lib/action_dispatch/testing/integration.rb:251:in `process' ``` Calls with `as: :html` result in a `NoMethodError` because `Hash#to_html` does not exist. Passing `as: :html` implies that the request parameters will come from a `POST` body encoded as `text/html`. That isn't entirely true -- browsers will encode `POST` parameters as with the `Content-Type:` header set to either [application/x-www-form-urlencoded][] or [multipart/form-data][]. This commit skips setting the `CONTENT_TYPE` Rack header when processed with `as: :html`. To account for that, extend the `RequestEncoder` constructor to accept a `content_type `argument to use when provided. When omitted, continue to fall back to the provided MIME type. Extend the default `:html` encoder configuration to default to submitting with `Content-Type: x-www-form-urlencoded`. [rails#50345]: rails#50345 [application/x-www-form-urlencoded]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_post_method [multipart/form-data]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_enctype_attribute
Closes [rails#50345][] First, handle the exception mentioned in [rails#50345][]: ``` BugTest#test_params_with_htm_content_type: NoMethodError: undefined method `to_html' for {:name=>"Muad'Dib"}:Hash .../actionpack/lib/action_dispatch/testing/request_encoder.rb:39:in `encode_params' .../actionpack/lib/action_dispatch/testing/integration.rb:251:in `process' ``` Calls with `as: :html` result in a `NoMethodError` because `Hash#to_html` does not exist. Passing `as: :html` implies that the request parameters will come from a `POST` body encoded as `text/html`. That isn't entirely true -- browsers will encode `POST` parameters as with the `Content-Type:` header set to either [application/x-www-form-urlencoded][] or [multipart/form-data][]. This commit skips setting the `CONTENT_TYPE` Rack header when processed with `as: :html`. To account for that, extend the `RequestEncoder` constructor to accept a `content_type `argument to use when provided. When omitted, continue to fall back to the provided MIME type. Extend the default `:html` encoder configuration to default to submitting with `Content-Type: x-www-form-urlencoded`. [rails#50345]: rails#50345 [application/x-www-form-urlencoded]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_post_method [multipart/form-data]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_enctype_attribute
Closes [rails#50345][] First, handle the exception mentioned in [rails#50345][]: ``` BugTest#test_params_with_htm_content_type: NoMethodError: undefined method `to_html' for {:name=>"Muad'Dib"}:Hash .../actionpack/lib/action_dispatch/testing/request_encoder.rb:39:in `encode_params' .../actionpack/lib/action_dispatch/testing/integration.rb:251:in `process' ``` Calls with `as: :html` result in a `NoMethodError` because `Hash#to_html` does not exist. Passing `as: :html` implies that the request parameters will come from a `POST` body encoded as `text/html`. That isn't entirely true -- browsers will encode `POST` parameters as with the `Content-Type:` header set to either [application/x-www-form-urlencoded][] or [multipart/form-data][]. This commit skips setting the `CONTENT_TYPE` Rack header when processed with `as: :html`. To account for that, extend the `RequestEncoder` constructor to accept a `content_type `argument to use when provided. When omitted, continue to fall back to the provided MIME type. Extend the default `:html` encoder configuration to default to submitting with `Content-Type: x-www-form-urlencoded`. [rails#50345]: rails#50345 [application/x-www-form-urlencoded]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_post_method [multipart/form-data]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_enctype_attribute
Closes [rails#50345][] First, handle the exception mentioned in [rails#50345][]: ``` BugTest#test_params_with_htm_content_type: NoMethodError: undefined method `to_html' for {:name=>"Muad'Dib"}:Hash .../actionpack/lib/action_dispatch/testing/request_encoder.rb:39:in `encode_params' .../actionpack/lib/action_dispatch/testing/integration.rb:251:in `process' ``` Calls with `as: :html` result in a `NoMethodError` because `Hash#to_html` does not exist. Passing `as: :html` implies that the request parameters will come from a `POST` body encoded as `text/html`. That isn't entirely true -- browsers will encode `POST` parameters as with the `Content-Type:` header set to either [application/x-www-form-urlencoded][] or [multipart/form-data][]. This commit skips setting the `CONTENT_TYPE` Rack header when processed with `as: :html`. To account for that, extend the `RequestEncoder` constructor to accept a `content_type `argument to use when provided. When omitted, continue to fall back to the provided MIME type. Extend the default `:html` encoder configuration to default to submitting with `Content-Type: x-www-form-urlencoded`. [rails#50345]: rails#50345 [application/x-www-form-urlencoded]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_post_method [multipart/form-data]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_enctype_attribute
Closes [rails#50345][] First, handle the exception mentioned in [rails#50345][]: ``` BugTest#test_params_with_htm_content_type: NoMethodError: undefined method `to_html' for {:name=>"Muad'Dib"}:Hash .../actionpack/lib/action_dispatch/testing/request_encoder.rb:39:in `encode_params' .../actionpack/lib/action_dispatch/testing/integration.rb:251:in `process' ``` Calls with `as: :html` result in a `NoMethodError` because `Hash#to_html` does not exist. Passing `as: :html` implies that the request parameters will come from a `POST` body encoded as `text/html`. That isn't entirely true -- browsers will encode `POST` parameters as with the `Content-Type:` header set to either [application/x-www-form-urlencoded][] or [multipart/form-data][]. This commit skips setting the `CONTENT_TYPE` Rack header when processed with `as: :html`. To account for that, extend the `RequestEncoder` constructor to accept a `content_type `argument to use when provided. When omitted, continue to fall back to the provided MIME type. Extend the default `:html` encoder configuration to default to submitting with `Content-Type: x-www-form-urlencoded`. [rails#50345]: rails#50345 [application/x-www-form-urlencoded]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_post_method [multipart/form-data]: https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data#the_enctype_attribute
Steps to reproduce
Expected behavior
In Rails 7.0, the second test works.
Actual behavior
In Rails 7.1, the second test will raise an error :
System configuration
Rails version:
Rails 7.1.2 & main
Ruby version:
Ruby 3.2.2
The text was updated successfully, but these errors were encountered: