committee 4.3.0 → 4.99.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/lib/committee/drivers/hyper_schema/schema.rb +2 -2
  3. data/lib/committee/drivers/open_api_2/driver.rb +0 -1
  4. data/lib/committee/drivers/open_api_2/schema.rb +2 -2
  5. data/lib/committee/drivers/open_api_3/schema.rb +2 -2
  6. data/lib/committee/drivers/schema.rb +1 -1
  7. data/lib/committee/middleware/base.rb +1 -1
  8. data/lib/committee/middleware/request_validation.rb +0 -3
  9. data/lib/committee/middleware/response_validation.rb +4 -0
  10. data/lib/committee/request_unpacker.rb +46 -60
  11. data/lib/committee/schema_validator/hyper_schema.rb +33 -26
  12. data/lib/committee/schema_validator/open_api_3.rb +34 -20
  13. data/lib/committee/schema_validator/option.rb +26 -5
  14. data/lib/committee/test/methods.rb +11 -4
  15. data/lib/committee/utils.rb +28 -0
  16. data/lib/committee.rb +1 -0
  17. data/test/drivers_test.rb +1 -1
  18. data/test/middleware/request_validation_open_api_3_test.rb +149 -6
  19. data/test/middleware/request_validation_test.rb +13 -0
  20. data/test/middleware/response_validation_open_api_3_test.rb +2 -2
  21. data/test/middleware/response_validation_test.rb +8 -0
  22. data/test/request_unpacker_test.rb +35 -123
  23. data/test/schema_validator/hyper_schema/router_test.rb +2 -2
  24. data/test/schema_validator/open_api_3/operation_wrapper_test.rb +3 -3
  25. data/test/schema_validator/open_api_3/request_validator_test.rb +0 -3
  26. data/test/schema_validator/open_api_3/response_validator_test.rb +1 -1
  27. data/test/test/methods_new_version_test.rb +13 -4
  28. data/test/test/methods_test.rb +6 -4
  29. data/test/test_helper.rb +13 -1
  30. metadata +45 -10
@@ -34,11 +34,27 @@ describe Committee::Middleware::RequestValidation do
34
34
  params = { "datetime_string" => "2016-04-01T16:00:00.000+09:00" }
35
35
 
36
36
  check_parameter = lambda { |env|
37
+ assert_equal DateTime, env['committee.query_hash']["datetime_string"].class
38
+ assert_equal String, env['rack.request.query_hash']["datetime_string"].class
39
+ [200, {}, []]
40
+ }
41
+
42
+ @app = new_rack_app_with_lambda(check_parameter, schema: open_api_3_schema, coerce_date_times: true, query_hash_key: "committee.query_hash")
43
+
44
+ get "/string_params_coercer", params
45
+ assert_equal 200, last_response.status
46
+ end
47
+
48
+ it "passes given a datetime and with coerce_date_times enabled on GET endpoint overwrite query_hash" do
49
+ params = { "datetime_string" => "2016-04-01T16:00:00.000+09:00" }
50
+
51
+ check_parameter = lambda { |env|
52
+ assert_equal nil, env['committee.query_hash']
37
53
  assert_equal DateTime, env['rack.request.query_hash']["datetime_string"].class
38
54
  [200, {}, []]
39
55
  }
40
56
 
41
- @app = new_rack_app_with_lambda(check_parameter, schema: open_api_3_schema, coerce_date_times: true)
57
+ @app = new_rack_app_with_lambda(check_parameter, schema: open_api_3_schema, coerce_date_times: true, query_hash_key: "rack.request.query_hash")
42
58
 
43
59
  get "/string_params_coercer", params
44
60
  assert_equal 200, last_response.status
@@ -154,7 +170,8 @@ describe Committee::Middleware::RequestValidation do
154
170
  }
155
171
 
