committee 1.15.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +5 -5
  2. data/bin/committee-stub +11 -38
  3. data/lib/committee/bin/committee_stub.rb +67 -0
  4. data/lib/committee/drivers/driver.rb +47 -0
  5. data/lib/committee/drivers/hyper_schema/driver.rb +105 -0
  6. data/lib/committee/drivers/hyper_schema/link.rb +68 -0
  7. data/lib/committee/drivers/hyper_schema/schema.rb +22 -0
  8. data/lib/committee/drivers/hyper_schema.rb +12 -0
  9. data/lib/committee/drivers/open_api_2/driver.rb +252 -0
  10. data/lib/committee/drivers/open_api_2/header_schema_builder.rb +33 -0
  11. data/lib/committee/drivers/open_api_2/link.rb +36 -0
  12. data/lib/committee/drivers/open_api_2/parameter_schema_builder.rb +83 -0
  13. data/lib/committee/drivers/open_api_2/schema.rb +26 -0
  14. data/lib/committee/drivers/open_api_2/schema_builder.rb +33 -0
  15. data/lib/committee/drivers/open_api_2.rb +13 -0
  16. data/lib/committee/drivers/open_api_3/driver.rb +51 -0
  17. data/lib/committee/drivers/open_api_3/schema.rb +41 -0
  18. data/lib/committee/drivers/open_api_3.rb +11 -0
  19. data/lib/committee/drivers/schema.rb +23 -0
  20. data/lib/committee/drivers.rb +84 -0
  21. data/lib/committee/errors.rb +17 -0
  22. data/lib/committee/middleware/base.rb +46 -29
  23. data/lib/committee/middleware/request_validation.rb +31 -49
  24. data/lib/committee/middleware/response_validation.rb +48 -25
  25. data/lib/committee/middleware/stub.rb +62 -37
  26. data/lib/committee/middleware.rb +11 -0
  27. data/lib/committee/request_unpacker.rb +58 -50
  28. data/lib/committee/schema_validator/hyper_schema/parameter_coercer.rb +79 -0
  29. data/lib/committee/schema_validator/hyper_schema/request_validator.rb +55 -0
  30. data/lib/committee/schema_validator/hyper_schema/response_generator.rb +102 -0
  31. data/lib/committee/schema_validator/hyper_schema/response_validator.rb +89 -0
  32. data/lib/committee/schema_validator/hyper_schema/router.rb +46 -0
  33. data/lib/committee/schema_validator/hyper_schema/string_params_coercer.rb +105 -0
  34. data/lib/committee/schema_validator/hyper_schema.rb +119 -0
  35. data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +139 -0
  36. data/lib/committee/schema_validator/open_api_3/request_validator.rb +52 -0
  37. data/lib/committee/schema_validator/open_api_3/response_validator.rb +29 -0
  38. data/lib/committee/schema_validator/open_api_3/router.rb +45 -0
  39. data/lib/committee/schema_validator/open_api_3.rb +120 -0
  40. data/lib/committee/schema_validator/option.rb +60 -0
  41. data/lib/committee/schema_validator.rb +23 -0
  42. data/lib/committee/test/methods.rb +68 -38
  43. data/lib/committee/test/schema_coverage.rb +101 -0
  44. data/lib/committee/utils.rb +28 -0
  45. data/lib/committee/validation_error.rb +5 -2
  46. data/lib/committee/version.rb +5 -0
  47. data/lib/committee.rb +31 -18
  48. data/test/bin/committee_stub_test.rb +57 -0
  49. data/test/bin_test.rb +25 -0
  50. data/test/committee_test.rb +77 -0
  51. data/test/drivers/hyper_schema/driver_test.rb +49 -0
  52. data/test/drivers/hyper_schema/link_test.rb +56 -0
  53. data/test/drivers/open_api_2/driver_test.rb +156 -0
  54. data/test/drivers/open_api_2/header_schema_builder_test.rb +26 -0
  55. data/test/drivers/open_api_2/link_test.rb +52 -0
  56. data/test/drivers/open_api_2/parameter_schema_builder_test.rb +195 -0
  57. data/test/drivers/open_api_3/driver_test.rb +84 -0
  58. data/test/drivers_test.rb +154 -0
  59. data/test/middleware/base_test.rb +96 -7
  60. data/test/middleware/request_validation_open_api_3_test.rb +626 -0
  61. data/test/middleware/request_validation_test.rb +423 -32
  62. data/test/middleware/response_validation_open_api_3_test.rb +291 -0
  63. data/test/middleware/response_validation_test.rb +125 -23
  64. data/test/middleware/stub_test.rb +81 -20
  65. data/test/request_unpacker_test.rb +126 -52
  66. data/test/schema_validator/hyper_schema/parameter_coercer_test.rb +111 -0
  67. data/test/schema_validator/hyper_schema/request_validator_test.rb +151 -0
  68. data/test/schema_validator/hyper_schema/response_generator_test.rb +142 -0
  69. data/test/{response_validator_test.rb → schema_validator/hyper_schema/response_validator_test.rb} +43 -6
  70. data/test/schema_validator/hyper_schema/router_test.rb +88 -0
  71. data/test/schema_validator/hyper_schema/string_params_coercer_test.rb +137 -0
  72. data/test/schema_validator/open_api_3/operation_wrapper_test.rb +218 -0
  73. data/test/schema_validator/open_api_3/request_validator_test.rb +110 -0
  74. data/test/schema_validator/open_api_3/response_validator_test.rb +92 -0
  75. data/test/test/methods_new_version_test.rb +97 -0
  76. data/test/test/methods_test.rb +334 -27
  77. data/test/test/schema_coverage_test.rb +216 -0
  78. data/test/test_helper.rb +108 -1
  79. data/test/validation_error_test.rb +3 -1
  80. metadata +190 -27
  81. data/lib/committee/query_params_coercer.rb +0 -45
  82. data/lib/committee/request_validator.rb +0 -44
  83. data/lib/committee/response_generator.rb +0 -35
  84. data/lib/committee/response_validator.rb +0 -59
  85. data/lib/committee/router.rb +0 -62
  86. data/test/query_params_coercer_test.rb +0 -70
  87. data/test/request_validator_test.rb +0 -103
  88. data/test/response_generator_test.rb +0 -61
  89. data/test/router_test.rb +0 -38
