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
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module SchemaValidator
5
+ class Option
6
+ # Boolean Options
7
+ attr_reader :allow_form_params,
8
+ :allow_get_body,
9
+ :allow_query_params,
10
+ :check_content_type,
11
+ :check_header,
12
+ :coerce_date_times,
13
+ :coerce_form_params,
14
+ :coerce_path_params,
15
+ :coerce_query_params,
16
+ :coerce_recursive,
17
+ :optimistic_json,
18
+ :validate_success_only,
19
+ :parse_response_by_content_type,
20
+ :parameter_overwite_by_rails_rule
21
+
22
+ # Non-boolean options:
23
+ attr_reader :headers_key,
24
+ :params_key,
25
+ :query_hash_key,
26
+ :request_body_hash_key,
27
+ :path_hash_key,
28
+ :prefix
29
+
30
+ def initialize(options, schema, schema_type)
31
+ # Non-boolean options
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
+
38
+ @prefix = options[:prefix]
39
+
40
+ # Boolean options and have a common value by default
41
+ @allow_form_params = options.fetch(:allow_form_params, true)
42
+ @allow_query_params = options.fetch(:allow_query_params, true)
43
+ @check_content_type = options.fetch(:check_content_type, true)
44
+ @check_header = options.fetch(:check_header, true)
45
+ @coerce_recursive = options.fetch(:coerce_recursive, true)
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)
49
+
50
+ # Boolean options and have a different value by default
51
+ @allow_get_body = options.fetch(:allow_get_body, schema.driver.default_allow_get_body)
52
+ @coerce_date_times = options.fetch(:coerce_date_times, schema.driver.default_coerce_date_times)
53
+ @coerce_form_params = options.fetch(:coerce_form_params, schema.driver.default_coerce_form_params)
54
+ @coerce_path_params = options.fetch(:coerce_path_params, schema.driver.default_path_params)
55
+ @coerce_query_params = options.fetch(:coerce_query_params, schema.driver.default_query_params)
56
+ @validate_success_only = options.fetch(:validate_success_only, schema.driver.default_validate_success_only)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module SchemaValidator
5
+ class << self
6
+ def request_media_type(request)
7
+ request.media_type.to_s
8
+ end
9
+
10
+ # @param [String] prefix
11
+ # @return [Regexp]
12
+ def build_prefix_regexp(prefix)
13
+ return nil unless prefix
14
+
15
+ /\A#{Regexp.escape(prefix)}/.freeze
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ require_relative "schema_validator/hyper_schema"
22
+ require_relative "schema_validator/open_api_3"
23
+ require_relative "schema_validator/option"
@@ -1,54 +1,84 @@
1
- module Committee::Test
2
- module Methods
3
- def assert_schema_conform
4
- if (data = schema_contents).is_a?(String)
5
- warn_string_deprecated
6
- data = JSON.parse(data)
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ module Test
5
+ module Methods
6
+ def assert_schema_conform(expected_status = nil)
7
+ assert_request_schema_confirm unless old_behavior
8
+ assert_response_schema_confirm(expected_status)
7
9
  end
8
10
 