156
172
  check_parameter = lambda { |env|
157
- hash = env['rack.request.query_hash']
173
+ # hash = env["committee.query_hash"] # 5.0.x-
174
+ hash = env["rack.request.query_hash"]
158
175
  assert_equal DateTime, hash['nested_array'].first['update_time'].class
159
176
  assert_equal 1, hash['nested_array'].first['per_page']
160
177
 
@@ -331,7 +348,7 @@ describe Committee::Middleware::RequestValidation do
331
348
  get "/coerce_path_params/#{not_an_integer}", nil
332
349
  end
333
350
 
334
- assert_match(/expected integer, but received String: abc/i, e.message)
351
+ assert_match(/expected integer, but received String: \"abc\"/i, e.message)
335
352
  end
336
353
 
337
354
  it "optionally raises an error" do
@@ -360,7 +377,8 @@ describe Committee::Middleware::RequestValidation do
360
377
 
361
378
  it "passes through a valid request for OpenAPI3" do
362
379
  check_parameter = lambda { |env|
363
- assert_equal 3, env['rack.request.query_hash']['limit']
380
+ # assert_equal 3, env['committee.query_hash']['limit'] #5.0.x-
381
+ assert_equal 3, env['rack.request.query_hash']['limit'] #5.0.x-
364
382
  [200, {}, []]
365
383
  }
366
384
 
@@ -374,7 +392,7 @@ describe Committee::Middleware::RequestValidation do
374
392
  get "/characters?limit=foo"
375
393
 
376
394
  assert_equal 400, last_response.status
377
- assert_match(/expected integer, but received String: foo/i, last_response.body)
395
+ assert_match(/expected integer, but received String: \\"foo\\"/i, last_response.body)
378
396
  end
379
397
 
380
398
  it "ignores errors when ignore_error: true" do
@@ -394,6 +412,131 @@ describe Committee::Middleware::RequestValidation do
394
412
  get "/coerce_path_params/1"
395
413
  end
396
414
 
415
+ describe "overwrite same parameter (old rule)" do
416
+ # (high priority) path_hash_key -> request_body_hash -> query_param
417
+ it "set query parameter to committee.params and query hash" do
418
+ @app = new_rack_app_with_lambda(lambda do |env|
419
+ assert_equal env['committee.params']['integer'], 42
420
+ assert_equal env['committee.params'][:integer], 42
421
+ assert_equal env['rack.request.query_hash']['integer'], 42
422
+ #assert_equal env['rack.request.query_hash'][:integer], 42 # this isn't hash indifferent hash because we use rack.request.query_hash
423
+ [204, {}, []]
424
+ end, schema: open_api_3_schema)
425
+
426
+ header "Content-Type", "application/json"
427
+ post '/overwrite_same_parameter?integer=42'
428
+ assert_equal 204, last_response.status
429
+ end
430
+
431
+ it "request body precedence over query parameter" do
432
+ @app = new_rack_app_with_lambda(lambda do |env|
433
+ assert_equal env['committee.params']['integer'], 21
434
+ assert_equal env['committee.params'][:integer], 21
435
+ assert_equal env['committee.request_body_hash']['integer'], 21
436
+ assert_equal env['committee.request_body_hash'][:integer], 21
437
+ assert_equal env['rack.request.query_hash']['integer'], 21 # we can't use query_parameter :(
438
+ #assert_equal env['rack.request.query_hash'][:integer], 21 # this isn't hash indifferent hash because we use rack.request.query_hash
439
+ [204, {}, []]
440
+ end, schema: open_api_3_schema)
441
+
442
+ params = {integer: 21}
443
+
444
+ header "Content-Type", "application/json"
445
+ post '/overwrite_same_parameter?integer=42', JSON.generate(params)
446
+ assert_equal 204, last_response.status
447
+ end
448
+
449
+ it "path parameter precedence over request body" do
450
+ @app = new_rack_app_with_lambda(lambda do |env|
451
+ assert_equal env['committee.params']['integer'], 84
452
+ assert_equal env['committee.params'][:integer], 84
453
+ assert_equal env['committee.path_hash']['integer'], 84
454
+ assert_equal env['committee.path_hash'][:integer], 84
455
+ assert_equal env['committee.request_body_hash']['integer'], 21
456
+ assert_equal env['committee.request_body_hash'][:integer], 21
457
+ assert_equal env['rack.request.query_hash']['integer'], 84 # we can't use query_parameter :(
458
+ #assert_equal env['rack.request.query_hash'][:integer], 21 # this isn't hash indifferent hash because we use rack.request.query_hash
459
+ [204, {}, []]
460
+ end, schema: open_api_3_schema)
461
+
462
+ params = {integer: 21}
463
+
464
+ header "Content-Type", "application/json"
465
+ post '/overwrite_same_parameter/84?integer=42', JSON.generate(params)
466
+ assert_equal 204, last_response.status
467
+ end
468
+ end
469
+
470
+ describe "overwrite same parameter (new rule and seme to Rails)" do
471
+ # (high priority) path_hash_key -> query_param -> request_body_hash
472
+ it "set request body to committee.params and query hash" do
473
+ @app = new_rack_app_with_lambda(lambda do |env|
474
+ assert_equal env['committee.params']['integer'], 21
475
+ assert_equal env['committee.params'][:integer], 21
476
+ assert_equal env['committee.request_body_hash']['integer'], 21
477
+ assert_equal env['committee.request_body_hash'][:integer], 21
478
+ [204, {}, []]
479
+ end, schema: open_api_3_schema, parameter_overwite_by_rails_rule: true)
480
+
481
+ params = {integer: 21}
482
+
483
+ header "Content-Type", "application/json"
484
+ post '/overwrite_same_parameter', JSON.generate(params)
485
+ assert_equal 204, last_response.status
486
+ end
487
+
488
+ it "query parameter precedence over request body" do
489
+ @app = new_rack_app_with_lambda(lambda do |env|
490
+ assert_equal env['committee.params']['integer'], 42
491
+ assert_equal env['committee.params'][:integer], 42
492
+ assert_equal env['committee.request_body_hash']['integer'], 21
493
+ assert_equal env['committee.request_body_hash'][:integer], 21
494
+ assert_equal env['rack.request.query_hash']['integer'], 42 # we can't use query_parameter :(
495
+ [204, {}, []]
496
+ end, schema: open_api_3_schema, parameter_overwite_by_rails_rule: true)
497
+
498
+ params = {integer: 21}
499
+
500
+ header "Content-Type", "application/json"
501
+ post '/overwrite_same_parameter?integer=42', JSON.generate(params)
502
+ assert_equal 204, last_response.status
503
+ end
504
+
505
+ it "path path parameter precedence over query parameter" do
506
+ @app = new_rack_app_with_lambda(lambda do |env|
507
+ assert_equal env['committee.params']['integer'], 84
508
+ assert_equal env['committee.params'][:integer], 84
509
+ assert_equal env['committee.request_body_hash']['integer'], 21
510
+ assert_equal env['committee.request_body_hash'][:integer], 21
511
+ assert_equal env['rack.request.query_hash']['integer'], 84 # we can't use query_parameter :(
512
+ assert_equal env['committee.path_hash']['integer'], 84
513
+ assert_equal env['committee.path_hash'][:integer], 84
514
+ [204, {}, []]
515
+ end, schema: open_api_3_schema, parameter_overwite_by_rails_rule: true)
516
+
517
+ params = {integer: 21}
518
+
519
+ header "Content-Type", "application/json"
520
+ post '/overwrite_same_parameter/84?integer=42', JSON.generate(params)
521
+ assert_equal 204, last_response.status
522
+ end
523
+ end
524
+
525
+ it "unpacker test" do
526
+ @app = new_rack_app_with_lambda(lambda do |env|
527
+ assert_equal env['committee.params']['integer'], 42
528
+ assert_equal env['committee.params'][:integer], 42
529
+ # overwrite by request body...
530
+ assert_equal env['rack.request.query_hash']['integer'], 42
531
+ # assert_equal env['rack.request.query_hash'][:integer], 42
532
+ [204, {}, []]
533
+ end, schema: open_api_3_schema, raise: true)
534
+
535
+ header "Content-Type", "application/x-www-form-urlencoded"
536
+ post '/validate?integer=21', "integer=42"
537
+ assert_equal 204, last_response.status
538
+ end
539
+
397
540
  it "OpenAPI3 raise not support method" do
398
541
  @app = new_rack_app(schema: open_api_3_schema)
399
542
 
@@ -408,7 +551,7 @@ describe Committee::Middleware::RequestValidation do
408
551
  [
409
552
  { check_header: true, description: 'valid value', value: 1, expected: { status: 200 } },
410
553
  { check_header: true, description: 'missing value', value: nil, expected: { status: 400, error: 'missing required parameters: integer' } },
411
- { check_header: true, description: 'invalid value', value: 'x', expected: { status: 400, error: 'expected integer, but received String: x' } },
554
+ { check_header: true, description: 'invalid value', value: 'x', expected: { status: 400, error: 'expected integer, but received String: \\"x\\"' } },
412
555
 
413
556
  { check_header: false, description: 'valid value', value: 1, expected: { status: 200 } },
414
557
  { check_header: false, description: 'missing value', value: nil, expected: { status: 200 } },
@@ -435,6 +435,19 @@ describe Committee::Middleware::RequestValidation do
435
435
  assert_equal 200, last_response.status
436
436
  end
437
437
 
438
+ it "corce form params" do
439
+ check_parameter = lambda { |env|
440
+ assert_equal 3, env['committee.params']['age']
441
+ assert_equal 3, env['committee.request_body_hash']['age']
442
+ [200, {}, []]
443
+ }
444
+
445
+ @app = new_rack_app_with_lambda(check_parameter, schema: open_api_2_form_schema, raise: true, allow_form_params: true, coerce_form_params: true)
446
+ header "Content-Type", "application/x-www-form-urlencoded"
447
+ post "/api/pets", "age=3&name=ab"
448
+ assert_equal 200, last_response.status
449
+ end
450
+
438
451
  it "detects an invalid request for OpenAPI" do
439
452
  @app = new_rack_app(schema: open_api_2_schema)
440
453
  get "/api/pets?limit=foo", nil, { "HTTP_AUTH_TOKEN" => "xxx" }
@@ -125,7 +125,7 @@ describe Committee::Middleware::ResponseValidation do
125
125
  [
126
126
  { check_header: true, description: 'valid value', header: { 'integer' => 1 }, expected: { status: 200 } },
127
127
  { check_header: true, description: 'missing value', header: { 'integer' => nil }, expected: { error: 'headers/integer/schema does not allow null values' } },
128
- { check_header: true, description: 'invalid value', header: { 'integer' => 'x' }, expected: { error: 'headers/integer/schema expected integer, but received String: x' } },
128
+ { check_header: true, description: 'invalid value', header: { 'integer' => 'x' }, expected: { error: 'headers/integer/schema expected integer, but received String: "x"' } },
129
129
 
130
130
  { check_header: false, description: 'valid value', header: { 'integer' => 1 }, expected: { status: 200 } },
131
131
  { check_header: false, description: 'missing value', header: { 'integer' => nil }, expected: { status: 200 } },
@@ -177,7 +177,7 @@ describe Committee::Middleware::ResponseValidation do
177
177
  get "/characters"
178
178
  end
179
179
 
180
- assert_match(/but received String: 1/i, e.message)
180
+ assert_match(/but received String: \"1\"/i, e.message)
181
181
  end
182
182
 
183
183
  it "detects an invalid response status code with validate_success_only=true" do
@@ -15,6 +15,14 @@ describe Committee::Middleware::ResponseValidation do
15
15
  assert_equal 200, last_response.status
16
16
  end
17
17
 
18
+ # TODO: remove 5.0.0
19
+ it "passes through a valid response" do
20
+ # will show deprecated message
21
+ @app = new_rack_app(JSON.generate([ValidApp]), {}, schema: hyper_schema, strict: true)
22
+ get "/apps"
23
+ assert_equal 200, last_response.status
24
+ end
25
+
18
26
  it "doesn't call error_handler (has a arg) when response is valid" do
19
27
  called = false
20
28
  pr = ->(_e) { called = true }
@@ -9,8 +9,8 @@ describe Committee::RequestUnpacker do
9
9
  "rack.input" => StringIO.new('{"x":"y"}'),
10
10
  }
11
11
  request = Rack::Request.new(env)
12
- params, _ = Committee::RequestUnpacker.new(request).call
13
- assert_equal({ "x" => "y" }, params)
12
+ unpacker = Committee::RequestUnpacker.new
13
+ assert_equal([{ "x" => "y" }, false], unpacker.unpack_request_params(request))
14
14
  end
15
15
 
16
16
  it "unpacks JSON on Content-Type: application/vnd.api+json" do
@@ -19,8 +19,8 @@ describe Committee::RequestUnpacker do
19
19
  "rack.input" => StringIO.new('{"x":"y"}'),
20
20
  }
21
21
  request = Rack::Request.new(env)
22
- params, _ = Committee::RequestUnpacker.new(request).call
23
- assert_equal({ "x" => "y" }, params)
22
+ unpacker = Committee::RequestUnpacker.new
23
+ assert_equal([{ "x" => "y" }, false], unpacker.unpack_request_params(request))
24
24
  end
25
25
 
26
26
  it "unpacks JSON on no Content-Type" do
@@ -28,8 +28,8 @@ describe Committee::RequestUnpacker do
28
28
  "rack.input" => StringIO.new('{"x":"y"}'),
29
29
  }
30
30
  request = Rack::Request.new(env)
31
- params, _ = Committee::RequestUnpacker.new(request).call
32
- assert_equal({ "x" => "y" }, params)
31
+ unpacker = Committee::RequestUnpacker.new
32
+ assert_equal([{ "x" => "y" }, false], unpacker.unpack_request_params(request))
33
33
  end
34
34
 
35
35
  it "doesn't unpack JSON on application/x-ndjson" do
@@ -38,8 +38,8 @@ describe Committee::RequestUnpacker do
38
38
  "rack.input" => StringIO.new('{"x":"y"}\n{"a":"b"}'),
39
39
  }
40
40
  request = Rack::Request.new(env)
41
- params, _ = Committee::RequestUnpacker.new(request).call
42
- assert_equal({}, params)
41
+ unpacker = Committee::RequestUnpacker.new
42
+ assert_equal([{}, false], unpacker.unpack_request_params(request))
43
43
  end
44
44
 
45
45
  it "doesn't unpack JSON under other Content-Types" do
@@ -49,8 +49,8 @@ describe Committee::RequestUnpacker do
49
49
  "rack.input" => StringIO.new('{"x":"y"}'),
50
50
  }