@@ -1,4 +1,6 @@
1
- require_relative "../test_helper"
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
2
4
 
3
5
  describe Committee::Middleware::RequestValidation do
4
6
  include Rack::Test::Methods
@@ -7,37 +9,334 @@ describe Committee::Middleware::RequestValidation do
7
9
  @app
8
10
  end
9
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
+ ]
55
+
10
56
  it "passes through a valid request" do
11
- @app = new_rack_app
57
+ @app = new_rack_app(schema: hyper_schema)
58
+ params = {
59
+ "name" => "cloudnasium"
60
+ }
61
+ header "Content-Type", "application/json"
62
+ post "/apps", JSON.generate(params)
63
+ assert_equal 200, last_response.status
64
+ end
65
+
66
+ it "doesn't call error_handler (has a arg) when request is valid" do
67
+ called_error = false
68
+ pr = ->(_e) { called_error = true }
69
+ @app = new_rack_app(schema: hyper_schema, error_handler: pr)
12
70
  params = {
13
71
  "name" => "cloudnasium"
14
72
  }
15
73
  header "Content-Type", "application/json"
16
74
  post "/apps", JSON.generate(params)
75
+ assert !called_error
76
+ end
77
+
78
+ it "doesn't call error_handler (has 2 args) when request is valid" do
79
+ called_error = false
80
+ pr = ->(_e, _env) { called_error = true }
81
+ @app = new_rack_app(schema: hyper_schema, error_handler: pr)
82
+ params = {
83
+ "name" => "cloudnasium"
84
+ }
85
+ header "Content-Type", "application/json"
86
+ post "/apps", JSON.generate(params)
87
+ assert !called_error
88
+ end
89
+
90
+ it "passes given a datetime and with coerce_date_times enabled on GET endpoint" do
91
+ key_name = "update_time"
92
+ params = {
93
+ key_name => "2016-04-01T16:00:00.000+09:00",
94
+ "query" => "cloudnasium"
95
+ }
96
+
97
+ check_parameter = lambda { |env|
98
+ assert_equal DateTime, env['rack.request.query_hash'][key_name].class
99
+ [200, {}, []]
100
+ }
101
+
102
+ @app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, schema: hyper_schema)
103
+
104
+ get "/search/apps", params
105
+ assert_equal 200, last_response.status
106
+ end
107
+
108
+ it "passes a nested object with recursive option" do
109
+ key_name = "update_time"
110
+ params = {
111
+ key_name => "2016-04-01T16:00:00.000+09:00",
112
+ "query" => "cloudnasium",
113
+ "array_property" => ARRAY_PROPERTY
114
+ }
115
+
116
+ check_parameter = lambda { |env|
117
+ hash = env['rack.request.query_hash']
118
+ assert_equal DateTime, hash['array_property'].first['update_time'].class
119
+ assert_equal 1, hash['array_property'].first['per_page']
120
+ assert_equal DateTime, hash['array_property'].first['nested_coercer_object']['update_time'].class
121
+ assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
122
+ assert_equal 2, hash['array_property'].first['integer_array'][1]
123
+ assert_equal DateTime, hash['array_property'].first['datetime_array'][0].class
124
+ assert_equal DateTime, hash[key_name].class
125
+ [200, {}, []]
126
+ }
127
+
128
+ @app = new_rack_app_with_lambda(check_parameter,
129
+ coerce_query_params: true,
130
+ coerce_recursive: true,
131
+ coerce_date_times: true,
132
+ schema: hyper_schema)
133
+
134
+ get "/search/apps", params
135
+ assert_equal 200, last_response.status
136
+ end
137
+
138
+ it "passes a nested object with coerce_recursive false" do
139
+ key_name = "update_time"
140
+ params = {
141
+ key_name => "2016-04-01T16:00:00.000+09:00",
142
+ "query" => "cloudnasium",
143
+ "array_property" => ARRAY_PROPERTY
144
+ }
145
+
146
+ @app = new_rack_app(coerce_query_params: true, coerce_date_times: true, coerce_recursive: false, schema: hyper_schema)
147
+
148
+ get "/search/apps", params
149
+ assert_equal 400, last_response.status # schema expect integer but we don't convert string to integer, so 400
150
+ end
151
+
152
+ it "passes a nested object with coerce_recursive default(true)" do
153
+ key_name = "update_time"
154
+ params = {
155
+ key_name => "2016-04-01T16:00:00.000+09:00",
156
+ "query" => "cloudnasium",
157
+ "array_property" => ARRAY_PROPERTY
158
+ }
159
+
160
+ @app = new_rack_app(coerce_query_params: true, coerce_date_times: true, schema: hyper_schema)
161
+
162
+ get "/search/apps", params
163
+ assert_equal 200, last_response.status # schema expect integer but we don't convert string to integer, so 400
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 DateTime, hash['array_property'].first['update_time'].class
176
+ assert_equal 1, hash['array_property'].first['per_page']
177
+ assert_equal DateTime, 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 DateTime, hash['array_property'].first['datetime_array'][0].class
181
+ assert_equal DateTime, env['committee.params'][key_name].class
182
+ [200, {}, []]
183
+ }
184
+
185
+ @app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, coerce_recursive: true, 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=true 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 String, env['committee.params'][key_name].class
208
+ [200, {}, []]
209
+ }
210
+
211
+ @app = new_rack_app_with_lambda(check_parameter, 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=true 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 DateTime, env['committee.params'][key_name].class
234
+ [200, {}, []]
235
+ }
236
+
237
+ @app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, coerce_recursive: false, schema: hyper_schema)
238
+
239
+ header "Content-Type", "application/json"
240
+ post "/apps", JSON.generate(params)
241
+ assert_equal 200, last_response.status
242
+ end
243
+
244
+ it "passes given a nested datetime and with coerce_recursive=false and coerce_date_times=false on POST endpoint" do
245
+ key_name = "update_time"
246
+ params = {
247
+ key_name => "2016-04-01T16:00:00.000+09:00",
248
+ "array_property" => ARRAY_PROPERTY
249
+ }
250
+
251
+ check_parameter = lambda { |env|
252
+ hash = env['committee.params']
253
+ assert_equal String, hash['array_property'].first['update_time'].class
254
+ assert_equal 1, hash['array_property'].first['per_page']
255
+ assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
256
+ assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
257
+ assert_equal 2, hash['array_property'].first['integer_array'][1]
258
+ assert_equal String, hash['array_property'].first['datetime_array'][0].class
259
+ assert_equal String, env['committee.params'][key_name].class
260
+ [200, {}, []]
261
+ }
262
+
263
+ @app = new_rack_app_with_lambda(check_parameter, schema: hyper_schema)
264
+
265
+ header "Content-Type", "application/json"
266
+ post "/apps", JSON.generate(params)
267
+ assert_equal 200, last_response.status
268
+ end
269
+
270
+ it "passes given an invalid datetime string with coerce_date_times enabled" do
271
+ @app = new_rack_app(coerce_date_times: true, schema: hyper_schema)
272
+ params = {
273
+ "update_time" => "invalid_datetime_format"
274
+ }
275
+ header "Content-Type", "application/json"
276
+ post "/apps", JSON.generate(params)
277
+ assert_equal 400, last_response.status
278
+ assert_match(/invalid request/i, last_response.body)
279
+ end
280
+
281
+ it "passes with coerce_date_times enabled and without a schema for a link" do
282
+ @app = new_rack_app(coerce_date_times: true, schema: hyper_schema)
283
+ header "Content-Type", "application/json"
284
+ get "/apps", JSON.generate({})
17
285
  assert_equal 200, last_response.status
