matahari 0.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/matahari/invocation_matcher.rb +60 -58
 - data/lib/matahari/spy.rb +37 -35
 - data/lib/matahari/version.rb +1 -1
 - metadata +3 -2
 
| 
         @@ -1,73 +1,75 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            module Matahari
         
     | 
| 
      
 2 
     | 
    
         
            +
              class InvocationMatcher
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
      
 4 
     | 
    
         
            +
                #TODO I can't work out how to disentangle the 2 responsibilities of this class:
         
     | 
| 
      
 5 
     | 
    
         
            +
                #1. Inspecting and acting on spy invocations
         
     | 
| 
      
 6 
     | 
    
         
            +
                #2. Presenting the results of those inspections.
         
     | 
| 
      
 7 
     | 
    
         
            +
                #
         
     | 
| 
      
 8 
     | 
    
         
            +
                #One to revisit later when my head is less befuddled.
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 10 
     | 
    
         
            +
                def initialize(iterator = nil)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @expected_call_count = iterator ? iterator.count : nil
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
                def matches?(subject)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @subject = subject
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @invocations_of_method = subject.invocations.select {|i| i[:method] == @call_to_verify}
         
     | 
| 
      
 17 
     | 
    
         
            +
                  verifying_args = @args_to_verify.size != 0
         
     | 
| 
       17 
18 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 19 
     | 
    
         
            +
                  match_passes?(verifying_args)
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
       20 
21 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
                def failure_message_for_should_not
         
     | 
| 
      
 23 
     | 
    
         
            +
                  "Spy(:#{@subject.name}) expected not to receive :#{@call_to_verify} but received it #{prettify_times(@matching_calls)}"
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
       24 
25 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
                def failure_message_for_should
         
     | 
| 
      
 27 
     | 
    
         
            +
                  if @args_to_verify.size > 0
         
     | 
| 
      
 28 
     | 
    
         
            +
                    "Spy(:#{@subject.name}) expected to receive :#{@call_to_verify}(#{@args_to_verify.map(&:inspect).join(", ")}) #{prettify_times(@expected_call_count)}, received #{prettify_times(@matching_calls)}"
         
     | 
| 
      
 29 
     | 
    
         
            +
                  else
         
     | 
| 
      
 30 
     | 
    
         
            +
                    "Spy(:#{@subject.name}) expected to receive :#{@call_to_verify} #{prettify_times(@expected_call_count)}, received #{prettify_times(@matching_calls)}"
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
       30 
32 
     | 
    
         
             
                end
         
     | 
| 
       31 
     | 
    
         
            -
              end
         
     | 
| 
       32 
33 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
      
 34 
     | 
    
         
            +
                #Allows chaining of method calls following has_received?/should have_received,
         
     | 
| 
      
 35 
     | 
    
         
            +
                #e.g. spy.should_have received.some_method, where #some_method is handled by
         
     | 
| 
      
 36 
     | 
    
         
            +
                #method_missing, its arguments and name being stored until #matches? is called.
         
     | 
| 
      
 37 
     | 
    
         
            +
                def method_missing(sym, *args, &block)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @call_to_verify = sym
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @args_to_verify = args
         
     | 
| 
      
 40 
     | 
    
         
            +
                  self
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
       41 
42 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
      
 43 
     | 
    
         
            +
                def prettify_times(times)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  case times
         
     | 
| 
      
 45 
     | 
    
         
            +
                  when 1
         
     | 
| 
      
 46 
     | 
    
         
            +
                    "once"
         
     | 
| 
      
 47 
     | 
    
         
            +
                  when nil
         
     | 
| 
      
 48 
     | 
    
         
            +
                    "once"
         
     | 
| 
      
 49 
     | 
    
         
            +
                  when 2
         
     | 
| 
      
 50 
     | 
    
         
            +
                    "twice"
         
     | 
| 
      
 51 
     | 
    
         
            +
                  else
         
     | 
| 
      
 52 
     | 
    
         
            +
                    "#{times} times"
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
       52 
54 
     | 
    
         
             
                end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
              private :prettify_times
         
     | 
| 
      
 55 
     | 
    
         
            +
                private :prettify_times
         
     | 
| 
       55 
56 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
      
 57 
     | 
    
         
            +
                def matching_calls(verifying_args=true)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @matching_calls ||= if verifying_args
         
     | 
| 
      
 59 
     | 
    
         
            +
                                        @invocations_of_method.select {|i| i[:args].flatten === @args_to_verify}.size
         
     | 
| 
      
 60 
     | 
    
         
            +
                                      else
         
     | 
| 
      
 61 
     | 
    
         
            +
                                        @invocations_of_method.size
         
     | 
| 
      
 62 
     | 
    
         
            +
                                      end
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
                private :matching_calls
         
     | 
| 
       64 
65 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
      
 66 
     | 
    
         
            +
                def match_passes?(verifying_args)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  if @expected_call_count
         
     | 
