openapi_contracts 0.13.0 → 0.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e3c770fbbdd4c6d8a18f69f9deaf65959ce70088232ad8291a5aa10bf4b6f0e
4
- data.tar.gz: 2248125b3e18a71d403f72b25eae01c2173628f0c58deaf7e004d501cb7f9b16
3
+ metadata.gz: 6a860586af31ca0bcf61a9301dba60df4466d367a495efbb306498eb71496f09
4
+ data.tar.gz: d74042e38633c207a4410ba6e961e68ed206f4b9d3a0d1fe0ea8d8aa1f4f4982
5
5
  SHA512:
6
- metadata.gz: 64d09afded34921b66bd12573998906882681cf68e62c277abb1f569afa3da93e856240877e9edffa1768c14d7a9766de0a9be57bf9f40a0b443c366187f8813
7
- data.tar.gz: 3b93196eaaf631d853d693a6082b19399b2db334190cd0bc7d8d27d80ddf67260556249f284c515fb6c0bf207d9d6599a916a2bfbccdbb4c40d6637ae08004fd
6
+ metadata.gz: 0bdddf66b9418f3374179566ebccfa5d7abad647708557ce5ec176afe620cbfcf79102743ffff6d293503278eeaccd8465e0a8627ff03b646b44c2c0aeb7e8f4
7
+ data.tar.gz: 9c0e8a0ba61f44bb8bde129524531a7a60918c9ff5fc23072c3d547a23a70ae45ef1e1a0983dc48b0ff2f57c8caf4e5998b5c80088d08aa645c99ccc0ed9acf6
data/README.md CHANGED
@@ -62,6 +62,12 @@ it { is_expected.to match_openapi_doc($doc, path: '/messages/{id}').with_http_st
62
62
  it { is_expected.to match_openapi_doc($doc, request_body: true).with_http_status(:created) }
63
63
  ```
64
64
 
65
+ * `parameters` can be set to `true` to validate request parameters against the parameter definitions
66
+
67
+ ```ruby
68
+ it { is_expected.to match_openapi_doc($doc, parameters: true) }
69
+ ```
70
+
65
71
  Both options can as well be used simultaneously.
66
72
 
67
73
  ### Without RSpec
@@ -14,33 +14,34 @@ module OpenapiContracts
14
14
  @in == 'path'
15
15
  end
16
16
 
17
+ def in_query?
18
+ @in == 'query'
19
+ end
20
+
17
21
  def matches?(value)
18
- case @spec.dig('schema', 'type')
19
- when 'integer'
20
- integer_parameter_matches?(value)
21
- when 'number'
22
- number_parameter_matches?(value)
23
- else
24
- schemer.valid?(value)
25
- end
22
+ errors = schemer.validate(convert_value(value))
23
+ # debug errors.to_a here
24
+ errors.none?
26
25
  end
27
26
 
28
- private
27
+ def required?
28
+ @required == true
29
+ end
29
30
 
30
- def schemer
31
- @schemer ||= Validators::SchemaValidation.validation_schemer(@spec.navigate('schema'))
31
+ def schema_for_validation
32
+ @spec.navigate('schema')
32
33
  end
33
34
 
34
- def integer_parameter_matches?(value)
35
- return false unless /^-?\d+$/.match?(value)
35
+ private
36
36
 
37
- schemer.valid?(value.to_i)
37
+ def convert_value(original)
38
+ OpenapiParameters::Converter.convert(original, schema_for_validation)
39
+ rescue StandardError
40
+ original
38
41
  end
39
42
 
40
- def number_parameter_matches?(value)
41
- return false unless /^-?(\d+\.)?\d+$/.match?(value)
42
-
43
- schemer.valid?(value.to_f)
43
+ def schemer
44
+ @schemer ||= Validators::SchemaValidation.validation_schemer(schema_for_validation)
44
45
  end
45
46
  end
46
47
  end
@@ -35,20 +35,20 @@ module OpenapiContracts
35
35
  end
36
36
 
37
37
  # Returns an Enumerator over all Operations
38
- def operations(&block) # rubocop:disable Naming/BlockForwarding
38
+ def operations(&block)
39
39
  return enum_for(:operations) unless block_given?
40
40
 
41
41
  paths.each do |path|
42
- path.operations.each(&block) # rubocop:disable Naming/BlockForwarding
42
+ path.operations.each(&block)
43
43
  end
44
44
  end
45
45
 
46
46
  # Returns an Enumerator over all Responses
47
- def responses(&block) # rubocop:disable Naming/BlockForwarding
47
+ def responses(&block)
48
48
  return enum_for(:responses) unless block_given?
49
49
 
50
50
  operations.each do |operation|
51
- operation.responses.each(&block) # rubocop:disable Naming/BlockForwarding
51
+ operation.responses.each(&block)
52
52
  end
53
53
  end
54
54
 
@@ -1,6 +1,9 @@
1
1
  module OpenapiContracts
2
2
  class Match
3
- DEFAULT_OPTIONS = {request_body: false}.freeze
3
+ DEFAULT_OPTIONS = {
4
+ parameters: false,
5
+ request_body: false
6
+ }.freeze
4
7
  MIN_REQUEST_ANCESTORS = %w(Rack::Request::Env Rack::Request::Helpers).freeze
5
8
  MIN_RESPONSE_ANCESTORS = %w(Rack::Response::Helpers).freeze
6
9
 
@@ -42,6 +45,7 @@ module OpenapiContracts
42
45
  )
43
46
  validators = Validators::ALL.dup
44
47
  validators.delete(Validators::HttpStatus) unless @options[:status]
48
+ validators.delete(Validators::Parameters) unless @options[:parameters]
45
49
  validators.delete(Validators::RequestBody) unless @options[:request_body]
46
50
  validators.reverse
47
51
  .reduce(->(err) { err }) { |s, m| m.new(s, env) }
@@ -30,7 +30,7 @@ module OpenapiContracts
30
30
  # file list consists of
31
31
  # - root file
32
32
  # - all files in components/
33
- # - all path files referenced by the root file
33
+ # - all path & webhook files referenced by the root file
34
34
  def build_file_list
35
35
  list = {@rootfile.relative_path_from(@cwd) => Doc::Pointer[]}
36
36
  Dir[File.expand_path('components/**/*.yaml', @cwd)].each do |file|
@@ -38,16 +38,21 @@ module OpenapiContracts
38
38
  pointer = Doc::Pointer.from_path pathname.sub_ext('')
39
39
  list.merge! pathname => pointer
40
40
  end
41
- YAML.safe_load_file(@rootfile).fetch('paths') { {} }.each_pair do |k, v|
42
- next unless v['$ref'] && !v['$ref'].start_with?('#')
41
+ rootdata = YAML.safe_load_file(@rootfile)
42
+ %w(paths webhooks).each do |name|
43
+ rootdata.fetch(name) { {} }.each_pair do |k, v|
44
+ next unless v['$ref'] && !v['$ref'].start_with?('#')
43
45
 
44
- list.merge! Pathname(v['$ref']).cleanpath => Doc::Pointer['paths', k]
46
+ list.merge! Pathname(v['$ref']).cleanpath => Doc::Pointer[name, k]
47
+ end
45
48
  end
46
49
  list
47
50
  end
48
51
 
49
52
  def file_to_data(pathname, pointer)
50
53
  YAML.safe_load_file(@cwd.join(pathname)).tap do |data|
54
+ break {} unless data.present?
55
+
51
56
  transform_objects!(data, pathname.parent, pointer)
52
57
  end
53
58
  end
@@ -0,0 +1,21 @@
1
+ module OpenapiContracts::Validators
2
+ # Validates the input parameters, eg path/url parameters
3
+ class Parameters < Base
4
+ include SchemaValidation
5
+
6
+ private
7
+
8
+ def validate
9
+ operation.parameters.select(&:in_query?).each do |parameter|
10
+ if request.GET.key?(parameter.name)
11
+ value = request.GET[parameter.name]
12
+ unless parameter.matches?(value)
13
+ @errors << "#{value.inspect} is not a valid value for the query parameter #{parameter.name.inspect}"
14
+ end
15
+ elsif parameter.required?
16
+ @errors << "Missing query parameter #{parameter.name.inspect}"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -4,6 +4,7 @@ module OpenapiContracts
4
4
  autoload :Documented, 'openapi_contracts/validators/documented'
5
5
  autoload :Headers, 'openapi_contracts/validators/headers'
6
6
  autoload :HttpStatus, 'openapi_contracts/validators/http_status'
7
+ autoload :Parameters, 'openapi_contracts/validators/parameters'
7
8
  autoload :RequestBody, 'openapi_contracts/validators/request_body'
8
9
  autoload :ResponseBody, 'openapi_contracts/validators/response_body'
9
10
  autoload :SchemaValidation, 'openapi_contracts/validators/schema_validation'
@@ -12,6 +13,7 @@ module OpenapiContracts
12
13
  ALL = [
13
14
  Documented,
14
15
  HttpStatus,
16
+ Parameters,
15
17
  RequestBody,
16
18
  ResponseBody,
17
19
  Headers
@@ -7,6 +7,7 @@ require 'active_support/core_ext/string'
7
7
  require 'rubygems/version'
8
8
 
9
9
  require 'json_schemer'
10
+ require 'openapi_parameters'
10
11
  require 'rack'
11
12
  require 'yaml'
12
13
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openapi_contracts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mkon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-09 00:00:00.000000000 Z
11
+ date: 2024-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -50,6 +50,26 @@ dependencies:
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '2.2'
53
+ - !ruby/object:Gem::Dependency
54
+ name: openapi_parameters
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 0.3.3
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '0.4'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 0.3.3
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '0.4'
53
73
  - !ruby/object:Gem::Dependency
54
74
  name: rack
55
75
  requirement: !ruby/object:Gem::Requirement
@@ -84,42 +104,42 @@ dependencies:
84
104
  requirements:
85
105
  - - "~>"
86
106
  - !ruby/object:Gem::Version
87
- version: 3.12.0
107
+ version: 3.13.0
88
108
  type: :development
89
109
  prerelease: false
90
110
  version_requirements: !ruby/object:Gem::Requirement
91
111
  requirements:
92
112
  - - "~>"
93
113
  - !ruby/object:Gem::Version
94
- version: 3.12.0
114
+ version: 3.13.0
95
115
  - !ruby/object:Gem::Dependency
96
116
  name: rubocop
97
117
  requirement: !ruby/object:Gem::Requirement
98
118
  requirements:
99
119
  - - '='
100
120
  - !ruby/object:Gem::Version
101
- version: 1.59.0
121
+ version: 1.64.1
102
122
  type: :development
103
123
  prerelease: false
104
124
  version_requirements: !ruby/object:Gem::Requirement
105
125
  requirements:
106
126
  - - '='
107
127
  - !ruby/object:Gem::Version
108
- version: 1.59.0
128
+ version: 1.64.1
109
129
  - !ruby/object:Gem::Dependency
110
130
  name: rubocop-rspec
111
131
  requirement: !ruby/object:Gem::Requirement
112
132
  requirements:
113
133
  - - '='
114
134
  - !ruby/object:Gem::Version
115
- version: 2.25.0
135
+ version: 2.31.0
116
136
  type: :development
117
137
  prerelease: false
118
138
  version_requirements: !ruby/object:Gem::Requirement
119
139
  requirements:
120
140
  - - '='
121
141
  - !ruby/object:Gem::Version
122
- version: 2.25.0
142
+ version: 2.31.0
123
143
  - !ruby/object:Gem::Dependency
124
144
  name: simplecov
125
145
  requirement: !ruby/object:Gem::Requirement
@@ -170,6 +190,7 @@ files:
170
190
  - lib/openapi_contracts/validators/documented.rb
171
191
  - lib/openapi_contracts/validators/headers.rb
172
192
  - lib/openapi_contracts/validators/http_status.rb
193
+ - lib/openapi_contracts/validators/parameters.rb
173
194
  - lib/openapi_contracts/validators/request_body.rb
174
195
  - lib/openapi_contracts/validators/response_body.rb
175
196
  - lib/openapi_contracts/validators/schema_validation.rb
@@ -196,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
217
  - !ruby/object:Gem::Version
197
218
  version: '0'
198
219
  requirements: []
199
- rubygems_version: 3.4.22
220
+ rubygems_version: 3.5.11
200
221
  signing_key:
201
222
  specification_version: 4
202
223
  summary: Openapi schemas as API contracts