18
286
  end
19
287
 
20
288
  it "detects an invalid request" do
21
- @app = new_rack_app
289
+ @app = new_rack_app(schema: hyper_schema)
22
290
  header "Content-Type", "application/json"
23
291
  params = {
24
292
  "name" => 1
25
293
  }
26
294
  post "/apps", JSON.generate(params)
27
295
  assert_equal 400, last_response.status
28
- assert_match /invalid request/i, last_response.body
296
+ assert_match(/invalid request/i, last_response.body)
297
+ end
298
+
299
+ it "ignores errors when ignore_error: true" do
300
+ @app = new_rack_app(schema: hyper_schema, ignore_error: true)
301
+ header "Content-Type", "application/json"
302
+ params = {
303
+ "name" => 1
304
+ }
305
+ post "/apps", JSON.generate(params)
306
+ assert_equal 200, last_response.status
307
+ end
308
+
309
+ it "calls error_handler (has two args) when request is invalid" do
310
+ called_err = nil
311
+ pr = ->(e, _env) { called_err = e }
312
+ @app = new_rack_app(schema: hyper_schema, error_handler: pr)
313
+ header "Content-Type", "application/json"
314
+ params = {
315
+ "name" => 1
316
+ }
317
+ post "/apps", JSON.generate(params)
318
+ assert_kind_of Committee::InvalidRequest, called_err
29
319
  end
