Class: RSpec::Rails::Api::Metadata

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec/rails/api/metadata.rb

Overview

Handles contexts and examples metadata.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeMetadata

Returns a new instance of Metadata.



15
16
17
18
19
20
21
22
23
# File 'lib/rspec/rails/api/metadata.rb', line 15

def initialize
  @resources  = {}
  @parameters = {}
  # Only used when building metadata during RSpec boot
  @current_resource = nil
  @current_method   = nil
  @current_url      = nil
  @current_code     = nil
end

Instance Attribute Details

#current_codeObject (readonly)

rubocop:disable Metrics/ClassLength



13
14
15
# File 'lib/rspec/rails/api/metadata.rb', line 13

def current_code
  @current_code
end

#current_methodObject (readonly)

rubocop:disable Metrics/ClassLength



13
14
15
# File 'lib/rspec/rails/api/metadata.rb', line 13

def current_method
  @current_method
end

#current_resourceObject (readonly)

rubocop:disable Metrics/ClassLength



13
14
15
# File 'lib/rspec/rails/api/metadata.rb', line 13

def current_resource
  @current_resource
end

#current_urlObject (readonly)

rubocop:disable Metrics/ClassLength



13
14
15
# File 'lib/rspec/rails/api/metadata.rb', line 13

def current_url
  @current_url
end

#parametersObject (readonly)

rubocop:disable Metrics/ClassLength



13
14
15
# File 'lib/rspec/rails/api/metadata.rb', line 13

def parameters
  @parameters
end

#resourcesObject (readonly)

rubocop:disable Metrics/ClassLength



13
14
15
# File 'lib/rspec/rails/api/metadata.rb', line 13

def resources
  @resources
end

Class Method Details

.add_entity(name, fields) ⇒ void

This method returns an undefined value.

Define an entity globally.

Global entities will be available within the specs, but if they are re-declared locally, the local variant will be used.

Parameters:

  • name (Symbol)

    Entity name

  • fields (Hash)

    Fields definitions



36
37
38
39
40
41
# File 'lib/rspec/rails/api/metadata.rb', line 36

def add_entity(name, fields)
  @entities ||= {}
  raise "#{name} is already declared" if @entities.key? name

  @entities[name] = EntityConfig.new fields
end

.default_expected_content_typeObject



51
52
53
# File 'lib/rspec/rails/api/metadata.rb', line 51

def default_expected_content_type
  @default_expected_content_type ||= 'application/json; charset=utf-8'
end

.default_expected_content_type=(value) ⇒ Object



55
56
57
# File 'lib/rspec/rails/api/metadata.rb', line 55

def default_expected_content_type=(value)
  @default_expected_content_type = value.downcase
end

.entitiesObject



43
44
45
# File 'lib/rspec/rails/api/metadata.rb', line 43

def entities
  @entities || {}
end

.resetObject



47
48
49
# File 'lib/rspec/rails/api/metadata.rb', line 47

def reset
  @entities = {}
end

Instance Method Details

#add_action(method, url, summary, description = '') ⇒ void

This method returns an undefined value.

