提交 eee3534b 编写于 作者: K Kasper Timm Hansen

Add `parsed_body` to spare writing out parsing routines.

When testing:

```ruby
post articles_path, params: { article: { title: 'Ahoy!' } }, as: :json
```

It's common to want to make assertions on the response body. Perhaps the
server responded with JSON, so you write `JSON.parse(response.body)`.
But that gets tedious real quick.

Instead add `parsed_body` which will automatically parse the reponse
body as what the last request was encoded `as`.
上级 688996da
......@@ -381,6 +381,7 @@ def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: n
response = _mock_session.last_response
@response = ActionDispatch::TestResponse.from_response(response)
@response.request = @request
@response.response_parser = request_encoder
@html_document = nil
@url_options = nil
......@@ -396,7 +397,7 @@ def build_full_uri(path, env)
class RequestEncoder # :nodoc:
@encoders = {}
def initialize(mime_name, param_encoder, url_encoded_form = false)
def initialize(mime_name, param_encoder, response_parser, url_encoded_form = false)
@mime = Mime[mime_name]
unless @mime
......@@ -406,7 +407,8 @@ def initialize(mime_name, param_encoder, url_encoded_form = false)
@url_encoded_form = url_encoded_form
@path_format = ".#{@mime.symbol}" unless @url_encoded_form
@param_encoder = param_encoder || :"to_#{@mime.symbol}".to_proc
@response_parser = response_parser || -> body { body }
@param_encoder = param_encoder || :"to_#{@mime.symbol}".to_proc
end
def append_format_to(path)
......@@ -422,17 +424,21 @@ def encode_params(params)
@param_encoder.call(params)
end
def parse_body(body)
@response_parser.call(body)
end
def self.encoder(name)
@encoders[name] || WWWFormEncoder
end
def self.register_encoder(mime_name, &param_encoder)
@encoders[mime_name] = new(mime_name, param_encoder)
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 :json
register_encoder :json, response_parser: -> body { JSON.parse(body) }
WWWFormEncoder = new(:url_encoded_form, -> params { params }, true)
WWWFormEncoder = new(:url_encoded_form, -> params { params }, nil, true)
end
end
......@@ -696,23 +702,31 @@ def method_missing(sym, *args, &block)
# require 'test_helper'
#
# class ApiTest < ActionDispatch::IntegrationTest
# test "creates articles" do
# test 'creates articles' do
# assert_difference -> { Article.count } do
# post articles_path, params: { article: { title: 'Ahoy!' } }, as: :json
# end
#
# assert_response :success
# assert_equal({ id: Arcticle.last.id, title: 'Ahoy!' }, response.parsed_body)
# end
# end
#
# The `as` option sets the format to JSON, sets the content type to
# 'application/json' and encodes the parameters as JSON.
#
# Calling `parsed_body` on the response parses the response body as what
# the last request was encoded as. If the request wasn't encoded `as` something,
# it's the same as calling `body`.
#
# For any custom MIME Types you've registered, you can even add your own encoders with:
#
# ActionDispatch::IntegrationTest.register_encoder :wibble do |params|
# params.to_wibble
# end
# ActionDispatch::IntegrationTest.register_encoder :wibble,
# param_encoder: -> params { params.to_wibble },
# response_parser: -> body { body }
#
# Where `param_encoder` defines how the params should be encoded and
# `response_parser` defines how the response body should be parsed.
#
# Consult the Rails Testing Guide for more.
......@@ -743,8 +757,8 @@ def document_root_element
html_document.root
end
def self.register_encoder(*args, &param_encoder)
Integration::Session::RequestEncoder.register_encoder(*args, &param_encoder)
def self.register_encoder(*args)
Integration::Session::RequestEncoder.register_encoder(*args)
end
end
end
......@@ -18,5 +18,11 @@ def self.from_response(response)
# Was there a server-side error?
alias_method :error?, :server_error?
attr_writer :response_parser # :nodoc:
def parsed_body
@response_parser.parse_body(body)
end
end
end
......@@ -1129,13 +1129,23 @@ def test_cookies_set_in_setup_are_persisted_through_the_session
class IntegrationRequestEncodersTest < ActionDispatch::IntegrationTest
class FooController < ActionController::Base
def foos
def foos_json
render json: params.permit(:foo)
end
def foos_wibble
render plain: 'ok'
end
end
def test_encoding_as_json
assert_encoded_as :json, content_type: 'application/json'
post_to_foos as: :json do
assert_response :success
assert_match 'foos_json.json', request.path
assert_equal 'application/json', request.content_type
assert_equal({ 'foo' => 'fighters' }, request.request_parameters)
assert_equal({ 'foo' => 'fighters' }, response.parsed_body)
end
end
def test_encoding_as_without_mime_registration
......@@ -1147,25 +1157,28 @@ def test_encoding_as_without_mime_registration
def test_registering_custom_encoder
Mime::Type.register 'text/wibble', :wibble
ActionDispatch::IntegrationTest.register_encoder(:wibble, &:itself)
ActionDispatch::IntegrationTest.register_encoder(:wibble,
param_encoder: -> params { params })
assert_encoded_as :wibble, content_type: 'text/wibble',
parsed_parameters: Hash.new # Unregistered MIME Type can't be parsed
post_to_foos as: :wibble do
assert_response :success
assert_match 'foos_wibble.wibble', request.path
assert_equal 'text/wibble', request.content_type
assert_equal Hash.new, request.request_parameters # Unregistered MIME Type can't be parsed.
assert_equal 'ok', response.parsed_body
end
ensure
Mime::Type.unregister :wibble
end
private
def assert_encoded_as(format, content_type:, parsed_parameters: { 'foo' => 'fighters' })
def post_to_foos(as:)
with_routing do |routes|
routes.draw { post ':action' => FooController }
post '/foos', params: { foo: 'fighters' }, as: format
post "/foos_#{as}", params: { foo: 'fighters' }, as: as
assert_response :success
assert_match "foos.#{format}", request.path
assert_equal content_type, request.content_type
assert_equal parsed_parameters, request.request_parameters
yield
end
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册