committee 3.3.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 { |_|
|