committee 3.0.0.alpha → 3.0.0.beta

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 (39) hide show
  1. checksums.yaml +5 -5
  2. data/lib/committee/drivers/hyper_schema.rb +8 -2
  3. data/lib/committee/drivers/open_api_2.rb +7 -2
  4. data/lib/committee/drivers/open_api_3.rb +9 -4
  5. data/lib/committee/drivers.rb +46 -0
  6. data/lib/committee/middleware/base.rb +9 -11
  7. data/lib/committee/middleware/response_validation.rb +8 -5
  8. data/lib/committee/request_unpacker.rb +4 -1
  9. data/lib/committee/{parameter_coercer.rb → schema_validator/hyper_schema/parameter_coercer.rb} +1 -2
  10. data/lib/committee/schema_validator/hyper_schema/request_validator.rb +1 -5
  11. data/lib/committee/schema_validator/hyper_schema/response_validator.rb +3 -9
  12. data/lib/committee/schema_validator/hyper_schema/router.rb +1 -1
  13. data/lib/committee/schema_validator/hyper_schema.rb +5 -4
  14. data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +46 -19
  15. data/lib/committee/schema_validator/open_api_3/request_validator.rb +14 -4
  16. data/lib/committee/schema_validator/open_api_3/response_validator.rb +9 -20
  17. data/lib/committee/schema_validator/open_api_3/router.rb +15 -4
  18. data/lib/committee/schema_validator/open_api_3.rb +14 -5
  19. data/lib/committee/schema_validator/option.rb +2 -5
  20. data/lib/committee/schema_validator/schema_validator.rb +15 -0
  21. data/lib/committee/test/methods.rb +3 -5
  22. data/lib/committee.rb +3 -1
  23. data/test/drivers/open_api_3_test.rb +2 -1
  24. data/test/drivers_test.rb +69 -0
  25. data/test/middleware/base_test.rb +20 -5
  26. data/test/middleware/request_validation_open_api_3_test.rb +136 -259
  27. data/test/middleware/request_validation_test.rb +18 -3
  28. data/test/middleware/response_validation_open_api_3_test.rb +83 -16
  29. data/test/middleware/response_validation_test.rb +19 -7
  30. data/test/middleware/stub_test.rb +1 -1
  31. data/test/{parameter_coercer_test.rb → schema_validator/hyper_schema/parameter_coercer_test.rb} +3 -3
  32. data/test/schema_validator/hyper_schema/router_test.rb +6 -0
  33. data/test/schema_validator/open_api_3/operation_wrapper_test.rb +29 -13
  34. data/test/schema_validator/open_api_3/request_validator_test.rb +31 -132
  35. data/test/schema_validator/open_api_3/response_validator_test.rb +19 -5
  36. data/test/test/methods_new_version_test.rb +19 -3
  37. data/test/test/methods_test.rb +15 -8
  38. data/test/test_helper.rb +15 -16
  39. metadata +8 -7
@@ -10,13 +10,13 @@ describe Committee::Middleware::ResponseValidation do
10
10
  end
11
11
 
12
12
  it "passes through a valid response" do
13
- @app = new_response_rack(JSON.generate(CHARACTERS_RESPONSE), {}, open_api_3: open_api_3_schema)
13
+ @app = new_response_rack(JSON.generate(CHARACTERS_RESPONSE), {}, schema: open_api_3_schema)
14
14
  get "/characters"
15
15
  assert_equal 200, last_response.status
16
16
  end
17
17
 
18
18
  it "passes through a invalid json" do
19
- @app = new_response_rack("not_json", {}, open_api_3: open_api_3_schema)
19
+ @app = new_response_rack("not_json", {}, schema: open_api_3_schema)
20
20
 
21
21
  get "/characters"
22
22
 
@@ -25,15 +25,15 @@ describe Committee::Middleware::ResponseValidation do
25
25
  end
26
26
 
27
27
  it "passes through not definition" do