Adds an action and sets ‘@current_url` and `@current_method`

Parameters:

  • method (:get, :post, :put, :patch, delete)

    Method name

  • url (String)

    Associated URL

  • summary (String)

    What the route does for given method

  • description (String) (defaults to: '')

    Longer description of this action



161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/rspec/rails/api/metadata.rb', line 161

def add_action(method, url, summary, description = '')
  check_current_context :resource

  Utils.deep_set(@resources, [@current_resource, 'paths', url, 'actions', method],
                 description: description || '',
                 summary:     summary,
                 statuses:    {},
                 params:      {})

  @current_url    = url
  @current_method = method
end

#add_expectations(one, many, content_type: nil) ⇒ void

This method returns an undefined value.

Adds expectations for current example

Parameters:

  • one (Hash, nil)

    Entity definition

  • many (Hash, nil)

    Entity definition

  • content_type (String, nil) (defaults to: nil)

    Custom content type



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/rspec/rails/api/metadata.rb', line 216

def add_expectations(one, many, content_type: nil)
  check_current_context :resource, :url, :method, :code
  none = !many && !one

  # rubocop:disable Layout/LineLength
  Utils.deep_set(@resources,
                 [@current_resource, 'paths', @current_url, 'actions', @current_method, 'statuses', @current_code, 'expectations'],
                 {
                   one:          one,
                   many:         many,
                   none:         none,
                   content_type: content_type,
                 })
  # rubocop:enable Layout/LineLength
end

#add_parameter(name, fields) ⇒ void

This method returns an undefined value.

Adds a parameter definition

Parameters:

  • name (Symbol)

    Parameter definition name

  • fields (Hash)

    Fields definitions



79
80
81
82
83
84
85
86
87
# File 'lib/rspec/rails/api/metadata.rb', line 79

def add_parameter(name, fields)
  raise "Parameter #{name} is already defined" if @parameters[name]

  fields.each_value do |field|
    field[:required] = field[:required] != false
    field[:schema] = { type: field[:of] } if field[:type] == :array && PRIMITIVES.include?(field[:of])
  end
  @parameters[name] = fields
end

#add_path_params(fields) ⇒ void

This method returns an undefined value.

Adds path parameters definition

Parameters:

  • fields (Hash)

    Parameters definitions



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/rspec/rails/api/metadata.rb', line 95

def add_path_params(fields) # rubocop:disable Metrics/MethodLength
  check_current_context :resource, :url

  chunks = @current_url.split('?')

  fields.each do |name, field|
    valid_attribute = Validator.valid_type?(field[:type], except: %i[array object])
    raise "Field type not allowed: #{field[:type]}" unless valid_attribute

    scope = path_param_scope(chunks, name)
    Utils.deep_set(@resources, [@current_resource, 'paths', @current_url, 'path_params', name],
                   description: field[:description] || nil,
                   type:        field[:type] || nil,
                   required:    field[:required] != false,
                   scope:       scope)
  end
end

#add_request_example(url: nil, action: nil, status_code: nil, response: nil, path_params: nil, params: nil) ⇒ Object

Adds a request example

rubocop:disable Metrics/ParameterLists

Parameters:

  • url (String, nil) (defaults to: nil)

    Visited URL

  • action (String, nil) (defaults to: nil)

    HTTP verb

  • status_code (Integer, nil) (defaults to: nil)

    Status code

  • response (String, nil) (defaults to: nil)

    Response body

  • path_params (Hash, nil) (defaults to: nil)

    Used path parameters

  • params (Hash, nil) (defaults to: nil)

    Used body parameters



243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/rspec/rails/api/metadata.rb', line 243

def add_request_example(url: nil, action: nil, status_code: nil, response: nil, path_params: nil, params: nil)
  resource = nil
  @resources.each do |key, res|
    resource = key if res.dig :paths, url.to_sym, :actions, action.to_sym, :statuses, status_code.to_s.to_sym
  end

  raise "Resource not found for #{action.upcase} #{url}" unless resource

  Utils.deep_set(@resources,
                 [resource, 'paths', url, 'actions', action, 'statuses', status_code, 'example'],
                 path_params: path_params,
                 params:      params,
                 response:    response)
end

#add_request_params(fields) ⇒ void

This method returns an undefined value.

Add request parameters (body)

Fields should be something like:

id:   {type: :number, description: 'Something'},
name: {type: string, description: 'Something'}

Ex. with sub elements:

id: {type: :number, description: 'Something'},
something: {type: :object, description: 'Something', properties: {
  property: {type: :string, description: 'Something'},
  ...
}}

Parameters:

  • fields (Hash)

    Parameters definitions



129
130
131
132
133
134
135
136
# File 'lib/rspec/rails/api/metadata.rb', line 129

def add_request_params(fields)
  check_current_context :resource, :url, :method

  params = organize_params fields
  Utils.deep_set(@resources,
                 [@current_resource, 'paths', @current_url, 'actions', @current_method, 'params'],
                 params)
end

#add_resource(name, description) ⇒ void

This method returns an undefined value.

Adds a resource to metadata

Parameters:

  • name (String)

    Resource name

  • description (String)

    Resource description



67
68
69
70
# File 'lib/rspec/rails/api/metadata.rb', line 67

def add_resource(name, description)
  @resources[name.to_sym] ||= { description: description, paths: {} }
  @current_resource       = name.to_sym
end

#add_security_references(*references) ⇒ Object

Associate a defined security scheme to this request

Parameters:

  • references (Array<Symbol>)

    Security scheme reference



141
142
143
144
145
146
147
148
149
150
# File 'lib/rspec/rails/api/metadata.rb', line 141

def add_security_references(*references)
  check_current_context :resource, :url, :method

  refs = @resources.dig @current_resource, 'paths', @current_url, 'actions', @current_method, 'security'
  refs ||= []
  refs += references
  Utils.deep_set(@resources,
                 [@current_resource, 'paths', @current_url, 'actions', @current_method, 'security'],
                 refs)
end

#add_status_code(status_code, description) ⇒ void

This method returns an undefined value.

Adds a status code to metadata and sets ‘@current_code`

rubocop:disable Layout/LineLength

Parameters:

  • status_code (Integer)

    The status code

  • description (String)

    Code description



183
184
185
186
187
188
189
190
191
# File 'lib/rspec/rails/api/metadata.rb', line 183

def add_status_code(status_code, description)
  check_current_context :resource, :url, :method

  Utils.deep_set(@resources,
                 [@current_resource, 'paths', @current_url, 'actions', @current_method, 'statuses', status_code],
                 description: description,
                 example:     { response: nil })
  @current_code = status_code
end

#current_exampleHash

Gets the current example

Returns:

  • (Hash)

    Current example metadata



198
199
200
201
202
203
204
205
206
# File 'lib/rspec/rails/api/metadata.rb', line 198

def current_example
  @resources.dig @current_resource,
                 :paths,
                 @current_url.to_sym,
                 :actions,
                 @current_method.to_sym,
                 :statuses,
                 @current_code.to_s.to_sym
end

#to_hHash

Returns Hash representation of the metadata.

Returns:

  • (Hash)

    Hash representation of the metadata



261
262
263
264
265
266
# File 'lib/rspec/rails/api/metadata.rb', line 261

def to_h
  {
    resources: @resources,
    entities:  @entities,
  }
end