30
320
 
31
321
  it "rescues JSON errors" do
32
- @app = new_rack_app
322
+ @app = new_rack_app(schema: hyper_schema)
33
323
  header "Content-Type", "application/json"
34
324
  post "/apps", "{x:y}"
35
325
  assert_equal 400, last_response.status
36
- assert_match /valid json/i, last_response.body
326
+ assert_match(/valid json/i, last_response.body)
327
+ end
328
+
329
+ it "calls error_handler (has two args) when it rescues JSON errors" do
330
+ called_err = nil
331
+ pr = ->(e, _env) { called_err = e }
332
+ @app = new_rack_app(schema: hyper_schema, error_handler: pr)
333
+ header "Content-Type", "application/json"
334
+ post "/apps", "{x:y}"
335
+ assert_kind_of JSON::ParserError, called_err
37
336
  end
38
337
 
39
338
  it "takes a prefix" do
40
- @app = new_rack_app(prefix: "/v1")
339
+ @app = new_rack_app(prefix: "/v1", schema: hyper_schema)
41
340
  params = {
42
341
  "name" => "cloudnasium"
43
342
  }
@@ -47,37 +346,26 @@ describe Committee::Middleware::RequestValidation do
47
346
  end
48
347
 
49
348
  it "ignores paths outside the prefix" do
