aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/test/controller/webservice_test.rb
blob: 23a46df5cde6129b331a1da6d1a56c09db6fc13e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# frozen_string_literal: true

require "abstract_unit"
require "active_support/json/decoding"

class WebServiceTest < ActionDispatch::IntegrationTest
  class TestController < ActionController::Base
    def assign_parameters
      if params[:full]
        render plain: dump_params_keys
      else
        render plain: (params.keys - ["controller", "action"]).sort.join(", ")
      end
    end

    def dump_params_keys(hash = params)
      hash.keys.sort.each_with_object(+"") do |k, s|
        value = hash[k]

        if value.is_a?(Hash) || value.is_a?(ActionController::Parameters)
          value = "(#{dump_params_keys(value)})"
        else
          value = ""
        end

        s << ", " unless s.empty?
        s << "#{k}#{value}"
      end
    end
  end

  def setup
    @controller = TestController.new
    @integration_session = nil
  end

  def test_check_parameters
    with_test_route_set do
      get "/"
      assert_equal "", @controller.response.body
    end
  end

  def test_post_json
    with_test_route_set do
      post "/",
        params: '{"entry":{"summary":"content..."}}',
        headers: { "CONTENT_TYPE" => "application/json" }

      assert_equal "entry", @controller.response.body
      assert @controller.params.has_key?(:entry)
      assert_equal "content...", @controller.params["entry"]["summary"]
    end
  end

  def test_put_json
    with_test_route_set do
      put "/",
        params: '{"entry":{"summary":"content..."}}',
        headers: { "CONTENT_TYPE" => "application/json" }

      assert_equal "entry", @controller.response.body
      assert @controller.params.has_key?(:entry)
      assert_equal "content...", @controller.params["entry"]["summary"]
    end
  end

  def test_register_and_use_json_simple
    with_test_route_set do
      with_params_parsers Mime[:json] => Proc.new { |data| ActiveSupport::JSON.decode(data)["request"].with_indifferent_access } do
        post "/",
          params: '{"request":{"summary":"content...","title":"JSON"}}',
          headers: { "CONTENT_TYPE" => "application/json" }

        assert_equal "summary, title", @controller.response.body
        assert @controller.params.has_key?(:summary)
        assert @controller.params.has_key?(:title)
        assert_equal "content...", @controller.params["summary"]
        assert_equal "JSON", @controller.params["title"]
      end
    end
  end

  def test_use_json_with_empty_request
    with_test_route_set do
      assert_nothing_raised { post "/", headers: { "CONTENT_TYPE" => "application/json" } }
      assert_equal "", @controller.response.body
    end
  end

  def test_dasherized_keys_as_json
    with_test_route_set do
      post "/?full=1",
        params: '{"first-key":{"sub-key":"..."}}',
        headers: { "CONTENT_TYPE" => "application/json" }
      assert_equal "action, controller, first-key(sub-key), full", @controller.response.body
      assert_equal "...", @controller.params["first-key"]["sub-key"]
    end
  end

  def test_parsing_json_doesnot_rescue_exception
    req = Class.new(ActionDispatch::Request) do
      def params_parsers
        { json: Proc.new { |data| raise Interrupt } }
      end

      def content_length; get_header("rack.input").length; end
    end.new("rack.input" => StringIO.new('{"title":"JSON"}}'), "CONTENT_TYPE" => "application/json")

    assert_raises(Interrupt) do
      req.request_parameters
    end
  end

  private
    def with_params_parsers(parsers = {})
      old_session = @integration_session
      original_parsers = ActionDispatch::Request.parameter_parsers
      ActionDispatch::Request.parameter_parsers = original_parsers.merge parsers
      reset!
      yield
    ensure
      ActionDispatch::Request.parameter_parsers = original_parsers
      @integration_session = old_session
    end

    def with_test_route_set
      with_routing do |set|
        set.draw do
          match "/", to: "web_service_test/test#assign_parameters", via: :all
        end
        yield
      end
    end
end