peeek 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+ require 'peeek/hooks'
3
+
4
+ def sample_hooks
5
+ Peeek::Hooks.new([
6
+ hook_stub(:object => String, :method_name => :%, :calls => 1, :linked => true),
7
+ hook_stub(:object => Numeric, :method_name => :abs, :calls => 0, :linked => false),
8
+ hook_stub(:object => String, :method_name => :index, :calls => 3, :linked => true)
9
+ ])
10
+ end
11
+
12
+ describe Peeek::Hooks, '#get' do
13
+ it 'returns a hook that corresponds to the object' do
14
+ hooks = sample_hooks
15
+ hooks.get(String).should == hooks[0]
16
+ hooks.get(Numeric).should == hooks[1]
17
+ end
18
+
19
+ it "returns nil if a hook that corresponds to the object doesn't exist" do
20
+ hooks = sample_hooks
21
+ hooks.get(Regexp).should be_nil
22
+ end
23
+
24
+ context 'with a method name' do
25
+ it 'returns a hook that corresponds to the object and the method name' do
26
+ hooks = sample_hooks
27
+ hooks.get(String, :%).should == hooks[0]
28
+ hooks.get(Numeric, :abs).should == hooks[1]
29
+ hooks.get(String, :index).should == hooks[2]
30
+ end
31
+
32
+ it "returns nil if a hook that corresponds to the object and the method name doesn't exist" do
33
+ hooks = sample_hooks
34
+ hooks.get(String, :rindex).should be_nil
35
+ end
36
+ end
37
+ end
38
+
39
+ describe Peeek::Hooks, '#clear' do
40
+ it 'unlinks the hooks from the methods' do
41
+ hooks = sample_hooks
42
+ original_hooks = hooks.dup
43
+ one_or_more(original_hooks).should be_any { |hook| hook.linked? } # assert
44
+ hooks.clear
45
+ one_or_more(original_hooks).should be_all { |hook| !hook.linked? }
46
+ end
47
+
48
+ it 'clears calls of the hooks' do
49
+ hooks = sample_hooks
50
+ original_hooks = hooks.dup
51
+ one_or_more(original_hooks).should be_any { |hook| !hook.calls.empty? } # assert
52
+ hooks.clear
53
+ one_or_more(original_hooks).should be_all { |hook| hook.calls.empty? }
54
+ end
55
+
56
+ it 'clears the hooks' do
57
+ hooks = sample_hooks
58
+ hooks.clear
59
+ hooks.should be_empty
60
+ end
61
+
62
+ it 'returns self' do
63
+ hooks = sample_hooks
64
+ hooks.clear.should equal(hooks)
65
+ end
66
+ end
67
+
68
+ describe Peeek::Hooks, '#circumvent' do
69
+ it 'unlinks the hooks from the methods in the block' do
70
+ hooks = sample_hooks
71
+
72
+ hooks.circumvent do
73
+ one_or_more(hooks).should be_all { |hook| !hook.linked? }
74
+ end
75
+ end
76
+
77
+ it 'reverts state of the hooks after calling' do
78
+ hooks = sample_hooks
79
+ linked_hooks = hooks.select(&:linked?)
80
+ unlinked_hooks = hooks.reject(&:linked?)
81
+ one_or_more(linked_hooks).should be_all { |hook| hook.linked? } # assert
82
+ one_or_more(unlinked_hooks).should be_all { |hook| !hook.linked? } # assert
83
+ hooks.circumvent { }
84
+ one_or_more(linked_hooks).should be_all { |hook| hook.linked? }
85
+ one_or_more(unlinked_hooks).should be_all { |hook| !hook.linked? }
86
+ end
87
+
88
+ it 'raises ArgumentError if a block not given' do
89
+ hooks = sample_hooks
90
+ lambda { hooks.circumvent }.should raise_error(ArgumentError, 'block not supplied')
91
+ end
92
+ end
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+ require 'peeek/supervisor'
3
+
4
+ def sample_supervisor
5
+ Peeek::Supervisor.create_for_instance.tap do |supervisor|
6
+ supervisor << hook_stub(:object => String, :method_name => :capitalize)
7
+ supervisor << hook_stub(:object => Numeric, :method_name => :days)
8
+ supervisor << hook_stub(:object => String, :method_name => :singularize)
9
+ end
10
+ end
11
+
12
+ describe Peeek::Supervisor, '.create_for_instance' do
13
+ it "calls #{described_class}.new with :method_added" do
14
+ described_class.should_receive(:new).with(:method_added)
15
+ described_class.create_for_instance
16
+ end
17
+
18
+ it "returns an instance of #{described_class}" do
19
+ supervisor = described_class.create_for_instance
20
+ supervisor.should be_a(described_class)
21
+ end
22
+ end
23
+
24
+ describe Peeek::Supervisor, '.create_for_singleton' do
25
+ it "calls #{described_class}.new with :singleton_method_added" do
26
+ described_class.should_receive(:new).with(:singleton_method_added)
27
+ described_class.create_for_singleton
28
+ end
29
+
30
+ it "returns an instance of #{described_class}" do
31
+ supervisor = described_class.create_for_singleton
32
+ supervisor.should be_a(described_class)
33
+ end
34
+ end
35
+
36
+ describe Peeek::Supervisor, '#add' do
37
+ before do
38
+ @supervisor = sample_supervisor
39
+ end
40
+
41
+ after do
42
+ @supervisor.clear
43
+ end
44
+
45
+ it 'adds the hook to the supervisor' do
46
+ hook = hook_stub(:object => String)
47
+ @supervisor.add(hook)
48
+ @supervisor.hooks.should be_include(hook)
49
+ end
50
+
51
+ it 'starts supervision to the object of the hook' do
52
+ Regexp.should_not be_supervised_for_instance # assert
53
+ hook = hook_stub(:object => Regexp)
54
+ @supervisor.add(hook)
55
+ @supervisor.original_callbacks.should be_include(Regexp)
56
+ Regexp.should be_supervised_for_instance
57
+ end
58
+
59
+ it "doesn't start supervision to object that is supervising already" do
60
+ hook = hook_stub(:object => String)
61
+ original_callback = @supervisor.original_callbacks[String]
62
+ @supervisor.add(hook)
63
+ @supervisor.original_callbacks[String].should equal(original_callback)
64
+ end
65
+
66
+ it 'returns self' do
67
+ hook = hook_stub(:object => String)
68
+ @supervisor.add(hook).should equal(@supervisor)
69
+ end
70
+ end
71
+
72
+ describe Peeek::Supervisor, '#clear' do
73
+ it 'clears the hooks in the supervisor' do
74
+ supervisor = sample_supervisor
75
+ supervisor.hooks.should_not be_empty # assert
76
+ supervisor.clear
77
+ supervisor.hooks.should be_empty
78
+ end
79
+
80
+ it 'clears the original callbacks in the supervisor' do
81
+ supervisor = sample_supervisor
82
+ supervisor.original_callbacks.should_not be_empty # assert
83
+ supervisor.clear
84
+ supervisor.original_callbacks.should be_empty
85
+ end
86
+
87
+ it 'revokes supervision to the objects' do
88
+ supervisor = sample_supervisor
89
+ String.should be_supervised_for_instance # assert
90
+ Numeric.should be_supervised_for_instance # assert
91
+ supervisor.clear
92
+ String.should_not be_supervised_for_instance
93
+ Numeric.should_not be_supervised_for_instance
94
+ end
95
+
96
+ it 'returns self' do
97
+ supervisor = sample_supervisor
98
+ supervisor.clear.should equal(supervisor)
99
+ end
100
+ end
101
+
102
+ describe Peeek::Supervisor, '#circumvent' do
103
+ before do
104
+ @supervisor = sample_supervisor
105
+ end
106
+
107
+ after do
108
+ @supervisor.clear
109
+ end
110
+
111
+ it 'revokes supervision to the objects in the block' do
112
+ @supervisor.circumvent do
113
+ String.should_not be_supervised_for_instance
114
+ Numeric.should_not be_supervised_for_instance
115
+ end
116
+ end
117
+
118
+ it 'restarts supervision to the objects after calling' do
119
+ String.should be_supervised_for_instance # assert
120
+ Numeric.should be_supervised_for_instance # assert
121
+ @supervisor.circumvent { }
122
+ String.should be_supervised_for_instance
123
+ Numeric.should be_supervised_for_instance
124
+ end
125
+
126
+ it 'raises ArgumentError if a block not given' do
127
+ lambda { @supervisor.circumvent }.should raise_error(ArgumentError, 'block not supplied')
128
+ end
129
+ end
@@ -0,0 +1,335 @@
1
+ require 'spec_helper'
2
+ require 'peeek'
3
+
4
+ describe Peeek, '.global' do
5
+ it 'returns the Peeek object' do
6
+ described_class.global.should be_a(described_class)
7
+ end
8
+
9
+ it 'returns same object' do
10
+ peeek = described_class.global
11
+ described_class.global.should equal(peeek)
12
+ end
13
+ end
14
+
15
+ describe Peeek, '.current' do
16
+ it 'returns the Peeek object' do
17
+ described_class.current.should be_a(described_class)
18
+ end
19
+
20
+ it 'returns same object' do
21
+ peeek = described_class.current
22
+ described_class.current.should equal(peeek)
23
+ end
24
+ end
25
+
26
+ describe Peeek, '.local' do
27
+ it 'returns return value from the block' do
28
+ result = described_class.local { 'local' }
29
+ result.should == 'local'
30
+ end
31
+
32
+ it 'switches the current Peeek object in the block' do
33
+ peeek = described_class.current
34
+
35
+ described_class.local do
36
+ described_class.current.should_not equal(peeek)
37
+ end
38
+ end
39
+
40
+ it 'gets back the current Peeek object after calling' do
41
+ peeek = described_class.current
42
+ described_class.local { }
43
+ described_class.current.should equal(peeek)
44
+ end
45
+
46
+ it 'supports nested calling' do
47
+ peeek1 = described_class.current
48
+
49
+ described_class.local do
50
+ peeek2 = described_class.current
51
+
52
+ described_class.local do
53
+ peeek3 = described_class.current
54
+ described_class.local { }
55
+ described_class.current.should equal(peeek3)
56
+ end
57
+
58
+ described_class.current.should equal(peeek2)
59
+ end
60
+
61
+ described_class.current.should equal(peeek1)
62
+ end
63
+
64
+ it 'unlinks the hooks of the current Peeek object over the block in the block, and revokes supervision' do
65
+ described_class.local do
66
+ peeek = described_class.current
67
+ peeek.hook(String, :to_s, :undefined_method)
68
+ peeek.hooks.get(String, :to_s).should be_linked # assert
69
+ peeek.hooks.get(String, :undefined_method).should_not be_linked # assert
70
+ String.should be_supervised_for_instance # assert
71
+
72
+ described_class.local do
73
+ peeek.hooks.should have(2).items
74
+ peeek.hooks.get(String, :to_s).should_not be_linked
75
+ peeek.hooks.get(String, :undefined_method).should_not be_linked
76
+ String.should_not be_supervised_for_instance
77
+ end
78
+ end
79
+ end
80
+
81
+ it 'links the hooks of the current Peeek object over the block after calling, and starts supervision' do
82
+ described_class.local do
83
+ peeek = described_class.current
84
+ peeek.hook(String, :to_s, :undefined_method)
85
+ described_class.local { }
86
+ peeek.hooks.should have(2).items
87
+ peeek.hooks.get(String, :to_s).should be_linked
88
+ peeek.hooks.get(String, :undefined_method).should_not be_linked
89
+ String.should be_supervised_for_instance
90
+ end
91
+ end
92
+
93
+ it 'releases the current Peeek object in the block after calling' do
94
+ hook = described_class.local do
95
+ described_class.current.hook(String, :%, :undefined_method)
96
+ '%s (%d)' % ['Koyomi', 18]
97
+ String.should be_supervised_for_instance # assert
98
+
99
+ described_class.current.hooks.get(String, :%).tap do |hook|
100
+ hook.should be_linked
101
+ hook.calls.should have(1).items
102
+ end
103
+ end
104
+
105
+ hook.should_not be_linked
106
+ hook.calls.should be_empty
107
+ String.should_not be_supervised_for_instance
108
+ end
109
+
110
+ it 'raises ArgumentError if a block not given' do
111
+ lambda { described_class.local }.should raise_error(ArgumentError, 'block not supplied')
112
+ end
113
+ end
114
+
115
+ describe Peeek, '.capture' do
116
+ it "calls #{described_class}.local with a block" do
117
+ described_class.should_receive(:local).with { }
118
+ described_class.capture(String => :%) { }
119
+ end
120
+
121
+ it 'links hooks to the objects and the methods in the block' do
122
+ described_class.capture(String => [:%, :index], $stdout => :write) do
123
+ hooks = described_class.current.hooks
124
+ hooks.get(String, :%).should be_linked
125
+ hooks.get(String, :index).should be_linked
126
+ hooks.get($stdout, :write).should be_linked
127
+ end
128
+ end
129
+
130
+ it "returns an instance of #{described_class}::Calls" do
131
+ calls = described_class.capture(String => :%) { }
132
+ calls.should be_a(Peeek::Calls)
133
+ end
134
+
135
+ it 'returns result that captured calls in the block' do
136
+ calls = described_class.capture(String => :%) do
137
+ format = '%s (%d)'
138
+ format % ['Koyomi', 18]
139
+ format % ['Karen', 14]
140
+ format % ['Tsukihi', 14]
141
+ end
142
+
143
+ calls.should have(3).items
144
+ end
145
+
146
+ it 'raises ArgumentError if a block not given' do
147
+ lambda { described_class.capture(String => :%) }.should raise_error(ArgumentError, 'block not supplied')
148
+ end
149
+ end
150
+
151
+ describe Peeek, '#calls' do
152
+ it "returns an instance of #{described_class}::Calls" do
153
+ peeek = described_class.new
154
+ peeek.calls.should be_a(Peeek::Calls)
155
+ end
156
+
157
+ it "returns an empty calls if hooks aren't registered" do
158
+ peeek = described_class.new
159
+ peeek.calls.should be_empty
160
+ end
161
+
162
+ it 'returns calls of the registered hooks' do
163
+ peeek = described_class.new
164
+ peeek.hook(String, :%, :index)
165
+ peeek.calls.should be_empty # assert
166
+ '%s (%d)' % ['Koyomi', 18]
167
+ 'abc'.index('x')
168
+ peeek.hooks.get(String, :%).calls.should have(1).items
169
+ peeek.hooks.get(String, :index).calls.should have(1).items
170
+ peeek.calls.should have(2).items
171
+ end
172
+ end
173
+
174
+ describe Peeek, '#hook' do
175
+ before do
176
+ @peeek = described_class.new
177
+ @peeek.hook(String, :%, :index)
178
+ end
179
+
180
+ after do
181
+ @peeek.release
182
+ end
183
+
184
+ it "calls #{described_class}::Hook.create with the object, the method specification and the block" do
185
+ block = lambda { }
186
+ Peeek::Hook.should_receive(:create).with($stdout, :write, &block).and_return(hook_stub)
187
+ Peeek::Hook.should_receive(:create).with(Numeric, :abs, &block).and_return(hook_stub)
188
+ @peeek.hook($stdout, :write, &block)
189
+ @peeek.hook(Numeric, :abs, &block)
190
+ end
191
+
192
+ it "returns an instance of #{described_class}::Calls" do
193
+ hooks = @peeek.hook($stdout, :write)
194
+ hooks.should be_a(Peeek::Hooks)
195
+ end
196
+
197
+ it "returns registered hooks at calling" do
198
+ hooks = @peeek.hook($stdout, :write)
199
+ hooks.should have(1).items
200
+ hooks.get($stdout, :write).should_not be_nil
201
+ end
202
+
203
+ it 'links a hook to the method' do
204
+ hook = @peeek.hook($stdout, :write).get($stdout, :write)
205
+ hook.should be_linked
206
+ end
207
+
208
+ it "starts supervision for instance method if the method isn't defined yet" do
209
+ String.should_not be_supervised_for_instance # assert
210
+ @peeek.hook(String, :undefined_method)
211
+ String.should be_supervised_for_instance
212
+
213
+ Numeric.should_not be_supervised_for_instance # assert
214
+ @peeek.hook(Numeric, :abs)
215
+ Numeric.should_not be_supervised_for_instance
216
+ end
217
+
218
+ it "starts supervision for singleton method if the method isn't defined yet" do
219
+ $stdout.should_not be_supervised_for_singleton # assert
220
+ @peeek.hook($stdout, :undefined_method)
221
+ $stdout.should be_supervised_for_singleton
222
+
223
+ Regexp.should_not be_supervised_for_singleton # assert
224
+ @peeek.hook(Regexp, '.quote')
225
+ Regexp.should_not be_supervised_for_singleton
226
+ end
227
+
228
+ it "adds hooks to the registered hooks" do
229
+ hook = @peeek.hook($stdout, :write).get($stdout, :write)
230
+ @peeek.hooks.should be_include(hook)
231
+ end
232
+ end
233
+
234
+ describe Peeek, '#release' do
235
+ before do
236
+ @peeek = described_class.new
237
+ @peeek.hook(String, :%, :undefined_method)
238
+ @peeek.hook($stdout, :undefined_method)
239
+ end
240
+
241
+ it 'cleras the hooks' do
242
+ @peeek.hooks.should_not be_empty # assert
243
+ @peeek.release
244
+ @peeek.hooks.should be_empty
245
+ end
246
+
247
+ it 'unlinks the hooks' do
248
+ original_hooks = @peeek.hooks.dup
249
+ one_or_more(original_hooks).should be_any { |hook| hook.linked? } # assert
250
+ @peeek.release
251
+ one_or_more(original_hooks).should be_all { |hook| !hook.linked? }
252
+ end
253
+
254
+ it 'clears calls of the hooks' do
255
+ '%s (%d)' % ['Koyomi', 18]
256
+ original_hooks = @peeek.hooks.dup
257
+ one_or_more(original_hooks).should be_any { |hook| !hook.calls.empty? } # assert
258
+ @peeek.release
259
+ one_or_more(original_hooks).should be_all { |hook| hook.calls.empty? }
260
+ end
261
+
262
+ it 'revokes supervision for instance method' do
263
+ String.should be_supervised_for_instance # assert
264
+ @peeek.release
265
+ String.should_not be_supervised_for_instance
266
+ end
267
+
268
+ it 'revokes supervision for singleton method' do
269
+ $stdout.should be_supervised_for_singleton # assert
270
+ @peeek.release
271
+ $stdout.should_not be_supervised_for_singleton
272
+ end
273
+
274
+ it 'returns self' do
275
+ @peeek.release.should equal(@peeek)
276
+ end
277
+ end
278
+
279
+ describe Peeek, '#circumvent' do
280
+ before do
281
+ @peeek = described_class.new
282
+ end
283
+
284
+ after do
285
+ @peeek.release
286
+ end
287
+
288
+ it 'unlinks the hooks only in the block' do
289
+ @peeek.hook(String, :%)
290
+ @peeek.hooks.get(String, :%).should be_linked # assert
291
+
292
+ @peeek.circumvent do
293
+ @peeek.hooks.get(String, :%).should_not be_linked
294
+ end
295
+
296
+ @peeek.hooks.get(String, :%).should be_linked
297
+ end
298
+
299
+ it 'revokes supervision for instance method only in the block' do
300
+ @peeek.hook(String, :undefined_method)
301
+ String.should be_supervised_for_instance # assert
302
+
303
+ @peeek.circumvent do
304
+ String.should_not be_supervised_for_instance
305
+ end
306
+
307
+ String.should be_supervised_for_instance
308
+ end
309
+
310
+ it 'revokes supervision for singleton method only in the block' do
311
+ @peeek.hook($stdout, :undefined_method)
312
+ $stdout.should be_supervised_for_singleton # assert
313
+
314
+ @peeek.circumvent do
315
+ $stdout.should_not be_supervised_for_singleton
316
+ end
317
+
318
+ $stdout.should be_supervised_for_singleton
319
+ end
320
+
321
+ it 'raises ArgumentError if a block not given' do
322
+ lambda { @peeek.circumvent }.should raise_error(ArgumentError, 'block not supplied')
323
+ end
324
+ end
325
+
326
+ describe Peeek::Readily, '#peeek' do
327
+ it 'registers hooks to the current Peeek object' do
328
+ Peeek.local do
329
+ Peeek.current.should_receive(:hook).with(String, :%, :index)
330
+ Peeek.current.should_receive(:hook).with(Numeric, :abs)
331
+ String.peeek(:%, :index)
332
+ Numeric.peeek(:abs)
333
+ end
334
+ end
335
+ end