50
- @app = new_rack_app(prefix: "/v1")
349
+ @app = new_rack_app(prefix: "/v1", schema: hyper_schema)
51
350
  header "Content-Type", "text/html"
52
351
  get "/hello"
53
352
  assert_equal 200, last_response.status
54
353
  end
55
354
 
56
- it "warns when sending a deprecated string" do
57
- mock(Committee).warn_deprecated.with_any_args
58
- @app = new_rack_app(schema: File.read("./test/data/schema.json"))
59
- params = {
60
- "name" => "cloudnasium"
61
- }
62
- header "Content-Type", "application/json"
63
- post "/apps", JSON.generate(params)
64
- assert_equal 200, last_response.status
65
- end
66
-
67
355
  it "routes to paths not in schema" do
68
- @app = new_rack_app
356
+ @app = new_rack_app(schema: hyper_schema)
69
357
  get "/not-a-resource"
70
358
  assert_equal 200, last_response.status
71
359
  end
72
360
 
73
361
  it "doesn't route to paths not in schema when in strict mode" do
74
- @app = new_rack_app(strict: true)
362
+ @app = new_rack_app(schema: hyper_schema, strict: true)
75
363
  get "/not-a-resource"
76
364
  assert_equal 404, last_response.status
77
365
  end
78
366
 
79
367
  it "optionally raises an error" do
80
- @app = new_rack_app(raise: true)
368
+ @app = new_rack_app(raise: true, schema: hyper_schema)
81
369
  header "Content-Type", "application/json"
82
370
  assert_raises(Committee::InvalidRequest) do
83
371
  post "/apps", "{x:y}"
@@ -85,7 +373,7 @@ describe Committee::Middleware::RequestValidation do
85
373
  end
86
374
 
87
375
  it "optionally skip content_type check" do
88
- @app = new_rack_app(check_content_type: false)
376
+ @app = new_rack_app(check_content_type: false, schema: hyper_schema)
89
377
  params = {
90
378
  "name" => "cloudnasium"
91
379
  }
@@ -95,31 +383,134 @@ describe Committee::Middleware::RequestValidation do
95
383
  end
96
384
 
97
385
  it "optionally coerces query params" do
98
- @app = new_rack_app(coerce_query_params: true)
386
+ @app = new_rack_app(coerce_query_params: true, schema: hyper_schema)
99
387
  header "Content-Type", "application/json"
100
388
  get "/search/apps", {"per_page" => "10", "query" => "cloudnasium"}
101
389
  assert_equal 200, last_response.status
102
390
  end
103
391
 
104
392
  it "still raises an error if query param coercion is not possible" do
105
- @app = new_rack_app(coerce_query_params: true)
393
+ @app = new_rack_app(coerce_query_params: true, schema: hyper_schema)
106
394
  header "Content-Type", "application/json"
107
395
  get "/search/apps", {"per_page" => "foo", "query" => "cloudnasium"}
108
396
  assert_equal 400, last_response.status
