committee 5.6.1 → 5.6.2

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/lib/committee/drivers/open_api_3/driver.rb +5 -0
  3. data/lib/committee/drivers.rb +2 -3
  4. data/lib/committee/errors.rb +11 -0
  5. data/lib/committee/middleware/base.rb +11 -5
  6. data/lib/committee/middleware/options/base.rb +107 -0
  7. data/lib/committee/middleware/options/request_validation.rb +80 -0
  8. data/lib/committee/middleware/options/response_validation.rb +46 -0
  9. data/lib/committee/middleware/options.rb +12 -0
  10. data/lib/committee/middleware/request_validation.rb +7 -1
  11. data/lib/committee/middleware/response_validation.rb +6 -2
  12. data/lib/committee/middleware.rb +1 -0
  13. data/lib/committee/schema_validator/hyper_schema/response_generator.rb +1 -3
  14. data/lib/committee/schema_validator/hyper_schema/response_validator.rb +14 -1
  15. data/lib/committee/schema_validator/hyper_schema/router.rb +1 -1
  16. data/lib/committee/schema_validator/hyper_schema.rb +2 -13
  17. data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +43 -13
  18. data/lib/committee/schema_validator/open_api_3/parameter_deserializer.rb +495 -0
  19. data/lib/committee/schema_validator/open_api_3/response_validator.rb +16 -2
  20. data/lib/committee/schema_validator/open_api_3.rb +18 -12
  21. data/lib/committee/schema_validator/option.rb +6 -17
  22. data/lib/committee/schema_validator.rb +5 -1
  23. data/lib/committee/test/except_parameter.rb +416 -0
  24. data/lib/committee/test/methods.rb +27 -2
  25. data/lib/committee/version.rb +1 -1
  26. data/lib/committee.rb +1 -1
  27. data/test/drivers/open_api_2/driver_test.rb +4 -16
  28. data/test/drivers/open_api_2/parameter_schema_builder_test.rb +4 -50
  29. data/test/drivers_test.rb +35 -21
  30. data/test/middleware/options/base_test.rb +120 -0
  31. data/test/middleware/options/request_validation_test.rb +177 -0
  32. data/test/middleware/options/response_validation_test.rb +121 -0
  33. data/test/middleware/request_validation_open_api_3_test.rb +113 -80
  34. data/test/middleware/request_validation_test.rb +13 -70
  35. data/test/middleware/response_validation_open_api_3_test.rb +33 -17
  36. data/test/middleware/response_validation_test.rb +3 -14
  37. data/test/request_unpacker_test.rb +2 -10
  38. data/test/schema_validator/hyper_schema/parameter_coercer_test.rb +1 -37
  39. data/test/schema_validator/hyper_schema/request_validator_test.rb +6 -30
  40. data/test/schema_validator/hyper_schema/router_test.rb +5 -0
  41. data/test/schema_validator/hyper_schema/string_params_coercer_test.rb +1 -37
  42. data/test/schema_validator/open_api_3/operation_wrapper_test.rb +40 -43
  43. data/test/schema_validator/open_api_3/parameter_deserializer_test.rb +457 -0
  44. data/test/schema_validator/open_api_3/request_validator_test.rb +1 -2
  45. data/test/schema_validator/open_api_3/response_validator_test.rb +3 -11
  46. data/test/schema_validator_test.rb +8 -0
  47. data/test/test/methods_test.rb +222 -105
  48. data/test/test/schema_coverage_test.rb +8 -155
  49. metadata +12 -2
@@ -84,42 +84,14 @@ describe Committee::Middleware::RequestValidation do
84
84
  [200, {}, []]
85
85
  }
86
86
 
87
- @app = new_rack_app_with_lambda(check_parameter,
88
- schema: open_api_3_schema,
89
- coerce_date_times: true,
90
- allow_get_body: true)
87
+ @app = new_rack_app_with_lambda(check_parameter, schema: open_api_3_schema, coerce_date_times: true, allow_get_body: true)
91
88
 
92
89
  get "/string_params_coercer", { no_problem: true }, { input: params.to_json }
93
90
  assert_equal 200, last_response.status
94
91
  end
95
92
 
96
93
  it "passes given a datetime and with coerce_date_times enabled on POST endpoint" do