51
51
  request = Rack::Request.new(env)
52
- params, _ = Committee::RequestUnpacker.new(request).call
53
- assert_equal({}, params)
52
+ unpacker = Committee::RequestUnpacker.new
53
+ assert_equal([{}, false], unpacker.unpack_request_params(request))
54
54
  end
55
55
  end
56
56
 
@@ -61,8 +61,8 @@ describe Committee::RequestUnpacker do
61
61
  "rack.input" => StringIO.new('{"x":"y"}'),
62
62
  }
63
63
  request = Rack::Request.new(env)
64
- params, _ = Committee::RequestUnpacker.new(request, optimistic_json: true).call
65
- assert_equal({ "x" => "y" }, params)
64
+ unpacker = Committee::RequestUnpacker.new(optimistic_json: true)
65
+ assert_equal([{ "x" => "y" }, false], unpacker.unpack_request_params(request))
66
66
  end
67
67
  end
68
68
 
@@ -73,8 +73,8 @@ describe Committee::RequestUnpacker do
73
73
  "rack.input" => StringIO.new('x=y&foo=42'),
74
74
  }
75
75
  request = Rack::Request.new(env)
76
- params, _ = Committee::RequestUnpacker.new(request, optimistic_json: true).call
77
- assert_equal({}, params)
76
+ unpacker = Committee::RequestUnpacker.new(optimistic_json: true)
77
+ assert_equal([{}, false], unpacker.unpack_request_params(request))
78
78
  end