9
- @schema ||= begin
10
- schema = JsonSchema.parse!(data)
11
- schema.expand_references!
12
- schema
11
+ def assert_request_schema_confirm
12
+ unless schema_validator.link_exist?
13
+ request = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema (prefix: #{committee_options[:prefix].inspect})."
14
+ raise Committee::InvalidRequest.new(request)
15
+ end
16
+
17
+ schema_validator.request_validate(request_object)
13
18
  end
14
- @router ||= Committee::Router.new(@schema, prefix: schema_url_prefix)
15
19
 
16
- unless link = @router.find_request_link(last_request)
17
- response = "`#{last_request.request_method} #{last_request.path_info}` undefined in schema."
18
- raise Committee::InvalidResponse.new(response)
20
+ def assert_response_schema_confirm(expected_status = nil)
21
+ unless schema_validator.link_exist?
22
+ response = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema (prefix: #{committee_options[:prefix].inspect})."
23
+ raise Committee::InvalidResponse.new(response)
24
+ end
25
+
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
+
40
+ schema_validator.response_validate(status, headers, [body], true) if validate_response?(status)
19
41
  end
20
42
 
21
- if validate_response?(last_response.status)
22
- data = JSON.parse(last_response.body)
23
- Committee::ResponseValidator.new(link).call(last_response.status, last_response.headers, data)
43
+ def committee_options
44
+ raise "please set options"
24
45
  end
25
- end
26
46
 
27
- def assert_schema_content_type
28
- Committee.warn_deprecated("Committee: use of #assert_schema_content_type is deprecated; use #assert_schema_conform instead.")
29
- end
47
+ def request_object
48
+ raise "please set object like 'last_request'"
49
+ end
30
50
 
31
- # can be overridden alternatively to #schema_path in case the schema is
32
- # easier to access as a string
33
- # blob
34
- def schema_contents
35
- JSON.parse(File.read(schema_path))
36
- end
51
+ def response_data
52
+ raise "please set response data like 'last_response.status, last_response.headers, last_response.body'"
53
+ end
37
54
 
38
- def schema_path
39
- raise "Please override #schema_contents or #schema_path."
40
- end
55
+ def validate_response?(status)
56
+ Committee::Middleware::ResponseValidation.validate?(status, committee_options.fetch(:validate_success_only, false))
57
+ end
41
58
 
42
- def schema_url_prefix
43
- nil
44
- end
59
+ def schema
60
+ @schema ||= Committee::Middleware::Base.get_schema(committee_options)
61
+ end
45
62
 
46
- def warn_string_deprecated
47
- Committee.warn_deprecated("Committee: returning a string from `#schema_contents` is deprecated; please return a deserialized hash instead.")
48
- end
63
+ def router
64
+ @router ||= schema.build_router(committee_options)
65
+ end
66
+
67
+ def schema_validator
68
+ @schema_validator ||= router.build_schema_validator(request_object)
69
+ end
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)
49
75
 
50
- def validate_response?(status)
51
- Committee::ResponseValidator.validate?(status)
76
+ coverage.is_a?(SchemaCoverage) ? coverage : nil
77
+ end
78
+
79
+ def old_behavior
80
+ committee_options.fetch(:old_assert_behavior, false)
81
+ end
52
82
  end
53
83
  end
54
84
  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
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Committee
2
4
  class ValidationError
3
- attr_reader :id, :message, :status
5
+ attr_reader :id, :message, :status, :request
4
6
 
5
- def initialize(status, id, message)
7
+ def initialize(status, id, message, request = nil)
6
8
  @status = status
7
9
  @id = id
8
10
  @message = message
11
+ @request = request
9
12
  end
10
13
 
11
14
  def error_body
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Committee
4
+ VERSION = '5.0.0'.freeze
5
+ end
data/lib/committee.rb CHANGED
@@ -1,27 +1,40 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
4
+ require "yaml"
2
5
  require "json_schema"
3
6
  require "rack"
7
+ require 'openapi_parser'
4
8
 
5
- require_relative "committee/errors"
6
- require_relative "committee/query_params_coercer"
7
- require_relative "committee/request_unpacker"
8
- require_relative "committee/request_validator"
9
- require_relative "committee/response_generator"
10
- require_relative "committee/response_validator"
11
- require_relative "committee/router"
12
- require_relative "committee/validation_error"
9
+ require_relative "committee/version"
13
10
 
14
- require_relative "committee/middleware/base"
15
- require_relative "committee/middleware/request_validation"
16
- require_relative "committee/middleware/response_validation"
17
- require_relative "committee/middleware/stub"
11
+ module Committee
12
+ def self.debug?
13
+ ENV["COMMITTEE_DEBUG"]
14
+ end
18
15
 
19
- require_relative "committee/test/methods"
16
+ def self.log_debug(message)
17
+ $stderr.puts(message) if debug?
18
+ end
20
19
 
21
- module Committee
22
- def self.warn_deprecated(message)
23
- if !$VERBOSE.nil?
24
- $stderr.puts(message)
25
- end
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
26
27
  end
27
28
  end
29
+
30
+ require_relative "committee/utils"
31
+ require_relative "committee/drivers"
32
+ require_relative "committee/errors"
33
+ require_relative "committee/middleware"
34
+ require_relative "committee/request_unpacker"
35
+ require_relative "committee/schema_validator"
36
+ require_relative "committee/validation_error"
37
+
38
+ require_relative "committee/bin/committee_stub"
39
+ require_relative "committee/test/methods"
40
+ require_relative "committee/test/schema_coverage"
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe Committee::Bin::CommitteeStub do
6
+ before do
7
+ @bin = Committee::Bin::CommitteeStub.new
8
+ end
9
+
10
+ it "produces a Rack app" do
11
+ app = @bin.get_app(hyper_schema, {})
12
+ assert_kind_of Rack::Builder, app
13
+ end
14
+
15
+ it "parses command line options" do
16
+ options, parser = @bin.get_options_parser
17
+
18
+ parser.parse!(["--help"])
19
+ assert_equal true, options[:help]
20
+
21
+ parser.parse!([
22
+ "--driver", "open_api_2",
23
+ "--tolerant", "true",
24
+ "--port", "1234"
25
+ ])
26
+ assert_equal :open_api_2, options[:driver]
27
+ assert_equal true, options[:tolerant]
28
+ assert_equal "1234", options[:port]
29
+ end
30
+
31
+ it "is not supported in OpenAPI 3" do
32
+ assert_raises(Committee::OpenAPI3Unsupported) do
33
+ @bin.get_app(open_api_3_schema, {})
34
+ end
35
+ end
36
+ end
37
+
38
+ describe Committee::Bin::CommitteeStub, "app" do
39
+ include Rack::Test::Methods
40
+
41
+ before do
42
+ @bin = Committee::Bin::CommitteeStub.new
43
+ end
44
+
45
+ def app
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)
51
+ end
52
+
53
+ it "defaults to a 404" do
54
+ get "/foos"
55
+ assert_equal 404, last_response.status
56
+ end
57
+ end
data/test/bin_test.rb ADDED
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ #
6
+ # The purpose of this sets of tests is just to include our Ruby executables
7
+ # where possible so that we can get very basic sanity checks on their syntax
8
+ # (which is something that of course Ruby can't do by default).
9
+ #
10
+ # We can do this without actually executing them because they're gated by `if
11
+ # $0 == __FILE__` statements.
12
+ #
13
+
14
+ describe "executables in bin/" do
15
+ before do
16
+ @bin_dir = File.expand_path("../../bin", __FILE__)
17
+ ARGV[0] = '-h'
18
+ end
19
+
20
+ it "has roughly valid Ruby structure for committee-stub" do
21
+ assert_output(%r{Usage: rackup \[options\] \[JSON Schema file\]}) do
22
+ load File.join(@bin_dir, "committee-stub")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe Committee do
6
+ it "debugs based off env" do
7
+ old = ENV["COMMITTEE_DEBUG"]
8
+ begin
9
+ ENV["COMMITTEE_DEBUG"] = nil
10
+ refute Committee.debug?
11
+ ENV["COMMITTEE_DEBUG"] = "true"
12
+ assert Committee.debug?
13
+ ensure
14
+ ENV["COMMITTEE_DEBUG"] = old
15
+ end
16
+ end
17
+
18
+ it "logs debug messages to stderr" do
19
+ old_stderr = $stderr
20
+ $stderr = StringIO.new
21
+ begin
22
+ stub(Committee).debug? { false }
23
+ Committee.log_debug "blah"
24
+ assert_equal "", $stderr.string
25
+
26
+ stub(Committee).debug? { true }
27
+ Committee.log_debug "blah"
28
+ assert_equal "blah\n", $stderr.string
29
+ ensure
30
+ $stderr = old_stderr
31
+ end
32
+ end
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
+
45
+ it "warns on deprecated unless $VERBOSE is nil" do
46
+ old_stderr = $stderr
47
+ old_verbose = $VERBOSE
48
+ $stderr = StringIO.new
49
+ begin
50
+ $VERBOSE = nil
51
+ Committee.warn_deprecated_until_6 true, "blah"
52
+ assert_equal "", $stderr.string
53
+
54
+ $VERBOSE = true
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
72
+ ensure
73
+ $stderr = old_stderr
74
+ $VERBOSE = old_verbose
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe Committee::Drivers::HyperSchema::Driver do
6
+ before do
7
+ @driver = Committee::Drivers::HyperSchema::Driver.new
8
+ end
9
+
10
+ it "has a name" do
11
+ assert_equal :hyper_schema, @driver.name
12
+ end
13
+
14
+ it "has a schema class" do
15
+ assert_equal Committee::Drivers::HyperSchema::Schema, @driver.schema_class
16
+ end
17
+
18
+ it "parses a hyper-schema and builds routes" do
19
+ schema = @driver.parse(hyper_schema_data)
20
+ assert_kind_of Committee::Drivers::HyperSchema::Schema, schema
21
+ assert_equal @driver, schema.driver
22
+
23
+ assert_kind_of Hash, schema.routes
24
+ refute schema.routes.empty?
25
+ assert(schema.routes.keys.all? { |m|
26
+ ["DELETE", "GET", "PATCH", "POST", "PUT"].include?(m)
27
+ })
28
+
29
+ schema.routes.each do |(_, method_routes)|
30
+ method_routes.each do |regex, link|
31
+ assert_kind_of Regexp, regex
32
+ assert_kind_of Committee::Drivers::HyperSchema::Link, link
33
+ end
34
+ end
35
+ end
36
+
37
+ it "defaults to not coercing form parameters" do
38
+ assert_equal false, @driver.default_coerce_form_params
39
+ end
40
+
41
+ it "defaults to no path parameters" do
42
+ assert_equal false, @driver.default_path_params
43
+ end
44
+
45
+ it "defaults to no query parameters" do
46
+ assert_equal false, @driver.default_query_params
47
+ end
48
+ end
49
+