97
- params = {
98
- "nested_array" => [
99
- {
100
- "update_time" => "2016-04-01T16:00:00.000+09:00",
101
- "nested_coercer_object" => {
102
- "update_time" => "2016-04-01T16:00:00.000+09:00",
103
- },
104
- "nested_no_coercer_object" => {
105
- "update_time" => "2016-04-01T16:00:00.000+09:00",
106
- },
107
- "nested_coercer_array" => [
108
- {
109
- "update_time" => "2016-04-01T16:00:00.000+09:00",
110
- }
111
- ],
112
- "nested_no_coercer_array" => [
113
- {
114
- "update_time" => "2016-04-01T16:00:00.000+09:00",
115
- }
116
- ]
117
- },
118
- {
119
- "update_time" => "2016-04-01T16:00:00.000+09:00",
120
- }
121
- ]
122
- }
94
+ params = { "nested_array" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", "nested_coercer_object" => { "update_time" => "2016-04-01T16:00:00.000+09:00", }, "nested_no_coercer_object" => { "update_time" => "2016-04-01T16:00:00.000+09:00", }, "nested_coercer_array" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", }], "nested_no_coercer_array" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", }] }, { "update_time" => "2016-04-01T16:00:00.000+09:00", }] }
123
95
 
124
96
  check_parameter = lambda { |env|
125
97
  nested_array = env['committee.params']["nested_array"]
@@ -166,11 +138,7 @@ describe Committee::Middleware::RequestValidation do
166
138
  [200, {}, []]
167
139
  }
168
140
 
169
- @app = new_rack_app_with_lambda(check_parameter,
170
- coerce_query_params: true,
171
- coerce_recursive: true,
172
- coerce_date_times: true,
173
- schema: open_api_3_schema)
141
+ @app = new_rack_app_with_lambda(check_parameter, coerce_query_params: true, coerce_recursive: true, coerce_date_times: true, schema: open_api_3_schema)
174
142
 
175
143
  get "/string_params_coercer", params
176
144
 
@@ -178,51 +146,7 @@ describe Committee::Middleware::RequestValidation do
178
146
  end
179
147
 
180
148
  it "passes given a nested datetime and with coerce_recursive=true and coerce_date_times=true on POST endpoint" do
181
- params = {
182
- "nested_array" => [
183
- {
184
- "update_time" => "2016-04-01T16:00:00.000+09:00",
185
- "per_page" => 1,
186
- "nested_coercer_object" => {
187
- "update_time" => "2016-04-01T16:00:00.000+09:00",
188
- "threshold" => 1.5
189
- },
190
- "nested_no_coercer_object" => {
191
- "per_page" => 1,
192
- "threshold" => 1.5
193
- },
194
- "nested_coercer_array" => [
195
- {
196
- "update_time" => "2016-04-01T16:00:00.000+09:00",
197
- "threshold" => 1.5
198
- }
199
- ],
200
- "nested_no_coercer_array" => [
201
- {
202
- "per_page" => 1,
203
- "threshold" => 1.5
204
- }
205
- ],
206
- "integer_array" => [
207
- 1, 2, 3
208
- ],
209
- "datetime_array" => [
210
- "2016-04-01T16:00:00.000+09:00",
211
- "2016-04-01T17:00:00.000+09:00",
212
- "2016-04-01T18:00:00.000+09:00"
213
- ]
214
- },
215
- {
216
- "update_time" => "2016-04-01T16:00:00.000+09:00",
217
- "per_page" => 1,
218
- "threshold" => 1.5
219
- },
220
- {
221
- "threshold" => 1.5,
222
- "per_page" => 1
223
- }
224
- ]
225
- }
149
+ params = { "nested_array" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", "per_page" => 1, "nested_coercer_object" => { "update_time" => "2016-04-01T16:00:00.000+09:00", "threshold" => 1.5 }, "nested_no_coercer_object" => { "per_page" => 1, "threshold" => 1.5 }, "nested_coercer_array" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", "threshold" => 1.5 }], "nested_no_coercer_array" => [{ "per_page" => 1, "threshold" => 1.5 }], "integer_array" => [1, 2, 3], "datetime_array" => ["2016-04-01T16:00:00.000+09:00", "2016-04-01T17:00:00.000+09:00", "2016-04-01T18:00:00.000+09:00"] }, { "update_time" => "2016-04-01T16:00:00.000+09:00", "per_page" => 1, "threshold" => 1.5 }, { "threshold" => 1.5, "per_page" => 1 }] }
226
150
 