28
- @app = new_response_rack(JSON.generate(CHARACTERS_RESPONSE), {}, open_api_3: open_api_3_schema)
28
+ @app = new_response_rack(JSON.generate(CHARACTERS_RESPONSE), {}, schema: open_api_3_schema)
29
29
  get "/no_data"
30
30
  assert_equal 200, last_response.status
31
31
  end
32
32
 
33
33
  it "detects a response invalid due to schema" do
34
- @app = new_response_rack("[]", {}, open_api_3: open_api_3_schema)
34
+ @app = new_response_rack("[]", {}, schema: open_api_3_schema, raise: true)
35
35
 
36
- e = assert_raises(Committee::InvalidRequest) { # TODO: change invalid request
36
+ e = assert_raises(Committee::InvalidResponse) {
37
37
  get "/characters"
38
38
  }
39
39
 
@@ -41,44 +41,111 @@ describe Committee::Middleware::ResponseValidation do
41
41
  end
42
42
 
43
43
  it "passes through a 204 (no content) response" do
44
- @app = new_response_rack("", {}, {open_api_3: open_api_3_schema}, {status: 204})
44
+ @app = new_response_rack("", {}, {schema: open_api_3_schema}, {status: 204})
45
45
  post "/validate"
46
46
  assert_equal 204, last_response.status
47
47
  end
48
48
 
49
49
  it "passes through a valid response with prefix" do
50
- @app = new_response_rack(JSON.generate(CHARACTERS_RESPONSE), {}, open_api_3: open_api_3_schema, prefix: "/v1")
50
+ @app = new_response_rack(JSON.generate(CHARACTERS_RESPONSE), {}, schema: open_api_3_schema, prefix: "/v1")
51
51
  get "/v1/characters"
52
52
  assert_equal 200, last_response.status
53
53
  end
54
54
 
55
55
  it "passes through a invalid json with prefix" do
56
- @app = new_response_rack("not_json", {}, open_api_3: open_api_3_schema, prefix: "/v1")
56
+ @app = new_response_rack("not_json", {}, schema: open_api_3_schema, prefix: "/v1")
57
57
 
58
58
  get "/v1/characters"
59
59
 
60
- # TODO: support prefix
61
- assert_equal 200, last_response.status
62
- # assert_equal 500, last_response.status
63
- # assert_equal "{\"id\":\"invalid_response\",\"message\":\"Response wasn't valid JSON.\"}", last_response.body
60
+ assert_equal 500, last_response.status
61
+ assert_equal "{\"id\":\"invalid_response\",\"message\":\"Response wasn't valid JSON.\"}", last_response.body
64
62
  end
65
63
 
66
64
  it "rescues JSON errors" do
67
- @app = new_response_rack("_42", {}, open_api_3: open_api_3_schema, raise: true)
65
+ @app = new_response_rack("_42", {}, schema: open_api_3_schema, raise: true)
68
66
  assert_raises(Committee::InvalidResponse) do
69
67
  get "/characters"
70
68
  end
71
69
  end
72
70
 
73
71
  it "not parameter requset" do
74
- @app = new_response_rack({integer: '1'}.to_json, {}, open_api_3: open_api_3_schema)
72
+ @app = new_response_rack({integer: '1'}.to_json, {}, schema: open_api_3_schema, raise: true)
75
73
 
76
- # TODO: error change
77
- assert_raises(Committee::InvalidRequest) do
74
+ assert_raises(Committee::InvalidResponse) do
78
75
  patch "/validate_no_parameter", {no_schema: 'no'}
79
76
  end
80
77
  end
81
78
 
79
+ it "optionally validates non-2xx blank responses" do
80
+ @app = new_response_rack("", {}, schema: open_api_3_schema, validate_success_only: false)
81
+ get "/characters"
82
+ assert_equal 200, last_response.status
83
+ end
84
+
85
+ it "optionally validates non-2xx invalid responses with invalid json" do
86
+ @app = new_response_rack("{_}", {}, schema: open_api_3_schema, validate_success_only: false)
87
+ get "/characters"
88
+ assert_equal 500, last_response.status
89
+ assert_match(/valid JSON/i, last_response.body)
90
+ end
91
+
92
+ describe 'check header' do
93
+ it 'valid type header' do
94
+ @app = new_response_rack({}.to_json, {'x-limit' => 1}, schema: open_api_3_schema, raise: true)
95
+
96
+ get "/header"
97
+
98
+ assert_equal 200, last_response.status
99
+ end
100
+
101
+ it 'invalid type header' do
102
+ @app = new_response_rack({}.to_json, {'x-limit' => '1'}, schema: open_api_3_schema, raise: true)
103
+
104
+ assert_raises(Committee::InvalidResponse) do
105
+ get "/header"
106
+ end
107
+ end
108
+
109
+ it 'invalid type but not check' do
110
+ @app = new_response_rack({}.to_json, {'x-limit' => '1'}, schema: open_api_3_schema, raise: true, check_header: false)
111
+
112
+ get "/header"
113
+
114
+ assert_equal 200, last_response.status
115
+ end
116
+ end
117
+
118
+ describe 'validate error option' do
119
+ it "detects an invalid response status code" do
120
+ @app = new_response_rack({ integer: '1' }.to_json,
121
+ {},
122
+ app_status: 400,
123
+ schema: open_api_3_schema,
124
+ raise: true,
125
+ validate_success_only: false)
126
+
127
+
128
+ e = assert_raises(Committee::InvalidResponse) do
129
+ get "/characters"
130
+ end
131
+ assert_match(/1 class is String/i, e.message)
132
+ end
133
+
134
+ it "detects an invalid response status code with validate_success_only=true" do
135
+ @app = new_response_rack({ string_1: :honoka }.to_json,
136
+ {},
137
+ app_status: 400,
138
+ schema: open_api_3_schema,
139
+ raise: true,
140
+ validate_success_only: true)
141
+
142
+
143
+ get "/characters"
144
+
145
+ assert_equal 400, last_response.status
146
+ end
147
+ end
148
+
82
149
  private
83
150
 
84
151
  def new_response_rack(response, headers = {}, options = {}, rack_options = {})
@@ -15,8 +15,8 @@ describe Committee::Middleware::ResponseValidation do
15
15
 
16
16
  it "doesn't call error_handler when response is valid" do
17
17
  called = false
18
- pr = ->(e) { called = true }
19
- @app = new_rack_app(JSON.generate([ValidApp]), {}, schema: hyper_schema)
18
+ pr = ->(_e) { called = true }
19
+ @app = new_rack_app(JSON.generate([ValidApp]), {}, schema: hyper_schema, error_handler: pr)
20
20
  get "/apps"
21
21
  assert !called, "error_handler is called"
22
22
  end
@@ -29,7 +29,7 @@ describe Committee::Middleware::ResponseValidation do
29
29
  end
30
30
 
31
31
  it "detects a response invalid due to not being JSON" do
32
- @app = new_rack_app("", {}, schema: hyper_schema)
32
+ @app = new_rack_app("{_}", {}, schema: hyper_schema)
33
33
  get "/apps"
34
34
  assert_equal 500, last_response.status
35
35
  assert_match(/valid JSON/i, last_response.body)
@@ -42,9 +42,14 @@ describe Committee::Middleware::ResponseValidation do
42
42
  end
43
43
 
44
44
  it "optionally validates non-2xx invalid responses" do
45
- @app = new_rack_app("", {}, app_status: 404, validate_errors: true,
46
- schema: hyper_schema)
45
+ @app = new_rack_app("", {}, app_status: 404, validate_success_only: false, schema: hyper_schema)
46
+ get "/apps"
47
+ assert_equal 500, last_response.status
48
+ assert_match(/Invalid response/i, last_response.body)
49
+ end
47
50
 
51
+ it "optionally validates non-2xx invalid responses with invalid json" do
52
+ @app = new_rack_app("{_}", {}, app_status: 404, validate_success_only: false, schema: hyper_schema)
48
53
  get "/apps"
49
54
  assert_equal 500, last_response.status
50
55
  assert_match(/valid JSON/i, last_response.body)
@@ -56,8 +61,15 @@ describe Committee::Middleware::ResponseValidation do
56
61
  assert_equal 204, last_response.status
57
62
  end
58
63
 
64
+ it "skip validation when 4xx" do
65
+ @app = new_rack_app("[{x:y}]", {}, schema: hyper_schema, validate_success_only: true, app_status: 400)
66
+ get "/apps"
67
+ assert_equal 400, last_response.status
68
+ assert_match("[{x:y}]", last_response.body)
69
+ end
70
+
59
71
  it "rescues JSON errors" do
60
- @app = new_rack_app("[{x:y}]", {}, schema: hyper_schema)
72
+ @app = new_rack_app("[{x:y}]", {}, schema: hyper_schema, validate_success_only: false)
61
73
  get "/apps"
62
74
  assert_equal 500, last_response.status
63
75
  assert_match(/valid json/i, last_response.body)
@@ -103,7 +115,7 @@ describe Committee::Middleware::ResponseValidation do
103
115
  end
104
116
 
105
117
  it "detects an invalid response for OpenAPI" do
106
- @app = new_rack_app("", {}, schema: open_api_2_schema)
118
+ @app = new_rack_app("{_}", {}, schema: open_api_2_schema)
107
119
  get "/api/pets"
108
120
  assert_equal 500, last_response.status
109
121
  assert_match(/valid JSON/i, last_response.body)
@@ -98,7 +98,7 @@ describe Committee::Middleware::Stub do
98
98
 
99
99
  it "caches the response if called multiple times" do
100
100
  cache = {}
101
- @app = new_rack_app(cache: cache, open_api_3: open_api_3_schema)
101
+ @app = new_rack_app(cache: cache, schema: open_api_3_schema)
102
102
 
103
103
  assert_raises(Committee::NotSupportOpenAPI3) do
104
104
  get "/characters"
@@ -1,8 +1,8 @@
1
- require_relative "test_helper"
1
+ require_relative "../../test_helper"
2
2
 
3
3
  require "stringio"
4
4
 
5
- describe Committee::ParameterCoercer do
5
+ describe Committee::SchemaValidator::HyperSchema::ParameterCoercer do
6
6
  before do
7
7
  @schema = JsonSchema.parse!(hyper_schema_data)
8
8
  @schema.expand_references!
@@ -106,6 +106,6 @@ describe Committee::ParameterCoercer do
106
106
 
107
107
  def call(params, options={})
108
108
  link = Committee::Drivers::HyperSchema::Link.new(@link)
109
- Committee::ParameterCoercer.new(params, link.schema, options).call!
109
+ Committee::SchemaValidator::HyperSchema::ParameterCoercer.new(params, link.schema, options).call!
110
110
  end
111
111
  end
@@ -60,6 +60,12 @@ describe Committee::SchemaValidator::HyperSchema::Router do
60
60
  assert_equal '/api/pets/dog', link.href
61
61
  end
62
62
 
63
+ it "fewer match not support in HyperSchema" do
64
+ link, _ = hyper_schema_router.find_link("GET", "/apps/abc")
65
+ refute_nil link
66
+ assert_equal '/apps/{(%23%2Fdefinitions%2Fapp%2Fdefinitions%2Fname)}', link.href
67
+ end
68
+
63
69
  def hyper_schema_router(options = {})
64
70
  schema = Committee::Drivers::HyperSchema.new.parse(hyper_schema_data)
65
71
  validator_option = Committee::SchemaValidator::Option.new(options, schema, :hyper_schema)
@@ -14,6 +14,8 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
14
14
  open_api_3_schema.operation_object(@path, @method)
15
15
  end
16
16
 
17
+ HEADER = { 'Content-Type' => 'application/json' }
18
+
17
19
  SCHEMA_PROPERTIES_PAIR = [
18
20
  ['string', 'str'],
19
21
  ['integer', 1],
@@ -23,7 +25,7 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
23
25
  ]
24
26
 
25
27
  it 'correct data' do
26
- operation_object.validate_request_params(SCHEMA_PROPERTIES_PAIR.to_h, @validator_option)
28
+ operation_object.validate_request_params(SCHEMA_PROPERTIES_PAIR.to_h, HEADER, @validator_option)
27
29
  assert true
28
30
  end
29
31
 
@@ -37,6 +39,7 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
37
39
  "number_1" => nil
38
40
  }
