robsharp-extlib 0.9.15

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.
Files changed (73) hide show
  1. data/.autotest +21 -0
  2. data/.document +5 -0
  3. data/.gitignore +22 -0
  4. data/LICENSE +47 -0
  5. data/README.rdoc +17 -0
  6. data/Rakefile +28 -0
  7. data/VERSION +1 -0
  8. data/extlib.gemspec +147 -0
  9. data/lib/extlib.rb +50 -0
  10. data/lib/extlib/array.rb +38 -0
  11. data/lib/extlib/assertions.rb +8 -0
  12. data/lib/extlib/blank.rb +89 -0
  13. data/lib/extlib/boolean.rb +11 -0
  14. data/lib/extlib/byte_array.rb +6 -0
  15. data/lib/extlib/class.rb +179 -0
  16. data/lib/extlib/datetime.rb +29 -0
  17. data/lib/extlib/dictionary.rb +433 -0
  18. data/lib/extlib/hash.rb +450 -0
  19. data/lib/extlib/hook.rb +407 -0
  20. data/lib/extlib/inflection.rb +442 -0
  21. data/lib/extlib/lazy_array.rb +453 -0
  22. data/lib/extlib/lazy_module.rb +18 -0
  23. data/lib/extlib/logger.rb +198 -0
  24. data/lib/extlib/mash.rb +157 -0
  25. data/lib/extlib/module.rb +51 -0
  26. data/lib/extlib/nil.rb +5 -0
  27. data/lib/extlib/numeric.rb +5 -0
  28. data/lib/extlib/object.rb +178 -0
  29. data/lib/extlib/object_space.rb +13 -0
  30. data/lib/extlib/pathname.rb +20 -0
  31. data/lib/extlib/pooling.rb +235 -0
  32. data/lib/extlib/rubygems.rb +38 -0
  33. data/lib/extlib/simple_set.rb +66 -0
  34. data/lib/extlib/string.rb +176 -0
  35. data/lib/extlib/struct.rb +17 -0
  36. data/lib/extlib/symbol.rb +21 -0
  37. data/lib/extlib/time.rb +44 -0
  38. data/lib/extlib/try_dup.rb +44 -0
  39. data/lib/extlib/virtual_file.rb +10 -0
  40. data/spec/array_spec.rb +40 -0
  41. data/spec/blank_spec.rb +86 -0
  42. data/spec/byte_array_spec.rb +8 -0
  43. data/spec/class_spec.rb +158 -0
  44. data/spec/datetime_spec.rb +22 -0
  45. data/spec/hash_spec.rb +536 -0
  46. data/spec/hook_spec.rb +1235 -0
  47. data/spec/inflection/plural_spec.rb +565 -0
  48. data/spec/inflection/singular_spec.rb +498 -0
  49. data/spec/inflection_extras_spec.rb +111 -0
  50. data/spec/lazy_array_spec.rb +1961 -0
  51. data/spec/lazy_module_spec.rb +38 -0
  52. data/spec/mash_spec.rb +312 -0
  53. data/spec/module_spec.rb +71 -0
  54. data/spec/object_space_spec.rb +10 -0
  55. data/spec/object_spec.rb +114 -0
  56. data/spec/pooling_spec.rb +511 -0
  57. data/spec/rcov.opts +6 -0
  58. data/spec/simple_set_spec.rb +58 -0
  59. data/spec/spec.opts +4 -0
  60. data/spec/spec_helper.rb +7 -0
  61. data/spec/string_spec.rb +222 -0
  62. data/spec/struct_spec.rb +13 -0
  63. data/spec/symbol_spec.rb +9 -0
  64. data/spec/time_spec.rb +31 -0
  65. data/spec/try_call_spec.rb +74 -0
  66. data/spec/try_dup_spec.rb +46 -0
  67. data/spec/virtual_file_spec.rb +22 -0
  68. data/tasks/ci.rake +1 -0
  69. data/tasks/metrics.rake +36 -0
  70. data/tasks/spec.rake +25 -0
  71. data/tasks/yard.rake +9 -0
  72. data/tasks/yardstick.rake +19 -0
  73. metadata +198 -0