227
151
  check_parameter = lambda { |env|
228
152
  hash = env['committee.params']
@@ -330,6 +254,14 @@ describe Committee::Middleware::RequestValidation do
330
254
  assert_equal 200, last_response.status
331
255
  end
332
256
 
257
+ it "ignores similar prefix paths outside the prefix in strict mode" do
258
+ @app = new_rack_app(prefix: "/v1", schema: open_api_3_schema, strict: true)
259
+ params = { "string_post_1" => 1 }
260
+ header "Content-Type", "application/json"
261
+ post "/v11/characters", JSON.generate(params)
262
+ assert_equal 200, last_response.status
263
+ end
264
+
333
265
  it "don't check prefix with no option" do
334
266
  @app = new_rack_app(schema: open_api_3_schema)
335
267
  params = { "string_post_1" => 1 }
@@ -431,6 +363,26 @@ describe Committee::Middleware::RequestValidation do
431
363
  get "/coerce_path_params/1"
432
364
  end
433
365
 
366
+ it "coerces path params even when query param coercion is disabled" do
367
+ check_parameter_string = lambda { |env|
368
+ assert env['committee.path_hash']['integer'].is_a?(Integer)
369
+ assert env['committee.params']['integer'].is_a?(Integer)
370
+ [200, {}, []]
371
+ }
372
+
373
+ @app = new_rack_app_with_lambda(check_parameter_string, schema: open_api_3_schema, coerce_path_params: true, coerce_query_params: false)
374
+ get "/coerce_path_params/1"
375
+ assert_equal 200, last_response.status
376
+ end
377
+
378
+ it "does not coerce path params when path coercion is disabled even if query coercion is enabled" do
379
+ @app = new_rack_app(schema: open_api_3_schema, coerce_path_params: false, coerce_query_params: true)
380
+ get "/coerce_path_params/1"
381
+
382
+ assert_equal 400, last_response.status
383
+ assert_match(/integer/i, last_response.body)
384
+ end
385
+
434
386
  describe "overwrite same parameter (old rule)" do
435
387
  # (high priority) path_hash_key -> request_body_hash -> query_param
436
388
  it "set query parameter to committee.params and query hash" do
@@ -627,6 +579,87 @@ describe Committee::Middleware::RequestValidation do
627
579
  end
628
580
  end
629
581
 
582
+ describe ':strict_query_params option' do
583
+ it 'allows unknown query params when strict_query_params is false' do
584
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: false)
585
+ get "/characters", { limit: 10, unknown_param: "value" }
586
+ assert_equal 200, last_response.status
587
+ end
588
+
589
+ it 'rejects unknown query params when strict_query_params is true' do
590
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
591
+ get "/characters", { limit: 10, unknown_param: "value" }
592
+ assert_equal 400, last_response.status
593
+ assert_match(/unknown_param/, last_response.body)
594
+ end
595
+
596
+ it 'allows defined query params when strict_query_params is true' do
597
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
598
+ get "/characters", { limit: 10, school_name: "test" }
599
+ assert_equal 200, last_response.status
600
+ end
601
+
602
+ it 'handles empty query params when strict_query_params is true' do
603
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
604
+ get "/characters"
605
+ assert_equal 200, last_response.status
606
+ end
607
+
608
+ it 'rejects multiple unknown query params' do
609
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
610
+ get "/characters", { limit: 10, unknown1: "a", unknown2: "b" }
611
+ assert_equal 400, last_response.status
612
+ assert_match(/unknown1/, last_response.body)
613
+ assert_match(/unknown2/, last_response.body)
614
+ end
615
+
616
+ it 'allows partial query params (only some defined params)' do
617
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
618
+ get "/characters", { limit: 10 }
619
+ assert_equal 200, last_response.status
620
+ end
621
+
622
+ it 'works with POST requests that have query params' do
623
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
624
+ header "Content-Type", "application/json"
625
+ post "/additional_properties?first_name=test&unknown=value", JSON.generate(last_name: "test")
626
+ assert_equal 400, last_response.status
627
+ assert_match(/unknown/, last_response.body)
628
+ end
629
+
630
+ it 'allows defined query params in POST requests' do
631
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
632
+ header "Content-Type", "application/json"
633
+ post "/additional_properties?first_name=test", JSON.generate(last_name: "test")
634
+ assert_equal 200, last_response.status
635
+ end
636
+
637
+ it 'works with DELETE requests' do
638
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
639
+ delete "/characters?limit=10"
640
+ assert_equal 200, last_response.status
641
+ end
642
+
643
+ it 'rejects unknown query params in DELETE requests' do
644
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
645
+ delete "/characters?limit=10&unknown=value"
646
+ assert_equal 400, last_response.status
647
+ assert_match(/unknown/, last_response.body)
648
+ end
649
+
650
+ it 'works with HEAD requests' do
651
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
652
+ head "/characters?limit=10"
653
+ assert_equal 200, last_response.status
654
+ end
655
+
656
+ it 'rejects unknown query params in HEAD requests' do
657
+ @app = new_rack_app(schema: open_api_3_schema, strict_query_params: true)
658
+ head "/characters?limit=10&unknown=value"
659
+ assert_equal 400, last_response.status
660
+ end
661
+ end
662
+
630
663
  private