39
41
  },
42
+ HEADER,
40
43
  @validator_option)
41
44
 
42
45
  assert true
@@ -44,7 +47,7 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
44
47
 
45
48
  it 'invalid params' do
46
49
  e = assert_raises(Committee::InvalidRequest) {
47
- operation_object.validate_request_params({"string" => 1}, @validator_option)
50
+ operation_object.validate_request_params({"string" => 1}, HEADER, @validator_option)
48
51
  }
49
52
 
50
53
  # FIXME: when ruby 2.3 dropped, fix because ruby 2.3 return Fixnum, ruby 2.4 or later return Integer
@@ -53,10 +56,10 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
53
56
 
54
57
  it 'support put method' do
55
58
  @method = "put"
56
- operation_object.validate_request_params({"string" => "str"}, @validator_option)
59
+ operation_object.validate_request_params({"string" => "str"}, HEADER, @validator_option)
57
60
 
58
61
  e = assert_raises(Committee::InvalidRequest) {
59
- operation_object.validate_request_params({"string" => 1}, @validator_option)
62
+ operation_object.validate_request_params({"string" => 1}, HEADER, @validator_option)
60
63
  }
61
64
 
62
65
  # FIXME: when ruby 2.3 dropped, fix because ruby 2.3 return Fixnum, ruby 2.4 or later return Integer