79
79
  end
80
80
 
@@ -84,8 +84,8 @@ describe Committee::RequestUnpacker do
84
84
  "rack.input" => StringIO.new(""),
85
85
  }
86
86
  request = Rack::Request.new(env)
87
- params, _ = Committee::RequestUnpacker.new(request).call
88
- assert_equal({}, params)
87
+ unpacker = Committee::RequestUnpacker.new
88
+ assert_equal([{}, false], unpacker.unpack_request_params(request))
89
89
  end
90
90
 
91
91
  it "doesn't unpack form params" do
@@ -95,8 +95,8 @@ describe Committee::RequestUnpacker do
95
95
  "rack.input" => StringIO.new("x=y"),
96
96
  }
97
97
  request = Rack::Request.new(env)
98
- params, _ = Committee::RequestUnpacker.new(request).call
99
- assert_equal({}, params)
98
+ unpacker = Committee::RequestUnpacker.new
99
+ assert_equal([{}, false], unpacker.unpack_request_params(request))
100
100
  end
101
101
  end
102
102
 
@@ -107,96 +107,8 @@ describe Committee::RequestUnpacker do
107
107
  "rack.input" => StringIO.new("x=y"),
108
108
  }
109
109
  request = Rack::Request.new(env)
110
- params, _ = Committee::RequestUnpacker.new(request, allow_form_params: true).call
111
- assert_equal({ "x" => "y" }, params)
112
- end
113
- end
114
-
115
- it "coerces form params with coerce_form_params and a schema" do
116
- %w[application/x-www-form-urlencoded multipart/form-data].each do |content_type|
117
- env = {
118
- "CONTENT_TYPE" => content_type,
119
- "rack.input" => StringIO.new("x=1"),
120
- }
121
- request = Rack::Request.new(env)
122
-
123
- options = {}
124
- # TODO: delete when 5.0.0 released because default value changed
125
- options[:parse_response_by_content_type] = false
126
- router = hyper_schema.build_router(options)
127
- validator = router.build_schema_validator(request)
128
-
129
- schema = JsonSchema::Schema.new
130
- schema.properties = { "x" => JsonSchema::Schema.new }
131
- schema.properties["x"].type = ["integer"]
132
-
133
- link_class = Struct.new(:schema)
134
- link_object = link_class.new(schema)
135
-
136
- validator.instance_variable_set(:@link, link_object)
137
-
138
- params, _ = Committee::RequestUnpacker.new(
139
- request,
140
- allow_form_params: true,
141
- coerce_form_params: true,
142
- schema_validator: validator,
143
- ).call
144
- assert_equal({ "x" => 1 }, params)
145
- end
146
- end
147
-
148
- it "coerces form params with coerce_form_params and an OpenAPI3 schema" do
149
- %w[application/x-www-form-urlencoded multipart/form-data].each do |content_type|
150
- env = {
151
- "CONTENT_TYPE" => content_type,
152
- "rack.input" => StringIO.new("limit=20"),
153
- "PATH_INFO" => "/characters",
154
- "SCRIPT_NAME" => "",
155
- "REQUEST_METHOD" => "GET",
156
- }
157
- request = Rack::Request.new(env)
158
-
159
- options = {}
160
- # TODO: delete when 5.0.0 released because default value changed
161
- options[:parse_response_by_content_type] = false
162
- router = open_api_3_schema.build_router(options)
163
- validator = router.build_schema_validator(request)
164
-
165
- params, _ = Committee::RequestUnpacker.new(
166
- request,
167
- allow_form_params: true,
168
- coerce_form_params: true,
169
- schema_validator: validator,
170
- ).call
171
- # openapi3 not support coerce in request unpacker
172
- assert_equal({ "limit" => '20' }, params)
173
- end
174
- end
175
-
176
- it "coerces error params with coerce_form_params and a OpenAPI3 schema" do
177
- %w[application/x-www-form-urlencoded multipart/form-data].each do |content_type|
178
- env = {
179
- "CONTENT_TYPE" => content_type,
180
- "rack.input" => StringIO.new("limit=twenty"),
181
- "PATH_INFO" => "/characters",
182
- "SCRIPT_NAME" => "",
183
- "REQUEST_METHOD" => "GET",
184
- }
185
- request = Rack::Request.new(env)
186
-
187
- options = {}
188
- # TODO: delete when 5.0.0 released because default value changed
189
- options[:parse_response_by_content_type] = false
190
- router = open_api_3_schema.build_router(options)
191
- validator = router.build_schema_validator(request)
192
-
193
- params, _ = Committee::RequestUnpacker.new(
194
- request,
195
- allow_form_params: true,
196
- coerce_form_params: true,
197
- schema_validator: validator,
198
- ).call
199
- assert_equal({ "limit" => "twenty" }, params)
110
+ unpacker = Committee::RequestUnpacker.new(allow_form_params: true)
111
+ assert_equal([{ "x" => "y" }, true], unpacker.unpack_request_params(request))
200
112
  end