@@ -0,0 +1,1235 @@
1
+ require 'spec_helper'
2
+ require 'extlib/hook'
3
+
4
+ describe Extlib::Hook do
5
+
6
+ before do
7
+ @module = Module.new do
8
+ def greet; greetings_from_module; end;
9
+ end
10
+
11
+ @class = Class.new do
12
+ include Extlib::Hook
13
+
14
+ def hookable; end;
15
+ def self.clakable; end;
16
+ def ambiguous; hi_mom!; end;
17
+ def self.ambiguous; hi_dad!; end;
18
+ end
19
+
20
+ @another_class = Class.new do
21
+ include Extlib::Hook
22
+ end
23
+
24
+ @other = Class.new do
25
+ include Extlib::Hook
26
+
27
+ def hookable; end
28
+ def self.clakable; end;
29
+ end
30
+
31
+ @class.register_instance_hooks :hookable
32
+ @class.register_class_hooks :clakable
33
+ end
34
+
35
+ #
36
+ # Specs out how hookable methods are registered
37
+ #
38
+ describe "explicit hookable method registration" do
39
+
40
+ describe "for class methods" do
41
+
42
+ it "shouldn't confuse instance method hooks and class method hooks" do
43
+ @class.register_instance_hooks :ambiguous
44
+ @class.register_class_hooks :ambiguous
45
+
46
+ @class.should_receive(:hi_dad!)
47
+ @class.ambiguous
48
+ end
49
+
50
+ it "should be able to register multiple hookable methods at once" do
51
+ %w(method_one method_two method_three).each do |method|
52
+ @another_class.class_eval %(def self.#{method}; end;)
53
+ end
54
+
55
+ @another_class.register_class_hooks :method_one, :method_two, :method_three
56
+ @another_class.class_hooks.should have_key(:method_one)
57
+ @another_class.class_hooks.should have_key(:method_two)
58
+ @another_class.class_hooks.should have_key(:method_three)
59
+ end
60
+
61
+ it "should not allow a method that does not exist to be registered as hookable" do
62
+ lambda { @another_class.register_class_hooks :method_one }.should raise_error(ArgumentError)
63
+ end
64
+
65
+ it "should allow hooks to be registered on methods from module extensions" do
66
+ @class.extend(@module)
67
+ @class.register_class_hooks :greet
68
+ @class.class_hooks[:greet].should_not be_nil
69
+ end
70
+
71
+ it "should allow modules to register hooks in the self.extended method" do
72
+ @module.class_eval do
73
+ def self.extended(base)
74
+ base.register_class_hooks :greet
75
+ end
76
+ end
77
+ @class.extend(@module)
78
+ @class.class_hooks[:greet].should_not be_nil
79
+ end
80
+
81
+ it "should be able to register protected methods as hooks" do
82
+ @class.class_eval %{protected; def self.protected_hookable; end;}
83
+ lambda { @class.register_class_hooks(:protected_hookable) }.should_not raise_error(ArgumentError)
84
+ end
85
+
86
+ it "should not be able to register private methods as hooks" do
87
+ @class.class_eval %{class << self; private; def private_hookable; end; end;}
88
+ lambda { @class.register_class_hooks(:private_hookable) }.should raise_error(ArgumentError)
89
+ end
90
+
91
+ it "should allow advising methods ending in ? or !" do
92
+ @class.class_eval do
93
+ def self.hookable!; two!; end;
94
+ def self.hookable?; three!; end;
95
+ register_class_hooks :hookable!, :hookable?
96
+ end
97
+ @class.before_class_method(:hookable!) { one! }
98
+ @class.after_class_method(:hookable?) { four! }
99
+
100
+ @class.should_receive(:one!).once.ordered
101
+ @class.should_receive(:two!).once.ordered
102
+ @class.should_receive(:three!).once.ordered
103
+ @class.should_receive(:four!).once.ordered
104
+
105
+ @class.hookable!
106
+ @class.hookable?
107
+ end
108
+
109
+ it "should allow hooking methods ending in ?, ! or = with method hooks" do
110
+ @class.class_eval do
111
+ def self.before_hookable!; one!; end;
112
+ def self.hookable!; two!; end;
113
+ def self.hookable?; three!; end;
114
+ def self.after_hookable?; four!; end;
115
+ register_class_hooks :hookable!, :hookable?
116
+ end
117
+ @class.before_class_method(:hookable!, :before_hookable!)
118
+ @class.after_class_method(:hookable?, :after_hookable?)
119
+
120
+ @class.should_receive(:one!).once.ordered
121
+ @class.should_receive(:two!).once.ordered
122
+ @class.should_receive(:three!).once.ordered
123
+ @class.should_receive(:four!).once.ordered
124
+
125
+ @class.hookable!
126
+ @class.hookable?
127
+ end
128
+
129
+ it "should allow hooking methods that have single character names" do
130
+ @class.class_eval do
131
+ def self.a; end;
132
+ def self.b; end;
133
+ end
134
+
135
+ @class.before_class_method(:a) { omg! }
136
+ @class.before_class_method(:b) { hi2u! }
137
+
138
+ @class.should_receive(:omg!).once.ordered
139
+ @class.should_receive(:hi2u!).once.ordered
140
+ @class.a
141
+ @class.b
142
+ end
143
+ end
144
+
145
+ describe "for instance methods" do
146
+
147
+ it "shouldn't confuse instance method hooks and class method hooks" do
148
+ @class.register_instance_hooks :ambiguous
149
+ @class.register_class_hooks :ambiguous
150
+
151
+ inst = @class.new
152
+ inst.should_receive(:hi_mom!)
153
+ inst.ambiguous
154
+ end
155
+
156
+ it "should be able to register multiple hookable methods at once" do
157
+ %w(method_one method_two method_three).each do |method|
158
+ @another_class.send(:define_method, method) {}
159
+ end
160
+
161
+ @another_class.register_instance_hooks :method_one, :method_two, :method_three
162
+ @another_class.instance_hooks.should have_key(:method_one)
163
+ @another_class.instance_hooks.should have_key(:method_two)
164
+ @another_class.instance_hooks.should have_key(:method_three)
165
+ end
166
+
167
+ it "should not allow a method that does not exist to be registered as hookable" do
168
+ lambda { @another_class.register_instance_hooks :method_one }.should raise_error(ArgumentError)
169
+ end
170
+
171
+ it "should allow hooks to be registered on included module methods" do
172
+ @class.send(:include, @module)
173
+ @class.register_instance_hooks :greet
174
+ @class.instance_hooks[:greet].should_not be_nil
175
+ end
176
+
177
+ it "should allow modules to register hooks in the self.included method" do
178
+ @module.class_eval do
179
+ def self.included(base)
180
+ base.register_instance_hooks :greet
181
+ end
182
+ end
183
+ @class.send(:include, @module)
184
+ @class.instance_hooks[:greet].should_not be_nil
185
+ end
186
+
187
+ it "should be able to register protected methods as hooks" do
188
+ @class.class_eval %{protected; def protected_hookable; end;}
189
+ lambda { @class.register_instance_hooks(:protected_hookable) }.should_not raise_error(ArgumentError)
190
+ end
191
+
192
+ it "should not be able to register private methods as hooks" do
193
+ @class.class_eval %{private; def private_hookable; end;}
194
+ lambda { @class.register_instance_hooks(:private_hookable) }.should raise_error(ArgumentError)
195
+ end
196
+
197
+ it "should allow hooking methods ending in ? or ! with block hooks" do
198
+ @class.class_eval do
199
+ def hookable!; two!; end;
200
+ def hookable?; three!; end;
201
+ register_instance_hooks :hookable!, :hookable?
202
+ end
203
+ @class.before(:hookable!) { one! }
204
+ @class.after(:hookable?) { four! }
205
+
206
+ inst = @class.new
207
+ inst.should_receive(:one!).once.ordered
208
+ inst.should_receive(:two!).once.ordered
209
+ inst.should_receive(:three!).once.ordered
210
+ inst.should_receive(:four!).once.ordered
211
+
212
+ inst.hookable!
213
+ inst.hookable?
214
+ end
215
+
216
+ it "should allow hooking methods ending in ?, ! or = with method hooks" do
217
+ @class.class_eval do
218
+ def before_hookable(val); one!; end;
219
+ def hookable=(val); two!; end;
220
+ def hookable?; three!; end;
221
+ def after_hookable?; four!; end;
222
+ register_instance_hooks :hookable=, :hookable?
223
+ end
224
+ @class.before(:hookable=, :before_hookable)
225
+ @class.after(:hookable?, :after_hookable?)
226
+
227
+ inst = @class.new
228
+ inst.should_receive(:one!).once.ordered
229
+ inst.should_receive(:two!).once.ordered
230
+ inst.should_receive(:three!).once.ordered
231
+ inst.should_receive(:four!).once.ordered
232
+
233
+ inst.hookable = 'hello'
234
+ inst.hookable?
235
+ end
236
+
237
+ it "should allow hooking methods that have single character names" do
238
+ @class.class_eval do
239
+ def a; end;
240
+ def b; end;
241
+ end
242
+
243
+ @class.before(:a) { omg! }
244
+ @class.before(:b) { hi2u! }
245
+
246
+ inst = @class.new
247
+ inst.should_receive(:omg!).once.ordered
248
+ inst.should_receive(:hi2u!).once.ordered
249
+ inst.a
250
+ inst.b
251
+ end
252
+ end
253
+
254
+ end
255
+
256
+ describe "implicit hookable method registration" do
257
+
258
+ describe "for class methods" do
259
+ it "should implicitly register the method as hookable" do
260
+ @class.class_eval %{def self.implicit_hook; end;}
261
+ @class.before_class_method(:implicit_hook) { hello }
262
+
263
+ @class.should_receive(:hello)
264
+ @class.implicit_hook
265
+ end
266
+ end
267
+
268
+ describe "for instance methods" do
269
+ it "should implicitly register the method as hookable" do
270
+ @class.class_eval %{def implicit_hook; end;}
271
+ @class.before(:implicit_hook) { hello }
272
+
273
+ inst = @class.new
274
+ inst.should_receive(:hello)
275
+ inst.implicit_hook
276
+ end
277
+
278
+ it 'should not overwrite methods included by modules after the hook is declared' do
279
+ my_module = Module.new do
280
+ # Just another module
281
+ @another_module = Module.new do
282
+ def some_method; "Hello " + super; end;
283
+ end
284
+
285
+ def some_method; "world"; end;
286
+
287
+ def self.included(base)
288
+ base.before(:some_method, :a_method)
289
+ base.send(:include, @another_module)
290
+ end
291
+ end
292
+
293
+ @class.class_eval { include my_module }
294
+
295
+ inst = @class.new
296
+ inst.should_receive(:a_method)
297
+ inst.some_method.should == "Hello world"
298
+ end
299
+ end
300
+
301
+ end
302
+
303
+ describe "hook method registration" do
304
+
305
+ describe "for class methods" do
306
+ it "should complain when only one argument is passed" do
307
+ lambda { @class.before_class_method(:clakable) }.should raise_error(ArgumentError)
308
+ lambda { @class.after_class_method(:clakable) }.should raise_error(ArgumentError)
309
+ end
310
+
311
+ it "should complain when target_method is not a symbol" do
312
+ lambda { @class.before_class_method("clakable", :ambiguous) }.should raise_error(ArgumentError)
313
+ lambda { @class.after_class_method("clakable", :ambiguous) }.should raise_error(ArgumentError)
314
+ end
315
+
316
+ it "should complain when method_sym is not a symbol" do
317
+ lambda { @class.before_class_method(:clakable, "ambiguous") }.should raise_error(ArgumentError)
318
+ lambda { @class.after_class_method(:clakable, "ambiguous") }.should raise_error(ArgumentError)
319
+ end
320
+
321
+ it "should not allow methods ending in = to be hooks" do
322
+ lambda { @class.before_class_method(:clakable, :annoying=) }.should raise_error(ArgumentError)
323
+ lambda { @class.after_class_method(:clakable, :annoying=) }.should raise_error(ArgumentError)
324
+ end
325
+ end
326
+
327
+ describe "for instance methods" do
328
+ it "should complain when only one argument is passed" do
329
+ lambda { @class.before(:hookable) }.should raise_error(ArgumentError)
330
+ lambda { @class.after(:hookable) }.should raise_error(ArgumentError)
331
+ end
332
+
333
+ it "should complain when target_method is not a symbol" do
334
+ lambda { @class.before("hookable", :ambiguous) }.should raise_error(ArgumentError)
335
+ lambda { @class.after("hookable", :ambiguous) }.should raise_error(ArgumentError)
336
+ end
337
+
338
+ it "should complain when method_sym is not a symbol" do
339
+ lambda { @class.before(:hookable, "ambiguous") }.should raise_error(ArgumentError)
340
+ lambda { @class.after(:hookable, "ambiguous") }.should raise_error(ArgumentError)
341
+ end
342
+
343
+ it "should not allow methods ending in = to be hooks" do
344
+ lambda { @class.before(:hookable, :annoying=) }.should raise_error(ArgumentError)
345
+ lambda { @class.after(:hookable, :annoying=) }.should raise_error(ArgumentError)
346
+ end
347
+ end
348
+
349
+ end
350
+
351
+ #
352
+ # Specs out how hook methods / blocks are invoked when there is no inheritance
353
+ # involved
354
+ #
355
+ describe "hook invocation without inheritance" do
356
+
357
+ describe "for class methods" do
358
+ it 'should run an advice block' do
359
+ @class.before_class_method(:clakable) { hi_mom! }
360
+ @class.should_receive(:hi_mom!)
361
+ @class.clakable
362
+ end
363
+
364
+ it 'should run an advice method' do
365
+ @class.class_eval %{def self.before_method; hi_mom!; end;}
366
+ @class.before_class_method(:clakable, :before_method)
367
+
368
+ @class.should_receive(:hi_mom!)
369
+ @class.clakable
370
+ end
371
+
372
+ it "should not pass any of the hookable method's arguments if the hook block does not accept arguments" do
373
+ @class.class_eval do
374
+ def self.method_with_args(one, two, three); end;
375
+ before_class_method(:method_with_args) { hi_mom! }
376
+ end
377
+
378
+ @class.should_receive(:hi_mom!)
379
+ @class.method_with_args(1, 2, 3)
380
+ end
381
+
382
+ it "should not pass any of the hookable method's arguments if the hook method does not accept arguments" do
383
+ @class.class_eval do
384
+ def self.method_with_args(one, two, three); end;
385
+ def self.before_method_with_args; hi_mom!; end;
386
+ before_class_method(:method_with_args, :before_method_with_args)
387
+ end
388
+
389
+ @class.should_receive(:hi_mom!)
390
+ @class.method_with_args(1, 2, 3)
391
+ end
392
+
393
+ it "should not pass any of the hookable method's arguments if the hook is declared after it is registered and does not accept arguments" do
394
+ @class.class_eval do
395
+ def self.method_with_args(one, two, three); end;
396
+ before_class_method(:method_with_args, :before_method_with_args)
397
+ def self.before_method_with_args; hi_mom!; end;
398
+ end
399
+
400
+ @class.should_receive(:hi_mom!)
401
+ @class.method_with_args(1, 2, 3)
402
+ end
403
+
404
+ it "should not pass any of the hookable method's arguments if the hook has been re-defined not to accept arguments" do
405
+ @class.class_eval do
406
+ def self.method_with_args(one, two, three); end;
407
+ def self.before_method_with_args(one, two, three); hi_mom!; end;
408
+ before_class_method(:method_with_args, :before_method_with_args)
409
+ orig_verbose, $VERBOSE = $VERBOSE, false
410
+ def self.before_method_with_args; hi_dad!; end;
411
+ $VERBOSE = orig_verbose
412
+ end
413
+
414
+ @class.should_not_receive(:hi_mom1)
415
+ @class.should_receive(:hi_dad!)
416
+ @class.method_with_args(1, 2, 3)
417
+ end
418
+
419
+ it 'should pass the hookable method arguments to the hook method if the hook method takes arguments' do
420
+ @class.class_eval do
421
+ def self.hook_this(word, lol); end;
422
+ register_class_hooks(:hook_this)
423
+ def self.before_hook_this(word, lol); hi_mom!(word, lol); end;
424
+ before_class_method(:hook_this, :before_hook_this)
425
+ end
426
+
427
+ @class.should_receive(:hi_mom!).with("omg", "hi2u")
428
+ @class.hook_this("omg", "hi2u")
429
+ end
430
+
431
+ it "should pass the hookable method arguments to the hook block if the hook block takes arguments" do
432
+ @class.class_eval do
433
+ def self.method_with_args(word, lol); end;
434
+ before_class_method(:method_with_args) { |one, two| hi_mom!(one, two) }
435
+ end
436
+
437
+ @class.should_receive(:hi_mom!).with('omg', 'hi2u')
438
+ @class.method_with_args('omg', 'hi2u')
439
+ end
440
+
441
+ it 'should pass the hookable method arguments to the hook method if the hook method was re-defined to accept arguments' do
442
+ @class.class_eval do
443
+ def self.method_with_args(word, lol); end;
444
+ def self.before_method_with_args; hi_mom!; end;
445
+ before_class_method(:method_with_args, :before_method_with_args)
446
+ orig_verbose, $VERBOSE = $VERBOSE, false
447
+ def self.before_method_with_args(word, lol); hi_dad!(word, lol); end;
448
+ $VERBOSE = orig_verbose
449
+ end
450
+
451
+ @class.should_not_receive(:hi_mom!)
452
+ @class.should_receive(:hi_dad!).with("omg", "hi2u")
453
+ @class.method_with_args("omg", "hi2u")
454
+ end
455
+
456
+ it 'should work with glob arguments (or whatever you call em)' do
457
+ @class.class_eval do
458
+ def self.hook_this(*args); end;
459
+ def self.before_hook_this(*args); hi_mom!(*args); end;
460
+ before_class_method(:hook_this, :before_hook_this)
461
+ end
462
+
463
+ @class.should_receive(:hi_mom!).with("omg", "hi2u", "lolercoaster")
464
+ @class.hook_this("omg", "hi2u", "lolercoaster")
465
+ end
466
+
467
+ it 'should allow the use of before and after together' do
468
+ @class.class_eval %{def self.before_hook; first!; end;}
469
+ @class.before_class_method(:clakable, :before_hook)
470
+ @class.after_class_method(:clakable) { last! }
471
+
472
+ @class.should_receive(:first!).once.ordered
473
+ @class.should_receive(:last!).once.ordered
474
+ @class.clakable
475
+ end
476
+
477
+ it 'should be able to use private methods as hooks' do
478
+ @class.class_eval do
479
+ class << self
480
+ private
481
+ def nike; doit!; end;
482
+ end
483
+ before_class_method(:clakable, :nike)
484
+ end
485
+
486
+ @class.should_receive(:doit!)
487
+ @class.clakable
488
+ end
489
+ end
490
+
491
+ describe "for instance methods" do
492
+ it 'should run an advice block' do
493
+ @class.before(:hookable) { hi_mom! }
494
+
495
+ inst = @class.new
496
+ inst.should_receive(:hi_mom!)
497
+ inst.hookable
498
+ end
499
+
500
+ it 'should run an advice method' do
501
+ @class.send(:define_method, :before_method) { hi_mom! }
502
+ @class.before(:hookable, :before_method)
503
+
504
+ inst = @class.new
505
+ inst.should_receive(:hi_mom!)
506
+ inst.hookable
507
+ end
508
+
509
+ it "should not pass any of the hookable method's arguments if the hook block does not accept arguments" do
510
+ @class.class_eval do
511
+ def method_with_args(one, two, three); end;
512
+ before(:method_with_args) { hi_mom! }
513
+ end
514
+
515
+ inst = @class.new
516
+ inst.should_receive(:hi_mom!)
517
+ inst.method_with_args(1, 2, 3)
518
+ end
519
+
520
+ it "should not pass any of the hookable method's arguments if the hook method does not accept arguments" do
521
+ @class.class_eval do
522
+ def method_with_args(one, two, three); end;
523
+ def before_method_with_args; hi_mom!; end;
524
+ before(:method_with_args, :before_method_with_args)
525
+ end
526
+
527
+ inst = @class.new
528
+ inst.should_receive(:hi_mom!)
529
+ inst.method_with_args(1, 2, 3)
530
+ end
531
+
532
+ it "should not pass any of the hookable method's arguments if the hook is declared after it is registered and does not accept arguments" do
533
+ @class.class_eval do
534
+ def method_with_args(one, two, three); end;
535
+ before(:method_with_args, :before_method_with_args)
536
+ def before_method_with_args; hi_mom!; end;
537
+ end
538
+
539
+ inst = @class.new
540
+ inst.should_receive(:hi_mom!)
541
+ inst.method_with_args(1, 2, 3)
542
+ end
543
+
544
+ it "should not pass any of the hookable method's arguments if the hook has been re-defined not to accept arguments" do
545
+ @class.class_eval do
546
+ def method_with_args(one, two, three); end;
547
+ def before_method_with_args(one, two, three); hi_mom!; end;
548
+ before(:method_with_args, :before_method_with_args)
549
+ orig_verbose, $VERBOSE = $VERBOSE, false
550
+ def before_method_with_args; hi_dad!; end;
551
+ $VERBOSE = orig_verbose
552
+ end
553
+
554
+ inst = @class.new
555
+ inst.should_not_receive(:hi_mom1)
556
+ inst.should_receive(:hi_dad!)
557
+ inst.method_with_args(1, 2, 3)
558
+ end
559
+
560
+ it 'should pass the hookable method arguments to the hook method if the hook method takes arguments' do
561
+ @class.class_eval do
562
+ def method_with_args(word, lol); end;
563
+ def before_method_with_args(one, two); hi_mom!(one, two); end;
564
+ before(:method_with_args, :before_method_with_args)
565
+ end
566
+
567
+ inst = @class.new
568
+ inst.should_receive(:hi_mom!).with("omg", "hi2u")
569
+ inst.method_with_args("omg", "hi2u")
570
+ end
571
+
572
+ it "should pass the hookable method arguments to the hook block if the hook block takes arguments" do
573
+ @class.class_eval do
574
+ def method_with_args(word, lol); end;
575
+ before(:method_with_args) { |one, two| hi_mom!(one, two) }
576
+ end
577
+
578
+ inst = @class.new
579
+ inst.should_receive(:hi_mom!).with('omg', 'hi2u')
580
+ inst.method_with_args('omg', 'hi2u')
581
+ end
582
+
583
+ it 'should pass the hookable method arguments to the hook method if the hook method was re-defined to accept arguments' do
584
+ @class.class_eval do
585
+ def method_with_args(word, lol); end;
586
+ def before_method_with_args; hi_mom!; end;
587
+ before(:method_with_args, :before_method_with_args)
588
+ orig_verbose, $VERBOSE = $VERBOSE, false
589
+ def before_method_with_args(word, lol); hi_dad!(word, lol); end;
590
+ $VERBOSE = orig_verbose
591
+ end
592
+
593
+ inst = @class.new
594
+ inst.should_not_receive(:hi_mom!)
595
+ inst.should_receive(:hi_dad!).with("omg", "hi2u")
596
+ inst.method_with_args("omg", "hi2u")
597
+ end
598
+
599
+ it "should not pass the method return value to the after hook if the method does not take arguments" do
600
+ @class.class_eval do
601
+ def method_with_ret_val; 'hello'; end;
602
+ def after_method_with_ret_val; hi_mom!; end;
603
+ after(:method_with_ret_val, :after_method_with_ret_val)
604
+ end
605
+
606
+ inst = @class.new
607
+ inst.should_receive(:hi_mom!)
608
+ inst.method_with_ret_val
609
+ end
610
+
611
+ it 'should work with glob arguments (or whatever you call em)' do
612
+ @class.class_eval do
613
+ def hook_this(*args); end;
614
+ def before_hook_this(*args); hi_mom!(*args) end;
615
+ before(:hook_this, :before_hook_this)
616
+ end
617
+
618
+ inst = @class.new
619
+ inst.should_receive(:hi_mom!).with("omg", "hi2u", "lolercoaster")
620
+ inst.hook_this("omg", "hi2u", "lolercoaster")
621
+ end
622
+
623
+ it 'should allow the use of before and after together' do
624
+ @class.class_eval %{def after_hook; last!; end;}
625
+ @class.before(:hookable) { first! }
626
+ @class.after(:hookable, :after_hook)
627
+
628
+ inst = @class.new
629
+ inst.should_receive(:first!).once.ordered
630
+ inst.should_receive(:last!).once.ordered
631
+ inst.hookable
632
+ end
633
+
634
+ it 'should be able to use private methods as hooks' do
635
+ @class.class_eval %{private; def nike; doit!; end;}
636
+ @class.before(:hookable, :nike)
637
+
638
+ inst = @class.new
639
+ inst.should_receive(:doit!)
640
+ inst.hookable
641
+ end
642
+ end
643
+
644
+ end
645
+
646
+ describe "hook invocation with class inheritance" do
647
+
648
+ describe "for class methods" do
649
+ it 'should run an advice block when the class is inherited' do
650
+ @class.before_class_method(:clakable) { hi_mom! }
651
+ @child = Class.new(@class)
652
+ @child.should_receive(:hi_mom!)
653
+ @child.clakable
654
+ end
655
+
656
+ it 'should run an advice block on child class when hook is registered in parent after inheritance' do
657
+ @child = Class.new(@class)
658
+ @class.before_class_method(:clakable) { hi_mom! }
659
+ @child.should_receive(:hi_mom!)
660
+ @child.clakable
661
+ end
662
+
663
+ it 'should be able to declare advice methods in child classes' do
664
+ @class.class_eval %{def self.before_method; hi_dad!; end;}
665
+ @class.before_class_method(:clakable, :before_method)
666
+
667
+ @child = Class.new(@class) do
668
+ def self.child; hi_mom!; end;
669
+ before_class_method(:clakable, :child)
670
+ end
671
+
672
+ @child.should_receive(:hi_dad!).once.ordered
673
+ @child.should_receive(:hi_mom!).once.ordered
674
+ @child.clakable
675
+ end
676
+
677
+ it "should not execute hooks added in the child classes when in the parent class" do
678
+ @child = Class.new(@class) { def self.child; hi_mom!; end; }
679
+ @child.before_class_method(:clakable, :child)
680
+ @class.should_not_receive(:hi_mom!)
681
+ @class.clakable
682
+ end
683
+
684
+ it 'should not call the hook stack if the hookable method is overwritten and does not call super' do
685
+ @class.before_class_method(:clakable) { hi_mom! }
686
+ @child = Class.new(@class) do
687
+ def self.clakable; end;
688
+ end
689
+
690
+ @child.should_not_receive(:hi_mom!)
691
+ @child.clakable
692
+ end
693
+
694
+ it 'should not call hooks defined in the child class for a hookable method in a parent if the child overwrites the hookable method without calling super' do
695
+ @child = Class.new(@class) do
696
+ before_class_method(:clakable) { hi_mom! }
697
+ def self.clakable; end;
698
+ end
699
+
700
+ @child.should_not_receive(:hi_mom!)
701
+ @child.clakable
702
+ end
703
+
704
+ it 'should not call hooks defined in child class even if hook method exists in parent' do
705
+ @class.class_eval %{def self.hello_world; hello_world!; end;}
706
+ @child = Class.new(@class) do
707
+ before_class_method(:clakable, :hello_world)
708
+ end
709
+
710
+ @class.should_not_receive(:hello_world!)
711
+ @class.clakable
712
+ end
713
+ end
714
+
715
+ describe "for instance methods" do
716
+ it 'should run an advice block when the class is inherited' do
717
+ @inherited_class = Class.new(@class)
718
+ @class.before(:hookable) { hi_dad! }
719
+
720
+ inst = @inherited_class.new
721
+ inst.should_receive(:hi_dad!)
722
+ inst.hookable
723
+ end
724
+
725
+ it 'should run an advice block on child class when hook is registered in parent after inheritance' do
726
+ @child = Class.new(@class)
727
+ @class.before(:hookable) { hi_mom! }
728
+
729
+ inst = @child.new
730
+ inst.should_receive(:hi_mom!)
731
+ inst.hookable
732
+ end
733
+
734
+ it 'should be able to declare advice methods in child classes' do
735
+ @class.send(:define_method, :before_method) { hi_dad! }
736
+ @class.before(:hookable, :before_method)
737
+
738
+ @child = Class.new(@class) do
739
+ def child; hi_mom!; end;
740
+ before :hookable, :child
741
+ end
742
+
743
+ inst = @child.new
744
+ inst.should_receive(:hi_dad!).once.ordered
745
+ inst.should_receive(:hi_mom!).once.ordered
746
+ inst.hookable
747
+ end
748
+
749
+ it "should not execute hooks added in the child classes when in parent class" do
750
+ @child = Class.new(@class)
751
+ @child.send(:define_method, :child) { hi_mom! }
752
+ @child.before(:hookable, :child)
753
+
754
+ inst = @class.new
755
+ inst.should_not_receive(:hi_mom!)
756
+ inst.hookable
757
+ end
758
+
759
+ it 'should not call the hook stack if the hookable method is overwritten and does not call super' do
760
+ @class.before(:hookable) { hi_mom! }
761
+ @child = Class.new(@class) do
762
+ def hookable; end;
763
+ end
764
+
765
+ inst = @child.new
766
+ inst.should_not_receive(:hi_mom!)
767
+ inst.hookable
768
+ end
769
+
770
+ it 'should not call hooks defined in the child class for a hookable method in a parent if the child overwrites the hookable method without calling super' do
771
+ @child = Class.new(@class) do
772
+ before(:hookable) { hi_mom! }
773
+ def hookable; end;
774
+ end
775
+
776
+ inst = @child.new
777
+ inst.should_not_receive(:hi_mom!)
778
+ inst.hookable
779
+ end
780
+
781
+ it 'should not call hooks defined in child class even if hook method exists in parent' do
782
+ @class.send(:define_method, :hello_world) { hello_world! }
783
+ @child = Class.new(@class) do
784
+ before(:hookable, :hello_world)
785
+ end
786
+
787
+ inst = @class.new
788
+ inst.should_not_receive(:hello_world!)
789
+ inst.hookable
790
+ end
791
+
792
+ it 'should call different hooks in different children when they are defined there' do
793
+ @class.send(:define_method, :hello_world) {}
794
+
795
+ @child1 = Class.new(@class) do
796
+ before(:hello_world){ hi_dad! }
797
+ end
798
+
799
+ @child2 = Class.new(@class) do
800
+ before(:hello_world){ hi_mom! }
801
+ end
802
+
803
+ @child3 = Class.new(@child1) do
804
+ before(:hello_world){ hi_grandma! }
805
+ end
806
+
807
+ inst1 = @child1.new
808
+ inst2 = @child2.new
809
+ inst3 = @child3.new
810
+ inst1.should_receive(:hi_dad!).once
811
+ inst2.should_receive(:hi_mom!).once
812
+ inst3.should_receive(:hi_dad!).once
813
+ inst3.should_receive(:hi_grandma!).once
814
+ inst1.hello_world
815
+ inst2.hello_world
816
+ inst3.hello_world
817
+ end
818
+
819
+ end
820
+
821
+ end
822
+
823
+ describe "hook invocation with module inclusions / extensions" do
824
+
825
+ describe "for class methods" do
826
+ it "should not overwrite methods included by extensions after the hook is declared" do
827
+ @module.class_eval do
828
+ @another_module = Module.new do
829
+ def greet; greetings_from_another_module; super; end;
830
+ end
831
+
832
+ def self.extended(base)
833
+ base.before_class_method(:clakable, :greet)
834
+ base.extend(@another_module)
835
+ end
836
+ end
837
+
838
+ @class.extend(@module)
839
+ @class.should_receive(:greetings_from_another_module).once.ordered
840
+ @class.should_receive(:greetings_from_module).once.ordered
841
+ @class.clakable
842
+ end
843
+ end
844
+
845
+ describe "for instance methods" do
846
+ it 'should not overwrite methods included by modules after the hook is declared' do
847
+ @module.class_eval do
848
+ @another_module = Module.new do
849
+ def greet; greetings_from_another_module; super; end;
850
+ end
851
+
852
+ def self.included(base)
853
+ base.before(:hookable, :greet)
854
+ base.send(:include, @another_module)
855
+ end
856
+ end
857
+
858
+ @class.send(:include, @module)
859
+
860
+ inst = @class.new
861
+ inst.should_receive(:greetings_from_another_module).once.ordered
862
+ inst.should_receive(:greetings_from_module).once.ordered
863
+ inst.hookable
864
+ end
865
+ end
866
+
867
+ end
868
+
869
+ describe "hook invocation with unrelated classes" do
870
+
871
+ describe "for class methods" do
872
+ it "should not execute hooks registered in an unrelated class" do
873
+ @class.before_class_method(:clakable) { hi_mom! }
874
+
875
+ @other.should_not_receive(:hi_mom!)
876
+ @other.clakable
877
+ end
878
+ end
879
+
880
+ describe "for instance methods" do
881
+ it "should not execute hooks registered in an unrelated class" do
882
+ @class.before(:hookable) { hi_mom! }
883
+
884
+ inst = @other.new
885
+ inst.should_not_receive(:hi_mom!)
886
+ inst.hookable
887
+ end
888
+ end
889
+
890
+ end
891
+
892
+ describe "using before hook" do
893
+
894
+ describe "for class methods" do
895
+
896
+ it 'should run the advice before the advised method' do
897
+ @class.class_eval %{def self.hook_me; second!; end;}
898
+ @class.register_class_hooks(:hook_me)
899
+ @class.before_class_method(:hook_me, :first!)
900
+
901
+ @class.should_receive(:first!).ordered
902
+ @class.should_receive(:second!).ordered
903
+ @class.hook_me
904
+ end
905
+
906
+ it 'should execute all advices once in order' do
907
+ @class.before_class_method(:clakable, :hook_1)
908
+ @class.before_class_method(:clakable, :hook_2)
909
+ @class.before_class_method(:clakable, :hook_3)
910
+
911
+ @class.should_receive(:hook_1).once.ordered
912
+ @class.should_receive(:hook_2).once.ordered
913
+ @class.should_receive(:hook_3).once.ordered
914
+ @class.clakable
915
+ end
916
+ end
917
+
918
+ describe "for instance methods" do
919
+
920
+ it 'should run the advice before the advised method' do
921
+ @class.class_eval %{
922
+ def hook_me; second!; end;
923
+ }
924
+ @class.register_instance_hooks(:hook_me)
925
+ @class.before(:hook_me, :first!)
926
+
927
+ inst = @class.new
928
+ inst.should_receive(:first!).ordered
929
+ inst.should_receive(:second!).ordered
930
+ inst.hook_me
931
+ end
932
+
933
+ it 'should execute all advices once in order' do
934
+ @class.before(:hookable, :hook_1)
935
+ @class.before(:hookable, :hook_2)
936
+ @class.before(:hookable, :hook_3)
937
+
938
+ inst = @class.new
939
+ inst.should_receive(:hook_1).once.ordered
940
+ inst.should_receive(:hook_2).once.ordered
941
+ inst.should_receive(:hook_3).once.ordered
942
+ inst.hookable
943
+ end
944
+ end
945
+
946
+ end
947
+
948
+ describe 'using after hook' do
949
+
950
+ describe "for class methods" do
951
+
952
+ it 'should run the advice after the advised method' do
953
+ @class.class_eval %{def self.hook_me; first!; end;}
954
+ @class.register_class_hooks(:hook_me)
955
+ @class.after_class_method(:hook_me, :second!)
956
+
957
+ @class.should_receive(:first!).ordered
958
+ @class.should_receive(:second!).ordered
959
+ @class.hook_me
960
+ end
961
+
962
+ it 'should execute all advices once in order' do
963
+ @class.after_class_method(:clakable, :hook_1)
964
+ @class.after_class_method(:clakable, :hook_2)
965
+ @class.after_class_method(:clakable, :hook_3)
966
+
967
+ @class.should_receive(:hook_1).once.ordered
968
+ @class.should_receive(:hook_2).once.ordered
969
+ @class.should_receive(:hook_3).once.ordered
970
+ @class.clakable
971
+ end
972
+
973
+ it "the advised method should still return its normal value" do
974
+ @class.class_eval %{def self.hello; "hello world"; end;}
975
+ @class.register_class_hooks(:hello)
976
+ @class.after_class_method(:hello) { "BAM" }
977
+
978
+ @class.hello.should == "hello world"
979
+ end
980
+
981
+ it "should pass the return value to a hook method" do
982
+ @class.class_eval do
983
+ def self.with_return_val; 'hello'; end;
984
+ def self.after_with_return_val(retval); retval.should == 'hello'; end;
985
+ after_class_method(:with_return_val, :after_with_return_val)
986
+ end
987
+
988
+ @class.with_return_val
989
+ end
990
+
991
+ it "should pass the return value to a hook block" do
992
+ @class.class_eval do
993
+ def self.with_return_val; 'hello'; end;
994
+ after_class_method(:with_return_val) { |ret| ret.should == 'hello' }
995
+ end
996
+
997
+ @class.with_return_val
998
+ end
999
+
1000
+ it "should pass the return value and method arguments to a hook block" do
1001
+ @class.class_eval do
1002
+ def self.with_args_and_return_val(world); 'hello'; end;
1003
+ after_class_method(:with_args_and_return_val) do |hello, world|
1004
+ hello.should == "hello"
1005
+ world.should == "world"
1006
+ end
1007
+ end
1008
+
1009
+ @class.with_args_and_return_val('world')
1010
+ end
1011
+ end
1012
+
1013
+ describe "for instance methods" do
1014
+
1015
+ it 'should run the advice after the advised method' do
1016
+ @class.class_eval %{def hook_me; first!; end;}
1017
+ @class.register_instance_hooks(:hook_me)
1018
+ @class.after(:hook_me, :second!)
1019
+
1020
+ inst = @class.new
1021
+ inst.should_receive(:first!).ordered
1022
+ inst.should_receive(:second!).ordered
1023
+ inst.hook_me
1024
+ end
1025
+
1026
+ it 'should execute all advices once in order' do
1027
+ @class.after(:hookable, :hook_1)
1028
+ @class.after(:hookable, :hook_2)
1029
+ @class.after(:hookable, :hook_3)
1030
+
1031
+ inst = @class.new
1032
+ inst.should_receive(:hook_1).once.ordered
1033
+ inst.should_receive(:hook_2).once.ordered
1034
+ inst.should_receive(:hook_3).once.ordered
1035
+ inst.hookable
1036
+ end
1037
+
1038
+ it "the advised method should still return its normal value" do
1039
+ @class.class_eval %{def hello; "hello world"; end;}
1040
+ @class.register_instance_hooks(:hello)
1041
+ @class.after(:hello) { "BAM" }
1042
+
1043
+ @class.new.hello.should == "hello world"
1044
+ end
1045
+
1046
+ it "should return nil if an after hook throws :halt without a return value" do
1047
+ @class.class_eval %{def with_value; "hello"; end;}
1048
+ @class.register_instance_hooks(:with_value)
1049
+ @class.after(:with_value) { throw :halt }
1050
+
1051
+ @class.new.with_value.should be_nil
1052
+ end
1053
+
1054
+ it "should pass the return value to a hook method" do
1055
+ @class.class_eval do
1056
+ def with_return_val; 'hello'; end;
1057
+ def after_with_return_val(retval); retval.should == 'hello'; end;
1058
+ after(:with_return_val, :after_with_return_val)
1059
+ end
1060
+
1061
+ @class.new.with_return_val
1062
+ end
1063
+
1064
+ it "should pass the return value to a hook block" do
1065
+ @class.class_eval do
1066
+ def with_return_val; 'hello'; end;
1067
+ after(:with_return_val) { |ret| ret.should == 'hello' }
1068
+ end
1069
+
1070
+ @class.new.with_return_val
1071
+ end
1072
+
1073
+ it "should pass the return value and method arguments to a hook block" do
1074
+ @class.class_eval do
1075
+ def with_args_and_return_val(world); 'hello'; end;
1076
+ after(:with_args_and_return_val) do |hello, world|
1077
+ hello.should == "hello"
1078
+ world.should == "world"
1079
+ end
1080
+ end
1081
+
1082
+ @class.new.with_args_and_return_val('world')
1083
+ end
1084
+ end
1085
+
1086
+ end
1087
+
1088
+ describe 'aborting' do
1089
+
1090
+ describe "for class methods" do
1091
+ it "should catch :halt from a before hook and abort the advised method" do
1092
+ @class.class_eval %{def self.no_love; love_me!; end;}
1093
+ @class.register_class_hooks :no_love
1094
+ @class.before_class_method(:no_love) { maybe! }
1095
+ @class.before_class_method(:no_love) { throw :halt }
1096
+ @class.before_class_method(:no_love) { what_about_me? }
1097
+
1098
+ @class.should_receive(:maybe!)
1099
+ @class.should_not_receive(:what_about_me?)
1100
+ @class.should_not_receive(:love_me!)
1101
+ lambda { @class.no_love }.should_not throw_symbol(:halt)
1102
+ end
1103
+
1104
+ it "should not run after hooks if a before hook throws :halt" do
1105
+ @class.before_class_method(:clakable) { throw :halt }
1106
+ @class.after_class_method(:clakable) { bam! }
1107
+
1108
+ @class.should_not_receive(:bam!)
1109
+ lambda { @class.clakable }.should_not throw_symbol(:halt)
1110
+ end
1111
+
1112
+ it "should return nil from the hookable method if a before hook throws :halt" do
1113
+ @class.class_eval %{def self.with_value; "hello"; end;}
1114
+ @class.register_class_hooks(:with_value)
1115
+ @class.before_class_method(:with_value) { throw :halt }
1116
+
1117
+ @class.with_value.should be_nil
1118
+ end
1119
+
1120
+ it "should catch :halt from an after hook and cease the advice" do
1121
+ @class.after_class_method(:clakable) { throw :halt }
1122
+ @class.after_class_method(:clakable) { never_see_me! }
1123
+
1124
+ @class.should_not_receive(:never_see_me!)
1125
+ lambda { @class.clakable }.should_not throw_symbol(:halt)
1126
+ end
1127
+
1128
+ it "should return nil if an after hook throws :halt without a return value" do
1129
+ @class.class_eval %{def self.with_value; "hello"; end;}
1130
+ @class.register_class_hooks(:with_value)
1131
+ @class.after_class_method(:with_value) { throw :halt }
1132
+
1133
+ @class.with_value.should be_nil
1134
+ end
1135
+ end
1136
+
1137
+ describe "for instance methods" do
1138
+ it "should catch :halt from a before hook and abort the advised method" do
1139
+ @class.class_eval %{def no_love; love_me!; end;}
1140
+ @class.register_instance_hooks :no_love
1141
+ @class.before(:no_love) { maybe! }
1142
+ @class.before(:no_love) { throw :halt }
1143
+ @class.before(:no_love) { what_about_me? }
1144
+
1145
+ inst = @class.new
1146
+ inst.should_receive(:maybe!)
1147
+ inst.should_not_receive(:what_about_me?)
1148
+ inst.should_not_receive(:love_me!)
1149
+ lambda { inst.no_love }.should_not throw_symbol(:halt)
1150
+ end
1151
+
1152
+ it "should not run after hooks if a before hook throws :halt" do
1153
+ @class.before(:hookable) { throw :halt }
1154
+ @class.after(:hookable) { bam! }
1155
+
1156
+ inst = @class.new
1157
+ inst.should_not_receive(:bam!)
1158
+ lambda { inst.hookable }.should_not throw_symbol(:halt)
1159
+ end
1160
+
1161
+ it "should return nil from the hookable method if a before hook throws :halt" do
1162
+ @class.class_eval %{def with_value; "hello"; end;}
1163
+ @class.register_instance_hooks(:with_value)
1164
+ @class.before(:with_value) { throw :halt }
1165
+
1166
+ @class.new.with_value.should be_nil
1167
+ end
1168
+
1169
+ it "should catch :halt from an after hook and cease the advice" do
1170
+ @class.after(:hookable) { throw :halt }
1171
+ @class.after(:hookable) { never_see_me! }
1172
+
1173
+ inst = @class.new
1174
+ inst.should_not_receive(:never_see_me!)
1175
+ lambda { inst.hookable }.should_not throw_symbol(:halt)
1176
+ end
1177
+ end
1178
+
1179
+ end
1180
+
1181
+ describe 'aborting with return values' do
1182
+
1183
+ describe "for class methods" do
1184
+
1185
+ it "should be able to abort from a before hook with a return value" do
1186
+ @class.before_class_method(:clakable) { throw :halt, 'omg' }
1187
+ @class.clakable.should == 'omg'
1188
+ end
1189
+
1190
+ it "should be able to abort from an after hook with a return value" do
1191
+ @class.after_class_method(:clakable) { throw :halt, 'omg' }
1192
+ @class.clakable.should == 'omg'
1193
+ end
1194
+
1195
+ end
1196
+
1197
+ describe "for instance methods" do
1198
+
1199
+ it "should be able to abort from a before hook with a return value" do
1200
+ @class.before(:hookable) { throw :halt, 'omg' }
1201
+
1202
+ inst = @class.new
1203
+ inst.hookable.should == 'omg'
1204
+ end
1205
+
1206
+ it "should be able to abort from an after hook with a return value" do
1207
+ @class.after(:hookable) { throw :halt, 'omg' }
1208
+
1209
+ inst = @class.new
1210
+ inst.hookable.should == 'omg'
1211
+ end
1212
+
1213
+ end
1214
+
1215
+ end
1216
+
1217
+ describe "helper methods" do
1218
+ it 'should generate the correct argument signature' do
1219
+ @class.class_eval do
1220
+ def some_method(a, b, c)
1221
+ [a, b, c]
1222
+ end
1223
+
1224
+ def yet_another(a, *heh)
1225
+ [a, *heh]
1226
+ end
1227
+ end
1228
+
1229
+ @class.args_for(@class.instance_method(:hookable)).should == "&block"
1230
+ @class.args_for(@class.instance_method(:some_method)).should == "_1, _2, _3, &block"
1231
+ @class.args_for(@class.instance_method(:yet_another)).should == "_1, *args, &block"
1232
+ end
1233
+ end
1234
+
1235
+ end