committee 3.3.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/committee/drivers/open_api_2/driver.rb +1 -2
- data/lib/committee/drivers/open_api_2/parameter_schema_builder.rb +1 -1
- data/lib/committee/drivers.rb +22 -10
- data/lib/committee/errors.rb +12 -0
- data/lib/committee/middleware/base.rb +5 -4
- data/lib/committee/middleware/request_validation.rb +4 -18
- data/lib/committee/middleware/response_validation.rb +15 -16
- data/lib/committee/request_unpacker.rb +46 -60
- data/lib/committee/schema_validator/hyper_schema/response_validator.rb +8 -2
- data/lib/committee/schema_validator/hyper_schema.rb +41 -27
- data/lib/committee/schema_validator/open_api_3/operation_wrapper.rb +44 -37
- data/lib/committee/schema_validator/open_api_3/request_validator.rb +11 -2
- data/lib/committee/schema_validator/open_api_3/router.rb +3 -1
- data/lib/committee/schema_validator/open_api_3.rb +52 -26
- data/lib/committee/schema_validator/option.rb +14 -3
- data/lib/committee/schema_validator.rb +1 -1
- data/lib/committee/test/methods.rb +27 -16
- data/lib/committee/test/schema_coverage.rb +101 -0
- data/lib/committee/utils.rb +28 -0
- data/lib/committee/validation_error.rb +3 -2
- data/lib/committee/version.rb +5 -0
- data/lib/committee.rb +11 -4
- data/test/bin/committee_stub_test.rb +5 -1
- data/test/committee_test.rb +29 -3
- data/test/drivers/open_api_3/driver_test.rb +1 -1
- data/test/drivers_test.rb +20 -7
- data/test/middleware/base_test.rb +9 -10
- data/test/middleware/request_validation_open_api_3_test.rb +175 -18
- data/test/middleware/request_validation_test.rb +20 -28
- data/test/middleware/response_validation_open_api_3_test.rb +96 -7
- data/test/middleware/response_validation_test.rb +21 -26
- data/test/middleware/stub_test.rb +4 -0
- data/test/request_unpacker_test.rb +51 -110
- data/test/schema_validator/hyper_schema/response_validator_test.rb +10 -0
- data/test/schema_validator/hyper_schema/router_test.rb +4 -0
- data/test/schema_validator/hyper_schema/string_params_coercer_test.rb +1 -1
- data/test/schema_validator/open_api_3/operation_wrapper_test.rb +72 -20
- data/test/schema_validator/open_api_3/request_validator_test.rb +27 -0
- data/test/schema_validator/open_api_3/response_validator_test.rb +26 -5
- data/test/test/methods_new_version_test.rb +17 -5
- data/test/test/methods_test.rb +155 -31
- data/test/test/schema_coverage_test.rb +216 -0
- data/test/test_helper.rb +34 -4
- metadata +47 -15
@@ -11,11 +11,11 @@ module Committee
|
|
11
11
|
@validator_option = validator_option
|
12
12
|
end
|
13
13
|
|
14
|
-
def call(request,
|
14
|
+
def call(request, path_params, query_params, body_params, headers)
|
15
15
|
content_type = ::Committee::SchemaValidator.request_media_type(request)
|
16
16
|
check_content_type(request, content_type) if @validator_option.check_content_type
|
17
17
|
|
18
|
-
@operation_object.validate_request_params(
|
18
|
+
@operation_object.validate_request_params(path_params, query_params, body_params, headers, @validator_option)
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
@@ -24,6 +24,7 @@ module Committee
|
|
24
24
|
# support post, put, patch only
|
25
25
|
return true unless request.post? || request.put? || request.patch?
|
26
26
|
return true if @operation_object.valid_request_content_type?(content_type)
|
27
|
+
return true if @operation_object.optional_body? && empty_request?(request)
|
27
28
|
|
28
29
|
message = if valid_content_types.size > 1
|
29
30
|
types = valid_content_types.map {|x| %{"#{x}"} }.join(', ')
|
@@ -37,6 +38,14 @@ module Committee
|
|
37
38
|
def valid_content_types
|
38
39
|
@operation_object&.request_content_types
|
39
40
|
end
|
41
|
+
|
42
|
+
def empty_request?(request)
|
43
|
+
return true if !request.body
|
44
|
+
|
45
|
+
data = request.body.read
|
46
|
+
request.body.rewind
|
47
|
+
data.empty?
|
48
|
+
end
|
40
49
|
end
|
41
50
|
end
|
42
51
|
end
|
@@ -22,8 +22,10 @@ module Committee
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def operation_object(request)
|
25
|
+
return nil unless includes_request?(request)
|
26
|
+
|
25
27
|
path = request.path
|
26
|
-
path = path.gsub(@prefix_regexp, '') if
|
28
|
+
path = path.gsub(@prefix_regexp, '') if @prefix_regexp
|
27
29
|
|
28
30
|
request_method = request.request_method.downcase
|
29
31
|
|
@@ -14,15 +14,10 @@ module Committee
|
|
14
14
|
def request_validate(request)
|
15
15
|
return unless link_exist?
|
16
16
|
|
17
|
-
path_params = validator_option.coerce_path_params ? coerce_path_params : {}
|
18
|
-
|
19
17
|
request_unpack(request)
|
20
|
-
|
21
|
-
request.env[validator_option.params_key]&.merge!(path_params) unless path_params.empty?
|
22
|
-
|
23
18
|
request_schema_validation(request)
|
24
19
|
|
25
|
-
|
20
|
+
copy_coerced_data_to_params(request)
|
26
21
|
end
|
27
22
|
|
28
23
|
def response_validate(status, headers, response, test_method = false)
|
@@ -30,8 +25,16 @@ module Committee
|
|
30
25
|
response.each do |chunk|
|
31
26
|
full_body << chunk
|
32
27
|
end
|
33
|
-
data = full_body.empty? ? {} : JSON.parse(full_body)
|
34
28
|
|
29
|
+
parse_to_json = !validator_option.parse_response_by_content_type ||
|
30
|
+
headers.fetch('Content-Type', nil)&.start_with?('application/json')
|
31
|
+
data = if parse_to_json
|
32
|
+
full_body.empty? ? {} : JSON.parse(full_body)
|
33
|
+
else
|
34
|
+
full_body
|
35
|
+
end
|
36
|
+
|
37
|
+
# TODO: refactoring name
|
35
38
|
strict = test_method
|
36
39
|
Committee::SchemaValidator::OpenAPI3::ResponseValidator.
|
37
40
|
new(@operation_object, validator_option).
|
@@ -42,23 +45,32 @@ module Committee
|
|
42
45
|
!@operation_object.nil?
|
43
46
|
end
|
44
47
|
|
45
|
-
def coerce_form_params(_parameter)
|
46
|
-
# Empty because request_schema_validation checks and coerces
|
47
|
-
end
|
48
|
-
|
49
48
|
private
|
50
49
|
|
51
50
|
attr_reader :validator_option
|
52
51
|
|
53
52
|
def coerce_path_params
|
54
|
-
|
53
|
+
return Committee::Utils.indifferent_hash unless validator_option.coerce_path_params
|
54
|
+
Committee::RequestUnpacker.indifferent_params(@operation_object.coerce_path_parameter(@validator_option))
|
55
55
|
end
|
56
56
|
|
57
57
|
def request_schema_validation(request)
|
58
58
|
return unless @operation_object
|
59
59
|
|
60
60
|
validator = Committee::SchemaValidator::OpenAPI3::RequestValidator.new(@operation_object, validator_option: validator_option)
|
61
|
-
validator.call(request, request
|
61
|
+
validator.call(request, path_params(request), query_params(request), body_params(request), header(request))
|
62
|
+
end
|
63
|
+
|
64
|
+
def path_params(request)
|
65
|
+
request.env[validator_option.path_hash_key]
|
66
|
+
end
|
67
|
+
|
68
|
+
def query_params(request)
|
69
|
+
request.env[validator_option.query_hash_key]
|
70
|
+
end
|
71
|
+
|
72
|
+
def body_params(request)
|
73
|
+
request.env[validator_option.request_body_hash_key]
|
62
74
|
end
|
63
75
|
|
64
76
|
def header(request)
|
@@ -66,22 +78,36 @@ module Committee
|
|
66
78
|
end
|
67
79
|
|
68
80
|
def request_unpack(request)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
81
|
+
unpacker = Committee::RequestUnpacker.new(
|
82
|
+
allow_form_params: validator_option.allow_form_params,
|
83
|
+
allow_get_body: validator_option.allow_get_body,
|
84
|
+
allow_query_params: validator_option.allow_query_params,
|
85
|
+
optimistic_json: validator_option.optimistic_json,
|
86
|
+
)
|
87
|
+
|
88
|
+
request.env[validator_option.headers_key] = unpacker.unpack_headers(request)
|
89
|
+
|
90
|
+
request_param, is_form_params = unpacker.unpack_request_params(request)
|
91
|
+
request.env[validator_option.request_body_hash_key] = request_param
|
92
|
+
request.env[validator_option.path_hash_key] = coerce_path_params
|
93
|
+
|
94
|
+
query_param = unpacker.unpack_query_params(request)
|
95
|
+
query_param.merge!(request_param) if request.get? && validator_option.allow_get_body
|
96
|
+
request.env[validator_option.query_hash_key] = query_param
|
78
97
|
end
|
79
98
|
|
80
|
-
def
|
81
|
-
|
99
|
+
def copy_coerced_data_to_params(request)
|
100
|
+
order = if validator_option.parameter_overwite_by_rails_rule
|
101
|
+
# (high priority) path_hash_key -> query_param -> request_body_hash
|
102
|
+
[validator_option.request_body_hash_key, validator_option.query_hash_key, validator_option.path_hash_key]
|
103
|
+
else
|
104
|
+
# (high priority) path_hash_key -> request_body_hash -> query_param
|
105
|
+
[validator_option.query_hash_key, validator_option.request_body_hash_key, validator_option.path_hash_key]
|
106
|
+
end
|
82
107
|
|
83
|
-
request.env[
|
84
|
-
|
108
|
+
request.env[validator_option.params_key] = Committee::Utils.indifferent_hash
|
109
|
+
order.each do |key|
|
110
|
+
request.env[validator_option.params_key].merge!(Committee::Utils.deep_copy(request.env[key]))
|
85
111
|
end
|
86
112
|
end
|
87
113
|
end
|
@@ -15,17 +15,26 @@ module Committee
|
|
15
15
|
:coerce_query_params,
|
16
16
|
:coerce_recursive,
|
17
17
|
:optimistic_json,
|
18
|
-
:validate_success_only
|
18
|
+
:validate_success_only,
|
19
|
+
:parse_response_by_content_type,
|
20
|
+
:parameter_overwite_by_rails_rule
|
19
21
|
|
20
22
|
# Non-boolean options:
|
21
23
|
attr_reader :headers_key,
|
22
24
|
:params_key,
|
25
|
+
:query_hash_key,
|
26
|
+
:request_body_hash_key,
|
27
|
+
:path_hash_key,
|
23
28
|
:prefix
|
24
29
|
|
25
30
|
def initialize(options, schema, schema_type)
|
26
31
|
# Non-boolean options
|
27
|
-
@headers_key = options[:headers_key]
|
28
|
-
@params_key = options[:params_key]
|
32
|
+
@headers_key = options[:headers_key] || "committee.headers"
|
33
|
+
@params_key = options[:params_key] || "committee.params"
|
34
|
+
@query_hash_key = options[:query_hash_key] || "committee.query_hash"
|
35
|
+
@path_hash_key = options[:path_hash_key] || "committee.path_hash"
|
36
|
+
@request_body_hash_key = options[:request_body_hash_key] || "committee.request_body_hash"
|
37
|
+
|
29
38
|
@prefix = options[:prefix]
|
30
39
|
|
31
40
|
# Boolean options and have a common value by default
|
@@ -35,6 +44,8 @@ module Committee
|
|
35
44
|
@check_header = options.fetch(:check_header, true)
|
36
45
|
@coerce_recursive = options.fetch(:coerce_recursive, true)
|
37
46
|
@optimistic_json = options.fetch(:optimistic_json, false)
|
47
|
+
@parse_response_by_content_type = options.fetch(:parse_response_by_content_type, true)
|
48
|
+
@parameter_overwite_by_rails_rule = options.fetch(:parameter_overwite_by_rails_rule, true)
|
38
49
|
|
39
50
|
# Boolean options and have a different value by default
|
40
51
|
@allow_get_body = options.fetch(:allow_get_body, schema.driver.default_allow_get_body)
|
@@ -3,27 +3,40 @@
|
|
3
3
|
module Committee
|
4
4
|
module Test
|
5
5
|
module Methods
|
6
|
-
def assert_schema_conform
|
6
|
+
def assert_schema_conform(expected_status = nil)
|
7
7
|
assert_request_schema_confirm unless old_behavior
|
8
|
-
assert_response_schema_confirm
|
8
|
+
assert_response_schema_confirm(expected_status)
|
9
9
|
end
|
10
10
|
|
11
11
|
def assert_request_schema_confirm
|
12
12
|
unless schema_validator.link_exist?
|
13
|
-
request = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema."
|
13
|
+
request = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema (prefix: #{committee_options[:prefix].inspect})."
|
14
14
|
raise Committee::InvalidRequest.new(request)
|
15
15
|
end
|
16
16
|
|
17
17
|
schema_validator.request_validate(request_object)
|
18
18
|
end
|
19
19
|
|
20
|
-
def assert_response_schema_confirm
|
20
|
+
def assert_response_schema_confirm(expected_status = nil)
|
21
21
|
unless schema_validator.link_exist?
|
22
|
-
response = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema."
|
22
|
+
response = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema (prefix: #{committee_options[:prefix].inspect})."
|
23
23
|
raise Committee::InvalidResponse.new(response)
|
24
24
|
end
|
25
25
|
|
26
26
|
status, headers, body = response_data
|
27
|
+
|
28
|
+
if expected_status.nil?
|
29
|
+
Committee.need_good_option('Pass expected response status code to check it against the corresponding schema explicitly.')
|
30
|
+
elsif expected_status != status
|
31
|
+
response = "Expected `#{expected_status}` status code, but it was `#{status}`."
|
32
|
+
raise Committee::InvalidResponse.new(response)
|
33
|
+
end
|
34
|
+
|
35
|
+
if schema_coverage
|
36
|
+
operation_object = router.operation_object(request_object)
|
37
|
+
schema_coverage&.update_response_coverage!(operation_object.original_path, operation_object.http_method, status)
|
38
|
+
end
|
39
|
+
|
27
40
|
schema_validator.response_validate(status, headers, [body], true) if validate_response?(status)
|
28
41
|
end
|
29
42
|
|
@@ -55,18 +68,16 @@ module Committee
|
|
55
68
|
@schema_validator ||= router.build_schema_validator(request_object)
|
56
69
|
end
|
57
70
|
|
71
|
+
def schema_coverage
|
72
|
+
return nil unless schema.is_a?(Committee::Drivers::OpenAPI3::Schema)
|
73
|
+
|
74
|
+
coverage = committee_options.fetch(:schema_coverage, nil)
|
75
|
+
|
76
|
+
coverage.is_a?(SchemaCoverage) ? coverage : nil
|
77
|
+
end
|
78
|
+
|
58
79
|
def old_behavior
|
59
|
-
|
60
|
-
if old_assert_behavior.nil?
|
61
|
-
warn <<-MSG
|
62
|
-
[DEPRECATION] now assert_schema_conform check response schema only.
|
63
|
-
but we will change check request and response in future major version.
|
64
|
-
so if you want to conform response only, please use assert_response_schema_confirm,
|
65
|
-
or you can suppress this message and keep old behavior by setting old_assert_behavior=true.
|
66
|
-
MSG
|
67
|
-
old_assert_behavior = true
|
68
|
-
end
|
69
|
-
old_assert_behavior
|
80
|
+
committee_options.fetch(:old_assert_behavior, false)
|
70
81
|
end
|
71
82
|
end
|
72
83
|
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Committee
|
4
|
+
module Test
|
5
|
+
class SchemaCoverage
|
6
|
+
attr_reader :schema
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def merge_report(first, second)
|
10
|
+
report = first.dup
|
11
|
+
second.each do |k, v|
|
12
|
+
if v.is_a?(Hash)
|
13
|
+
if report[k].nil?
|
14
|
+
report[k] = v
|
15
|
+
else
|
16
|
+
report[k] = merge_report(report[k], v)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
report[k] ||= v
|
20
|
+
end
|
21
|
+
end
|
22
|
+
report
|
23
|
+
end
|
24
|
+
|
25
|
+
def flatten_report(report)
|
26
|
+
responses = []
|
27
|
+
report.each do |path_name, path_coverage|
|
28
|
+
path_coverage.each do |method, method_coverage|
|
29
|
+
responses_coverage = method_coverage['responses']
|
30
|
+
responses_coverage.each do |response_status, is_covered|
|
31
|
+
responses << {
|
32
|
+
path: path_name,
|
33
|
+
method: method,
|
34
|
+
status: response_status,
|
35
|
+
is_covered: is_covered,
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
{
|
41
|
+
responses: responses,
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(schema)
|
47
|
+
raise 'Unsupported schema' unless schema.is_a?(Committee::Drivers::OpenAPI3::Schema)
|
48
|
+
|
49
|
+
@schema = schema
|
50
|
+
@covered = {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def update_response_coverage!(path, method, response_status)
|
54
|
+
method = method.to_s.downcase
|
55
|
+
response_status = response_status.to_s
|
56
|
+
|
57
|
+
@covered[path] ||= {}
|
58
|
+
@covered[path][method] ||= {}
|
59
|
+
@covered[path][method]['responses'] ||= {}
|
60
|
+
@covered[path][method]['responses'][response_status] = true
|
61
|
+
end
|
62
|
+
|
63
|
+
def report
|
64
|
+
report = {}
|
65
|
+
|
66
|
+
schema.open_api.paths.path.each do |path_name, path_item|
|
67
|
+
report[path_name] = {}
|
68
|
+
path_item._openapi_all_child_objects.each do |object_name, object|
|
69
|
+
next unless object.is_a?(OpenAPIParser::Schemas::Operation)
|
70
|
+
|
71
|
+
method = object_name.split('/').last&.downcase
|
72
|
+
next unless method
|
73
|
+
|
74
|
+
report[path_name][method] ||= {}
|
75
|
+
|
76
|
+
# TODO: check coverage on request params/body as well?
|
77
|
+
|
78
|
+
report[path_name][method]['responses'] ||= {}
|
79
|
+
object.responses.response.each do |response_status, _|
|
80
|
+
is_covered = @covered.dig(path_name, method, 'responses', response_status) || false
|
81
|
+
report[path_name][method]['responses'][response_status] = is_covered
|
82
|
+
end
|
83
|
+
if object.responses.default
|
84
|
+
is_default_covered = (@covered.dig(path_name, method, 'responses') || {}).any? do |status, is_covered|
|
85
|
+
is_covered && !object.responses.response.key?(status)
|
86
|
+
end
|
87
|
+
report[path_name][method]['responses']['default'] = is_default_covered
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
report
|
93
|
+
end
|
94
|
+
|
95
|
+
def report_flatten
|
96
|
+
self.class.flatten_report(report)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Committee
|
4
|
+
module Utils
|
5
|
+
# Creates a Hash with indifferent access.
|
6
|
+
#
|
7
|
+
# (Copied from Sinatra)
|
8
|
+
def self.indifferent_hash
|
9
|
+
Hash.new { |hash,key| hash[key.to_s] if Symbol === key }
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.deep_copy(from)
|
13
|
+
if from.is_a?(Hash)
|
14
|
+
h = Committee::Utils.indifferent_hash
|
15
|
+
from.each_pair do |k, v|
|
16
|
+
h[k] = deep_copy(v)
|
17
|
+
end
|
18
|
+
return h
|
19
|
+
end
|
20
|
+
|
21
|
+
if from.is_a?(Array)
|
22
|
+
return from.map{ |v| deep_copy(v) }
|
23
|
+
end
|
24
|
+
|
25
|
+
return from
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
module Committee
|
4
4
|
class ValidationError
|
5
|
-
attr_reader :id, :message, :status
|
5
|
+
attr_reader :id, :message, :status, :request
|
6
6
|
|
7
|
-
def initialize(status, id, message)
|
7
|
+
def initialize(status, id, message, request = nil)
|
8
8
|
@status = status
|
9
9
|
@id = id
|
10
10
|
@message = message
|
11
|
+
@request = request
|
11
12
|
end
|
12
13
|
|
13
14
|
def error_body
|
data/lib/committee.rb
CHANGED
@@ -6,6 +6,8 @@ require "json_schema"
|
|
6
6
|
require "rack"
|
7
7
|
require 'openapi_parser'
|
8
8
|
|
9
|
+
require_relative "committee/version"
|
10
|
+
|
9
11
|
module Committee
|
10
12
|
def self.debug?
|
11
13
|
ENV["COMMITTEE_DEBUG"]
|
@@ -15,13 +17,17 @@ module Committee
|
|
15
17
|
$stderr.puts(message) if debug?
|
16
18
|
end
|
17
19
|
|
18
|
-
def self.
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def self.need_good_option(message)
|
21
|
+
warn(message)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.warn_deprecated_until_6(cond, message)
|
25
|
+
raise "remove deprecated!" unless Committee::VERSION.start_with?("5")
|
26
|
+
warn("[DEPRECATION] #{message}") if cond
|
22
27
|
end
|
23
28
|
end
|
24
29
|
|
30
|
+
require_relative "committee/utils"
|
25
31
|
require_relative "committee/drivers"
|
26
32
|
require_relative "committee/errors"
|
27
33
|
require_relative "committee/middleware"
|
@@ -31,3 +37,4 @@ require_relative "committee/validation_error"
|
|
31
37
|
|
32
38
|
require_relative "committee/bin/committee_stub"
|
33
39
|
require_relative "committee/test/methods"
|
40
|
+
require_relative "committee/test/schema_coverage"
|
@@ -43,7 +43,11 @@ describe Committee::Bin::CommitteeStub, "app" do
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def app
|
46
|
-
|
46
|
+
options = {}
|
47
|
+
# TODO: delete when 5.0.0 released because default value changed
|
48
|
+
options[:parse_response_by_content_type] = false
|
49
|
+
|
50
|
+
@bin.get_app(hyper_schema, options)
|
47
51
|
end
|
48
52
|
|
49
53
|
it "defaults to a 404" do
|
data/test/committee_test.rb
CHANGED
@@ -31,18 +31,44 @@ describe Committee do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
it "warns need_good_option" do
|
35
|
+
old_stderr = $stderr
|
36
|
+
$stderr = StringIO.new
|
37
|
+
begin
|
38
|
+
Committee.need_good_option "show"
|
39
|
+
assert_equal "show\n", $stderr.string
|
40
|
+
ensure
|
41
|
+
$stderr = old_stderr
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
34
45
|
it "warns on deprecated unless $VERBOSE is nil" do
|
35
46
|
old_stderr = $stderr
|
36
47
|
old_verbose = $VERBOSE
|
37
48
|
$stderr = StringIO.new
|
38
49
|
begin
|
39
50
|
$VERBOSE = nil
|
40
|
-
Committee.
|
51
|
+
Committee.warn_deprecated_until_6 true, "blah"
|
41
52
|
assert_equal "", $stderr.string
|
42
53
|
|
43
54
|
$VERBOSE = true
|
44
|
-
Committee.
|
45
|
-
assert_equal "blah\n", $stderr.string
|
55
|
+
Committee.warn_deprecated_until_6 true, "blah"
|
56
|
+
assert_equal "[DEPRECATION] blah\n", $stderr.string
|
57
|
+
ensure
|
58
|
+
$stderr = old_stderr
|
59
|
+
$VERBOSE = old_verbose
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
it "doesn't warns on deprecated if cond is false" do
|
65
|
+
old_stderr = $stderr
|
66
|
+
old_verbose = $VERBOSE
|
67
|
+
$stderr = StringIO.new
|
68
|
+
begin
|
69
|
+
$VERBOSE = true
|
70
|
+
Committee.warn_deprecated_until_6 false, "blah"
|
71
|
+
assert_equal "", $stderr.string
|
46
72
|
ensure
|
47
73
|
$stderr = old_stderr
|
48
74
|
$VERBOSE = old_verbose
|
@@ -16,7 +16,7 @@ describe Committee::Drivers::OpenAPI3::Driver do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it "override methods" do
|
19
|
-
parser = OpenAPIParser.parse(open_api_3_data)
|
19
|
+
parser = OpenAPIParser.parse(open_api_3_data, strict_reference_validation: false)
|
20
20
|
schema = @driver.parse(parser)
|
21
21
|
|
22
22
|
assert_kind_of Committee::Drivers::OpenAPI3::Schema, schema
|
data/test/drivers_test.rb
CHANGED
@@ -37,20 +37,33 @@ describe Committee::Drivers do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'loads OpenAPI 3' do
|
40
|
-
s = Committee::Drivers.load_from_file(open_api_3_schema_path)
|
40
|
+
s = Committee::Drivers.load_from_file(open_api_3_schema_path, parser_options:{strict_reference_validation: true})
|
41
41
|
assert_kind_of Committee::Drivers::Schema, s
|
42
42
|
assert_kind_of Committee::Drivers::OpenAPI3::Schema, s
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'load OpenAPI 3 (patch version 3.0.1)' do
|
46
|
-
s = Committee::Drivers.load_from_file(open_api_3_0_1_schema_path)
|
46
|
+
s = Committee::Drivers.load_from_file(open_api_3_0_1_schema_path, parser_options:{strict_reference_validation: true})
|
47
47
|
assert_kind_of Committee::Drivers::Schema, s
|
48
48
|
assert_kind_of Committee::Drivers::OpenAPI3::Schema, s
|
49
49
|
end
|
50
50
|
|
51
|
+
it 'fails to load OpenAPI 3 with invalid reference' do
|
52
|
+
parser_options = { strict_reference_validation: true }
|
53
|
+
assert_raises(OpenAPIParser::MissingReferenceError) do
|
54
|
+
Committee::Drivers.load_from_file(open_api_3_invalid_reference_path, parser_options: parser_options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# This test can be removed when the test above (raising on invalid reference) becomes default behavior?
|
59
|
+
it 'allows loading OpenAPI 3 with invalid reference as existing behavior' do
|
60
|
+
s = Committee::Drivers.load_from_file(open_api_3_invalid_reference_path, parser_options:{strict_reference_validation: false})
|
61
|
+
assert_kind_of Committee::Drivers::OpenAPI3::Schema, s
|
62
|
+
end
|
63
|
+
|
51
64
|
it 'errors on an unsupported file extension' do
|
52
65
|
e = assert_raises(StandardError) do
|
53
|
-
Committee::Drivers.load_from_file('test.xml')
|
66
|
+
Committee::Drivers.load_from_file('test.xml', parser_options:{strict_reference_validation: true})
|
54
67
|
end
|
55
68
|
assert_equal "Committee only supports the following file extensions: '.json', '.yaml', '.yml'", e.message
|
56
69
|
end
|
@@ -58,13 +71,13 @@ describe Committee::Drivers do
|
|
58
71
|
|
59
72
|
describe 'load_from_json(schema_path)' do
|
60
73
|
it 'loads OpenAPI2' do
|
61
|
-
s = Committee::Drivers.load_from_json(open_api_2_schema_path)
|
74
|
+
s = Committee::Drivers.load_from_json(open_api_2_schema_path, parser_options:{strict_reference_validation: true})
|
62
75
|
assert_kind_of Committee::Drivers::Schema, s
|
63
76
|
assert_kind_of Committee::Drivers::OpenAPI2::Schema, s
|
64
77
|
end
|
65
78
|
|
66
79
|
it 'loads Hyper-Schema' do
|
67
|
-
s = Committee::Drivers.load_from_json(hyper_schema_schema_path)
|
80
|
+
s = Committee::Drivers.load_from_json(hyper_schema_schema_path, parser_options:{strict_reference_validation: true})
|
68
81
|
assert_kind_of Committee::Drivers::Schema, s
|
69
82
|
assert_kind_of Committee::Drivers::HyperSchema::Schema, s
|
70
83
|
end
|
@@ -72,7 +85,7 @@ describe Committee::Drivers do
|
|
72
85
|
|
73
86
|
describe 'load_from_yaml(schema_path)' do
|
74
87
|
it 'loads OpenAPI3' do
|
75
|
-
s = Committee::Drivers.load_from_yaml(open_api_3_schema_path)
|
88
|
+
s = Committee::Drivers.load_from_yaml(open_api_3_schema_path, parser_options:{strict_reference_validation: true})
|
76
89
|
assert_kind_of Committee::Drivers::Schema, s
|
77
90
|
assert_kind_of Committee::Drivers::OpenAPI3::Schema, s
|
78
91
|
end
|
@@ -80,7 +93,7 @@ describe Committee::Drivers do
|
|
80
93
|
|
81
94
|
describe 'load_from_data(schema_path)' do
|
82
95
|
it 'loads OpenAPI3' do
|
83
|
-
s = Committee::Drivers.load_from_data(open_api_3_data)
|
96
|
+
s = Committee::Drivers.load_from_data(open_api_3_data, parser_options:{strict_reference_validation: false})
|
84
97
|
assert_kind_of Committee::Drivers::Schema, s
|
85
98
|
assert_kind_of Committee::Drivers::OpenAPI3::Schema, s
|
86
99
|
end
|
@@ -102,18 +102,14 @@ describe Committee::Middleware::Base do
|
|
102
102
|
end
|
103
103
|
|
104
104
|
describe 'initialize option' do
|
105
|
-
it "
|
106
|
-
|
107
|
-
|
105
|
+
it "accepts OpenAPI3 parser config of strict_reference_validation and raises" do
|
106
|
+
assert_raises(OpenAPIParser::MissingReferenceError) do
|
107
|
+
Committee::Middleware::Base.new(nil, schema_path: open_api_3_invalid_reference_path, strict_reference_validation: true)
|
108
|
+
end
|
108
109
|
end
|
109
110
|
|
110
|
-
it "
|
111
|
-
b = Committee::Middleware::Base.new(nil, schema_path:
|
112
|
-
assert_kind_of Committee::Drivers::OpenAPI2::Schema, b.instance_variable_get(:@schema)
|
113
|
-
end
|
114
|
-
|
115
|
-
it "schema_path option with OpenAPI3" do
|
116
|
-
b = Committee::Middleware::Base.new(nil, schema_path: open_api_3_schema_path)
|
111
|
+
it "does not raise by default even with invalid reference OpenAPI3 specification" do
|
112
|
+
b = Committee::Middleware::Base.new(nil, schema_path: open_api_3_invalid_reference_path, strict_reference_validation: false)
|
117
113
|
assert_kind_of Committee::Drivers::OpenAPI3::Schema, b.instance_variable_get(:@schema)
|
118
114
|
end
|
119
115
|
end
|
@@ -121,6 +117,9 @@ describe Committee::Middleware::Base do
|
|
121
117
|
private
|
122
118
|
|
123
119
|
def new_rack_app(options = {})
|
120
|
+
# TODO: delete when 5.0.0 released because default value changed
|
121
|
+
options[:parse_response_by_content_type] = true if options[:parse_response_by_content_type] == nil
|
122
|
+
|
124
123
|
Rack::Builder.new {
|
125
124
|
use Committee::Middleware::RequestValidation, options
|
126
125
|
run lambda { |_|
|