mock_proxy 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 418d9ed605b34dd982aeff5551e6447ece2ffe9f
4
- data.tar.gz: aa8df9a51b6d698c9828d5a5519648c91156e389
3
+ metadata.gz: 4be99a98663982f26b85d5b18b0f4b8aeb60a889
4
+ data.tar.gz: 56eabef1a63825f91c4375960677ed0dc3a0c37c
5
5
  SHA512:
6
- metadata.gz: 0b4c189c8f36de7bd7fdad795bef7b2116657b68c18bf81caff076492ca627a6f38124450f9af4720bfe0757dd91145f26e80e1ea3112d5a49efea660756ab83
7
- data.tar.gz: 4b49efca88282b9f55da569508dd7858c8b4c010c2e63e3efb14fdccf46e1a47b0604376187a7ef6dc71678e296264c4626a521774530897047d283946aa039a
6
+ metadata.gz: e355f02c7587ab7b2e194db9cb3d170e5baf970bdc620a86501902344440c75d3aa1c0fbd2eac1eacf9074b9fcca90037bf2cb78b2c1ba2f5f1157bcd018d1c6
7
+ data.tar.gz: 38e6f423b030d606c29e3fc1e524027223032bfd3bb2dff2196a2a9ff33b79e3c8d978b758c37e697bf2e0b8cf6bff682ee9ff0e2b353fb42e58656ded28c1b7
@@ -9,15 +9,15 @@ require 'active_support/core_ext'
9
9
  # That would have be 5-6 lines of stubbing. If this sounds like stub_chain, you're on the right track. It was removed in
10
10
  # RSpec 3 (or 2?). It's similar to that but it does things differently
11
11
  # First, it doesn't require you to use it in a stub
12
- # Second, it's use of procs means you can define anything, a stub or a mock (expectation) or a spy or whatever you want
12
+ # Second, it's use of callbacks means you can define anything, a stub or a mock (expectation) or a spy or whatever you want
13
13
  #
14
14
  # To use MockProxy, initialize it with a hash. Each key is a method call. Each call either returns a new proxy or calls
15
- # the proc. If the value is a proc, it calls it immediately with the args and block. If the value is a hash, it returns
16
- # a new proxy with the value as the hash. MockProxy will warn if you don't use hashes or procs and will also warn if
15
+ # the callback. If the value is a callback, it calls it immediately with the args and block. If the value is a hash, it returns
16
+ # a new proxy with the value as the hash. MockProxy will warn if you don't use hashes or callbacks and will also warn if
17
17
  # you did not define all the method calls (it won't automatically return itself for methods not defined in the hash)
18
18
  #
19
19
  # Example use:
20
- # let(:model_proxy) { MockProxy.new(receive_email: proc {}, generate_email: { validate!: { send: proc { |to| email } } }) }
20
+ # let(:model_proxy) { MockProxy.new(receive_email: callback {}, generate_email: { validate!: { send: callback { |to| email } } }) }
21
21
  # before { allow(Model).to receive(:new).and_return model_proxy }
22
22
  # # ...
23
23
  # describe 'Model' do
@@ -34,13 +34,13 @@ require 'active_support/core_ext'
34
34
  #
35
35
  # Example:
36
36
  # let(:model_proxy) do
37
- # callback = proc do |type|
38
- # MockProxy.merge(generator_proxy, decorate: proc { |*args| method_call(type, *args) })
37
+ # callback = callback do |type|
38
+ # MockProxy.merge(generator_proxy, decorate: callback { |*args| method_call(type, *args) })
39
39
  # generator_proxy
40
40
  # end
41
41
  # MockProxy.new(generate_email: callback)
42
42
  # end
43
- # let(:generator_proxy) { MockProxy.new(validate!: { send: proc { |to| email } }) }
43
+ # let(:generator_proxy) { MockProxy.new(validate!: { send: callback { |to| email } }) }
44
44
  #
45
45
  #
46
46
  # @author Geoff Lee
@@ -51,7 +51,7 @@ class MockProxy
51
51
  #
52
52
  # NOTE: We freeze the hash so you cannot modify it
53
53
  #
54
- # Use case: Retrieve proc to mock
54
+ # Use case: Retrieve callback to mock
55
55
  #
56
56
  # @param [MockProxy] proxy existing proxy
57
57
  # @param [String, Symbol, #to_s, Array<String, Symbol, #to_s>] key_path the chain of methods or key path. Can be a
@@ -79,11 +79,11 @@ class MockProxy
79
79
  proxy
80
80
  end
81
81
 
82
- # Replaces the proc at the specified key path, but only if there was one there before.
82
+ # Replaces the callback at the specified key path, but only if there was one there before.
83
83
  # Without creating new paths comes validation, including checking that this replaces an
