Skip to content

Commit

Permalink
Document ActionDispatch::IntegrationTest#register_encoder
Browse files Browse the repository at this point in the history
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
  • Loading branch information
seanpdoyle committed Apr 20, 2024
1 parent 284baa1 commit b1815cf
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
17 changes: 14 additions & 3 deletions actionpack/lib/action_dispatch/testing/integration.rb
Expand Up @@ -623,12 +623,12 @@ def method_missing(method, ...)
# Calling TestResponse#parsed_body on the response parses the response body
# based on the last response MIME type.
#
# Out of the box, only `:json` is supported. But for any custom MIME types
# you've registered, you can add your own encoders with:
# Out of the box, only `:html` and `:json` are supported. But for any custom MIME
# types you've registered, you can add your own encoders with:
#
# ActionDispatch::IntegrationTest.register_encoder :wibble,
# param_encoder: -> params { params.to_wibble },
# response_parser: -> body { body }
# response_parser: -> body { Wibble.parse(body) }
#
# Where `param_encoder` defines how the params should be encoded and
# `response_parser` defines how the response body should be parsed through
Expand Down Expand Up @@ -675,6 +675,17 @@ def app=(app)
@@app = app
end

# Registers an encoder used to parse the response body returned by
# TestResponse#parsed_body.
#
# Out of the box, only `:html` and `:json` are supported. For additional
# registered MIME types, register encoders with a `:param_encoder` option
# to encode a `params` argument and a `:response_parser` option to parsed
# the value of TestResponse#parsed_body:
#
# ActionDispatch::IntegrationTest.register_encoder :wibble,
# param_encoder: -> params { params.to_wibble },
# response_parser: -> body { Wibble.parse(body) }
def register_encoder(*args, **options)
RequestEncoder.register_encoder(*args, **options)
end
Expand Down
31 changes: 30 additions & 1 deletion guides/source/testing.md
Expand Up @@ -1130,7 +1130,7 @@ In addition to the standard testing helpers, inheriting from `ActionDispatch::In

For dealing with the integration test runner, see [`ActionDispatch::Integration::Runner`](https://api.rubyonrails.org/classes/ActionDispatch/Integration/Runner.html).

When performing requests, we will have [`ActionDispatch::Integration::RequestHelpers`](https://api.rubyonrails.org/classes/ActionDispatch/Integration/RequestHelpers.html) available for our use.
When performing requests, we will have [`ActionDispatch::Integration::RequestHelpers`](https://api.rubyonrails.org/classes/ActionDispatch/Integration/RequestHelpers.html) available for our use. Responses will be instances of [`ActionDispatch::TestResponse`](https://api.rubyonrails.org/classes/ActionDispatch/TestResponse.html).

If we need to upload files, take a look at [`ActionDispatch::TestProcess::FixtureFile`](https://api.rubyonrails.org/classes/ActionDispatch/TestProcess/FixtureFile.html) to help.

Expand Down Expand Up @@ -1340,6 +1340,35 @@ All of request types have equivalent methods that you can use. In a typical C.R.

NOTE: Functional tests do not verify whether the specified request type is accepted by the action, we're more concerned with the result. Request tests exist for this use case to make your tests more purposeful.

### Functional Tests with JSON

When testing a request, Action Dispatch serializes the `:params` argument based on an optional `:as` argument that specifies the content type. For example, Action Dispatch encodes the `:params` argument into the request body as JSON. When asserting the response, the [`ActionDispatch::TestResponse#parsed_body`](https://api.rubyonrails.org/classes/ActionDispatch/TestResponse.html#method-i-parsed_body) method parses the response body into a [`HashWithIndifferentAccess`](https://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html):

```ruby
class ArticlesControllerTest < ActionDispatch::IntegrationTest
test "should create an Article with JSON" do
post articles_path, params: { article: { body: "Rails is awesome!", title: "Hello Rails" } }, as: :json

assert_equal "Rails is awesome!", response.parsed_body[:body]
assert_equal "Hello Rails", response.parsed_body[:title]
end
end
```

Since `response.parsed_body` returns a `HashWithIndifferentAccess` for JSON responses, tests can combine Ruby [pattern matching](https://docs.ruby-lang.org/en/master/syntax/pattern_matching_rdoc.html) with Minitest's [`assert_pattern`](https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-assert_pattern) assertion:

```ruby
class ArticlesControllerTest < ActionDispatch::IntegrationTest
test "should create an Article with JSON" do
post articles_path, params: { article: { body: "Rails is awesome!", title: "Hello Rails" } }, as: :json

assert_pattern { response.parsed_body => { body: "Rails is awesome!", title: /hello rails/i } }
end
end
```

Test request encoding and response parsing is configurable, and can be configuring with [`ActionDispatch::IntegrationTest.register_encoder`](https://api.rubyonrails.org/classes/ActionDispatch/IntegrationTest/Behavior/ClassMethods.html#method-i-register_encoder). The `register_encoder` method accepts a two callable options. The `:param_encoder` option controls how the `:params` option is encoded into the request, and the `:response_parser` option controls how the body is parsed from the response.

### Testing XHR (Ajax) Requests

To test Ajax requests, you can specify the `xhr: true` option to `get`, `post`,
Expand Down

0 comments on commit b1815cf

Please sign in to comment.