From 8c9e4d520291871e5319bc0e0a890527d8aea099 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Thu, 28 Apr 2011 15:56:11 +0700 Subject: Add `ActionController::ParamsWrapper` to wrap parameters into a nested hash This will allow us to do a rootless JSON/XML request to server. --- actionpack/test/controller/params_wrapper_test.rb | 187 +++++++++++++++++++++ .../dispatch/request/json_params_parsing_test.rb | 53 ++++++ .../dispatch/request/xml_params_parsing_test.rb | 38 +++++ 3 files changed, 278 insertions(+) create mode 100644 actionpack/test/controller/params_wrapper_test.rb (limited to 'actionpack/test') diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb new file mode 100644 index 0000000000..2e5d096fcd --- /dev/null +++ b/actionpack/test/controller/params_wrapper_test.rb @@ -0,0 +1,187 @@ +require 'abstract_unit' + +module Admin; class User; end; end + +class ParamsWrapperTest < ActionController::TestCase + class UsersController < ActionController::Base + def test + render :json => params.except(:controller, :action) + end + end + + class User; end + class Person; end + + tests UsersController + + def test_derivered_name_from_controller + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu' } + assert_equal '{"username":"sikachu","user":{"username":"sikachu"}}', @response.body + end + end + + def test_specify_wrapper_name + with_default_wrapper_options do + UsersController.wrap_parameters :person + + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu' } + assert_equal '{"username":"sikachu","person":{"username":"sikachu"}}', @response.body + end + end + + def test_specify_wrapper_model + with_default_wrapper_options do + UsersController.wrap_parameters Person + + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu' } + assert_equal '{"username":"sikachu","person":{"username":"sikachu"}}', @response.body + end + end + + def test_specify_only_option + with_default_wrapper_options do + UsersController.wrap_parameters :only => :username + + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_equal '{"username":"sikachu","title":"Developer","user":{"username":"sikachu"}}', @response.body + end + end + + def test_specify_except_option + with_default_wrapper_options do + UsersController.wrap_parameters :except => :title + + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_equal '{"username":"sikachu","title":"Developer","user":{"username":"sikachu"}}', @response.body + end + end + + def test_specify_both_wrapper_name_and_only_option + with_default_wrapper_options do + UsersController.wrap_parameters :person, :only => :username + + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_equal '{"username":"sikachu","title":"Developer","person":{"username":"sikachu"}}', @response.body + end + end + + def test_not_enabled_format + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/xml' + post :test, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_equal '{"username":"sikachu","title":"Developer"}', @response.body + end + end + + def test_specify_format + with_default_wrapper_options do + UsersController.wrap_parameters :format => :xml + + @request.env['CONTENT_TYPE'] = 'application/xml' + post :test, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_equal '{"username":"sikachu","title":"Developer","user":{"username":"sikachu","title":"Developer"}}', @response.body + end + end + + def test_not_wrap_reserved_parameters + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'authenticity_token' => 'pwned', '_method' => 'put', 'utf8' => '☃', 'username' => 'sikachu' } + assert_equal '{"authenticity_token":"pwned","_method":"put","utf8":"☃","username":"sikachu","user":{"username":"sikachu"}}', @response.body + end + end + + def test_no_double_wrap_if_key_exists + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'user' => { 'username' => 'sikachu' }} + assert_equal '{"user":{"username":"sikachu"}}', @response.body + end + end + + def test_nested_params + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'person' => { 'username' => 'sikachu' }} + assert_equal '{"person":{"username":"sikachu"},"user":{"person":{"username":"sikachu"}}}', @response.body + end + end + + def test_derived_wrapped_keys_from_matching_model + with_default_wrapper_options do + User.expects(:respond_to?).with(:column_names).returns(true) + User.expects(:column_names).returns(["username"]) + + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_equal '{"username":"sikachu","title":"Developer","user":{"username":"sikachu"}}', @response.body + end + end + + def test_derived_wrapped_keys_from_specified_model + with_default_wrapper_options do + Person.expects(:respond_to?).with(:column_names).returns(true) + Person.expects(:column_names).returns(["username"]) + + UsersController.wrap_parameters Person + + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_equal '{"username":"sikachu","title":"Developer","person":{"username":"sikachu"}}', @response.body + end + end + + private + def with_default_wrapper_options(&block) + @controller.class._wrapper_options = {:format => [:json]} + @controller.class.inherited(@controller.class) + yield + end +end + +class NamespacedParamsWrapperTest < ActionController::TestCase + module Admin + class UsersController < ActionController::Base + def test + render :json => params.except(:controller, :action) + end + end + + class User; end + end + class User; end + class Person; end + + tests Admin::UsersController + + def test_derivered_name_from_controller + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu' } + assert_equal '{"username":"sikachu","user":{"username":"sikachu"}}', @response.body + end + end + + def test_namespace_lookup_when_namespaced_model_available + with_default_wrapper_options do + Admin::User.expects(:respond_to?).with(:column_names).returns(false) + + @request.env['CONTENT_TYPE'] = 'application/json' + post :test, { 'username' => 'sikachu' } + end + end + + private + def with_default_wrapper_options(&block) + @controller.class._wrapper_options = {:format => [:json]} + @controller.class.inherited(@controller.class) + yield + end +end diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb index 34db7a4c66..d854d55173 100644 --- a/actionpack/test/dispatch/request/json_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb @@ -63,3 +63,56 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest end end end + +class RootLessJSONParamsParsingTest < ActionDispatch::IntegrationTest + class UsersController < ActionController::Base + wrap_parameters :format => :json + + class << self + attr_accessor :last_request_parameters, :last_parameters + end + + def parse + self.class.last_request_parameters = request.request_parameters + self.class.last_parameters = params + head :ok + end + end + + def teardown + UsersController.last_request_parameters = nil + end + + test "parses json params for application json" do + assert_parses( + {"user" => {"username" => "sikachu"}, "username" => "sikachu"}, + "{\"username\": \"sikachu\"}", { 'CONTENT_TYPE' => 'application/json' } + ) + end + + test "parses json params for application jsonrequest" do + assert_parses( + {"user" => {"username" => "sikachu"}, "username" => "sikachu"}, + "{\"username\": \"sikachu\"}", { 'CONTENT_TYPE' => 'application/jsonrequest' } + ) + end + + private + def assert_parses(expected, actual, headers = {}) + with_test_routing(UsersController) do + post "/parse", actual, headers + assert_response :ok + assert_equal(expected, UsersController.last_request_parameters) + assert_equal(expected.merge({"action" => "parse"}), UsersController.last_parameters) + end + end + + def with_test_routing(controller) + with_routing do |set| + set.draw do + match ':action', :to => controller + end + yield + end + end +end diff --git a/actionpack/test/dispatch/request/xml_params_parsing_test.rb b/actionpack/test/dispatch/request/xml_params_parsing_test.rb index ad9de02eb4..38453dfe48 100644 --- a/actionpack/test/dispatch/request/xml_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/xml_params_parsing_test.rb @@ -115,3 +115,41 @@ class LegacyXmlParamsParsingTest < XmlParamsParsingTest {'HTTP_X_POST_DATA_FORMAT' => 'xml'} end end + +class RootLessXmlParamsParsingTest < ActionDispatch::IntegrationTest + class TestController < ActionController::Base + wrap_parameters :person, :format => :xml + + class << self + attr_accessor :last_request_parameters + end + + def parse + self.class.last_request_parameters = request.request_parameters + head :ok + end + end + + def teardown + TestController.last_request_parameters = nil + end + + test "parses hash params" do + with_test_routing do + xml = "David" + post "/parse", xml, {'CONTENT_TYPE' => 'application/xml'} + assert_response :ok + assert_equal({"name" => "David", "person" => {"name" => "David"}}, TestController.last_request_parameters) + end + end + + private + def with_test_routing + with_routing do |set| + set.draw do + match ':action', :to => ::RootLessXmlParamsParsingTest::TestController + end + yield + end + end +end -- cgit v1.2.3