class RSpec::Rails::Api::Metadata
Handles contexts and examples metadatas.
Attributes
current_resource[R]
entities[R]
parameters[R]
resources[R]
Public Class Methods
new()
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 14 def initialize @resources = {} @entities = {} @parameters = {} # Only used when building metadata during RSpec boot @current_resource = nil @current_method = nil @current_url = nil @current_code = nil end
Public Instance Methods
add_action(method, url, description)
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 78 def add_action(method, url, description) check_current_context :resource Utils.deep_set(@resources, "#{@current_resource}.paths.#{url}.actions.#{method}", description: description, statuses: {}, params: {}) @current_url = url @current_method = method end
add_entity(type, fields)
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 30 def add_entity(type, fields) Utils.deep_set(@resources, "#{@current_resource}.entities.#{type}", EntityConfig.new(fields)) end
add_parameter(type, fields)
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 36 def add_parameter(type, fields) raise "Parameter #{type} is already defined" if @parameters[type] @parameters[type] = fields end
add_path_params(fields)
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 42 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 = Utils.check_attribute_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] || true, scope: scope) end end
add_request_example(url: nil, action: nil, status_code: nil, response: nil, path_params: nil, params: nil)
click to toggle source
rubocop:disable Metrics/ParameterLists
# File lib/rspec/rails/api/metadata.rb, line 103 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 Utils.deep_get(res, "paths.#{url}.actions.#{action}.statuses.#{status_code}") 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)
click to toggle source
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'}, ... }}
# File lib/rspec/rails/api/metadata.rb, line 69 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)
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 25 def add_resource(name, description) @resources[name.to_sym] = { description: description, paths: {} } @current_resource = name.to_sym end
add_status_code(status_code, description)
click to toggle source
rubocop:disable Layout/LineLength
# File lib/rspec/rails/api/metadata.rb, line 91 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
to_h()
click to toggle source
rubocop:enable Metrics/ParameterLists
# File lib/rspec/rails/api/metadata.rb, line 119 def to_h { resources: @resources, entities: @entities, } end
Private Instance Methods
check_current_context(*scope)
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 128 def check_current_context(*scope) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity scope ||= [] raise 'No resource declared' if scope.include?(:resource) && !@current_resource raise 'No action declared' if scope.include?(:method) && !@current_method raise 'No url declared' if scope.include?(:url) && !@current_url raise 'No status code declared' if scope.include?(:code) && !@current_code end
fill_request_param(field)
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 162 def fill_request_param(field) if field[:type] == :object && field[:properties] organize_params field[:properties] else properties = { type: PARAM_TYPES[field[:type]][:type], description: field[:description] || nil, } properties[:items] = organize_params field[:of] if field[:type] == :array && field[:of] properties end end
organize_params(fields)
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 146 def organize_params(fields) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength out = { properties: {} } required = [] allowed_types = %i[array object] fields.each do |name, field| allowed_type = allowed_types.include?(field[:type]) || PARAM_TYPES.key?(field[:type]) raise "Field type not allowed: #{field[:type]}" unless allowed_type required.push name.to_s if field[:required] out[:properties][name] = fill_request_param field end out[:required] = required if required.count.positive? out end
path_param_scope(url_chunks, name)
click to toggle source
# File lib/rspec/rails/api/metadata.rb, line 136 def path_param_scope(url_chunks, name) if /:#{name}/.match?(url_chunks[0]) :path elsif url_chunks[1] && /:#{name}/ =~ url_chunks[1] :query else raise "#{name} not found in URL #{@current_url}" end end