lib/swagalicious/swagger_formatter.rb in swagalicious-0.1.0 vs lib/swagalicious/swagger_formatter.rb in swagalicious-0.2.0

- old
+ new

@@ -1,80 +1,84 @@ # frozen_string_literal: true require_relative "../core/ext/hash" -module Swagalicious +class Swagalicious class SwaggerFormatter - RSpec::Core::Formatters.register self, :example_group_finished, :stop + RSpec::Core::Formatters.register self, :stop - def initialize(output, config = Swagalicious.config) + def config + @config ||= Swagalicious.config + end + + def initialize(output, config = nil) @output = output @config = config @output.puts "Generating Swagger docs ..." end - def example_group_finished(notification) - metadata = notification.group.metadata + def merge_metadata_to_document(doc, example) + metadata = example.metadata + # !metadata[:document] won"t work, since nil means we should generate + # docs. + return {} if metadata[:document] == false + return {} unless metadata.key?(:response) + # This is called multiple times per file! + # metadata[:operation] is also re-used between examples within file + # therefore be careful NOT to modify its content here. + upgrade_servers!(doc) + upgrade_oauth!(doc) + upgrade_response_produces!(doc, metadata) + upgrade_request_type!(metadata) - # !metadata[:document] won"t work, since nil means we should generate - # docs. - return if metadata[:document] == false - return unless metadata.key?(:response) + unless doc_version(doc).start_with?("2") + doc[:paths]&.each_pair do |_k, v| + v.each_pair do |_verb, value| + is_hash = value.is_a?(Hash) + if is_hash && value.dig(:parameters) + schema_param = value.dig(:parameters)&.find { |p| (p[:in] == :body || p[:in] == :formData) && p[:schema] } + mime_list = value.dig(:consumes) + if value && schema_param && mime_list + value[:requestBody] = { content: {} } unless value.dig(:requestBody, :content) + mime_list.each do |mime| + value[:requestBody][:content][mime] = { schema: schema_param[:schema] } + end + end - swagger_doc = @config.get_swagger_doc(metadata[:swagger_doc]) + value[:parameters].reject! { |p| p[:in] == :body || p[:in] == :formData } + end + remove_invalid_operation_keys!(value) + end + end + end - # This is called multiple times per file! - # metadata[:operation] is also re-used between examples within file - # therefore be careful NOT to modify its content here. - upgrade_request_type!(metadata) - upgrade_servers!(swagger_doc) - upgrade_oauth!(swagger_doc) - upgrade_response_produces!(swagger_doc, metadata) - - swagger_doc.deep_merge!(metadata_to_swagger(metadata)) + doc.deep_merge!(metadata_to_swagger(metadata)) end - def stop(_notification = nil) - @config.swagger_docs.each do |url_path, doc| - unless doc_version(doc).start_with?("2") - doc[:paths]&.each_pair do |_k, v| - v.each_pair do |_verb, value| - is_hash = value.is_a?(Hash) - if is_hash && value.dig(:parameters) - schema_param = value.dig(:parameters)&.find { |p| (p[:in] == :body || p[:in] == :formData) && p[:schema] } - mime_list = value.dig(:consumes) - if value && schema_param && mime_list - value[:requestBody] = { content: {} } unless value.dig(:requestBody, :content) - mime_list.each do |mime| - value[:requestBody][:content][mime] = { schema: schema_param[:schema] } - end - end + def stop(notification = nil) + config.swagger_docs.each do |url_path, doc| + examples = notification.examples.select { |e| e.metadata[:swagger_doc] == url_path } - value[:parameters].reject! { |p| p[:in] == :body || p[:in] == :formData } - end - remove_invalid_operation_keys!(value) - end - end - end + merged_doc = examples.each_with_object(doc) { |e, doc| doc = doc.deep_merge!(merge_metadata_to_document(doc, e)) } - file_path = File.join(@config.swagger_root, url_path) + file_path = File.join(config.swagger_root, url_path) dirname = File.dirname(file_path) FileUtils.mkdir_p dirname unless File.exist?(dirname) File.open(file_path, "w") do |file| - file.write(pretty_generate(doc)) + file.write(pretty_generate(merged_doc)) end @output.puts "Swagger doc generated at #{file_path}" end end private def pretty_generate(doc) - if @config.swagger_format == :yaml + if config.swagger_format == :yaml clean_doc = yaml_prepare(doc) YAML.dump(clean_doc) else # config errors are thrown in "def swagger_format", no throw needed here JSON.pretty_generate(doc) end @@ -101,10 +105,10 @@ { paths: { path_template => path_item } } end def doc_version(doc) - doc[:openapi] || doc[:swagger] || "3" + doc[:openapi] || doc[:swagger] || "3.0.0" end def upgrade_response_produces!(swagger_doc, metadata) # Accept header mime_list = Array(metadata[:operation][:produces] || swagger_doc[:produces])