201
113
  end
202
114
 
@@ -208,8 +120,8 @@ describe Committee::RequestUnpacker do
208
120
  "QUERY_STRING" => "a=b"
209
121
  }
210
122
  request = Rack::Request.new(env)
211
- params, _ = Committee::RequestUnpacker.new(request, allow_form_params: true, allow_query_params: true).call
212
- assert_equal({ "x" => "y", "a" => "b" }, params)
123
+ unpacker = Committee::RequestUnpacker.new(allow_form_params: true, allow_query_params: true)
124
+ assert_equal([ { "x" => "y"}, true], unpacker.unpack_request_params(request))
213
125
  end
214
126
  end
215
127
 
@@ -219,8 +131,8 @@ describe Committee::RequestUnpacker do
219
131
  "QUERY_STRING" => "a=b"
220
132
  }
221
133
  request = Rack::Request.new(env)
222
- params, _ = Committee::RequestUnpacker.new(request, allow_query_params: true).call
223
- assert_equal({ "a" => "b" }, params)
134
+ unpacker = Committee::RequestUnpacker.new(allow_query_params: true)
135
+ assert_equal({ "a" => "b" }, unpacker.unpack_query_params(request))
224
136
  end
225
137
 
226
138
  it "errors if JSON is not an object" do
@@ -230,7 +142,7 @@ describe Committee::RequestUnpacker do
230
142
  }