@@ -65,17 +68,17 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
65
68
 
66
69
  it 'support patch method' do
67
70
  @method = "patch"
68
- operation_object.validate_request_params({"integer" => 1}, @validator_option)
71
+ operation_object.validate_request_params({"integer" => 1}, HEADER, @validator_option)
69
72
 
70
73
  e = assert_raises(Committee::InvalidRequest) {
71
- operation_object.validate_request_params({"integer" => "str"}, @validator_option)
74
+ operation_object.validate_request_params({"integer" => "str"}, HEADER, @validator_option)
72
75
  }
73
76
 
74
77
  assert e.message.start_with?("str class is String but it's not valid")
75
78
  end
76
79
 
77
80
  it 'unknown param' do
78
- operation_object.validate_request_params({"unknown" => 1}, @validator_option)
81
+ operation_object.validate_request_params({"unknown" => 1}, HEADER, @validator_option)
79
82
  end
80
83
 
81
84
  describe 'support get method' do
@@ -84,15 +87,24 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
84
87
  end
85
88
 
86
89
  it 'correct' do
87
- operation_object.validate_request_params({"query_string" => "query", "query_integer_list" => [1, 2]}, @validator_option)
88
- operation_object.validate_request_params({"query_string" => "query", "query_integer_list" => [1, 2], "optional_integer" => 1}, @validator_option)
90
+ operation_object.validate_request_params(
91
+ {"query_string" => "query", "query_integer_list" => [1, 2]},
92
+ HEADER,
93
+ @validator_option
94
+ )
95
+
96
+ operation_object.validate_request_params(
97
+ {"query_string" => "query", "query_integer_list" => [1, 2], "optional_integer" => 1},
98
+ HEADER,
99
+ @validator_option
100
+ )
89
101
 
