Class: Crispy::CrispyInternal::SpyBase

Inherits:
Module
  • Object
show all
Defined in:
lib/crispy/crispy_internal/spy_base.rb

Direct Known Subclasses

ClassSpy, Spy

Constant Summary collapse

BLACK_LISTED_METHODS =
[
  :__CRISPY_SPY__,
]
COMMON_RECEIVED_MESSAGE_METHODS_DEFINITION =
{
  'received?'      => 'include? %s',
  'received_once?' => 'one? {|self_thing| self_thing == %s }',
  'count_received' => 'count %s',
}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target, except: []) ⇒ SpyBase

Returns a new instance of SpyBase.



13
14
15
16
17
18
19
20
21
# File 'lib/crispy/crispy_internal/spy_base.rb', line 13

def initialize target, except: []
  @exceptions = Array(except).map(&:to_sym)

  prepend_features target_to_class(target)

  @stubbed_methods = []

  @spying = true
end

Class Method Details

.new(target, except: []) ⇒ Object



23
24
25
26
27
28
29
30
31
# File 'lib/crispy/crispy_internal/spy_base.rb', line 23

def self.new target, except: []
  spy = self.of_target(target)
  if spy
    spy.update_exceptions(target, except)
    spy.reinitialize
  else
    super
  end
end

.of_target(target) ⇒ Object

Raises:

  • (NotImplementedError)


33
34
35
# File 'lib/crispy/crispy_internal/spy_base.rb', line 33

def self.of_target target
  raise NotImplementedError
end

Instance Method Details

#append_received_message(receiver, method_name, *arguments, &attached_block) ⇒ Object

Raises:

  • (NotImplementedError)


49
50
51
# File 'lib/crispy/crispy_internal/spy_base.rb', line 49

def append_received_message receiver, method_name, *arguments, &attached_block
  raise NotImplementedError
end

#append_received_message_when_spying(receiver, method_name, *arguments, &attached_block) ⇒ Object



93
94
95
96
97
# File 'lib/crispy/crispy_internal/spy_base.rb', line 93

def append_received_message_when_spying receiver, method_name, *arguments, &attached_block
  if @spying
    append_received_message receiver, method_name, *arguments, &attached_block
  end
end

#assert_symbol!(maybe_symbol) ⇒ Object



185
186
187
188
189
# File 'lib/crispy/crispy_internal/spy_base.rb', line 185

def assert_symbol! maybe_symbol
  unless maybe_symbol.respond_to?(:to_sym) && maybe_symbol.to_sym.instance_of?(::Symbol)
    raise TypeError, "TypeError: no implicit conversion from #{maybe_symbol.inspect} to symbol"
  end
end

#erase_logObject

Raises:

  • (NotImplementedError)


45
46
47
# File 'lib/crispy/crispy_internal/spy_base.rb', line 45

def erase_log
  raise NotImplementedError
end

#received_messagesObject

Raises:

  • (NotImplementedError)


41
42
43
# File 'lib/crispy/crispy_internal/spy_base.rb', line 41

def received_messages
  raise NotImplementedError
end

#redefine_wrappers(klass, method_names) ⇒ Object



177
178
179
180
181
182
183
# File 'lib/crispy/crispy_internal/spy_base.rb', line 177

def redefine_wrappers klass, method_names
  self.module_eval do
    define_public_wrappers_only(klass, method_names)
    define_protected_wrappers_only(klass, method_names)
    define_private_wrappers_only(klass, method_names)
  end
end

#reinitializeObject



53
54
55
56
57
58
# File 'lib/crispy/crispy_internal/spy_base.rb', line 53

def reinitialize
  restart
  erase_log
  reinitialize_stubber
  self
end

#reinitialize_stubberObject



147
148
149
150
151
# File 'lib/crispy/crispy_internal/spy_base.rb', line 147

def reinitialize_stubber
  remove_method(*@stubbed_methods)
  @stubbed_methods.each {|stubbed_method| define_wrapper stubbed_method }
  @stubbed_methods.clear
end

#restartObject



78
79
80
# File 'lib/crispy/crispy_internal/spy_base.rb', line 78

def restart
  @spying = true
end

#stopObject



74
75
76
# File 'lib/crispy/crispy_internal/spy_base.rb', line 74

def stop
  @spying = false
end

#stub(method_name_or_hash, returned_value = nil, &definition) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/crispy/crispy_internal/spy_base.rb', line 121

def stub method_name_or_hash, returned_value = nil, &definition
  case method_name_or_hash
  when Hash
    hash = method_name_or_hash
    hash.each do|method_name, value|
      stub method_name, value
    end
  when ::Symbol, ::String
    @stubbed_methods << method_name_or_hash

    self.module_exec method_name_or_hash do|method_name|
      spy = self

      # remove methods already defined (maybe by define_wrapper) to avoid warning.
      remove_method method_name if public_method_defined? method_name

      # TODO: should not ignore arguments?
      define_method(method_name) do|*arguments, &block|
        spy.append_received_message_when_spying self, method_name, *arguments, &block
        returned_value
      end
    end
  end
  self
end

#target_to_class(target) ⇒ Object

Raises:

  • (NotImplementedError)


37
38
39
# File 'lib/crispy/crispy_internal/spy_base.rb', line 37

def target_to_class target
  raise NotImplementedError
end

#update_exceptions(target, exceptions) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/crispy/crispy_internal/spy_base.rb', line 60

def update_exceptions target, exceptions
  return if exceptions.empty?

  given_exceptions = Array(exceptions).map(&:to_sym)

  new_exceptions = given_exceptions - @exceptions
  remove_method(*new_exceptions)

  old_exceptions = @exceptions - given_exceptions
  redefine_wrappers target_to_class(target), old_exceptions

  @exceptions.replace given_exceptions
end