committee 2.0.0.pre8 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/committee/middleware/request_validation.rb +10 -23
- data/lib/committee/parameter_coercer.rb +46 -14
- data/lib/committee/request_unpacker.rb +1 -4
- data/lib/committee/string_params_coercer.rb +74 -25
- data/test/middleware/request_validation_test.rb +197 -4
- data/test/parameter_coercer_test.rb +84 -6
- data/test/string_params_coercer_test.rb +89 -32
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0719ce2f2d3336816d822c41eace6161265ab86b
|
4
|
+
data.tar.gz: 8eaf8c70a09ed4ef5b6613897e54d370f8523ea6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c94926b7b0f4a0e92b99d448d5eb186c751b5b29fe7734038027f824ae2d892e8d93939d9c0d6f738b11d21926ef4235ac8a0818b2a03d8b4f421cbab5d396cf
|
7
|
+
data.tar.gz: 5df57d46e4d3f639705339a88c0464eb9c1677d314eccf1ea877d8449b13fb9f8d3da3d56f865fe1da5fcfe038eb1d3b2c43754de064a825a05ff4062447e5d6
|
@@ -9,6 +9,7 @@ module Committee::Middleware
|
|
9
9
|
@optimistic_json = options.fetch(:optimistic_json, false)
|
10
10
|
@strict = options[:strict]
|
11
11
|
@coerce_date_times = options.fetch(:coerce_date_times, false)
|
12
|
+
@coerce_recursive = options.fetch(:coerce_recursive, true)
|
12
13
|
|
13
14
|
@coerce_form_params = options.fetch(:coerce_form_params,
|
14
15
|
@schema.driver.default_coerce_form_params)
|
@@ -23,29 +24,18 @@ module Committee::Middleware
|
|
23
24
|
|
24
25
|
def handle(request)
|
25
26
|
link, param_matches = @router.find_request_link(request)
|
26
|
-
path_params = {}
|
27
27
|
|
28
28
|
if link
|
29
29
|
# Attempts to coerce parameters that appear in a link's URL to Ruby
|
30
30
|
# types that can be validated with a schema.
|
31
31
|
if @coerce_path_params
|
32
|
-
|
33
|
-
Committee::StringParamsCoercer.new(
|
34
|
-
param_matches,
|
35
|
-
link.schema
|
36
|
-
).call
|
37
|
-
)
|
32
|
+
Committee::StringParamsCoercer.new(param_matches, link.schema, coerce_recursive: @coerce_recursive).call!
|
38
33
|
end
|
39
34
|
|
40
35
|
# Attempts to coerce parameters that appear in a query string to Ruby
|
41
36
|
# types that can be validated with a schema.
|
42
37
|
if @coerce_query_params && !request.GET.nil? && !link.schema.nil?
|
43
|
-
request.
|
44
|
-
Committee::StringParamsCoercer.new(
|
45
|
-
request.GET,
|
46
|
-
link.schema
|
47
|
-
).call
|
48
|
-
)
|
38
|
+
Committee::StringParamsCoercer.new(request.GET, link.schema, coerce_recursive: @coerce_recursive).call!
|
49
39
|
end
|
50
40
|
end
|
51
41
|
|
@@ -58,14 +48,14 @@ module Committee::Middleware
|
|
58
48
|
schema: link ? link.schema : nil
|
59
49
|
).call
|
60
50
|
|
61
|
-
request.env[@params_key].merge!(
|
51
|
+
request.env[@params_key].merge!(param_matches) if param_matches
|
62
52
|
|
63
53
|
if link
|
64
54
|
validator = Committee::RequestValidator.new(link, check_content_type: @check_content_type)
|
65
55
|
validator.call(request, request.env[@params_key])
|
66
56
|
|
67
|
-
parameter_coerce(request, link, @params_key)
|
68
|
-
parameter_coerce(request, link, "rack.request.query_hash") if !request.GET.nil? && !link.schema.nil?
|
57
|
+
parameter_coerce!(request, link, @params_key)
|
58
|
+
parameter_coerce!(request, link, "rack.request.query_hash") if !request.GET.nil? && !link.schema.nil?
|
69
59
|
|
70
60
|
@app.call(request.env)
|
71
61
|
elsif @strict
|
@@ -90,13 +80,10 @@ module Committee::Middleware
|
|
90
80
|
|
91
81
|
private
|
92
82
|
|
93
|
-
def parameter_coerce(request, link, coerce_key)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
coerce_date_times: @coerce_date_times)
|
98
|
-
.call
|
99
|
-
)
|
83
|
+
def parameter_coerce!(request, link, coerce_key)
|
84
|
+
Committee::ParameterCoercer.
|
85
|
+
new(request.env[coerce_key], link.schema, coerce_date_times: @coerce_date_times, coerce_recursive: @coerce_recursive).
|
86
|
+
call!
|
100
87
|
end
|
101
88
|
end
|
102
89
|
end
|
@@ -5,31 +5,63 @@ module Committee
|
|
5
5
|
@schema = schema
|
6
6
|
|
7
7
|
@coerce_date_times = options.fetch(:coerce_date_times, false)
|
8
|
+
@coerce_recursive = options.fetch(:coerce_recursive, false)
|
8
9
|
end
|
9
10
|
|
10
|
-
def call
|
11
|
-
|
12
|
-
|
11
|
+
def call!
|
12
|
+
coerce_object!(@params, @schema)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
def coerce_object!(hash, schema)
|
18
|
+
return false unless schema.respond_to?(:properties)
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
is_coerced = false
|
21
|
+
schema.properties.each do |k, s|
|
22
|
+
original_val = hash[k]
|
23
|
+
unless original_val.nil?
|
24
|
+
new_value, is_changed = coerce_value!(original_val, s)
|
25
|
+
if is_changed
|
26
|
+
hash[k] = new_value
|
27
|
+
is_coerced = true
|
22
28
|
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
is_coerced
|
33
|
+
end
|
23
34
|
|
24
|
-
|
35
|
+
def coerce_value!(original_val, s)
|
36
|
+
s.type.each do |to_type|
|
37
|
+
if @coerce_date_times && to_type == "string" && s.format == "date-time"
|
38
|
+
coerced_val = parse_date_time(original_val)
|
39
|
+
return coerced_val, true if coerced_val
|
25
40
|
end
|
41
|
+
|
42
|
+
return original_val, true if @coerce_recursive && (to_type == "array") && coerce_array_data!(original_val, s)
|
43
|
+
|
44
|
+
return original_val, true if @coerce_recursive && (to_type == "object") && coerce_object!(original_val, s)
|
26
45
|
end
|
46
|
+
return nil, false
|
27
47
|
end
|
28
48
|
|
29
|
-
|
30
|
-
|
49
|
+
def coerce_array_data!(original_val, schema)
|
50
|
+
return false unless schema.respond_to?(:items)
|
51
|
+
return false unless original_val.is_a?(Array)
|
52
|
+
|
53
|
+
is_coerced = false
|
54
|
+
original_val.each_with_index do |d, index|
|
55
|
+
new_value, is_changed = coerce_value!(d, schema.items)
|
56
|
+
if is_changed
|
57
|
+
original_val[index] = new_value
|
58
|
+
is_coerced = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
is_coerced
|
63
|
+
end
|
31
64
|
|
32
|
-
private
|
33
65
|
def parse_date_time(original_val)
|
34
66
|
begin
|
35
67
|
DateTime.parse(original_val)
|
@@ -10,41 +10,90 @@ module Committee
|
|
10
10
|
# errors are simply ignored and expected to be handled later by schema
|
11
11
|
# validation.
|
12
12
|
class StringParamsCoercer
|
13
|
-
def initialize(query_hash, schema)
|
13
|
+
def initialize(query_hash, schema, options = {})
|
14
14
|
@query_hash = query_hash
|
15
15
|
@schema = schema
|
16
|
+
|
17
|
+
@coerce_recursive = options.fetch(:coerce_recursive, false)
|
18
|
+
end
|
19
|
+
|
20
|
+
def call!
|
21
|
+
coerce_object!(@query_hash, @schema)
|
16
22
|
end
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
private
|
25
|
+
|
26
|
+
def coerce_object!(hash, schema)
|
27
|
+
return false unless schema.respond_to?(:properties)
|
28
|
+
|
29
|
+
is_coerced = false
|
30
|
+
schema.properties.each do |k, s|
|
31
|
+
original_val = hash[k]
|
32
|
+
unless original_val.nil?
|
33
|
+
new_value, is_changed = coerce_value!(original_val, s)
|
34
|
+
if is_changed
|
35
|
+
hash[k] = new_value
|
36
|
+
is_coerced = true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
is_coerced
|
42
|
+
end
|
43
|
+
|
44
|
+
def coerce_value!(original_val, s)
|
22
45
|
unless original_val.nil?
|
23
46
|
s.type.each do |to_type|
|
24
47
|
case to_type
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
48
|
+
when "null"
|
49
|
+
return nil, true if original_val.empty?
|
50
|
+
when "integer"
|
51
|
+
begin
|
52
|
+
return Integer(original_val), true
|
53
|
+
rescue ArgumentError => e
|
54
|
+
raise e unless e.message =~ /invalid value for Integer/
|
55
|
+
end
|
56
|
+
when "number"
|
57
|
+
begin
|
58
|
+
return Float(original_val), true
|
59
|
+
rescue ArgumentError => e
|
60
|
+
raise e unless e.message =~ /invalid value for Float/
|
61
|
+
end
|
62
|
+
when "boolean"
|
63
|
+
if original_val == "true" || original_val == "1"
|
64
|
+
return true, true
|
65
|
+
end
|
66
|
+
if original_val == "false" || original_val == "0"
|
67
|
+
return false, true
|
68
|
+
end
|
69
|
+
when "array"
|
70
|
+
if @coerce_recursive && coerce_array_data!(original_val, s)
|
71
|
+
return original_val, true # change original value
|
72
|
+
end
|
73
|
+
when "object"
|
74
|
+
if @coerce_recursive && coerce_object!(original_val, s)
|
75
|
+
return original_val, true # change original value
|
76
|
+
end
|
42
77
|
end
|
43
|
-
break if coerced.key?(k)
|
44
78
|
end
|
45
79
|
end
|
80
|
+
return nil, false
|
81
|
+
end
|
82
|
+
|
83
|
+
def coerce_array_data!(original_val, schema)
|
84
|
+
return false unless schema.respond_to?(:items)
|
85
|
+
return false unless original_val.is_a?(Array)
|
86
|
+
|
87
|
+
is_coerced = false
|
88
|
+
original_val.each_with_index do |d, index|
|
89
|
+
new_value, is_changed = coerce_value!(d, schema.items)
|
90
|
+
if is_changed
|
91
|
+
original_val[index] = new_value
|
92
|
+
is_coerced = true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
is_coerced
|
46
97
|
end
|
47
|
-
coerced
|
48
|
-
end
|
49
98
|
end
|
50
99
|
end
|
@@ -7,6 +7,50 @@ describe Committee::Middleware::RequestValidation do
|
|
7
7
|
@app
|
8
8
|
end
|
9
9
|
|
10
|
+
ARRAY_PROPERTY = [
|
11
|
+
{
|
12
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
13
|
+
"per_page" => 1,
|
14
|
+
"nested_coercer_object" => {
|
15
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
16
|
+
"threshold" => 1.5
|
17
|
+
},
|
18
|
+
"nested_no_coercer_object" => {
|
19
|
+
"per_page" => 1,
|
20
|
+
"threshold" => 1.5
|
21
|
+
},
|
22
|
+
"nested_coercer_array" => [
|
23
|
+
{
|
24
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
25
|
+
"threshold" => 1.5
|
26
|
+
}
|
27
|
+
],
|
28
|
+
"nested_no_coercer_array" => [
|
29
|
+
{
|
30
|
+
"per_page" => 1,
|
31
|
+
"threshold" => 1.5
|
32
|
+
}
|
33
|
+
],
|
34
|
+
"integer_array" => [
|
35
|
+
1, 2, 3
|
36
|
+
],
|
37
|
+
"datetime_array" => [
|
38
|
+
"2016-04-01T16:00:00.000+09:00",
|
39
|
+
"2016-04-01T17:00:00.000+09:00",
|
40
|
+
"2016-04-01T18:00:00.000+09:00"
|
41
|
+
]
|
42
|
+
},
|
43
|
+
{
|
44
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
45
|
+
"per_page" => 1,
|
46
|
+
"threshold" => 1.5
|
47
|
+
},
|
48
|
+
{
|
49
|
+
"threshold" => 1.5,
|
50
|
+
"per_page" => 1
|
51
|
+
}
|
52
|
+
]
|
53
|
+
|
10
54
|
it "passes through a valid request" do
|
11
55
|
@app = new_rack_app(schema: hyper_schema)
|
12
56
|
params = {
|
@@ -35,18 +79,162 @@ describe Committee::Middleware::RequestValidation do
|
|
35
79
|
assert_equal 200, last_response.status
|
36
80
|
end
|
37
81
|
|
38
|
-
it "passes
|
82
|
+
it "passes a nested object with recursive option" do
|
39
83
|
key_name = "update_time"
|
40
84
|
params = {
|
41
|
-
key_name => "2016-04-01T16:00:00.000+09:00"
|
85
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
86
|
+
"query" => "cloudnasium",
|
87
|
+
"array_property" => ARRAY_PROPERTY
|
42
88
|
}
|
43
89
|
|
44
90
|
check_parameter = lambda { |env|
|
91
|
+
hash = env['rack.request.query_hash']
|
92
|
+
assert_equal DateTime, hash['array_property'].first['update_time'].class
|
93
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
94
|
+
assert_equal DateTime, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
95
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
96
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
97
|
+
assert_equal DateTime, hash['array_property'].first['datetime_array'][0].class
|
98
|
+
assert_equal DateTime, hash[key_name].class
|
99
|
+
[200, {}, []]
|
100
|
+
}
|
101
|
+
|
102
|
+
@app = new_rack_app_with_lambda(check_parameter,
|
103
|
+
coerce_query_params: true,
|
104
|
+
coerce_recursive: true,
|
105
|
+
coerce_date_times: true,
|
106
|
+
schema: hyper_schema)
|
107
|
+
|
108
|
+
get "/search/apps", params
|
109
|
+
assert_equal 200, last_response.status
|
110
|
+
end
|
111
|
+
|
112
|
+
it "passes a nested object with coerce_recursive false" do
|
113
|
+
key_name = "update_time"
|
114
|
+
params = {
|
115
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
116
|
+
"query" => "cloudnasium",
|
117
|
+
"array_property" => ARRAY_PROPERTY
|
118
|
+
}
|
119
|
+
|
120
|
+
@app = new_rack_app(coerce_query_params: true, coerce_date_times: true, coerce_recursive: false, schema: hyper_schema)
|
121
|
+
|
122
|
+
get "/search/apps", params
|
123
|
+
assert_equal 400, last_response.status # schema expect integer but we don't convert string to integer, so 400
|
124
|
+
end
|
125
|
+
|
126
|
+
it "passes a nested object with coerce_recursive default(true)" do
|
127
|
+
key_name = "update_time"
|
128
|
+
params = {
|
129
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
130
|
+
"query" => "cloudnasium",
|
131
|
+
"array_property" => ARRAY_PROPERTY
|
132
|
+
}
|
133
|
+
|
134
|
+
@app = new_rack_app(coerce_query_params: true, coerce_date_times: true, schema: hyper_schema)
|
135
|
+
|
136
|
+
get "/search/apps", params
|
137
|
+
assert_equal 200, last_response.status # schema expect integer but we don't convert string to integer, so 400
|
138
|
+
end
|
139
|
+
|
140
|
+
it "passes given a nested datetime and with coerce_recursive=true and coerce_date_times=true on POST endpoint" do
|
141
|
+
key_name = "update_time"
|
142
|
+
params = {
|
143
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
144
|
+
"array_property" => ARRAY_PROPERTY
|
145
|
+
}
|
146
|
+
|
147
|
+
check_parameter = lambda { |env|
|
148
|
+
hash = env['committee.params']
|
149
|
+
assert_equal DateTime, hash['array_property'].first['update_time'].class
|
150
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
151
|
+
assert_equal DateTime, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
152
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
153
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
154
|
+
assert_equal DateTime, hash['array_property'].first['datetime_array'][0].class
|
45
155
|
assert_equal DateTime, env['committee.params'][key_name].class
|
46
156
|
[200, {}, []]
|
47
157
|
}
|
48
158
|
|
49
|
-
@app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, schema: hyper_schema)
|
159
|
+
@app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, coerce_recursive: true, schema: hyper_schema)
|
160
|
+
|
161
|
+
header "Content-Type", "application/json"
|
162
|
+
post "/apps", JSON.generate(params)
|
163
|
+
assert_equal 200, last_response.status
|
164
|
+
end
|
165
|
+
|
166
|
+
it "passes given a nested datetime and with coerce_recursive=true and coerce_date_times=true on POST endpoint" do
|
167
|
+
key_name = "update_time"
|
168
|
+
params = {
|
169
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
170
|
+
"array_property" => ARRAY_PROPERTY
|
171
|
+
}
|
172
|
+
|
173
|
+
check_parameter = lambda { |env|
|
174
|
+
hash = env['committee.params']
|
175
|
+
assert_equal String, hash['array_property'].first['update_time'].class
|
176
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
177
|
+
assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
178
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
179
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
180
|
+
assert_equal String, hash['array_property'].first['datetime_array'][0].class
|
181
|
+
assert_equal String, env['committee.params'][key_name].class
|
182
|
+
[200, {}, []]
|
183
|
+
}
|
184
|
+
|
185
|
+
@app = new_rack_app_with_lambda(check_parameter, schema: hyper_schema)
|
186
|
+
|
187
|
+
header "Content-Type", "application/json"
|
188
|
+
post "/apps", JSON.generate(params)
|
189
|
+
assert_equal 200, last_response.status
|
190
|
+
end
|
191
|
+
|
192
|
+
it "passes given a nested datetime and with coerce_recursive=false and coerce_date_times=true on POST endpoint" do
|
193
|
+
key_name = "update_time"
|
194
|
+
params = {
|
195
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
196
|
+
"array_property" => ARRAY_PROPERTY
|
197
|
+
}
|
198
|
+
|
199
|
+
check_parameter = lambda { |env|
|
200
|
+
hash = env['committee.params']
|
201
|
+
assert_equal String, hash['array_property'].first['update_time'].class
|
202
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
203
|
+
assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
204
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
205
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
206
|
+
assert_equal String, hash['array_property'].first['datetime_array'][0].class
|
207
|
+
assert_equal DateTime, env['committee.params'][key_name].class
|
208
|
+
[200, {}, []]
|
209
|
+
}
|
210
|
+
|
211
|
+
@app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, coerce_recursive: false, schema: hyper_schema)
|
212
|
+
|
213
|
+
header "Content-Type", "application/json"
|
214
|
+
post "/apps", JSON.generate(params)
|
215
|
+
assert_equal 200, last_response.status
|
216
|
+
end
|
217
|
+
|
218
|
+
it "passes given a nested datetime and with coerce_recursive=false and coerce_date_times=false on POST endpoint" do
|
219
|
+
key_name = "update_time"
|
220
|
+
params = {
|
221
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
222
|
+
"array_property" => ARRAY_PROPERTY
|
223
|
+
}
|
224
|
+
|
225
|
+
check_parameter = lambda { |env|
|
226
|
+
hash = env['committee.params']
|
227
|
+
assert_equal String, hash['array_property'].first['update_time'].class
|
228
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
229
|
+
assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
230
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
231
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
232
|
+
assert_equal String, hash['array_property'].first['datetime_array'][0].class
|
233
|
+
assert_equal String, env['committee.params'][key_name].class
|
234
|
+
[200, {}, []]
|
235
|
+
}
|
236
|
+
|
237
|
+
@app = new_rack_app_with_lambda(check_parameter, schema: hyper_schema)
|
50
238
|
|
51
239
|
header "Content-Type", "application/json"
|
52
240
|
post "/apps", JSON.generate(params)
|
@@ -153,7 +341,12 @@ describe Committee::Middleware::RequestValidation do
|
|
153
341
|
end
|
154
342
|
|
155
343
|
it "passes through a valid request for OpenAPI" do
|
156
|
-
|
344
|
+
check_parameter = lambda { |env|
|
345
|
+
assert_equal 3, env['rack.request.query_hash']['limit']
|
346
|
+
[200, {}, []]
|
347
|
+
}
|
348
|
+
|
349
|
+
@app = new_rack_app_with_lambda(check_parameter, schema: open_api_2_schema)
|
157
350
|
get "/api/pets?limit=3"
|
158
351
|
assert_equal 200, last_response.status
|
159
352
|
end
|
@@ -12,22 +12,100 @@ describe Committee::ParameterCoercer do
|
|
12
12
|
|
13
13
|
it "pass datetime string" do
|
14
14
|
params = { "update_time" => "2016-04-01T16:00:00.000+09:00"}
|
15
|
-
|
15
|
+
call(params, coerce_date_times: true)
|
16
16
|
|
17
|
-
assert_kind_of DateTime,
|
17
|
+
assert_kind_of DateTime, params["update_time"]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "don't change object type" do
|
21
|
+
params = HashLikeObject.new
|
22
|
+
params["update_time"] = "2016-04-01T16:00:00.000+09:00"
|
23
|
+
call(params, coerce_date_times: true)
|
24
|
+
|
25
|
+
assert_kind_of DateTime, params["update_time"]
|
26
|
+
assert_kind_of HashLikeObject, params
|
18
27
|
end
|
19
28
|
|
20
29
|
it "pass invalid datetime string, not convert" do
|
21
|
-
|
22
|
-
|
30
|
+
invalid_datetime = "llmfllmf"
|
31
|
+
params = { "update_time" => invalid_datetime}
|
32
|
+
call(params, coerce_date_times: true)
|
23
33
|
|
24
|
-
|
34
|
+
assert_equal invalid_datetime, params["update_time"]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "pass array property" do
|
38
|
+
params = {
|
39
|
+
"array_property" => [
|
40
|
+
{
|
41
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
42
|
+
"per_page" => 1,
|
43
|
+
"nested_coercer_object" => {
|
44
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
45
|
+
"threshold" => 1.5
|
46
|
+
},
|
47
|
+
"nested_no_coercer_object" => {
|
48
|
+
"per_page" => 1,
|
49
|
+
"threshold" => 1.5
|
50
|
+
},
|
51
|
+
"nested_coercer_array" => [
|
52
|
+
{
|
53
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
54
|
+
"threshold" => 1.5
|
55
|
+
}
|
56
|
+
],
|
57
|
+
"nested_no_coercer_array" => [
|
58
|
+
{
|
59
|
+
"per_page" => 1,
|
60
|
+
"threshold" => 1.5
|
61
|
+
}
|
62
|
+
]
|
63
|
+
},
|
64
|
+
{
|
65
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
66
|
+
"per_page" => 1,
|
67
|
+
"threshold" => 1.5
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"threshold" => 1.5,
|
71
|
+
"per_page" => 1
|
72
|
+
}
|
73
|
+
],
|
74
|
+
}
|
75
|
+
call(params, coerce_date_times: true, coerce_recursive: true)
|
76
|
+
|
77
|
+
first_data = params["array_property"][0]
|
78
|
+
assert_kind_of DateTime, first_data["update_time"]
|
79
|
+
assert_kind_of Integer, first_data["per_page"]
|
80
|
+
|
81
|
+
second_data = params["array_property"][1]
|
82
|
+
assert_kind_of DateTime, second_data["update_time"]
|
83
|
+
assert_kind_of Integer, second_data["per_page"]
|
84
|
+
assert_kind_of Float, second_data["threshold"]
|
85
|
+
|
86
|
+
third_data = params["array_property"][1]
|
87
|
+
assert_kind_of Integer, third_data["per_page"]
|
88
|
+
assert_kind_of Float, third_data["threshold"]
|
89
|
+
|
90
|
+
assert_kind_of DateTime, first_data["nested_coercer_object"]["update_time"]
|
91
|
+
assert_kind_of Float, first_data["nested_coercer_object"]["threshold"]
|
92
|
+
|
93
|
+
assert_kind_of Integer, first_data["nested_no_coercer_object"]["per_page"]
|
94
|
+
assert_kind_of Float, first_data["nested_no_coercer_object"]["threshold"]
|
95
|
+
|
96
|
+
assert_kind_of DateTime, first_data["nested_coercer_array"].first["update_time"]
|
97
|
+
assert_kind_of Float, first_data["nested_coercer_array"].first["threshold"]
|
98
|
+
|
99
|
+
assert_kind_of Integer, first_data["nested_no_coercer_array"].first["per_page"]
|
100
|
+
assert_kind_of Float, first_data["nested_no_coercer_array"].first["threshold"]
|
25
101
|
end
|
26
102
|
|
27
103
|
private
|
28
104
|
|
105
|
+
class HashLikeObject < Hash; end
|
106
|
+
|
29
107
|
def call(params, options={})
|
30
108
|
link = Committee::Drivers::HyperSchema::Link.new(@link)
|
31
|
-
Committee::ParameterCoercer.new(params, link.schema, options).call
|
109
|
+
Committee::ParameterCoercer.new(params, link.schema, options).call!
|
32
110
|
end
|
33
111
|
end
|
@@ -9,65 +9,122 @@ describe Committee::StringParamsCoercer do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it "doesn't coerce params not in the schema" do
|
12
|
-
|
13
|
-
assert_equal({}, call(data))
|
12
|
+
check_convert("onwer", "admin", "admin")
|
14
13
|
end
|
15
14
|
|
16
15
|
it "skips values for string param" do
|
17
|
-
|
18
|
-
assert_equal({}, call(data))
|
16
|
+
check_convert("name", "foo", "foo")
|
19
17
|
end
|
20
18
|
|
21
19
|
it "coerces valid values for boolean param" do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
data = {"deleted" => "1"}
|
27
|
-
assert_equal({"deleted" => true}, call(data))
|
28
|
-
data = {"deleted" => "0"}
|
29
|
-
assert_equal({"deleted" => false}, call(data))
|
20
|
+
check_convert("deleted", "true", true)
|
21
|
+
check_convert("deleted", "false", false)
|
22
|
+
check_convert("deleted", "1", true)
|
23
|
+
check_convert("deleted", "0", false)
|
30
24
|
end
|
31
25
|
|
32
26
|
it "skips invalid values for boolean param" do
|
33
|
-
|
34
|
-
assert_equal({}, call(data))
|
27
|
+
check_convert("deleted", "foo", "foo")
|
35
28
|
end
|
36
29
|
|
37
30
|
it "coerces valid values for integer param" do
|
38
|
-
|
39
|
-
assert_equal({"per_page" => 3}, call(data))
|
31
|
+
check_convert("per_page", "3", 3)
|
40
32
|
end
|
41
33
|
|
42
34
|
it "skips invalid values for integer param" do
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
assert_equal({}, call(data))
|
47
|
-
data = {"per_page" => ""}
|
48
|
-
assert_equal({}, call(data))
|
35
|
+
check_convert("per_page", "3.5", "3.5")
|
36
|
+
check_convert("per_page", "false", "false")
|
37
|
+
check_convert("per_page", "", "")
|
49
38
|
end
|
50
39
|
|
51
40
|
it "coerces valid values for number param" do
|
52
|
-
|
53
|
-
|
54
|
-
data = {"threshold" => "3.5"}
|
55
|
-
assert_equal({"threshold" => 3.5}, call(data))
|
41
|
+
check_convert("threshold", "3", 3.0)
|
42
|
+
check_convert("threshold", "3.5", 3.5)
|
56
43
|
end
|
57
44
|
|
58
45
|
it "skips invalid values for number param" do
|
59
|
-
|
60
|
-
assert_equal({}, call(data))
|
46
|
+
check_convert("threshold", "false", "false")
|
61
47
|
end
|
62
48
|
|
63
49
|
it "coerces valid values for null param" do
|
64
|
-
|
65
|
-
|
50
|
+
check_convert("threshold", "", nil)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "pass array property" do
|
54
|
+
params = {
|
55
|
+
"array_property" => [
|
56
|
+
{
|
57
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
58
|
+
"per_page" => "1",
|
59
|
+
"nested_coercer_object" => {
|
60
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
61
|
+
"threshold" => "1.5"
|
62
|
+
},
|
63
|
+
"nested_no_coercer_object" => {
|
64
|
+
"per_page" => "1",
|
65
|
+
"threshold" => "1.5"
|
66
|
+
},
|
67
|
+
"nested_coercer_array" => [
|
68
|
+
{
|
69
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
70
|
+
"threshold" => "1.5"
|
71
|
+
}
|
72
|
+
],
|
73
|
+
"nested_no_coercer_array" => [
|
74
|
+
{
|
75
|
+
"per_page" => "1",
|
76
|
+
"threshold" => "1.5"
|
77
|
+
}
|
78
|
+
]
|
79
|
+
},
|
80
|
+
{
|
81
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
82
|
+
"per_page" => "1",
|
83
|
+
"threshold" => "1.5"
|
84
|
+
},
|
85
|
+
{
|
86
|
+
"threshold" => "1.5",
|
87
|
+
"per_page" => "1"
|
88
|
+
}
|
89
|
+
],
|
90
|
+
}
|
91
|
+
call(params, coerce_recursive: true)
|
92
|
+
|
93
|
+
first_data = params["array_property"][0]
|
94
|
+
assert_kind_of String, first_data["update_time"]
|
95
|
+
assert_kind_of Integer, first_data["per_page"]
|
96
|
+
|
97
|
+
second_data = params["array_property"][1]
|
98
|
+
assert_kind_of String, second_data["update_time"]
|
99
|
+
assert_kind_of Integer, second_data["per_page"]
|
100
|
+
assert_kind_of Float, second_data["threshold"]
|
101
|
+
|
102
|
+
third_data = params["array_property"][1]
|
103
|
+
assert_kind_of Integer, third_data["per_page"]
|
104
|
+
assert_kind_of Float, third_data["threshold"]
|
105
|
+
|
106
|
+
assert_kind_of String, first_data["nested_coercer_object"]["update_time"]
|
107
|
+
assert_kind_of Float, first_data["nested_coercer_object"]["threshold"]
|
108
|
+
|
109
|
+
assert_kind_of Integer, first_data["nested_no_coercer_object"]["per_page"]
|
110
|
+
assert_kind_of Float, first_data["nested_no_coercer_object"]["threshold"]
|
111
|
+
|
112
|
+
assert_kind_of String, first_data["nested_coercer_array"].first["update_time"]
|
113
|
+
assert_kind_of Float, first_data["nested_coercer_array"].first["threshold"]
|
114
|
+
|
115
|
+
assert_kind_of Integer, first_data["nested_no_coercer_array"].first["per_page"]
|
116
|
+
assert_kind_of Float, first_data["nested_no_coercer_array"].first["threshold"]
|
66
117
|
end
|
67
118
|
|
68
119
|
private
|
69
120
|
|
70
|
-
def
|
71
|
-
|
121
|
+
def check_convert(key, before_value, after_value)
|
122
|
+
data = {key => before_value}
|
123
|
+
call(data)
|
124
|
+
assert_equal(data[key], after_value)
|
125
|
+
end
|
126
|
+
|
127
|
+
def call(data, options={})
|
128
|
+
Committee::StringParamsCoercer.new(data, @link.schema, options).call!
|
72
129
|
end
|
73
130
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: committee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandur
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-05
|
12
|
+
date: 2017-09-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json_schema
|
@@ -207,12 +207,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
207
207
|
version: '0'
|
208
208
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
209
209
|
requirements:
|
210
|
-
- - "
|
210
|
+
- - ">="
|
211
211
|
- !ruby/object:Gem::Version
|
212
|
-
version:
|
212
|
+
version: '0'
|
213
213
|
requirements: []
|
214
214
|
rubyforge_project:
|
215
|
-
rubygems_version: 2.
|
215
|
+
rubygems_version: 2.6.12
|
216
216
|
signing_key:
|
217
217
|
specification_version: 4
|
218
218
|
summary: A collection of Rack middleware to support JSON Schema.
|