delegate_matcher 0.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +3 -3
  3. data/README.md +101 -8
  4. data/README.md.erb +216 -0
  5. data/Rakefile +6 -1
  6. data/delegate_matcher.gemspec +1 -1
  7. data/lib/delegate_matcher/delegate.rb +5 -12
  8. data/lib/delegate_matcher/delegate_matcher.rb +5 -14
  9. data/lib/delegate_matcher/delegation.rb +32 -23
  10. data/lib/delegate_matcher/dispatcher.rb +4 -1
  11. data/lib/delegate_matcher/expected.rb +31 -18
  12. data/lib/delegate_matcher/nil_delegate.rb +3 -2
  13. data/lib/delegate_matcher/stub_delegate.rb +7 -3
  14. data/lib/delegate_matcher/version.rb +1 -1
  15. data/spec/{lib → examples}/active_support_delegation_spec.rb +11 -2
  16. data/spec/{lib → examples}/forwardable_delegation_spec.rb +11 -2
  17. data/spec/shared/author.rb +23 -0
  18. data/spec/{lib/shared/a_simple_delegator.rb → shared/basic.rb} +4 -6
  19. data/spec/{lib/shared → shared}/nil_check.rb +15 -15
  20. data/spec/shared/post_delegation.rb +42 -0
  21. data/spec/shared/post_methods.rb +15 -0
  22. data/spec/spec_helper.rb +1 -1
  23. data/spec/to_a_class_method_spec.rb +37 -0
  24. data/spec/to_a_class_variable_spec.rb +38 -0
  25. data/spec/to_a_constant_spec.rb +37 -0
  26. data/spec/to_an_instance_method_spec.rb +39 -0
  27. data/spec/to_an_instance_variable_spec.rb +35 -0
  28. data/spec/to_an_object_spec.rb +45 -0
  29. data/spec/to_multiple_targets_spec.rb +34 -0
  30. data/spec/with_args_spec.rb +151 -0
  31. data/spec/with_as_spec.rb +25 -0
  32. data/spec/with_block_spec.rb +75 -0
  33. data/spec/with_prefix_spec.rb +37 -0
  34. data/spec/with_return_value_spec.rb +46 -0
  35. data/spec/with_to_spec.rb +53 -0
  36. metadata +45 -43
  37. data/.bundle/config +0 -3
  38. data/spec/lib/aggregate_delegate_matcher_spec.rb +0 -62
  39. data/spec/lib/class_method_spec.rb +0 -84
  40. data/spec/lib/class_variable_spec.rb +0 -85
  41. data/spec/lib/constant_spec.rb +0 -86
  42. data/spec/lib/delegate_spec.rb +0 -15
  43. data/spec/lib/instance_method_spec.rb +0 -84
  44. data/spec/lib/instance_variable_spec.rb +0 -102
  45. data/spec/lib/object_spec.rb +0 -103
  46. data/spec/lib/shared/args.rb +0 -24
  47. data/spec/lib/shared/args_and_a_block.rb +0 -6
  48. data/spec/lib/shared/author.rb +0 -10
  49. data/spec/lib/shared/block.rb +0 -71
  50. data/spec/lib/shared/different_method_name.rb +0 -12
  51. data/spec/lib/shared/different_return_value.rb +0 -19
  52. data/spec/lib/shared/prefix.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b01a0155696471c53b2e5d758ee3acfb321fe843
4
- data.tar.gz: 5c153cefb6be729954baf5f1a71251f929ab7d15
3
+ metadata.gz: 5e342a7ea43c74991c773ae7093fd017383dd22e
4
+ data.tar.gz: f9b3cec53a47692c6b65ca529b46a59bc89a8a68
5
5
  SHA512:
6
- metadata.gz: d2bbb26693117c40694240b49c5f1ecc192aaa0d6bdd5a3b1dbecb6e5c1bfc4b4b6e40a6a462143139001f036726dea5ff865ffb90a2b394f15107ee411f2c9e
7
- data.tar.gz: a52c23c8dea9252b407dc9aead40ace210095d19de17ab469547bd8514589f1e0c2ccfbf9e8c2648f43820ab533b2a4d23a4212908c50a4e25b6b12a89ac6419
6
+ metadata.gz: 4a91f85a9c888ea5e659c1dbdeeac00a0395eabf55149beba29a3d123bd22d38e6e5d1a209df6e3a747483b1a6e22dfe158aea9834f7c62e79d44e00c57bf6b7
7
+ data.tar.gz: f2c93b90808e178b51b6ac52bffc6e7ff62473397618371c258b5f1c6421683b652a3cac70a4128213f7ad9544b1df1f51956492498f68530406ffd2304d177a
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- delegate_matcher (0.3)
5
- proc_extensions (~> 0.1)
4
+ delegate_matcher (0.4)
5
+ proc_extensions (~> 0.2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -66,7 +66,7 @@ GEM
66
66
  parser (2.2.3.0)
67
67
  ast (>= 1.1, < 3.0)
68
68
  powerpack (0.1.1)
69
- proc_extensions (0.1.2)
69
+ proc_extensions (0.2)
70
70
  sourcify (~> 0.5)
71
71
  pry (0.10.3)
72
72
  coderay (~> 1.1.0)
data/README.md CHANGED
@@ -41,6 +41,7 @@ This matcher allows you to validate delegation to:
41
41
  * class variables
42
42
  * constants
43
43
  * arbitrary objects
44
+ * multiple targets
44
45
 
45
46
  ```ruby
46
47
  describe Post do
@@ -112,13 +113,29 @@ describe Post do
112
113
  end
113
114
  ```
114
115
 
115
- Also, in some cases the delegator might make minor changes to the arguments. While this is arguably no
116
+ Also, in some cases, the delegator change the arguments. While this is arguably no
116
117
  longer true delegation you can still check that arguments are correctly passed by using a second `with`
117
118
  method to specify the arguments expected by the delegate.
118
119
 
119
120
  ```ruby
120
121
  describe Post do
121
- it { should delegate(:name).with('Ms.')to(:author).with('Miss') } # name('Ms.') => author.name('Miss')
122
+ it { should delegate(:name).with('Ms.').to(:author).with('Miss') } # name('Ms.') => author.name('Miss')
123
+ end
124
+ ```
125
+ You can use the `with(no_args).` rather than `with.` or `with().` to test delegation with no arguments passed
126
+ to the delegator.
127
+
128
+ ```ruby
129
+ describe Post do
130
+ it { should delegate(:name).with(no_args).to(:author) } # name() => author.name()
131
+ end
132
+ ```
133
+
134
+ For the second `with` you can use any RSpec argument matcher.
135
+
136
+ ```ruby
137
+ describe Post do
138
+ it { should delegate(:name).with('Ms.').to(:author).with(anything) } # name('Ms.') => author.name(*)
122
139
  end
123
140
  ```
124
141
 
@@ -144,6 +161,11 @@ describe Post do
144
161
  end
145
162
  ```
146
163
 
164
+ If the `proc` passed to `with_block` is not the same `proc` used y the delegator
165
+ then the sources of the `proc`'s will be compared for equality using the `proc_extensions` gem.
166
+ For this comparison to work the `proc` must not be not have been created via an `eval` of a string
167
+ and must be the only `proc` declared on that line of source code.
168
+
147
169
  See [proc_extensions](https://github.com/dwhelan/proc_extensions/) for more details on how the source for procs is compared.
148
170
 
149
171
  ### Return Value
@@ -156,10 +178,55 @@ describe Post do
156
178
  end
157
179
  ```
158
180
 
181
+ ### Multiple Targets
182
+ You can test delegation to more than one target by specifing more than one target via `to`.
183
+ ```ruby
184
+ require 'spec_helper'
185
+
186
+ module RSpec
187
+ module Matchers
188
+ module DelegateMatcher
189
+ module Composite
190
+ describe 'delegation to multiple targets' do
191
+ class Post
192
+ include PostMethods
193
+
194
+ attr_accessor :authors, :catherine_asaro, :isaac_asimov
195
+
196
+ def initialize
197
+ self.catherine_asaro = Author.new('Catherine Asaro')
198
+ self.isaac_asimov = Author.new('Isaac Asimov')
199
+ self.authors = [catherine_asaro, isaac_asimov]
200
+ end
201
+
202
+ def name
203
+ authors.map(&:name)
204
+ end
205
+ end
206
+
207
+ subject { Post.new }
208
+
209
+ it { should delegate(:name).to(*subject.authors) }
210
+ it { should delegate(:name).to(subject.catherine_asaro, subject.isaac_asimov) }
211
+ it { should delegate(:name).to(:catherine_asaro, :isaac_asimov) }
212
+ it { should delegate(:name).to(:@catherine_asaro, :@isaac_asimov) }
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ ```
220
+
159
221
  ### Active Support
160
222
  You can test delegation based on the [delegate](http://api.rubyonrails.org/classes/Module.html#method-i-delegate) method in the Active Support gem.
161
223
 
162
224
  ```ruby
225
+ require 'spec_helper'
226
+ require 'active_support/core_ext/module/delegation'
227
+
228
+ module ActiveSupportDelegation
229
+ # rubocop:disable Style/ClassVars
163
230
  class Post
164
231
  attr_accessor :author
165
232
 
@@ -172,15 +239,24 @@ You can test delegation based on the [delegate](http://api.rubyonrails.org/class
172
239
  delegate :name, to: :class, prefix: true
173
240
  delegate :count, to: :@@authors
174
241
  delegate :first, to: :GENRES
242
+ delegate :length, to: :'author.name', prefix: :name
175
243
 
176
244
  def initialize
177
245
  @author = Author.new
178
246
  end
247
+
248
+ def inspect
249
+ 'post'
250
+ end
179
251
  end
180
252
 
181
253
  class Author
182
- def name
183
- @name ||= 'Catherine Asaro'
254
+ def initialize
255
+ @name = 'Catherine Asaro'
256
+ end
257
+
258
+ def name(*)
259
+ @name
184
260
  end
185
261
  end
186
262
 
@@ -197,6 +273,7 @@ You can test delegation based on the [delegate](http://api.rubyonrails.org/class
197
273
  it { should delegate(:name).to(:author).with_prefix(:writer) }
198
274
  it { should delegate(:name).to(:author).with_block }
199
275
  it { should delegate(:name).to(:author).with('Ms.') }
276
+ it { should delegate(:name).to(:author).with('Ms.').with_block }
200
277
 
201
278
  it { should delegate(:name).to(:class).with_prefix }
202
279
  it { should delegate(:count).to(:@@authors) }
@@ -205,15 +282,19 @@ You can test delegation based on the [delegate](http://api.rubyonrails.org/class
205
282
  it { should delegate(:name_length).to(:'author.name').as(:length) }
206
283
  it { should delegate(:length).to(:'author.name').with_prefix(:name) }
207
284
  end
285
+ end
286
+
208
287
  ```
209
288
  However, don't use the following features as they are not supported by the delegate method:
210
289
  * delegation to objects
211
- * different arguments passed to delegate
212
290
 
213
291
  ### Forwardable Module
214
292
  You can test delegation based on the [Forwardable](http://ruby-doc.org/stdlib-2.0.0/libdoc/forwardable/rdoc/Forwardable.html) module.
215
293
 
216
294
  ```ruby
295
+ require 'spec_helper'
296
+
297
+ module ForwardableDelegation
217
298
  class Post
218
299
  extend Forwardable
219
300
 
@@ -226,11 +307,21 @@ You can test delegation based on the [Forwardable](http://ruby-doc.org/stdlib-2.
226
307
  def_delegator :author, :name
227
308
  def_delegator :author, :name, :author_name
228
309
  def_delegator :author, :name, :writer
310
+
311
+ def_delegator :'author.name', :length, :name_length
312
+
313
+ def inspect
314
+ 'post'
315
+ end
229
316
  end
230
317
 
231
318
  class Author
232
- def name
233
- @name ||= 'Catherine Asaro'
319
+ def initialize
320
+ @name = 'Catherine Asaro'
321
+ end
322
+
323
+ def name(*)
324
+ @name
234
325
  end
235
326
  end
236
327
 
@@ -244,19 +335,21 @@ You can test delegation based on the [Forwardable](http://ruby-doc.org/stdlib-2.
244
335
  it { should delegate(:name).to(:author) }
245
336
  it { should delegate(:name).to(:author).with('Ms.') }
246
337
  it { should delegate(:name).to(:author).with_block }
338
+ it { should delegate(:name).to(:author).with('Ms.').with_block }
247
339
  it { should delegate(:name).to(:author).with_prefix }
248
340
  it { should delegate(:writer).to(:author).as(:name) }
249
341
 
250
342
  it { should delegate(:name_length).to(:'author.name').as(:length) }
251
343
  it { should delegate(:length).to(:'author.name').with_prefix(:name) }
252
344
  end
345
+ end
346
+
253
347
  ```
254
348
  However, don't use the following features as they are not supported by the Forwardable module:
255
349
  * `allow_nil`
256
350
  * delegation to class variables
257
351
  * delegation to constants
258
352
  * delegation to objects
259
- * different arguments passed to the delegate
260
353
 
261
354
  ## Contributing
262
355
  1. Fork it ( https://github.com/dwhelan/delegate_matcher/fork )
data/README.md.erb ADDED
@@ -0,0 +1,216 @@
1
+ [![Gem Version](https://badge.fury.io/rb/delegate_matcher.png)](http://badge.fury.io/rb/delegate_matcher)
2
+ [![Build Status](https://travis-ci.org/dwhelan/delegate_matcher.png?branch=master)](https://travis-ci.org/dwhelan/delegate_matcher)
3
+ [![Code Climate](https://codeclimate.com/github/dwhelan/delegate_matcher/badges/gpa.svg)](https://codeclimate.com/github/dwhelan/delegate_matcher)
4
+ [![Coverage Status](https://coveralls.io/repos/dwhelan/delegate_matcher/badge.svg?branch=master&service=github)](https://coveralls.io/github/dwhelan/delegate_matcher?branch=master)
5
+
6
+ # Delegate Matcher
7
+ An RSpec matcher for validating delegation. This matcher works with delegation based on the [Forwardable](http://ruby-doc.org/stdlib-2.0.0/libdoc/forwardable/rdoc/Forwardable.html) module,
8
+ the [delegate](http://api.rubyonrails.org/classes/Module.html#method-i-delegate) method in the Active Support gem or with
9
+ simple custom delegation.
10
+
11
+ ## Installation
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'delegate_matcher'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ ```bash
21
+ $ bundle
22
+ ```
23
+
24
+ Or install it yourself as:
25
+
26
+ ```bash
27
+ $ gem install delegate_matcher
28
+ ```
29
+
30
+ Then add the following to your `spec_helper.rb` file:
31
+
32
+ ```ruby
33
+ require 'delegate_matcher'
34
+ ```
35
+
36
+ ## Usage
37
+ This matcher allows you to validate delegation to:
38
+ * instance methods
39
+ * class methods
40
+ * instance variables
41
+ * class variables
42
+ * constants
43
+ * arbitrary objects
44
+ * multiple targets
45
+
46
+ ```ruby
47
+ describe Post do
48
+ it { should delegate(:name).to(:author) } # name => author().name instance method
49
+ it { should delegate(:name).to(:class) } # name => self.class.name class method
50
+ it { should delegate(:name).to(:@author) } # name => @author.name instance variable
51
+ it { should delegate(:name).to(:@@author) } # name => @@author.name class variable
52
+ it { should delegate(:first).to(:GENRES) } # first => GENRES.first constant
53
+ it { should delegate(:name).to(author) } # name => author.name object
54
+ end
55
+ ```
56
+
57
+ ### Delegate Method Name
58
+ If the name of the method being invoked on the delegate is different from the method being called you
59
+ can check this using the `with_prefix` method (based on Active Support `delegate` method) or the
60
+ `as` method.
61
+
62
+ ```ruby
63
+ describe Post do
64
+ it { should delegate(:name).to(:author).with_prefix } # author_name => author.name
65
+ it { should delegate(:name).to(:author).with_prefix(:writer) } # writer_name => author.name
66
+ it { should delegate(:writer).to(:author).as(:name) } # writer => author.name
67
+ end
68
+ ```
69
+
70
+ **Note**: if you are delegating to an object (i.e. `to` is not a string or symbol) then a prefix of `''` will be used:
71
+
72
+ ```ruby
73
+ describe Post do
74
+ it { should delegate(:name).to(author).with_prefix } # an error will be raised
75
+ it { should delegate(:name).to(author).with_prefix(:writer) } # writer_name => author.name
76
+ end
77
+ ```
78
+
79
+ You can test delegation to a chain of objects by using a `to` that can be `eval`'d.
80
+
81
+ ```ruby
82
+ describe Post do
83
+ it { should delegate(:name_length).to(:'author.name').as(:length) } # name_length => author.name.length
84
+ it { should delegate(:length).to(:'author.name').with_prefix(:name) } # name_length => author.name.length
85
+ end
86
+ ```
87
+
88
+ ### Handling Nil Delegates
89
+ If you expect the delegate to return `nil` when the delegate is `nil` rather than raising an error
90
+ then you can check this using the `allow_nil` method.
91
+
92
+ ```ruby
93
+ describe Post do
94
+ it { should delegate(:name).to(:author).allow_nil } # name => author && author.name
95
+ it { should delegate(:name).to(:author).allow_nil(true) } # name => author && author.name
96
+ it { should delegate(:name).to(:author).allow_nil(false) } # name => author.name
97
+ end
98
+ ```
99
+
100
+ Nil handling is only checked if `allow_nil` is specified.
101
+
102
+ Note that the matcher will raise an error if you use this when checking delegation to an
103
+ object since the matcher cannot validate `nil` handling as it cannot gain access to the subject
104
+ reference to the object to set it `nil`.
105
+
106
+ ### Arguments
107
+ If the method being delegated takes arguments you can supply them with the `with` method. The matcher
108
+ will check that the provided arguments are in turn passed to the delegate.
109
+
110
+ ```ruby
111
+ describe Post do
112
+ it { should delegate(:name).with('Ms.').to(:author) } # name('Ms.') => author.name('Ms.')
113
+ end
114
+ ```
115
+
116
+ Also, in some cases, the delegator change the arguments. While this is arguably no
117
+ longer true delegation you can still check that arguments are correctly passed by using a second `with`
118
+ method to specify the arguments expected by the delegate.
119
+
120
+ ```ruby
121
+ describe Post do
122
+ it { should delegate(:name).with('Ms.').to(:author).with('Miss') } # name('Ms.') => author.name('Miss')
123
+ end
124
+ ```
125
+ You can use the `with(no_args).` rather than `with.` or `with().` to test delegation with no arguments passed
126
+ to the delegator.
127
+
128
+ ```ruby
129
+ describe Post do
130
+ it { should delegate(:name).with(no_args).to(:author) } # name() => author.name()
131
+ end
132
+ ```
133
+
134
+ For the second `with` you can use any RSpec argument matcher.
135
+
136
+ ```ruby
137
+ describe Post do
138
+ it { should delegate(:name).with('Ms.').to(:author).with(anything) } # name('Ms.') => author.name(*)
139
+ end
140
+ ```
141
+
142
+ ### Blocks
143
+ You can check that a block passed is in turn passed to the delegate via the `with_block` method.
144
+ By default, block delegation is only checked if `with_a_block` or `without_a_block` is specified.
145
+
146
+ ```ruby
147
+ describe Post do
148
+ it { should delegate(:name).to(author).with_a_block } # name(&block) => author.name(&block)
149
+ it { should delegate(:name).to(author).with_block } # name(&block) => author.name(&block) # alias for with_a_block
150
+
151
+ it { should delegate(:name).to(author).without_a_block } # name(&block) => author.name
152
+ it { should delegate(:name).to(author).without_block } # name(&block) => author.name # alias for without_a_block
153
+ end
154
+ ```
155
+ You can also pass an explicit block in which case the block passed will be compared against
156
+ the block received by the delegate. The comparison is based on having equivalent source for the blocks.
157
+
158
+ ```ruby
159
+ describe Post do
160
+ it { should delegate(:tainted?).to(authors).as(:all?).with_block { |a| a.tainted? } } # tainted? => authors.all? { |a| a.tainted? }
161
+ end
162
+ ```
163
+
164
+ If the `proc` passed to `with_block` is not the same `proc` used y the delegator
165
+ then the sources of the `proc`'s will be compared for equality using the `proc_extensions` gem.
166
+ For this comparison to work the `proc` must not be not have been created via an `eval` of a string
167
+ and must be the only `proc` declared on that line of source code.
168
+
169
+ See [proc_extensions](https://github.com/dwhelan/proc_extensions/) for more details on how the source for procs is compared.
170
+
171
+ ### Return Value
172
+ Normally the matcher will check that the value return is the same as the value
173
+ returned from the delegate. You can skip this check by using `without_return`.
174
+
175
+ ```ruby
176
+ describe Post do
177
+ it { should delegate(:name).to(:author).without_return }
178
+ end
179
+ ```
180
+
181
+ ### Multiple Targets
182
+ You can test delegation to more than one target by specifing more than one target via `to`.
183
+ ```ruby
184
+ <%= File.open('./spec/to_multiple_targets_spec.rb', 'rb') { |f| f.read } %>
185
+ ```
186
+
187
+ ### Active Support
188
+ You can test delegation based on the [delegate](http://api.rubyonrails.org/classes/Module.html#method-i-delegate) method in the Active Support gem.
189
+
190
+ ```ruby
191
+ <%= File.open('./spec/examples/active_support_delegation_spec.rb', 'rb') { |f| f.read } %>
192
+ ```
193
+ However, don't use the following features as they are not supported by the delegate method:
194
+ * delegation to objects
195
+
196
+ ### Forwardable Module
197
+ You can test delegation based on the [Forwardable](http://ruby-doc.org/stdlib-2.0.0/libdoc/forwardable/rdoc/Forwardable.html) module.
198
+
199
+ ```ruby
200
+ <%= File.open('./spec/examples/forwardable_delegation_spec.rb', 'rb') { |f| f.read } %>
201
+ ```
202
+ However, don't use the following features as they are not supported by the Forwardable module:
203
+ * `allow_nil`
204
+ * delegation to class variables
205
+ * delegation to constants
206
+ * delegation to objects
207
+
208
+ ## Contributing
209
+ 1. Fork it ( https://github.com/dwhelan/delegate_matcher/fork )
210
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
211
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
212
+ 4. Push to the branch (`git push origin my-new-feature`)
213
+ 5. Create a new Pull Request
214
+
215
+ ## Notes
216
+ This matcher was inspired by [Alan Winograd](https://github.com/awinograd) via the gist https://gist.github.com/awinograd/6158961
data/Rakefile CHANGED
@@ -7,4 +7,9 @@ RuboCop::RakeTask.new do |task|
7
7
  task.options << '--display-cop-names'
8
8
  end
9
9
 
10
- task default: [:spec, :rubocop, :build]
10
+ desc 'Updates README with code examples'
11
+ task :readme do
12
+ `erb README.md.erb > README.md`
13
+ end
14
+
15
+ task default: [:spec, :rubocop, :readme, :build]
@@ -19,7 +19,7 @@ Gem::Specification.new do |gem|
19
19
  gem.test_files = gem.files.grep(%r{^spec/})
20
20
  gem.require_paths = ['lib']
21
21
 
22
- gem.add_runtime_dependency 'proc_extensions', '~> 0.1'
22
+ gem.add_runtime_dependency 'proc_extensions', '~> 0.2'
23
23
 
24
24
  gem.add_development_dependency 'activesupport', '~> 4.2'
25
25
  gem.add_development_dependency 'bundler', '~> 1.7'
@@ -6,10 +6,11 @@ module RSpec
6
6
 
7
7
  RSpec::Mocks::Syntax.enable_expect(self)
8
8
 
9
- attr_reader :received, :args
9
+ attr_reader :to, :received, :args
10
10
 
11
- def initialize(expected)
11
+ def initialize(expected, to)
12
12
  self.expected = expected
13
+ self.to = to
13
14
  self.received = false
14
15
  end
15
16
 
@@ -33,26 +34,18 @@ module RSpec
33
34
  end
34
35
 
35
36
  def argument_description
36
- args ? "(#{args.map { |a| format('%p', a) }.join(', ')})" : ''
37
- end
38
-
39
- def return_value
40
- self
37
+ args ? "(#{args.map(&:inspect).join(', ')})" : ''
41
38
  end
42
39
 
43
40
  private
44
41
 
45
42
  attr_accessor :expected
46
- attr_writer :received, :args, :block
43
+ attr_writer :to, :received, :args, :block
47
44
 
48
45
  def subject
49
46
  expected.subject
50
47
  end
51
48
 
52
- def to
53
- expected.to
54
- end
55
-
56
49
  def name
57
50
  to.to_s
58
51
  end
@@ -4,7 +4,9 @@ module RSpec
4
4
  module Matchers
5
5
  define(:delegate) do |method_name|
6
6
  match do |subject|
7
- delegation_ok?(method_name, subject)
7
+ fail 'need to provide a "to"' unless expected.to
8
+ expected.subject = subject
9
+ delegation.ok?
8
10
  end
9
11
 
10
12
  description do
@@ -19,7 +21,7 @@ module RSpec
19
21
  delegation.failure_message(true) || super
20
22
  end
21
23
 
22
- chain(:to) { |to| expected.to = to }
24
+ chain(:to) { |*to| expected.to = *to; expected.method_name = method_name }
23
25
  chain(:as) { |as| expected.as = as }
24
26
  chain(:allow_nil) { |allow_nil = true| expected.allow_nil = allow_nil }
25
27
  chain(:with_prefix) { |prefix = nil| expected.prefix = prefix }
@@ -27,6 +29,7 @@ module RSpec
27
29
  chain(:with_a_block) { |&block| expected.block = block || true }
28
30
  chain(:without_a_block) { expected.block = false }
29
31
  chain(:without_return) { expected.check_return = false }
32
+ chain(:and_return) { |value| expected.return_value = value }
30
33
 
31
34
  alias_method :with_block, :with_a_block
32
35
  alias_method :without_block, :without_a_block
@@ -40,18 +43,6 @@ module RSpec
40
43
  def expected
41
44
  @expected ||= DelegateMatcher::Expected.new
42
45
  end
43
-
44
- def delegation_ok?(method_name, subject)
45
- fail 'need to provide a "to"' unless expected.to
46
-
47
- expected.method_name = method_name
48
- expected.subject = subject
49
-
50
- delegation.ok?
51
- end
52
46
  end
53
47
  end
54
48
  end
55
-
56
- # TODO: Handle nested delegation strings "a.b.c"
57
- # TODO: Test SingleForwardable