90
102
  assert true
91
103
  end
92
104
 
93
105
  it 'not exist required' do
94
106
  e = assert_raises(Committee::InvalidRequest) {
95
- operation_object.validate_request_params({"query_integer_list" => [1, 2]}, @validator_option)
107
+ operation_object.validate_request_params({"query_integer_list" => [1, 2]}, HEADER, @validator_option)
96
108
  }
97
109
 
98
110
  assert e.message.start_with?("required parameters query_string not exist in")
@@ -100,7 +112,11 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
100
112
 
101
113
  it 'invalid type' do
102
114
  e = assert_raises(Committee::InvalidRequest) {
103
- operation_object.validate_request_params({"query_string" => 1, "query_integer_list" => [1, 2], "optional_integer" => 1}, @validator_option)
115
+ operation_object.validate_request_params(
116
+ {"query_string" => 1, "query_integer_list" => [1, 2], "optional_integer" => 1},
117
+ HEADER,
118
+ @validator_option
119
+ )
104
120
  }
105
121
 
106
122
  # FIXME: when ruby 2.3 dropped, fix because ruby 2.3 return Fixnum, ruby 2.4 or later return Integer
@@ -115,14 +131,14 @@ describe Committee::SchemaValidator::OpenAPI3::OperationWrapper do
115
131
  end
