lib/dox/formatter.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
95%
require 'rspec/core'
require 'rspec/core/formatters/base_formatter'
require 'rspec/core/formatters/console_codes'

module Dox
  class Formatter < RSpec::Core::Formatters::BaseFormatter
    extend Forwardable

    RSpec::Core::Formatters.register self, :example_passed, :stop, :dump_summary

    def initialize(output)
      super
      self.passed_examples = {}
    end

    def example_passed(passed)
      self.current_example = CurrentExample.new(passed.example)
      move_example_to_passed if current_example.document?
    end

    def stop(notification)
      if notification.failed_examples.any?
        warn(notification.fully_formatted_failed_examples)
      else
        printer.print(passed_examples)
      end
    end

    def dump_summary(summary)
      return if summary.failed_examples.none?

      warn(summary.fully_formatted)
      exit(-1)
    end

    private

    attr_accessor :passed_examples
    attr_accessor :current_example

    def load_or_save_group
      group_name = current_example.resource_group_name
      group = passed_examples[group_name]

      if group
        group.tap { |g| g.desc ||= current_example.resource_group_desc }
      else
        passed_examples[group_name] = Entities::ResourceGroup.new(current_example.metadata)
      end
    end

    def load_or_save_resource_to_group(group)
      group.resources[current_example.resource_name] ||= Entities::Resource.new(current_example.metadata)
    end

    def load_or_save_action_to_resource(resource)
      resource.actions[current_example.action_name] ||= Entities::Action.new(current_example.metadata,
                                                                             current_example.request)
    end

    def move_example_to_passed
      group = load_or_save_group
      resource = load_or_save_resource_to_group(group)
      action = load_or_save_action_to_resource(resource)
      action.examples << Entities::Example.new(current_example.metadata,
                                               current_example.request,
                                               current_example.response)
    end

    def printer
      @printer ||= Printers::DocumentPrinter.new(output)
    end

    class CurrentExample # :nodoc:
      extend Forwardable

      delegate [:metadata] => :example

      attr_reader :example

      def initialize(example)
        @example = example
      end

      def resource_group_name
        metadata[:resource_group_name]
      end

      def resource_group_desc
        metadata[:resource_group_desc]
      end

      def resource_name
        metadata[:resource_name]
      end

      def action_name
        metadata[:action_name]
      end

      def request
        metadata[:request]
      end

      def response
        metadata[:response]
      end

      def document?
        tagged_with?(:apidoc) && tagged_with?(:dox) && !tagged_with?(:nodoc)
      end

      private

      def tagged_with?(key)
        metadata.key?(key) && metadata[key] == true
      end
    end
  end
end