Class: OpenApi::RSpec::SchemaParser

Inherits:
Object
  • Object
show all
Defined in:
lib/open_api/rspec/schema_parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(openapi_schema, request, response) ⇒ SchemaParser

Returns a new instance of SchemaParser.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/open_api/rspec/schema_parser.rb', line 8

def initialize(openapi_schema, request, response)
  @openapi_schema = openapi_schema
  @request = request
  @response = response

  url = request.path.gsub(@openapi_schema['basePath'], '')
  url_fragments = url.split('/')

  @openapi_schema['paths'].each do |path, meta|
    path_fragments = path.to_s.split('/')
    next if path_fragments.count != url_fragments.count

    mismatch = false
    @request_path_params = {}
    path_fragments.each_with_index do |a, i|
      if has_documented_param_in_openapi_url_fragments(a)
        openapi_for_http_method = meta[request.method.to_s.downcase.to_s]
        unless openapi_for_http_method
          mismatch = true
          break
        end
        openapi_params = openapi_for_http_method['parameters']
        unless openapi_params
          mismatch = true
          break
        end
        openapi_path_params = openapi_params.select do |path_param|
          path_param['in'].to_s == 'path'
        end
        unless openapi_path_params
          mismatch = true
          break
        end
        meta_param = openapi_path_params.find do |path_param|
          path_param['name'].to_s == openapi_url_fragment_name(a).to_s
        end
        if meta_param
          case meta_param['type'].to_s
          when 'integer'
            if (url_fragments[i] =~ /\d/) != 0
              mismatch = true
              break
            else
              @request_path_params[a.delete('{').delete('}')] = url_fragments[i]
              next
            end
          when 'string'
            @request_path_params[a.delete('{').delete('}')] = url_fragments[i]
            next
          else
            mismatch = true
            break
          end
        else
          mismatch = true
          break
        end
      end

      mismatch = a != url_fragments[i]
      break if mismatch
    end

    next if mismatch

    @schema_for_url = meta

    break
  end
end

Instance Attribute Details

#openapi_schemaObject (readonly)

Returns the value of attribute openapi_schema.



6
7
8
# File 'lib/open_api/rspec/schema_parser.rb', line 6

def openapi_schema
  @openapi_schema
end

#requestObject (readonly)

Returns the value of attribute request.



6
7
8
# File 'lib/open_api/rspec/schema_parser.rb', line 6

def request
  @request
end

#responseObject (readonly)

Returns the value of attribute response.



6
7
8
# File 'lib/open_api/rspec/schema_parser.rb', line 6

def response
  @response
end

#schema_for_urlObject (readonly)

Returns the value of attribute schema_for_url.



6
7
8
# File 'lib/open_api/rspec/schema_parser.rb', line 6

def schema_for_url
  @schema_for_url
end

Instance Method Details

#deep_body_keys(name, hash) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/open_api/rspec/schema_parser.rb', line 175

def deep_body_keys(name, hash)
  if hash['type'] == 'object'
    hash['properties'].flat_map do |p_name, p_hash|
      parent = name.to_s.camelize(:lower).to_s
      sub_keys = deep_body_keys(p_name, p_hash)
      sub_keys.flat_map do |sub|
        "#{parent}##{sub}".to_s
      end
    end
  else
    [name.to_s.camelize(:lower).to_s]
  end
end

#get_deep_keys(hash) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/open_api/rspec/schema_parser.rb', line 222

def get_deep_keys(hash)
  return [] if hash.empty?

  hash.flat_map do |k, v|
    if v.is_a? Hash
      parent = k.to_s.camelize(:lower).to_s
      sub_keys = get_deep_keys(v)
      sub_keys.map do |sub|
        "#{parent}##{sub}".to_s
      end
    else
      k.to_s.camelize(:lower).to_s
    end
  end
end

#has_documented_param_in_openapi_url_fragments(fragment) ⇒ Object



79
80
81
# File 'lib/open_api/rspec/schema_parser.rb', line 79

def has_documented_param_in_openapi_url_fragments(fragment)
  (fragment =~ /^{.+}$/) == 0
end

#openapi_body_paramsObject



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/open_api/rspec/schema_parser.rb', line 144

def openapi_body_params
  schema_for_url_and_request_method_body_parameters.flat_map do |p|
    if p['schema'].present?
      body = if p['schema']['$ref']
               scheme = p['schema']['$ref'].tr('/', ' ')[2..-1].strip.split.map(&:to_s)
               @openapi_schema.dig(*scheme)
             else
               p['schema']
             end

      if body['allOf']
        scheme = body['allOf'].first['$ref'].tr('/', ' ')[2..-1].strip.split.map(&:to_s)
        all_of_schema_properties = @openapi_schema.dig(*scheme)
        scheme_props = all_of_schema_properties['properties'].flat_map do |k, v|
          deep_body_keys(k, v)
        end
        additional_props = body['allOf'].last['properties'].flat_map do |k, v|
          deep_body_keys(k, v)
        end
        scheme_props + additional_props
      else
        body['properties'].flat_map do |k, v|
          deep_body_keys(k, v)
        end
      end
    else
      p['name'].to_s
    end
  end