116
132
 
117
133
  it 'correct' do
118
- operation_object.validate_request_params({"limit" => "1"}, @validator_option)
134
+ operation_object.validate_request_params({"limit" => "1"}, HEADER, @validator_option)
119
135
 
120
136
  assert true
121
137
  end
122
138
 
123
139
  it 'invalid type' do
124
140
  e = assert_raises(Committee::InvalidRequest) {
125
- operation_object.validate_request_params({"limit" => "a"}, @validator_option)
141
+ operation_object.validate_request_params({"limit" => "a"}, HEADER, @validator_option)
126
142
  }
127
143
 
128
144
  assert e.message.start_with?("a class is String but")
@@ -1,151 +1,50 @@
1
1
  require_relative "../../test_helper"
2
2
 
3
- require "stringio"
4
-
5
- # TODO: fix
6
-
7
3
  describe Committee::SchemaValidator::OpenAPI3::RequestValidator do
8
- describe 'open_api_3' do
9
- before do
10
- @schema = JsonSchema.parse!(hyper_schema_data)
11
- @schema.expand_references!
12
- # POST /apps/:id
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
- })
19
- end
4
+ describe 'OpenAPI3' do
5
+ include Rack::Test::Methods
20
6
 
21
- it "passes through a valid request with Content-Type options" do
22
- @headers = { "Content-Type" => "application/json; charset=utf-8" }
23
- call({})
7
+ def app
8
+ @app
24
9
  end
25
10
 