84
- # existing proc, sort of like mkdir (without the -p option)
84
+ # existing callback, sort of like mkdir (without the -p option)
85
85
  #
86
- # Use case: Replace existing stub with a new proc without creating new method chains
86
+ # Use case: Replace existing stub with a new callback without creating new method chains
87
87
  #
88
88
  # @param [MockProxy] proxy existing proxy
89
89
  # @param [String, Symbol, #to_s, Array<String, Symbol, #to_s>] key_path the chain of methods or key path. Can be a
@@ -94,7 +94,7 @@ class MockProxy
94
94
  proxy
95
95
  end
96
96
 
97
- # Sets the proc at the specified key path, regardless if there was a proc there before.
97
+ # Sets the callback at the specified key path, regardless if there was a callback there before.
98
98
  # No validation comes with automatic path creation, meaning the key path will be defined
99
99
  # it it hasn't already, sort of like mkdir -p
100
100
  #
@@ -124,7 +124,7 @@ class MockProxy
124
124
  # Wrap existing callback, calling the provided block before it
125
125
  # Multiple calls to .observe will create a pyramid of callbacks, calling the observers before
126
126
  # eventually calling the existing callback
127
- new_callback = proc do |*args|
127
+ new_callback = callback do |*args|
128
128
  block.call(*args)
129
129
  callback.call(*args)
130
130
  end
@@ -134,7 +134,7 @@ class MockProxy
134
134
 
135
135
  # Wraps the existing callback with your block
136
136
  #
137
- # Use case: Get full control of the existing proc while running custom code
137
+ # Use case: Get full control of the existing callback while running custom code
138
138
  #
139
139
  # @param [MockProxy] proxy existing proxy
140
140
  # @param [String, Symbol, #to_s, Array<String, Symbol, #to_s>] key_path the chain of methods or key path. Can be a
@@ -147,7 +147,7 @@ class MockProxy
147
147
  # Wrap existing callback, calling the provided block before it
148
148
  # Multiple calls to .observe will create a pyramid of callbacks, calling the observers before
149
149
  # eventually calling the existing callback
150
- new_callback = proc do |*args|
150
+ new_callback = callback do |*args|
151
151
  block.call(*args, &callback)
152
152
  end
153
153
  set_callback(proxy, key_path, new_callback)
@@ -158,8 +158,8 @@ class MockProxy
158
158
  # @param [MockProxy] proxy existing proxy
159
159
  # @param [String, Symbol, #to_s, Array<String, Symbol, #to_s>] key_path the chain of methods or key path. Can be a
160
160
  # dot delimited key path or an array of method names as strings or symbols
161
- # @return [Proc] if proc found at key path
162
- # @raise [ArgumentError] if proc not found or hash found at key path
161
+ # @return [AnyObject, !Hash] if callback found at key path
162
+ # @raise [ArgumentError] if callback not found or hash found at key path
163
163
  def self.get_callback(proxy, key_path)
164
164
  key_paths = key_path.is_a?(Array) ? key_path.map(&:to_s) : key_path.split('.')
165
165
  existing_callback_hash = proxy.instance_variable_get('@callback_hash')
@@ -177,12 +177,12 @@ class MockProxy
177
177
  # @param [MockProxy] proxy existing proxy
178
178
  # @param [String, Symbol, #to_s, Array<String, Symbol, #to_s>] key_path the chain of methods or key path. Can be a
179
179
  # dot delimited key path or an array of method names as strings or symbols
180
- # @return [Proc] if proc found at key path
181
- # @raise [ArgumentError] if proc not found or hash found at key path
180
+ # @return [AnyObject, !Hash] if callback found at key path
181
+ # @raise [ArgumentError] if callback not found or hash found at key path
182
182
  def self.get_and_validate_callback(proxy, key_path)
183
183
  callback = get_callback(proxy, key_path)
184
- return callback if callback.is_a?(Proc)
185
- fail ArgumentError, "The existing callback tree contains the full key path you provided but continues going (i.e. no proc at exact key path). If you want to shorten the callback tree, use MockProxy.set_at. The callback tree looks like this: #{proxy.instance_variable_get('@callback_hash')}"
184
+ return callback if valid_callback?(callback)
185
+ fail ArgumentError, "The existing callback tree contains the full key path you provided but continues going (i.e. no callback at exact key path). If you want to shorten the callback tree, use MockProxy.set_at. The callback tree looks like this: #{proxy.instance_variable_get('@callback_hash')}"
186
186
  end
187
187
  private_class_method :get_and_validate_callback
188
188
 
@@ -190,15 +190,15 @@ class MockProxy
190
190
  # @param [MockProxy] proxy existing proxy
191
191
  # @param [String, Symbol, #to_s, Array<String, Symbol, #to_s>] key_path the chain of methods or key path. Can be a
192
192
  # dot delimited key path or an array of method names as strings or symbols
