spy_rb 0.2.2 → 0.3.0
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.
- checksums.yaml +4 -4
- data/lib/spy/api.rb +20 -20
- data/lib/spy/instance.rb +28 -15
- data/lib/spy/instance/api/internal.rb +75 -0
- data/lib/spy/instance/strategy/intercept.rb +1 -12
- data/lib/spy/instance/strategy/wrap.rb +1 -12
- data/lib/spy/method_call.rb +11 -0
- data/lib/spy/version.rb +1 -1
- metadata +4 -4
- data/lib/spy/callbacks/when.rb +0 -13
- data/lib/spy/callbacks/with_args.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47b608d05670cc1e49baec91115ecfdf0e87feb6
|
4
|
+
data.tar.gz: a7519779804fa1ac600149a87bfed851cacca168
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a3853df7bcb3ae2440b6585ea519d4466b7130ddb061a2d29db1ba88a9e31a410c1a22adb614782c337a035356d82d8350d9024aeabb1b588ae00c97cc04078
|
7
|
+
data.tar.gz: dc92ea6560aa6b5fbfbc260cdbc9b2cdb2acae4bc92b0662b56b65b40c34dd149c0a195cf18872f41f5a05284dce90eaf514ea9ca973979828ffecbd025e3f47
|
data/lib/spy/api.rb
CHANGED
@@ -2,23 +2,22 @@ require 'spy/core'
|
|
2
2
|
|
3
3
|
module Spy
|
4
4
|
module API
|
5
|
-
#
|
5
|
+
# Spies on calls to a method made on an object
|
6
6
|
#
|
7
|
-
#
|
8
|
-
# @param
|
9
|
-
|
10
|
-
|
11
|
-
case args.length
|
12
|
-
when 2
|
13
|
-
spied, msg = *args
|
14
|
-
return core.add_spy(spied, spied.method(msg))
|
15
|
-
end
|
16
|
-
raise ArgumentError
|
7
|
+
# @param target - the object you want to spy on
|
8
|
+
# @param msg - the name of the method to spy on
|
9
|
+
def on(target, msg)
|
10
|
+
core.add_spy(target, target.method(msg))
|
17
11
|
end
|
18
12
|
|
19
|
-
#
|
20
|
-
|
21
|
-
|
13
|
+
# Spies on calls to a method made on any instance of some class or module
|
14
|
+
#
|
15
|
+
# @param target - class or module to spy on
|
16
|
+
# @param msg - name of the method to spy on
|
17
|
+
# @returns [Spy::Instance]
|
18
|
+
def on_any_instance(target, msg)
|
19
|
+
raise ArgumentError unless target.respond_to?(:instance_method)
|
20
|
+
core.add_spy(target, target.instance_method(msg))
|
22
21
|
end
|
23
22
|
|
24
23
|
# Stops spying on the method and restores its original functionality
|
@@ -36,15 +35,16 @@ module Spy
|
|
36
35
|
def restore(*args)
|
37
36
|
case args.length
|
38
37
|
when 1
|
39
|
-
|
38
|
+
core.remove_all_spies if args.first == :all
|
40
39
|
when 2
|
41
|
-
|
42
|
-
|
40
|
+
target, msg = *args
|
41
|
+
core.remove_spy(target, target.method(msg))
|
43
42
|
when 3
|
44
|
-
|
45
|
-
|
43
|
+
target, msg, method_type = *args
|
44
|
+
core.remove_spy(target, target.send(method_type, msg))
|
45
|
+
else
|
46
|
+
raise ArgumentError
|
46
47
|
end
|
47
|
-
raise ArgumentError
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
data/lib/spy/instance.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
require 'spy/callbacks/with_args'
|
2
|
-
require 'spy/callbacks/when'
|
3
1
|
require 'spy/instance/strategy'
|
2
|
+
require 'spy/instance/api/internal'
|
4
3
|
|
5
4
|
# An instance of a spied method
|
6
5
|
# - Holds a reference to the original method
|
@@ -8,17 +7,26 @@ require 'spy/instance/strategy'
|
|
8
7
|
# - Provides hooks for callbacks
|
9
8
|
module Spy
|
10
9
|
class Instance
|
11
|
-
|
10
|
+
include API::Internal
|
11
|
+
|
12
|
+
attr_reader :original, :spied, :strategy, :visibility, :call_history
|
12
13
|
|
13
14
|
def initialize(spied, original)
|
14
15
|
@spied = spied
|
15
16
|
@original = original
|
16
17
|
@visibility = extract_visibility
|
17
|
-
@
|
18
|
-
@
|
18
|
+
@conditional_filters = []
|
19
|
+
@before_callbacks = []
|
20
|
+
@after_callbacks = []
|
21
|
+
@around_procs = []
|
22
|
+
@call_history = []
|
19
23
|
@strategy = Strategy.factory_build(self)
|
20
24
|
end
|
21
25
|
|
26
|
+
def call_count
|
27
|
+
@call_history.size
|
28
|
+
end
|
29
|
+
|
22
30
|
def start
|
23
31
|
@strategy.apply
|
24
32
|
self
|
@@ -29,25 +37,30 @@ module Spy
|
|
29
37
|
self
|
30
38
|
end
|
31
39
|
|
32
|
-
def
|
33
|
-
@
|
40
|
+
def when(&block)
|
41
|
+
@conditional_filters << block
|
42
|
+
self
|
34
43
|
end
|
35
44
|
|
36
|
-
|
37
|
-
|
45
|
+
# Expect block to yield. Call the rest of the chain
|
46
|
+
# when it does
|
47
|
+
def wrap(&block)
|
48
|
+
@around_procs << block
|
49
|
+
self
|
38
50
|
end
|
39
51
|
|
40
|
-
def
|
41
|
-
|
52
|
+
def before(&block)
|
53
|
+
@before_callbacks << block
|
54
|
+
self
|
42
55
|
end
|
43
56
|
|
44
|
-
|
45
|
-
|
46
|
-
def add_before_filter(filter)
|
47
|
-
@before_filters << filter
|
57
|
+
def after(&block)
|
58
|
+
@after_callbacks << block
|
48
59
|
self
|
49
60
|
end
|
50
61
|
|
62
|
+
private
|
63
|
+
|
51
64
|
def extract_visibility
|
52
65
|
owner = @original.owner
|
53
66
|
[:public, :protected, :private].each do |vis|
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spy/method_call'
|
2
|
+
|
3
|
+
module Spy
|
4
|
+
class Instance
|
5
|
+
module API
|
6
|
+
# The API we expose internally to our collaborators
|
7
|
+
module Internal
|
8
|
+
# TODO: Not sure if this is the best place for this
|
9
|
+
#
|
10
|
+
# Defines the spy on the target object
|
11
|
+
def attach_to(target)
|
12
|
+
spy = self
|
13
|
+
target.class_eval do
|
14
|
+
define_method spy.original.name do |*args|
|
15
|
+
spy.call(self, *args)
|
16
|
+
end
|
17
|
+
send(spy.visibility, spy.original.name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Call the spied method using the given context and arguments.
|
22
|
+
#
|
23
|
+
# Context is required for calling UnboundMethods such as
|
24
|
+
# instance methods defined on a Class
|
25
|
+
def call(context, *args)
|
26
|
+
is_active = @conditional_filters.all? {|f| f.call(*args)}
|
27
|
+
|
28
|
+
if is_active
|
29
|
+
@before_callbacks.each {|f| f.call(*args)}
|
30
|
+
end
|
31
|
+
|
32
|
+
if @around_procs.any?
|
33
|
+
# Procify the original call
|
34
|
+
original_proc = Proc.new do
|
35
|
+
record = track_call(context, *args) if is_active
|
36
|
+
result = call_original(context, *args)
|
37
|
+
record.result = result if is_active
|
38
|
+
end
|
39
|
+
|
40
|
+
# Keep wrapping the original proc with each around_proc
|
41
|
+
@around_procs.reduce(original_proc) do |p, wrapper|
|
42
|
+
Proc.new { wrapper.call context, *args, &p }
|
43
|
+
end.call
|
44
|
+
else
|
45
|
+
record = track_call(context, *args) if is_active
|
46
|
+
result = call_original(context, *args)
|
47
|
+
record.result = result if is_active
|
48
|
+
end
|
49
|
+
|
50
|
+
if is_active
|
51
|
+
@after_callbacks.each {|f| f.call(*args)}
|
52
|
+
end
|
53
|
+
|
54
|
+
result
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def track_call(context, *args)
|
60
|
+
record = Spy::MethodCall.new(context, *args)
|
61
|
+
@call_history << record
|
62
|
+
record
|
63
|
+
end
|
64
|
+
|
65
|
+
def call_original(context, *args)
|
66
|
+
if original.is_a?(UnboundMethod)
|
67
|
+
original.bind(context).call(*args)
|
68
|
+
else
|
69
|
+
original.call(*args)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -8,18 +8,7 @@ module Spy
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def apply
|
11
|
-
spy
|
12
|
-
@intercept_target.class_eval do
|
13
|
-
define_method spy.original.name do |*args|
|
14
|
-
spy.before_call(*args)
|
15
|
-
if spy.original.is_a?(UnboundMethod)
|
16
|
-
spy.original.bind(self).call(*args)
|
17
|
-
else
|
18
|
-
spy.original.call(*args)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
send(spy.visibility, spy.original.name)
|
22
|
-
end
|
11
|
+
@spy.attach_to(@intercept_target)
|
23
12
|
end
|
24
13
|
|
25
14
|
def undo
|
@@ -7,18 +7,7 @@ module Spy
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def apply
|
10
|
-
spy
|
11
|
-
spy.original.owner.class_eval do
|
12
|
-
define_method spy.original.name do |*args|
|
13
|
-
spy.before_call(*args)
|
14
|
-
if spy.original.is_a?(UnboundMethod)
|
15
|
-
spy.original.bind(self).call(*args)
|
16
|
-
else
|
17
|
-
spy.original.call(*args)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
send(spy.visibility, spy.original.name)
|
21
|
-
end
|
10
|
+
@spy.attach_to(@spy.original.owner)
|
22
11
|
end
|
23
12
|
|
24
13
|
def undo
|
data/lib/spy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spy_rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Bodah
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Spy brings everything that's great about Sinon.JS to Ruby. Mocking frameworks
|
14
14
|
work by stubbing out functionality. Spy works by listening in on functionality and
|
@@ -21,16 +21,16 @@ extra_rdoc_files: []
|
|
21
21
|
files:
|
22
22
|
- lib/spy.rb
|
23
23
|
- lib/spy/api.rb
|
24
|
-
- lib/spy/callbacks/when.rb
|
25
|
-
- lib/spy/callbacks/with_args.rb
|
26
24
|
- lib/spy/collection.rb
|
27
25
|
- lib/spy/collection/entry.rb
|
28
26
|
- lib/spy/core.rb
|
29
27
|
- lib/spy/errors.rb
|
30
28
|
- lib/spy/instance.rb
|
29
|
+
- lib/spy/instance/api/internal.rb
|
31
30
|
- lib/spy/instance/strategy.rb
|
32
31
|
- lib/spy/instance/strategy/intercept.rb
|
33
32
|
- lib/spy/instance/strategy/wrap.rb
|
33
|
+
- lib/spy/method_call.rb
|
34
34
|
- lib/spy/version.rb
|
35
35
|
homepage: https://github.com/jbodah/spy_rb
|
36
36
|
licenses:
|
data/lib/spy/callbacks/when.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
module Spy
|
2
|
-
module Callbacks
|
3
|
-
class WithArgs
|
4
|
-
def initialize(*args)
|
5
|
-
puts 'Spy::Callbacks::WithArgs is deprecated; use Spy::Callbacks::When instead'
|
6
|
-
@match_args = args
|
7
|
-
end
|
8
|
-
|
9
|
-
def before_call(*args)
|
10
|
-
@match_args == args
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|