26
- it "passes through a valid request" do
27
- data = {
28
- "name" => "heroku-api",
11
+ it "optionally content_type check" do
12
+ @app = new_rack_app(check_content_type: true, schema: open_api_3_schema)
13
+ params = {
14
+ "string_post_1" => "cloudnasium"
29
15
  }
30
- call(data)
16
+ header "Content-Type", "text/html"
17
+ post "/characters", JSON.generate(params)
18
+ assert_equal 400, last_response.status
31
19
  end
32
20
 
33
- it "passes through a valid request with Content-Type options" do
34
- @request =
35
- Rack::Request.new({
36
- "CONTENT_TYPE" => "application/json; charset=utf-8",
37
- "rack.input" => StringIO.new("{}"),
38
- })
39
- data = {
40
- "name" => "heroku-api",
21
+ it "optionally skip content_type check" do
22
+ @app = new_rack_app(check_content_type: false, schema: open_api_3_schema)
23
+ params = {
24
+ "string_post_1" => "cloudnasium"
41
25
  }
42
- call(data)
26
+ header "Content-Type", "text/html"
27
+ post "/characters", JSON.generate(params)
28
+ assert_equal 200, last_response.status
43
29
  end
44
30
 
45
- it "detects an invalid request Content-Type" do
46
- e = assert_raises(Committee::InvalidRequest) {
47
- @request =
48
- Rack::Request.new({
49
- "CONTENT_TYPE" => "application/x-www-form-urlencoded",
50
- "rack.input" => StringIO.new("{}"),
51
- })
52
- call({})
31
+ it "if not exist requsetBody definition, skip content_type check" do
32
+ @app = new_rack_app(check_content_type: true, schema: open_api_3_schema)
33
+ params = {
34
+ "string_post_1" => "cloudnasium"
53
35
  }
54
- message =
55
- %{"Content-Type" request header must be set to "application/json".}
56
- assert_equal message, e.message
57
- end
58
-
59
- it "allows skipping content_type check" do
60
- @request =
61
- Rack::Request.new({
62
- "CONTENT_TYPE" => "application/x-www-form-urlencoded",
63
- "rack.input" => StringIO.new("{}"),
64
- })
65
- call({}, {}, check_content_type: false)
66
- end
67
-
68
- it "detects an missing parameter in GET requests" do
69
- # GET /apps/search?query=...
70
- @link = @schema.properties["app"].links[5]
71
- @request = Rack::Request.new({})
72
- e = assert_raises(Committee::InvalidRequest) do
73
- call({})
74
- end
75
- message =
76
- %{Invalid request.\n\n#: failed schema #/definitions/app/links/5/schema: "query" wasn't supplied.}
77
- assert_equal message, e.message
78
- end
79
-
80
- it "allows an invalid Content-Type with an empty body" do
81
- @request =
82
- Rack::Request.new({
83
- "CONTENT_TYPE" => "application/x-www-form-urlencoded",
84
- "rack.input" => StringIO.new(""),
85
- })
86
- call({})
87
- end
88
-
89
- it "detects a parameter of the wrong pattern" do
90
- data = {
91
- "name" => "%@!"
92
- }
93
- e = assert_raises(Committee::InvalidRequest) do
94
- call(data)
95
- end
96
- message = %{Invalid request.\n\n#/name: failed schema #/definitions/app/links/0/schema/properties/name: %@! does not match /^[a-z][a-z0-9-]{3,30}$/.}
97
- assert_equal message, e.message
98
- end
99
-
100
- private
101
-
102
- def call(data, headers={}, options={})
103
- # hyper-schema link should be dropped into driver wrapper before it's used
104
- link = Committee::Drivers::HyperSchema::Link.new(@link)
105
- Committee::SchemaValidator::HyperSchema::RequestValidator.new(link, options).call(@request, data, headers)
36
+ header "Content-Type", "application/json"
37
+ patch "/validate_no_parameter", JSON.generate(params)
38
+ assert_equal 200, last_response.status
106
39
  end
107
- end
108
40
 
109
- describe 'OpenAPI 2' do
110
- before do
111
- @schema = open_api_2_schema
112
- @link = @schema.routes['GET'][0][1]
113
- @request = Rack::Request.new({
114
- "CONTENT_TYPE" => "application/json",
115
- "rack.input" => StringIO.new("{}"),
116
- "REQUEST_METHOD" => "POST"
117
- })
118
- end
119
-
120
-
121
- it "passes through a valid request" do
122
- headers = {
123
- "AUTH-TOKEN" => "xxx"
41
+ def new_rack_app(options = {})
42
+ Rack::Builder.new {
43
+ use Committee::Middleware::RequestValidation, options
44
+ run lambda { |_|
45
+ [200, {}, []]
46
+ }
124
47
  }
125
- call({}, headers)
126
- end
127
-
128
- it "detects an missing header parameter in GET requests" do
129
- @link = @schema.routes['GET'][0][1]
130
- @request = Rack::Request.new({})
131
- e = assert_raises(Committee::InvalidRequest) do
132
- call({}, {})
133
- end
134
- message = %{Invalid request.\n\n#: failed schema : "AUTH-TOKEN" wasn't supplied.}
135
- assert_equal message, e.message
136
- end
137
-
138
- it "allows skipping header schema check" do
139
- @link = @schema.routes['GET'][0][1]
140
- @request = Rack::Request.new({})
141
- call({}, {}, { check_header: false })
142
- end
143
-
144
- private
145
-
146
- def call(data, headers={}, options={})
147
- # hyper-schema link should be dropped into driver wrapper before it's used
148
- Committee::SchemaValidator::HyperSchema::RequestValidator.new(@link, options).call(@request, data, headers)
149
48
  end
150
49
  end
151
50
  end
@@ -22,18 +22,30 @@ describe Committee::SchemaValidator::OpenAPI3::ResponseValidator do
22
22
  call_response_validator
23
23
  end
24
24
 
25
- # TODO: raise error option
26
- it "passes through a valid response with no registered Content-Type" do
25
+ it "passes through a valid response with no registered Content-Type with strict = false" do
27
26
  @headers = { "Content-Type" => "application/xml" }
28
27
  call_response_validator
29
28
  end
30
29
 
31
- # TODO: raise error option
30
+ it "passes through a valid response with no registered Content-Type with strict = true" do
31
+ @headers = { "Content-Type" => "application/xml" }
32
+ assert_raises(Committee::InvalidResponse) {
33
+ call_response_validator(true)
34
+ }
35
+ end
36
+
32
37
  it "passes through a valid response with no Content-Type" do
33
38
  @headers = {}
34
39
  call_response_validator
35
40
  end
36
41
 
42
+ it "passes through a valid response with no Content-Type with strict option" do
43
+ @headers = {}
44
+ assert_raises(Committee::InvalidResponse) {
45
+ call_response_validator(true)
46
+ }
47
+ end
48
+
37
49
  it "passes through a valid list response" do
38
50
  @path = '/validate_response_array'
39
51
  @method = 'get'
@@ -48,8 +60,10 @@ describe Committee::SchemaValidator::OpenAPI3::ResponseValidator do
48
60
 
49
61
  private
50
62
 
51
- def call_response_validator
63
+ def call_response_validator(strict = false)
52
64
  @operation_object = open_api_3_schema.operation_object(@path, @method)
53
- Committee::SchemaValidator::OpenAPI3::ResponseValidator.new(@operation_object, @validator_option).call(@status, @headers, @data)
65
+ Committee::SchemaValidator::OpenAPI3::ResponseValidator.
66
+ new(@operation_object, @validator_option).
67
+ call(@status, @headers, @data, strict)
54
68
  end
55
69
  end
@@ -46,7 +46,23 @@ describe Committee::Test::Methods do
46
46
  end
47
47
 
48
48
  it "detects an invalid response Content-Type" do
49
- @app = new_rack_app(JSON.generate([ValidApp]), {})
49
+ @app = new_rack_app(JSON.generate([ValidApp]), 200, {})
50
+ get "/apps"
51
+ e = assert_raises(Committee::InvalidResponse) do
52
+ assert_schema_conform
53
+ end
54
+ assert_match(/response header must be set to/i, e.message)
55
+ end
56
+
57
+ it "detects an invalid response Content-Type but ignore because it's not success status code" do
58
+ @committee_options.merge!(validate_success_only: true)
59
+ @app = new_rack_app(JSON.generate([ValidApp]), 400, {})
60
+ get "/apps"
61
+ assert_schema_conform
62
+ end
63
+
64
+ it "detects an invalid response Content-Type and check all status code" do
65
+ @app = new_rack_app(JSON.generate([ValidApp]), 400, {})
50
66
  get "/apps"
51
67
  e = assert_raises(Committee::InvalidResponse) do
52
68
  assert_schema_conform
@@ -57,10 +73,10 @@ describe Committee::Test::Methods do
57
73
 
58
74
  private
59
75
 
60
- def new_rack_app(response, headers={ "Content-Type" => "application/json" })
76
+ def new_rack_app(response, status=200, headers={ "Content-Type" => "application/json" })
61
77
  Rack::Builder.new {
62
78
  run lambda { |_|
63
- [200, headers, [response]]
79
+ [status, headers, [response]]
64
80
  }
65
81
  }
66
82
  end