231
143
  request = Rack::Request.new(env)
232
144
  assert_raises(Committee::BadRequest) do
233
- Committee::RequestUnpacker.new(request).call
145
+ Committee::RequestUnpacker.new.unpack_request_params(request)
234
146
  end
235
147
  end
236
148
 
@@ -240,8 +152,8 @@ describe Committee::RequestUnpacker do
240
152
  "rack.input" => StringIO.new('{"x":"y"}'),
241
153
  }
242
154
  request = Rack::Request.new(env)
243
- params, _ = Committee::RequestUnpacker.new(request).call
244
- assert_equal({}, params)
155
+ unpacker = Committee::RequestUnpacker.new
156
+ assert_equal([{}, false], unpacker.unpack_request_params(request))
245
157
  end
246
158
 
247
159
  # this is mostly here for line coverage
@@ -250,8 +162,8 @@ describe Committee::RequestUnpacker do
250
162
  "rack.input" => StringIO.new('{"x":[]}'),
251
163
  }
252
164
  request = Rack::Request.new(env)
253
- params, _ = Committee::RequestUnpacker.new(request).call
254
- assert_equal({ "x" => [] }, params)
165
+ unpacker = Committee::RequestUnpacker.new
166
+ assert_equal([{ "x" => [] }, false], unpacker.unpack_request_params(request))
255
167
  end