631
664
 
632
665
  def new_rack_app(options = {})
@@ -9,49 +9,7 @@ describe Committee::Middleware::RequestValidation do
9
9
  @app
10
10
  end
11
11
 
12
- ARRAY_PROPERTY = [
13
- {
14
- "update_time" => "2016-04-01T16:00:00.000+09:00",
15
- "per_page" => 1,
16
- "nested_coercer_object" => {
17
- "update_time" => "2016-04-01T16:00:00.000+09:00",
18
- "threshold" => 1.5
19
- },
20
- "nested_no_coercer_object" => {
21
- "per_page" => 1,
22
- "threshold" => 1.5
23
- },
24
- "nested_coercer_array" => [
25
- {
26
- "update_time" => "2016-04-01T16:00:00.000+09:00",
27
- "threshold" => 1.5
28
- }
29
- ],
30
- "nested_no_coercer_array" => [
31
- {
32
- "per_page" => 1,
33
- "threshold" => 1.5
34
- }
35
- ],
36
- "integer_array" => [
37
- 1, 2, 3
38
- ],
39
- "datetime_array" => [
40
- "2016-04-01T16:00:00.000+09:00",
41
- "2016-04-01T17:00:00.000+09:00",
42
- "2016-04-01T18:00:00.000+09:00"
43
- ]
44
- },
45
- {
46
- "update_time" => "2016-04-01T16:00:00.000+09:00",
47
- "per_page" => 1,
48
- "threshold" => 1.5
49
- },
50
- {
51
- "threshold" => 1.5,
52
- "per_page" => 1
53
- }
54
- ]
12
+ ARRAY_PROPERTY = [{ "update_time" => "2016-04-01T16:00:00.000+09:00", "per_page" => 1, "nested_coercer_object" => { "update_time" => "2016-04-01T16:00:00.000+09:00", "threshold" => 1.5 }, "nested_no_coercer_object" => { "per_page" => 1, "threshold" => 1.5 }, "nested_coercer_array" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", "threshold" => 1.5 }], "nested_no_coercer_array" => [{ "per_page" => 1, "threshold" => 1.5 }], "integer_array" => [1, 2, 3], "datetime_array" => ["2016-04-01T16:00:00.000+09:00", "2016-04-01T17:00:00.000+09:00", "2016-04-01T18:00:00.000+09:00"] }, { "update_time" => "2016-04-01T16:00:00.000+09:00", "per_page" => 1, "threshold" => 1.5 }, { "threshold" => 1.5, "per_page" => 1 }]
55
13
 
56
14
  it "passes through a valid request" do
57
15
  @app = new_rack_app(schema: hyper_schema)
@@ -98,11 +56,7 @@ describe Committee::Middleware::RequestValidation do
98
56
 
99
57
  it "passes a nested object with recursive option" do
100
58
  key_name = "update_time"
101
- params = {
102
- key_name => "2016-04-01T16:00:00.000+09:00",
103
- "query" => "cloudnasium",
104
- "array_property" => ARRAY_PROPERTY
105
- }
59
+ params = { key_name => "2016-04-01T16:00:00.000+09:00", "query" => "cloudnasium", "array_property" => ARRAY_PROPERTY }
106
60
 
107
61
  check_parameter = lambda { |env|
108
62
  hash = env['rack.request.query_hash']
@@ -116,11 +70,7 @@ describe Committee::Middleware::RequestValidation do
116
70
  [200, {}, []]
117
71
  }
118
72
 
119
- @app = new_rack_app_with_lambda(check_parameter,
120
- coerce_query_params: true,
121
- coerce_recursive: true,
122
- coerce_date_times: true,
123
- schema: hyper_schema)
73
+ @app = new_rack_app_with_lambda(check_parameter, coerce_query_params: true, coerce_recursive: true, coerce_date_times: true, schema: hyper_schema)
124
74
 
125
75
  get "/search/apps", params
126
76
  assert_equal 200, last_response.status
@@ -128,11 +78,7 @@ describe Committee::Middleware::RequestValidation do
128
78
 
129
79
  it "passes a nested object with coerce_recursive false" do
130
80
  key_name = "update_time"
131
- params = {
132
- key_name => "2016-04-01T16:00:00.000+09:00",
133
- "query" => "cloudnasium",
134
- "array_property" => ARRAY_PROPERTY
135
- }
81
+ params = { key_name => "2016-04-01T16:00:00.000+09:00", "query" => "cloudnasium", "array_property" => ARRAY_PROPERTY }
136
82
 
137
83
  @app = new_rack_app(coerce_query_params: true, coerce_date_times: true, coerce_recursive: false, schema: hyper_schema)
138
84
 
@@ -142,11 +88,7 @@ describe Committee::Middleware::RequestValidation do
142
88
 
143
89
  it "passes a nested object with coerce_recursive default(true)" do
144
90
  key_name = "update_time"
145
- params = {
146
- key_name => "2016-04-01T16:00:00.000+09:00",
147
- "query" => "cloudnasium",
148
- "array_property" => ARRAY_PROPERTY
149
- }
91
+ params = { key_name => "2016-04-01T16:00:00.000+09:00", "query" => "cloudnasium", "array_property" => ARRAY_PROPERTY }
150
92
 
151
93
  @app = new_rack_app(coerce_query_params: true, coerce_date_times: true, schema: hyper_schema)
152
94
 
@@ -321,6 +263,13 @@ describe Committee::Middleware::RequestValidation do
321
263
  assert_equal 200, last_response.status
322
264
  end
323
265
 
266
+ it "ignores similar prefix paths outside the prefix in strict mode" do
267
+ @app = new_rack_app(prefix: "/v1", schema: hyper_schema, strict: true)
268
+ header "Content-Type", "application/json"
269
+ post "/v11/apps", JSON.generate({ "name" => 1 })
270
+ assert_equal 200, last_response.status
271
+ end
272
+
324
273
  it "routes to paths not in schema" do
325
274
  @app = new_rack_app(schema: hyper_schema)
326
275
  get "/not-a-resource"
@@ -429,13 +378,7 @@ describe Committee::Middleware::RequestValidation do
429
378
  end
430
379
 
431
380
  it "not exist path and options" do
432
- options = {
433
- coerce_form_params: true,
434
- coerce_date_times: true,
435
- coerce_query_params: true,
436
- coerce_path_params: true,
437
- coerce_recursive: true
438
- }
381
+ options = { coerce_form_params: true, coerce_date_times: true, coerce_query_params: true, coerce_path_params: true, coerce_recursive: true }
439
382
 
440
383
  @app = new_rack_app({ schema: hyper_schema }.merge(options))
441
384
  header "Content-Type", "application/x-www-form-urlencoded"
@@ -187,12 +187,7 @@ describe Committee::Middleware::ResponseValidation do
187
187
 
188
188
  describe 'validate error option' do
189
189
  it "detects an invalid response status code" do
190
- @app = new_response_rack({ integer: '1' }.to_json,
191
- {},
192
- app_status: 400,
193
- schema: open_api_3_schema,
194
- raise: true,
195
- validate_success_only: false)
190
+ @app = new_response_rack({ integer: '1' }.to_json, {}, app_status: 400, schema: open_api_3_schema, raise: true, validate_success_only: false)
196
191
 
197
192
  e = assert_raises(Committee::InvalidResponse) do
198
193
  get "/characters"
@@ -202,12 +197,7 @@ describe Committee::Middleware::ResponseValidation do
202
197
  end
203
198
 
204
199
  it "detects an invalid response status code with validate_success_only=true" do
205
- @app = new_response_rack({ string_1: :honoka }.to_json,
206
- {},
207
- app_status: 400,
208
- schema: open_api_3_schema,
209
- raise: true,
210
- validate_success_only: true)
200
+ @app = new_response_rack({ string_1: :honoka }.to_json, {}, app_status: 400, schema: open_api_3_schema, raise: true, validate_success_only: true)
211
201
 
212
202
  get "/characters"
213
203
 
@@ -235,6 +225,36 @@ describe Committee::Middleware::ResponseValidation do
235
225
  end
236
226
  end
237
227
 
228
+ describe 'response type validation' do
229
+ it "detects string value for number field when coerce_response_values is false" do
230
+ @app = new_response_rack({ integer: '726' }.to_json, {}, app_status: 400, schema: open_api_3_schema, raise: true, validate_success_only: false, coerce_response_values: false)
231
+
232
+ e = assert_raises(Committee::InvalidResponse) do
233
+ get "/characters"
234
+ end
235
+
236
+ assert_match(/expected integer, but received String/i, e.message)
237
+ end
238
+
239
+ it "passes string value for number field when coerce_response_values is true" do
240
+ @app = new_response_rack({ integer: '726' }.to_json, {}, app_status: 400, schema: open_api_3_schema, raise: true, validate_success_only: false, coerce_response_values: true)
241
+
242
+ get "/characters"
243
+
244
+ assert_equal 400, last_response.status
245
+ end
246
+
247
+ it "detects string value for number field by default (coerce_response_values defaults to false)" do
248
+ @app = new_response_rack({ integer: '726' }.to_json, {}, app_status: 400, schema: open_api_3_schema, raise: true, validate_success_only: false)
249
+
250
+ e = assert_raises(Committee::InvalidResponse) do
251
+ get "/characters"
252
+ end
253
+
254
+ assert_match(/expected integer, but received String/i, e.message)
255
+ end
256
+ end
257
+
238
258
  it 'does not suppress application error' do
239
259
  @app = Rack::Builder.new {
240
260
  use Committee::Middleware::ResponseValidation, { schema: open_api_3_schema, raise: true }
@@ -269,11 +289,7 @@ describe Committee::Middleware::ResponseValidation do
269
289
  end
270
290
 
271
291
  it "strict and invalid content type with raise" do
272
- @app = new_response_rack("abc",
273
- {},
274
- { schema: open_api_3_schema, strict: true, raise: true },
275
- { content_type: 'application/text' }
276
- )
292
+ @app = new_response_rack("abc", {}, { schema: open_api_3_schema, strict: true, raise: true }, { content_type: 'application/text' })
277
293
 
278
294
  assert_raises(Committee::InvalidResponse) do
279
295
  get "/characters"
@@ -199,10 +199,7 @@ describe Committee::Middleware::ResponseValidation do
199
199
  describe 'streaming response' do
200
200
  describe "text/event-stream; e.g. server-sent events" do
201
201
  it 'validates the response stream as a string' do
202
- options = {
203
- schema: open_api_3_streaming_response_schema,
204
- streaming_content_parsers: { 'text/event-stream' => ->(body) { body } },
205
- }
202
+ options = { schema: open_api_3_streaming_response_schema, streaming_content_parsers: { 'text/event-stream' => ->(body) { body } }, }
206
203
  status = 200
207
204
  headers = { 'content-type' => 'text/event-stream' }
208
205
  @app = Rack::Builder.new {
@@ -221,11 +218,7 @@ describe Committee::Middleware::ResponseValidation do
221
218
  it "successfully validates the response as a special stream using a customized parser" do
222
219
  error_handler_called = false
223
220
  error_handler = ->(_e, _env) { error_handler_called = true }
224
- options = {
225
- schema: open_api_3_streaming_response_schema,
226
- streaming_content_parsers: { 'application/x-json-stream' => ->(body) { JSON.parse!(body) } },
227
- error_handler: error_handler,
228
- }
221
+ options = { schema: open_api_3_streaming_response_schema, streaming_content_parsers: { 'application/x-json-stream' => ->(body) { JSON.parse!(body) } }, error_handler: error_handler, }
229
222
  status = 200
230
223
  headers = { 'content-type' => 'application/x-json-stream' }
231
224
  @app = Rack::Builder.new {
@@ -243,11 +236,7 @@ describe Committee::Middleware::ResponseValidation do
243
236
  it "fails to validate the response as a special stream using a customized parser due to a schema mismatch" do
244
237
  error_handler_called = false
245
238
  error_handler = ->(_e, _env) { error_handler_called = true }
246
- options = {
247
- schema: open_api_3_streaming_response_schema,
248
- streaming_content_parsers: { 'application/x-json-stream' => ->(body) { JSON.parse!(body) } },
249
- error_handler: error_handler,
250
- }
239
+ options = { schema: open_api_3_streaming_response_schema, streaming_content_parsers: { 'application/x-json-stream' => ->(body) { JSON.parse!(body) } }, error_handler: error_handler, }
251
240
  status = 200
252
241
  headers = { 'content-type' => 'application/x-json-stream' }
253
242
  @app = Rack::Builder.new {
@@ -137,22 +137,14 @@ describe Committee::RequestUnpacker do
137
137
  end
138
138
 
139
139
  it "includes request body when`use_get_body` is true" do
140
- env = {
141
- "rack.input" => StringIO.new('{"x":1, "y":2}'),
142
- "REQUEST_METHOD" => "GET",
143
- "QUERY_STRING" => "data=value&x=aaa",
144
- }
140
+ env = { "rack.input" => StringIO.new('{"x":1, "y":2}'), "REQUEST_METHOD" => "GET", "QUERY_STRING" => "data=value&x=aaa", }
145
141
  request = Rack::Request.new(env)
146
142
  unpacker = Committee::RequestUnpacker.new({ allow_query_params: true, allow_get_body: true })
147
143
  assert_equal([{ 'x' => 1, 'y' => 2 }, false], unpacker.unpack_request_params(request))
148
144
  end
149
145
 
150
146
  it "doesn't include request body when `use_get_body` is false" do
151
- env = {
152
- "rack.input" => StringIO.new('{"x":1, "y":2}'),
153
- "REQUEST_METHOD" => "GET",
154
- "QUERY_STRING" => "data=value&x=aaa",
155
- }
147
+ env = { "rack.input" => StringIO.new('{"x":1, "y":2}'), "REQUEST_METHOD" => "GET", "QUERY_STRING" => "data=value&x=aaa", }
156
148
  request = Rack::Request.new(env)
157
149
  unpacker = Committee::RequestUnpacker.new({ allow_query_params: true, use_get_body: false })
158
150
  assert_equal({ 'data' => 'value', 'x' => 'aaa' }, unpacker.unpack_query_params(request))
@@ -35,43 +35,7 @@ describe Committee::SchemaValidator::HyperSchema::ParameterCoercer do
35
35
  end
36
36
 
37
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
- }
38
+ params = { "array_property" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", "per_page" => 1, "nested_coercer_object" => { "update_time" => "2016-04-01T16:00:00.000+09:00", "threshold" => 1.5 }, "nested_no_coercer_object" => { "per_page" => 1, "threshold" => 1.5 }, "nested_coercer_array" => [{ "update_time" => "2016-04-01T16:00:00.000+09:00", "threshold" => 1.5 }], "nested_no_coercer_array" => [{ "per_page" => 1, "threshold" => 1.5 }] }, { "update_time" => "2016-04-01T16:00:00.000+09:00", "per_page" => 1, "threshold" => 1.5 }, { "threshold" => 1.5, "per_page" => 1 }], }
75
39
  call(params, coerce_date_times: true, coerce_recursive: true)
76
40
 
77
41
  first_data = params["array_property"][0]
@@ -11,11 +11,7 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
11
11
  @schema.expand_references!
12
12
  # POST /apps/:id
13
13
  @link = @schema.properties["app"].links[0]
14
- @request = Rack::Request.new({
15
- "CONTENT_TYPE" => "application/json",
16
- "rack.input" => StringIO.new("{}"),
17
- "REQUEST_METHOD" => "POST"
18
- })
14
+ @request = Rack::Request.new({ "CONTENT_TYPE" => "application/json", "rack.input" => StringIO.new("{}"), "REQUEST_METHOD" => "POST" })
19
15
  end
20
16
 
21
17
  it "passes through a valid request with Content-Type options" do
@@ -29,22 +25,14 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
29
25
  end
30
26
 
31
27
  it "passes through a valid request with Content-Type options" do
32
- @request =
33
- Rack::Request.new({
34
- "CONTENT_TYPE" => "application/json; charset=utf-8",
35
- "rack.input" => StringIO.new("{}"),
36
- })
28
+ @request = Rack::Request.new({ "CONTENT_TYPE" => "application/json; charset=utf-8", "rack.input" => StringIO.new("{}"), })
37
29
  data = { "name" => "heroku-api", }
38
30
  call(data)
39
31
  end
40
32
 
41
33
  it "detects an invalid request Content-Type" do
42
34
  e = assert_raises(Committee::InvalidRequest) {
43
- @request =
44
- Rack::Request.new({
45
- "CONTENT_TYPE" => "application/x-www-form-urlencoded",
46
- "rack.input" => StringIO.new("{}"),
47
- })
35
+ @request = Rack::Request.new({ "CONTENT_TYPE" => "application/x-www-form-urlencoded", "rack.input" => StringIO.new("{}"), })
48
36
  call({})
49
37
  }
50
38
  message = %{"Content-Type" request header must be set to "application/json".}
@@ -52,11 +40,7 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
52
40
  end
53
41
 
54
42
  it "allows skipping content_type check" do
55
- @request =
56
- Rack::Request.new({
57
- "CONTENT_TYPE" => "application/x-www-form-urlencoded",
58
- "rack.input" => StringIO.new("{}"),
59
- })
43
+ @request = Rack::Request.new({ "CONTENT_TYPE" => "application/x-www-form-urlencoded", "rack.input" => StringIO.new("{}"), })
60
44
  call({}, {}, check_content_type: false)
61
45
  end
62
46
 
@@ -73,11 +57,7 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
73
57
  end
74
58
 
75
59
  it "allows an invalid Content-Type with an empty body" do
76
- @request =
77
- Rack::Request.new({
78
- "CONTENT_TYPE" => "application/x-www-form-urlencoded",
79
- "rack.input" => StringIO.new(""),
80
- })
60
+ @request = Rack::Request.new({ "CONTENT_TYPE" => "application/x-www-form-urlencoded", "rack.input" => StringIO.new(""), })
81
61
  call({})
82
62
  end
83
63
 
@@ -103,11 +83,7 @@ describe Committee::SchemaValidator::HyperSchema::RequestValidator do
103
83
  before do
104
84
  @schema = open_api_2_schema
105
85
  @link = @schema.routes['GET'][0][1]
106
- @request = Rack::Request.new({
107
- "CONTENT_TYPE" => "application/json",
108
- "rack.input" => StringIO.new("{}"),
109
- "REQUEST_METHOD" => "POST"
110
- })
86
+ @request = Rack::Request.new({ "CONTENT_TYPE" => "application/json", "rack.input" => StringIO.new("{}"), "REQUEST_METHOD" => "POST" })
111
87
  end
112
88
 
113
89
  it "passes through a valid request" do
@@ -43,6 +43,11 @@ describe Committee::SchemaValidator::HyperSchema::Router do
43
43
  refute_nil link
44
44
  end
45
45
 
46
+ it "does not include a similar prefix path segment" do
47
+ link, _ = hyper_schema_router(prefix: "/kpi").includes?("/kpi2/apps")
48
+ assert_nil link
49
+ end
50
+
46
51
  it "provides named parameters" do
47
52
  link, param_matches = open_api_2_router.find_link("GET", "/api/pets/fido")
48
53
  refute_nil link