109
- assert_match /invalid request/i, last_response.body
397
+ assert_match(/invalid request/i, last_response.body)
398
+ end
399
+
400
+ it "passes through a valid request for OpenAPI" do
401
+ check_parameter = lambda { |env|
402
+ assert_equal 3, env['rack.request.query_hash']['limit']
403
+ [200, {}, []]
404
+ }
405
+
406
+ @app = new_rack_app_with_lambda(check_parameter, schema: open_api_2_schema)
407
+ get "/api/pets?limit=3", nil, { "HTTP_AUTH_TOKEN" => "xxx" }
408
+ assert_equal 200, last_response.status
409
+ end
410
+
411
+ it "coerce form params" do
412
+ check_parameter = lambda { |env|
413
+ assert_equal 3, env['committee.params']['age']
414
+ assert_equal 3, env['committee.request_body_hash']['age']
415
+ [200, {}, []]
416
+ }
417
+
418
+ @app = new_rack_app_with_lambda(check_parameter, schema: open_api_2_form_schema, raise: true, allow_form_params: true, coerce_form_params: true)
419
+ header "Content-Type", "application/x-www-form-urlencoded"
420
+ post "/api/pets", "age=3&name=ab"
421
+ assert_equal 200, last_response.status
422
+ end
423
+
424
+ it "detects an invalid request for OpenAPI" do
425
+ @app = new_rack_app(schema: open_api_2_schema)
426
+ get "/api/pets?limit=foo", nil, { "HTTP_AUTH_TOKEN" => "xxx" }
427
+ assert_equal 400, last_response.status
428
+ assert_match(/invalid request/i, last_response.body)
429
+ end
430
+
431
+ it "passes through a valid request for OpenAPI including path parameters" do
432
+ @app = new_rack_app(schema: open_api_2_schema)
433
+ # not that ID is expect to be an integer
434
+ get "/api/pets/123"
435
+ assert_equal 200, last_response.status
436
+ end
437
+
438
+ it "detects an invalid request for OpenAPI including path parameters" do
439
+ @app = new_rack_app(schema: open_api_2_schema)
440
+ # not that ID is expect to be an integer
441
+ get "/api/pets/not-integer"
442
+ assert_equal 400, last_response.status
443
+ assert_match(/invalid request/i, last_response.body)
444
+ end
445
+
446
+ it "OpenAPI3 pass through a valid request" do
447
+ @app = new_rack_app(schema: open_api_3_schema)
448
+ get "/characters"
449
+ assert_equal 200, last_response.status
450
+ end
451
+
452
+ it "OpenAPI3 pass not exist href" do
453
+ @app = new_rack_app(schema: open_api_3_schema)
454
+ get "/unknown"
455
+ assert_equal 200, last_response.status
456
+ end
457
+
458
+ it "OpenAPI3 pass not exist href in strict mode" do
459
+ @app = new_rack_app(schema: open_api_3_schema, strict: true)
460
+ get "/unknown"
461
+ assert_equal 404, last_response.status
462
+ end
463
+
464
+ it "not exist path and options" do
465
+ options = {
466
+ coerce_form_params: true,
467
+ coerce_date_times: true,
468
+ coerce_query_params: true,
469
+ coerce_path_params: true,
470
+ coerce_recursive: true
471
+ }
472
+
473
+ @app = new_rack_app({schema: hyper_schema}.merge(options))
474
+ header "Content-Type", "application/x-www-form-urlencoded"
475
+ post "/unknown"
476
+ assert_equal 200, last_response.status
477
+ end
478
+
479
+ describe ':accept_request_filter' do
480
+ [
481
+ { description: 'when not specified, includes everything', accept_request_filter: nil, expected: { status: 400 } },
482
+ { description: 'when predicate matches, performs validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/a') }, expected: { status: 400 } },
483
+ { description: 'when predicate does not match, skips validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/x') }, expected: { status: 200 } },
484
+ ].each do |h|
485
+ description = h[:description]
486
+ accept_request_filter = h[:accept_request_filter]
487
+ expected = h[:expected]
488
+ it description do
489
+ @app = new_rack_app(prefix: '/v1', schema: hyper_schema, accept_request_filter: accept_request_filter)
490
+
491
+ post '/v1/apps', '{x:y}'
492
+
493
+ assert_equal expected[:status], last_response.status
494
+ end
495
+ end
110
496
  end
111
497
 
112
498
  private
113
499
 
114
500
  def new_rack_app(options = {})
115
- options = {
116
- schema: JSON.parse(File.read("./test/data/schema.json"))
117
- }.merge(options)
501
+ new_rack_app_with_lambda(lambda { |_|
502
+ [200, {}, []]
503
+ }, options)
504
+ end
505
+
506
+
507
+ def new_rack_app_with_lambda(check_lambda, options = {})
508
+ # TODO: delete when 5.0.0 released because default value changed
509
+ options[:parse_response_by_content_type] = true if options[:parse_response_by_content_type] == nil
510
+
118
511
  Rack::Builder.new {
119
512
  use Committee::Middleware::RequestValidation, options
120
- run lambda { |_|
121
- [200, {}, []]
122
- }
513
+ run check_lambda
123
514
  }
124
515
  end
125
516
  end