256
168
 
257
169
  it "unpacks http header" do
@@ -260,8 +172,8 @@ describe Committee::RequestUnpacker do
260
172
  "rack.input" => StringIO.new(""),
261
173
  }
262
174
  request = Rack::Request.new(env)
263
- _, headers = Committee::RequestUnpacker.new(request, { allow_header_params: true }).call
264
- assert_equal({ "FOO-BAR" => "some header value" }, headers)
175
+ unpacker = Committee::RequestUnpacker.new({ allow_header_params: true })
176
+ assert_equal({ "FOO-BAR" => "some header value" }, unpacker.unpack_headers(request))
265
177
  end
266
178
 
267
179
  it "includes request body when`use_get_body` is true" do
@@ -271,8 +183,8 @@ describe Committee::RequestUnpacker do
271
183
  "QUERY_STRING"=>"data=value&x=aaa",
272
184
  }
273
185
  request = Rack::Request.new(env)
274
- params, _ = Committee::RequestUnpacker.new(request, { allow_query_params: true, allow_get_body: true }).call
275
- assert_equal({ 'data' => 'value', 'x' => 1, 'y' => 2 }, params)
186
+ unpacker = Committee::RequestUnpacker.new({ allow_query_params: true, allow_get_body: true })
187
+ assert_equal([{ 'x' => 1, 'y' => 2 }, false], unpacker.unpack_request_params(request))
276
188
  end
277
189
 
278
190
  it "doesn't include request body when `use_get_body` is false" do
@@ -282,7 +194,7 @@ describe Committee::RequestUnpacker do
282
194
  "QUERY_STRING"=>"data=value&x=aaa",
283
195
  }
284
196
  request = Rack::Request.new(env)
285
- params, _ = Committee::RequestUnpacker.new(request, { allow_query_params: true, use_get_body: false }).call
286
- assert_equal({ 'data' => 'value', 'x' => 'aaa' }, params)
197
+ unpacker = Committee::RequestUnpacker.new({ allow_query_params: true, use_get_body: false })
198
+ assert_equal({ 'data' => 'value', 'x' => 'aaa' }, unpacker.unpack_query_params(request))
287
199
  end
288
200
  end
@@ -72,7 +72,7 @@ describe Committee::SchemaValidator::HyperSchema::Router do
72
72
  # TODO: delete when 5.0.0 released because default value changed
73
73
  options[:parse_response_by_content_type] = true if options[:parse_response_by_content_type] == nil
74
74
  schema = Committee::Drivers::HyperSchema::Driver.new.parse(hyper_schema_data)
75
- validator_option = Committee::SchemaValidator::Option.new(options, schema, :hyper_schema)
75
+ validator_option = Committee::SchemaValidator::Option.new(options, schema, :hyper_schema, true)
76
76
 
77
77
  Committee::SchemaValidator::HyperSchema::Router.new(schema, validator_option)
78
78
  end
@@ -81,7 +81,7 @@ describe Committee::SchemaValidator::HyperSchema::Router do
81
81
  # TODO: delete when 5.0.0 released because default value changed
82
82
  options[:parse_response_by_content_type] = true if options[:parse_response_by_content_type] == nil
83
83
  schema = Committee::Drivers::OpenAPI2::Driver.new.parse(open_api_2_data)
84
- validator_option = Committee::SchemaValidator::Option.new(options, schema, :hyper_schema)
84
+ validator_option = Committee::SchemaValidator::Option.new(options, schema, :hyper_schema, true)
85
85
 
86
86
  Committee::SchemaValidator::HyperSchema::Router.new(schema, validator_option)
87
87
  end
@@ -14,7 +14,7 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
14
14
  options = {}
