class RSpec::Rails::Api::OpenApiRenderer
Class to render metadatas. Example:
```rb renderer = RSpec::Rails::Api::OpenApiRenderer.new renderer.merge_context(example_context) renderer.write_files ```
Attributes
api_description[W]
api_servers[W]
api_title[W]
api_tos[W]
api_version[W]
Public Class Methods
new()
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 19 def initialize @metadata = { resources: {}, entities: {} } @api_infos = {} @api_servers = [] @api_paths = {} @api_components = {} @api_tags = [] @api_contact = {} @api_license = {} end
Public Instance Methods
api_contact=(name: nil, email: nil, url: nil)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 64 def api_contact=(name: nil, email: nil, url: nil) @api_contact[:name] = name if name @api_contact[:email] = email if email @api_contact[:url] = url if url end
api_license=(name: nil, url: nil)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 70 def api_license=(name: nil, url: nil) @api_license[:name] = name if name @api_license[:url] = url if url end
merge_context(context, dump_metadata: false)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 30 def merge_context(context, dump_metadata: false) @metadata[:resources].deep_merge! context[:resources] @metadata[:entities].deep_merge! context[:entities] # Save context for debug and fixtures File.write ::Rails.root.join('tmp', 'rra_metadata.yaml'), context.to_yaml if dump_metadata end
prepare_metadata()
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 51 def prepare_metadata # Example: https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore-expanded.yaml extract_metadatas { openapi: '3.0.0', info: @api_infos, servers: @api_servers, paths: @api_paths, components: @api_components, tags: @api_tags, }.deep_stringify_keys end
write_files(path = nil, only: %i[yaml json])
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 38 def write_files(path = nil, only: %i[yaml json]) content = prepare_metadata path ||= ::Rails.root.join('tmp', 'rspec_api_rails') file_types = %i[yaml json] only.each do |type| next unless file_types.include? type File.write "#{path}.#{type}", JSON.parse(JSON.pretty_generate(content)).send("to_#{type}") end end
Private Instance Methods
api_infos()
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 225 def api_infos @api_infos = { title: @api_title || 'Some sample app', version: @api_version || '1.0', } @api_infos[:description] = @api_description if @api_description @api_infos[:termsOfService] = @api_tos if @api_tos @api_infos[:contact] = @api_contact if @api_contact[:name] @api_infos[:license] = @api_license if @api_license[:name] @api_infos end
api_servers()
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 238 def api_servers @api_servers || [ { url: 'http://api.example.com' }, ] end
escape_operation_id(string)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 221 def escape_operation_id(string) string.downcase.gsub(/[^\w]+/, '_') end
extract_from_resources()
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 83 def extract_from_resources @metadata[:resources].each do |resource_key, resource| @api_tags.push( name: resource_key.to_s, description: resource[:description] ) process_resource resource: resource_key, resource_config: resource end end
extract_metadatas()
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 77 def extract_metadatas extract_from_resources api_infos api_servers end
path_with_params(string)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 215 def path_with_params(string) string.gsub(/(?::(\w*))/) do |e| "{#{e.sub(':', '')}}" end end
process_action(resource: nil, path: nil, path_config: nil, action_config: nil, parameters: nil)
click to toggle source
rubocop:disable Metrics/AbcSize, Metrics/MethodLength
# File lib/rspec/rails/api/open_api_renderer.rb, line 140 def process_action(resource: nil, path: nil, path_config: nil, action_config: nil, parameters: nil) responses = {} request_body = nil if %i[post put patch].include?(action_config) && path_config[:actions][action_config][:params].keys.count.positive? schema = path_config[:actions][action_config][:params] schema_ref = escape_operation_id("#{action_config}_#{path}") examples = process_examples(path_config[:actions][action_config][:statuses]) request_body = process_request_body schema: schema, ref: schema_ref, examples: examples end path_config[:actions][action_config][:statuses].each do |status_key, status| content = status[:example][:response] responses[status_key] = process_response status: status_key, status_config: status, content: content end description = path_config[:actions][action_config][:description] action = { description: description, operationId: "#{resource} #{description}".downcase.gsub(/[^\w]/, '_'), parameters: parameters, responses: responses, tags: [resource.to_s], } action[:requestBody] = request_body if request_body action end
process_examples(statuses)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 202 def process_examples(statuses) request_examples = {} statuses.each do |code, request| request_examples[code] = { summary: "Example for a #{code} code", value: request[:example][:params], } end request_examples end
process_path_param(name, param)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 123 def process_path_param(name, param) # rubocop:disable Metrics/MethodLength parameter = { name: name.to_s, description: param[:description], required: param[:required] || true, in: param[:scope].to_s, schema: { type: PARAM_TYPES[param[:type]][:type], }, } parameter[:schema][:format] = PARAM_TYPES[param[:type]][:format] if PARAM_TYPES[param[:type]][:format] parameter end
process_path_params(params)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 114 def process_path_params(params) parameters = [] params.each do |name, param| parameters.push process_path_param name, param end parameters end
process_request_body(schema: nil, ref: nil, examples: {})
click to toggle source
rubocop:enable Metrics/AbcSize, Metrics/MethodLength
# File lib/rspec/rails/api/open_api_renderer.rb, line 172 def process_request_body(schema: nil, ref: nil, examples: {}) Utils.deep_set @api_components, "schemas.#{ref}", schema { # description: '', required: true, content: { 'application/json' => { schema: { '$ref' => "#/components/schemas/#{ref}" }, examples: examples, }, }, } end
process_resource(resource: nil, resource_config: nil)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 93 def process_resource(resource: nil, resource_config: nil) # rubocop:disable Metrics/MethodLength http_verbs = %i[get post put patch delete] resource_config[:paths].each do |path_key, path| url = path_with_params path_key.to_s actions = {} parameters = path.key?(:path_params) ? process_path_params(path[:path_params]) : [] path[:actions].each_key do |action| next unless http_verbs.include? action actions[action] = process_action resource: resource, path: path_key, path_config: path, action_config: action, parameters: parameters end @api_paths[url] = actions end end
process_response(status: nil, status_config: nil, content: nil)
click to toggle source
# File lib/rspec/rails/api/open_api_renderer.rb, line 186 def process_response(status: nil, status_config: nil, content: nil) response = { description: status_config[:description], } return response if status.to_s == '204' && content # No content response[:content] = { 'application/json': { examples: { default: { value: JSON.parse(content) } }, }, } response end