neopoly/neo-rails

View on GitHub
lib/neo/rails/mock.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'set'

# A Mock can fake an object.
#
# This is useful when frontend developers want to fill a page with
# mock data. Mocks can pre-define interface for real data.
#
# == Usage
#
# app/mocks/user_mock.rb:
#
#   class UserMock < Neo::Rails::Mock
#     def age
#       mock.tagged?(:old) ? 78 : 23
#     end
#
#     def name
#       "Uncle bob"
#     end
#
#     def logged_in?
#       true
#     end
#
#     def sexy?
#       mock.tagged?(:sexy)
#     end
#
#     def car
#       mock.option(:car)
#     end
#   end
#
# Further...
#
#   old_man = UserMock.new(:old)
#   old_man.age   # => 78
#   old_man.name  # => "Uncle Bob"
#   old_man.car   # => nil
#
#   old_sexbomb = UserMock.new(:old, :sexy, :car => CarMock.new(:porsche))
#   old_sexbomb.age   # => 78
#   old_sexbomb.sexy? # => true
#   old_sexbomb.car   # => CarMock
#
module Neo
  module Rails
    class Mock
      attr_reader :mock

      # Initializes a Mock with optional tag list.
      def initialize(*args)
        options = Hash === args.last ? args.pop : {}
        @mock = MockConfig.new(args, options)
      end

      class MockConfig
        def initialize(tags, options={})
          @tags     = Set.new(tags)
          @options  = options
        end

        # Returns a human readable tag list.
        def description
          @tags.map { |tag| tag.to_s.capitalize }.join(", ")
        end

        def tags
          @tags.to_a
        end

        # Tag mock with +tags+.
        def tag(*tags)
          tags.each { |tag| @tags << tag }
        end

        # Untag mock.
        def untag(*tags)
          tags.each { |tag| @tags.delete(tag) }
        end

        # Checks if this mock is tagged with +tag+.
        def tagged?(tag)
          @tags.include?(tag)
        end

        def option(name)
          @options[name]
        end
      end
    end
  end
end