193
- # @param [Proc] proc the new proc to replace the existing proc
193
+ # @param [AnyObject, !Hash] callback the new callback to replace the existing callback
194
194
  # @param [Bool] validate true will throw error if nil at any part of key path, false to
195
195
  # create key path if missing (mkdir vs mkdir -p) (Defaults: true)
196
- # @return [MockProxy] if proc existed at key path
197
- # @raise [ArgumentError] if proc not found or hash found at key path
198
- def self.set_callback(proxy, key_path, proc, validate = true)
199
- fail ArgumentError, 'proc must be provided' unless proc
200
- fail ArgumentError, 'proc must be a proc' unless proc.is_a?(Proc)
201
- # Validate by checking if proc exists at key path
196
+ # @return [MockProxy] if callback existed at key path
197
+ # @raise [ArgumentError] if callback not found or hash found at key path
198
+ def self.set_callback(proxy, key_path, callback, validate = true)
199
+ fail ArgumentError, 'callback must be provided' unless callback
200
+ fail ArgumentError, 'callback must have a non-hash value' unless valid_callback?(callback)
201
+ # Validate by checking if callback exists at key path
202
202
  get_and_validate_callback(proxy, key_path) if validate
203
203
  # Set callback at key path, validating if set
204
204
  key_paths = key_path.is_a?(Array) ? key_path.map(&:to_s) : key_path.to_s.split('.')
@@ -208,11 +208,11 @@ class MockProxy
208
208
  # Last key
209
209
  if key_paths.last == key
210
210
  # Type check value, if validate
211
- if validate && !callback_hash[key].is_a?(Proc)
212
- fail ArgumentError, "The existing callback tree contains the full key path you provided but continues going (i.e. no proc at exact key path). If you want to shorten the callback tree, use MockProxy.set_at. The callback tree looks like this: #{copied_callback_hash}"
211
+ if validate && !valid_callback?(callback_hash[key])
212
+ fail ArgumentError, "The existing callback tree contains the full key path you provided but continues going (i.e. no callback at exact key path). If you want to shorten the callback tree, use MockProxy.set_at. The callback tree looks like this: #{copied_callback_hash}"
213
213
  else
214
- # Assign new proc if pass validations
215
- callback_hash[key] = proc
214
+ # Assign new callback if pass validations
215
+ callback_hash[key] = callback
216
216
  end
217
217
  else
218
218
  # In-between keys
@@ -230,18 +230,47 @@ class MockProxy
230
230
  end
231
231
  private_class_method :set_callback
232
232
 
233
+ # @private
234
+ # Supporting not just callbacks but other values for callbacks. To make the code easier to
235
+ # read and more reliable, hashes are not a supported callback value. To return one, use
236
+ # a callback like you would normally
237
+ #
238
+ # @param [AnyObject, !Hash] callback
239
+ # @return [Boolean] true if callback is valid, false if not
240
+ def self.valid_callback?(callback)
241
+ callback && !callback.is_a?(Hash)
242
+ end
243
+ private_class_method :valid_callback?
244
+
245
+ # @private
246
+ # Supporting not just callbacks but other values for callbacks. To make the code easier to
247
+ # read and more reliable, hashes are not a supported callback value. To return one, use
248
+ # a callback like you would normally
249
+ #
250
+ # @param [#to_s => AnyObject, !Hash] callback_tree
251
+ # @return [Boolean] true if callback is valid, false if not
252
+ def self.valid_callback_tree?(callback_tree)
253
+ return false unless callback_tree.is_a?(Hash)
254
+ callback_tree.all? do |key, value|
255
+ next false unless key.responds_to?(:to_s)
256
+ value.is_a?(Hash) ? valid_callback_tree?(value) : valid_callback?(value)
257
+ end
258
+ end
259
+ private_class_method :valid_callback_tree?
260
+
233
261
  # @param [Hash] callback_hash the tree of chained method calls
234
262
  def initialize(callback_hash)
263
+ valid_callback_tree?(callback_hash)
235
264
  @callback_hash = callback_hash.deep_stringify_keys.freeze
236
265
  end
237
266
 
238
267
  # @private
239
268
  def method_missing(name, *args, &block)
240
269
  current = @callback_hash[name.to_s]
241
- if current.is_a?(Proc)
270
+ if MockProxy.valid_callback?(current)
242
271
  current.call(*args, &block)
243
272
  else
244
- if !current.is_a?(Proc) && !current.is_a?(Hash)
273
+ if !current
245
274
  fail "Missing method #{name}. Please add this definition to your mock proxy"
246
275
  end
247
276
  MockProxy.new(current.freeze)
@@ -1,4 +1,4 @@
1
1
  class MockProxy
2
2
  # The version number
3
- VERSION = '0.2.3'
3
+ VERSION = '0.3.0'
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mock_proxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - matrinox