require 'active_support/core_ext/hash/deep_merge' require 'rspec/core/formatters/base_text_formatter' require 'swagger_helper' module Rswag module Specs class SwaggerFormatter # NOTE: rspec 2.x support if RSPEC_VERSION > 2 ::RSpec::Core::Formatters.register self, :example_group_finished, :stop end def initialize(output) @output = output @swagger_root = ::RSpec.configuration.swagger_root raise ConfigurationError, 'Missing swagger_root. See swagger_helper.rb' if @swagger_root.nil? @swagger_docs = ::RSpec.configuration.swagger_docs || [] raise ConfigurationError, 'Missing swagger_docs. See swagger_helper.rb' if @swagger_docs.empty? @output.puts 'Generating Swagger docs ...' end def example_group_finished(notification) # NOTE: rspec 2.x support if RSPEC_VERSION > 2 metadata = notification.group.metadata else metadata = notification.metadata end return unless metadata.has_key?(:response) swagger_doc = get_swagger_doc(metadata[:swagger_doc]) swagger_doc.deep_merge!(metadata_to_swagger(metadata)) end def stop(notification=nil) @swagger_docs.each do |url_path, doc| file_path = File.join(@swagger_root, url_path) dirname = File.dirname(file_path) FileUtils.mkdir_p dirname unless File.exists?(dirname) File.open(file_path, 'w') do |file| file.write(JSON.pretty_generate(doc)) end @output.puts "Swagger doc generated at #{file_path}" end end private def get_swagger_doc(tag) return @swagger_docs.values.first if tag.nil? raise ConfigurationError, "Unknown swagger_doc '#{tag}'" unless @swagger_docs.has_key?(tag) @swagger_docs[tag] end def metadata_to_swagger(metadata) response_code = metadata[:response][:code] response = metadata[:response].reject { |k,v| k == :code } verb = metadata[:operation][:verb] operation = metadata[:operation] .reject { |k,v| k == :verb } .merge(responses: { response_code => response }) { paths: { metadata[:path] => { verb => operation } } } end end class ConfigurationError < StandardError; end end end