15
15
  options[:parse_response_by_content_type] = true if options[:parse_response_by_content_type] == nil
16
16
 
17
- @validator_option = Committee::SchemaValidator::Option.new(options, open_api_3_schema, :open_api_3)
17
+ @validator_option = Committee::SchemaValidator::Option.new(options, open_api_3_schema, :open_api_3, true)
18
18
  end
19
19
 
20
20
  def operation_object
@@ -81,7 +81,7 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
81
81
  operation_object.validate_request_params({"integer" => "str"}, HEADER, @validator_option)
82
82
  }
83
83
 
84
- assert_match(/expected integer, but received String: str/i, e.message)
84
+ assert_match(/expected integer, but received String: "str"/i, e.message)
85
85
  assert_kind_of(OpenAPIParser::OpenAPIError, e.original_error)
86
86
  end
87
87
 
@@ -150,7 +150,7 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
150
150
  operation_object.validate_request_params({"limit" => "a"}, HEADER, @validator_option)
151
151
  }
152
152
 
153
- assert_match(/expected integer, but received String: a/i, e.message)
153
+ assert_match(/expected integer, but received String: "a"/i, e.message)
154
154
  assert_kind_of(OpenAPIParser::OpenAPIError, e.original_error)
155
155
  end
156
156
  end
@@ -72,9 +72,6 @@ describe Committee::SchemaValidator::OpenAPI3::RequestValidator do
72
72
  end
73
73
 
74
74
  def new_rack_app(options = {})
75
- # TODO: delete when 5.0.0 released because default value changed
76
- options[:parse_response_by_content_type] = true if options[:parse_response_by_content_type] == nil
77
-
78
75
  Rack::Builder.new {
79
76
  use Committee::Middleware::RequestValidation, options
80
77
  run lambda { |_|
@@ -17,7 +17,7 @@ describe Committee::SchemaValidator::OpenAPI3::ResponseValidator do
17
17
  options = {}
18
18
  options[:parse_response_by_content_type] = true if options[:parse_response_by_content_type] == nil
19
19
 
20
- @validator_option = Committee::SchemaValidator::Option.new(options, open_api_3_schema, :open_api_3)
20
+ @validator_option = Committee::SchemaValidator::Option.new(options, open_api_3_schema, :open_api_3, false)
21
21
  end
22
22
 
23
23
  it "passes through a valid response" do
@@ -39,7 +39,7 @@ describe Committee::Test::Methods do
39
39
  it "passes through a valid response" do
40
40
  @app = new_rack_app(JSON.generate([ValidApp]))
41
41
  get "/apps"
42
- assert_schema_conform
42
+ assert_schema_conform(200)
43
43
  end
44
44
 
45
45
  it "passes with prefix" do
@@ -47,18 +47,27 @@ describe Committee::Test::Methods do
47
47
 
48
48
  @app = new_rack_app(JSON.generate([ValidApp]))
49
49
  get "/v1/apps"
50
- assert_schema_conform
50
+ assert_schema_conform(200)
51
51
  end
52
52
 
53
53
  it "detects an invalid response Content-Type" do
54
54
  @app = new_rack_app(JSON.generate([ValidApp]), 200, {})
55
55
  get "/apps"
56
56
  e = assert_raises(Committee::InvalidResponse) do
57
- assert_schema_conform
57
+ assert_schema_conform(200)
58
58
  end
59
59
  assert_match(/response header must be set to/i, e.message)
60
60
  end
61
61
 
62
+ it "it detects unexpected response code" do
63
+ @app = new_rack_app(JSON.generate([ValidApp]), 400)
64
+ get "/apps"
65
+ e = assert_raises(Committee::InvalidResponse) do
66
+ assert_schema_conform(200)
67
+ end
68
+ assert_match(/Expected `200` status code, but it was `400`/i, e.message)
69
+ end
70
+
62
71
  it "detects an invalid response Content-Type but ignore because it's not success status code" do
63
72
  @committee_options.merge!(validate_success_only: true)
64
73
  @app = new_rack_app(JSON.generate([ValidApp]), 400, {})
@@ -70,7 +79,7 @@ describe Committee::Test::Methods do
70
79
  @app = new_rack_app(JSON.generate([ValidApp]), 400, {})
71
80
  get "/apps"
72
81
  e = assert_raises(Committee::InvalidResponse) do
73
- assert_schema_conform
82
+ assert_schema_conform(400)
74
83
  end
75
84
  assert_match(/response header must be set to/i, e.message)
76
85
  end