end

#openapi_form_data_paramsObject



140
141
142
# File 'lib/open_api/rspec/schema_parser.rb', line 140

def openapi_form_data_params
  schema_for_url_and_request_method_form_data_parameters.map { |p| p['name'].to_s }
end

#openapi_path_paramsObject



136
137
138
# File 'lib/open_api/rspec/schema_parser.rb', line 136

def openapi_path_params
  schema_for_url_and_request_method_path_parameters.map { |p| p['name'].to_s }
end

#openapi_query_string_paramsObject



132
133
134
# File 'lib/open_api/rspec/schema_parser.rb', line 132

def openapi_query_string_params
  schema_for_url_and_request_method_query_string_parameters.map { |p| p['name'].to_s }
end

#openapi_request_paramsObject



189
190
191
192
193
194
195
196
# File 'lib/open_api/rspec/schema_parser.rb', line 189

def openapi_request_params
  [
    openapi_query_string_params,
    openapi_path_params,
    openapi_form_data_params,
    openapi_body_params
  ].flatten.compact
end

#openapi_required_form_data_paramsObject



198
199
200
201
202
# File 'lib/open_api/rspec/schema_parser.rb', line 198

def openapi_required_form_data_params
  schema_for_url_and_request_method_form_data_parameters
    .select { |p| p['required'] == true }
    .map { |p| p['name'].to_s }
end

#openapi_required_path_paramsObject



204
205
206
207
208
# File 'lib/open_api/rspec/schema_parser.rb', line 204

def openapi_required_path_params
  schema_for_url_and_request_method_path_parameters
    .select { |p| p['required'] == true }
    .map { |p| p['name'].to_s }
end

#openapi_required_query_string_paramsObject



210
211
212
213
214
# File 'lib/open_api/rspec/schema_parser.rb', line 210

def openapi_required_query_string_params
  schema_for_url_and_request_method_query_string_parameters
    .select { |p| p['required'] == true }
    .map { |p| p['name'].to_s }
end

#openapi_url_fragment_name(fragment) ⇒ Object



83
84
85
# File 'lib/open_api/rspec/schema_parser.rb', line 83

def openapi_url_fragment_name(fragment)
  fragment.match(/^{(.+)}$/).captures.first
end

#request_paramsObject



216
217
218
219
220
# File 'lib/open_api/rspec/schema_parser.rb', line 216

def request_params
  valid_params = get_deep_keys(request.params.except('format', 'action', 'controller'))

  valid_params - request_path_params
end

#request_path_paramsObject



87
88
89
# File 'lib/open_api/rspec/schema_parser.rb', line 87

def request_path_params
  @request_path_params.map { |k, _| k.to_s }
end

#schema_for_url_and_request_methodObject



91
92
93
94
95
96
97
# File 'lib/open_api/rspec/schema_parser.rb', line 91

def schema_for_url_and_request_method
  if schema_for_url
    schema_for_url[request.method.to_s.downcase.to_s]
  else
    {}
  end
end

#schema_for_url_and_request_method_and_response_statusObject



123
124
125
126
127
128
129
130
# File 'lib/open_api/rspec/schema_parser.rb', line 123

def schema_for_url_and_request_method_and_response_status
  if schema_for_url_and_request_method['responses']
    schema = schema_for_url_and_request_method['responses'][response.status.to_s]
    schema
  else
    {}
  end
end

#schema_for_url_and_request_method_body_parametersObject



118
119
120
121
# File 'lib/open_api/rspec/schema_parser.rb', line 118

def schema_for_url_and_request_method_body_parameters
  schema_for_url_and_request_method_parameters
    .select { |p| p['in'].to_s == 'body' }
end

#schema_for_url_and_request_method_form_data_parametersObject



113
114
115
116
# File 'lib/open_api/rspec/schema_parser.rb', line 113

def schema_for_url_and_request_method_form_data_parameters
  schema_for_url_and_request_method_parameters
    .select { |p| p['in'].to_s == 'formData' }
end

#schema_for_url_and_request_method_parametersObject



99
100
101
# File 'lib/open_api/rspec/schema_parser.rb', line 99

def schema_for_url_and_request_method_parameters
  schema_for_url_and_request_method['parameters'] || [{}]
end

#schema_for_url_and_request_method_path_parametersObject



108
109
110
111
# File 'lib/open_api/rspec/schema_parser.rb', line 108

def schema_for_url_and_request_method_path_parameters
  schema_for_url_and_request_method_parameters
    .select { |p| p['in'].to_s == 'path' }
end

#schema_for_url_and_request_method_query_string_parametersObject



103
104
105
106
# File 'lib/open_api/rspec/schema_parser.rb', line 103

def schema_for_url_and_request_method_query_string_parameters
  schema_for_url_and_request_method_parameters
    .select { |p| p['in'].to_s == 'query' }
end