| 
      
 68 
     | 
    
         
            +
                    matching_calls(verifying_args) == @expected_call_count
         
     | 
| 
      
 69 
     | 
    
         
            +
                  else
         
     | 
| 
      
 70 
     | 
    
         
            +
                    matching_calls(verifying_args) > 0
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
       70 
72 
     | 
    
         
             
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
                private :match_passes?
         
     | 
| 
       71 
74 
     | 
    
         
             
              end
         
     | 
| 
       72 
     | 
    
         
            -
              private :match_passes?
         
     | 
| 
       73 
75 
     | 
    
         
             
            end
         
     | 
    
        data/lib/matahari/spy.rb
    CHANGED
    
    | 
         @@ -1,45 +1,47 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
               
     | 
| 
      
 1 
     | 
    
         
            +
            module Matahari
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Spy
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :name, :invocations
         
     | 
| 
       3 
4 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(name = nil, opts={})
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @subject = opts[:subject]
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @invocations = []
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @stubbed_calls = {}
         
     | 
| 
      
 10 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 11 
     | 
    
         
            +
                    instance_methods.each do |meth|
         
     | 
| 
      
 12 
     | 
    
         
            +
                      whitelist = [:name, :define_method, :stubs, :passes_on, :method_missing, :record_invocation, :invocations, :has_received?, :object_id, :respond_to?, :respond_to_missing?, :instance_eval, :instance_exec, :class_eval, :__send__, :send, :should, :should_not, :__id__, :__send__]
         
     | 
| 
      
 13 
     | 
    
         
            +
                      next if whitelist.include?(meth) || whitelist.include?(meth.to_sym)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      undef_method(meth)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
       14 
16 
     | 
    
         
             
                  end
         
     | 
| 
       15 
17 
     | 
    
         
             
                end
         
     | 
| 
       16 
     | 
    
         
            -
              end
         
     | 
| 
       17 
18 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 19 
     | 
    
         
            +
                #When a given method call, sym, is invoked on self, call block and return its result
         
     | 
| 
      
 20 
     | 
    
         
            +
                def stubs(sym, &block)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @stubbed_calls[sym] = block
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
       22 
23 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
      
 24 
     | 
    
         
            +
                def passes_on(sym)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @stubbed_calls[sym] = @subject.method(sym)
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
       26 
27 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
                #Captures the details of any method call and store for later inspection
         
     | 
| 
      
 29 
     | 
    
         
            +
                def method_missing(sym, *args, &block)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  record_invocation(sym, args)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @stubbed_calls[sym].call if @stubbed_calls[sym]
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
       32 
33 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
      
 34 
     | 
    
         
            +
                #Pass an iterator to this method to specify the number of times the method should
         
     | 
| 
      
 35 
     | 
    
         
            +
                #have been called. E.g. spy.has_received?(3.times). While other iterators might work,
         
     | 
| 
      
 36 
     | 
    
         
            +
                #the idea is to allow this nice DSL-ish way of asserting on the number of calls, hence
         
     | 
| 
      
 37 
     | 
    
         
            +
                #the odd method signature.
         
     | 
| 
      
 38 
     | 
    
         
            +
                def has_received?(times=nil)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  InvocationMatcher.new(times)
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
       40 
41 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
      
 42 
     | 
    
         
            +
                private
         
     | 
| 
      
 43 
     | 
    
         
            +
                def record_invocation(sym, *args)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @invocations << {:method => sym, :args => args}
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
       44 
46 
     | 
    
         
             
              end
         
     | 
| 
       45 
47 
     | 
    
         
             
            end
         
     | 
    
        data/lib/matahari/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -5,7 +5,8 @@ version: !ruby/object:Gem::Version 
     | 
|
| 
       5 
5 
     | 
    
         
             
              segments: 
         
     | 
| 
       6 
6 
     | 
    
         
             
              - 0
         
     | 
| 
       7 
7 
     | 
    
         
             
              - 3
         
     | 
| 
       8 
     | 
    
         
            -
               
     | 
| 
      
 8 
     | 
    
         
            +
              - 1
         
     | 
| 
      
 9 
     | 
    
         
            +
              version: 0.3.1
         
     | 
| 
       9 
10 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       10 
11 
     | 
    
         
             
            authors: 
         
     | 
| 
       11 
12 
     | 
    
         
             
            - Tom Stuart
         
     | 
| 
         @@ -13,7 +14,7 @@ autorequire: 
     | 
|
| 
       13 
14 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       14 
15 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
            date: 2011-06- 
     | 
| 
      
 17 
     | 
    
         
            +
            date: 2011-06-29 00:00:00 +01:00
         
     | 
| 
       17 
18 
     | 
    
         
             
            default_executable: 
         
     | 
| 
       18 
19 
     | 
    
         
             
            dependencies: 
         
     | 
| 
       19 
20 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     |