delegate_matcher 0.0.3 → 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.bundle/config +3 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +8 -0
- data/.travis.yml +7 -2
- data/Gemfile.lock +90 -37
- data/Guardfile +4 -0
- data/README.md +106 -98
- data/Rakefile +3 -1
- data/delegate_matcher.gemspec +17 -8
- data/lib/delegate_matcher/delegate.rb +79 -0
- data/lib/delegate_matcher/delegate_matcher.rb +41 -266
- data/lib/delegate_matcher/delegation.rb +115 -0
- data/lib/delegate_matcher/dispatcher.rb +26 -0
- data/lib/delegate_matcher/expected.rb +108 -0
- data/lib/delegate_matcher/nil_delegate.rb +41 -0
- data/lib/delegate_matcher/stub_delegate.rb +26 -0
- data/lib/delegate_matcher/version.rb +1 -1
- data/lib/delegate_matcher.rb +9 -0
- data/spec/lib/active_support_delegation_spec.rb +24 -29
- data/spec/lib/aggregate_delegate_matcher_spec.rb +62 -0
- data/spec/lib/delegate_spec.rb +15 -0
- data/spec/lib/delegate_to_class_variable_spec.rb +85 -0
- data/spec/lib/delegate_to_constant_spec.rb +86 -0
- data/spec/lib/delegate_to_instance_variable_spec.rb +86 -0
- data/spec/lib/delegate_to_method_spec.rb +84 -0
- data/spec/lib/delegate_to_object_spec.rb +103 -0
- data/spec/lib/forwardable_delegation_spec.rb +14 -13
- data/spec/lib/shared/a_simple_delegator.rb +17 -0
- data/spec/lib/shared/args.rb +24 -0
- data/spec/lib/shared/args_and_a_block.rb +6 -0
- data/spec/lib/shared/author.rb +10 -0
- data/spec/lib/shared/block.rb +45 -0
- data/spec/lib/shared/different_method_name.rb +12 -0
- data/spec/lib/shared/different_return_value.rb +19 -0
- data/spec/lib/shared/nil_check.rb +52 -0
- data/spec/lib/shared/prefix.rb +16 -0
- data/spec/spec_helper.rb +6 -2
- metadata +85 -7
- data/spec/lib/delegate_matcher_spec.rb +0 -467
- data/spec/lib/version_spec.rb +0 -7
@@ -0,0 +1,79 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
module DelegateMatcher
|
4
|
+
class Delegate
|
5
|
+
RSpec::Mocks::Syntax.enable_expect(self)
|
6
|
+
|
7
|
+
attr_reader :received, :args, :block
|
8
|
+
|
9
|
+
def initialize(expected)
|
10
|
+
self.expected = expected
|
11
|
+
self.received = false
|
12
|
+
end
|
13
|
+
|
14
|
+
# rubocop:disable Metrics/AbcSize
|
15
|
+
def receiver
|
16
|
+
@receiver ||= case
|
17
|
+
when a_class_variable?
|
18
|
+
subject.class.class_variable_get(name)
|
19
|
+
when an_instance_variable?
|
20
|
+
subject.instance_variable_get(name)
|
21
|
+
when a_constant?
|
22
|
+
subject.class.const_get(name)
|
23
|
+
when a_method?
|
24
|
+
fail "#{subject.inspect} does not respond to #{name}" unless subject.respond_to?(name, true)
|
25
|
+
fail "#{subject.inspect}'s' #{name} method expects parameters" unless [0, -1].include?(subject.method(name).arity)
|
26
|
+
subject.send(name)
|
27
|
+
else # is an object
|
28
|
+
to
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def argument_description
|
33
|
+
args ? "(#{args.map { |a| format('%p', a) }.join(', ')})" : ''
|
34
|
+
end
|
35
|
+
|
36
|
+
def return_value
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_accessor :expected
|
43
|
+
attr_writer :received, :args, :block
|
44
|
+
|
45
|
+
def subject
|
46
|
+
expected.subject
|
47
|
+
end
|
48
|
+
|
49
|
+
def to
|
50
|
+
expected.to
|
51
|
+
end
|
52
|
+
|
53
|
+
def name
|
54
|
+
to.to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
def a_class_variable?
|
58
|
+
a_reference? && name.start_with?('@@')
|
59
|
+
end
|
60
|
+
|
61
|
+
def an_instance_variable?
|
62
|
+
a_reference? && name.start_with?('@')
|
63
|
+
end
|
64
|
+
|
65
|
+
def a_constant?
|
66
|
+
a_reference? && name =~ /^[A-Z]/
|
67
|
+
end
|
68
|
+
|
69
|
+
def a_method?
|
70
|
+
a_reference?
|
71
|
+
end
|
72
|
+
|
73
|
+
def a_reference?
|
74
|
+
to.is_a?(String) || to.is_a?(Symbol)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -1,282 +1,57 @@
|
|
1
1
|
require 'rspec/matchers'
|
2
2
|
|
3
|
-
RSpec
|
4
|
-
|
5
|
-
|
3
|
+
module RSpec
|
4
|
+
module Matchers
|
5
|
+
define(:delegate) do |method_name|
|
6
|
+
match do |subject|
|
7
|
+
delegation_ok?(method_name, subject)
|
8
|
+
end
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
description do
|
11
|
+
expected.description
|
12
|
+
end
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
description do
|
14
|
-
"delegate #{delegator_description} to #{delegate_description}#{nil_description}#{block_description}"
|
15
|
-
end
|
14
|
+
def failure_message
|
15
|
+
delegation.failure_message(false) || super
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def failure_message_when_negated
|
19
|
+
delegation.failure_message(true) || super
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
chain(:to) { |to| expected.to = to }
|
23
|
+
chain(:as) { |as| expected.as = as }
|
24
|
+
chain(:allow_nil) { |allow_nil = true| expected.allow_nil = allow_nil }
|
25
|
+
chain(:with_prefix) { |prefix = nil| expected.prefix = prefix }
|
26
|
+
chain(:with) { |*args| expected.args = args }
|
27
|
+
chain(:with_a_block) { expected.block = true }
|
28
|
+
chain(:without_a_block) { expected.block = false }
|
29
|
+
chain(:without_return) { expected.check_return = false }
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
chain(:allow_nil) { |allow_nil = true| @expected_nil_check = allow_nil }
|
28
|
-
chain(:with_prefix) { |prefix = nil| @prefix = prefix || delegate.to_s.sub(/@/, '') }
|
29
|
-
chain(:with) { |*args| @expected_args = args; @args ||= args }
|
30
|
-
chain(:with_a_block) { @expected_block = true }
|
31
|
-
chain(:without_a_block) { @expected_block = false }
|
31
|
+
alias_method :with_block, :with_a_block
|
32
|
+
alias_method :without_block, :without_a_block
|
32
33
|
|
33
|
-
|
34
|
-
alias_method :without_block, :without_a_block
|
34
|
+
private
|
35
35
|
|
36
|
-
|
36
|
+
def delegation
|
37
|
+
@delegation ||= DelegateMatcher::Delegation.new(expected)
|
38
|
+
end
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
attr_reader :expected_block, :actual_block
|
42
|
-
attr_reader :actual_return_value
|
40
|
+
def expected
|
41
|
+
@expected ||= DelegateMatcher::Expected.new
|
42
|
+
end
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
when delegate_is_a_class_variable?
|
47
|
-
delegate_to_class_variable(test_delegate)
|
48
|
-
when delegate_is_an_instance_variable?
|
49
|
-
delegate_to_instance_variable(test_delegate)
|
50
|
-
when delegate_is_a_constant?
|
51
|
-
delegate_to_constant
|
52
|
-
when delegate_is_a_method?
|
53
|
-
delegate_to_method(test_delegate)
|
54
|
-
else
|
55
|
-
delegate_to_object
|
56
|
-
end
|
44
|
+
def delegation_ok?(method_name, subject)
|
45
|
+
fail 'need to provide a "to"' unless expected.to
|
57
46
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
def delegate_is_a_class_variable?
|
62
|
-
delegate.to_s.start_with?('@@')
|
63
|
-
end
|
64
|
-
|
65
|
-
def delegate_is_an_instance_variable?
|
66
|
-
delegate.to_s[0] == '@'
|
67
|
-
end
|
68
|
-
|
69
|
-
def delegate_is_a_constant?
|
70
|
-
(delegate.is_a?(String) || delegate.is_a?(Symbol)) && (delegate.to_s =~ /^[A-Z]/)
|
71
|
-
end
|
72
|
-
|
73
|
-
def delegate_is_a_method?
|
74
|
-
delegate.is_a?(String) || delegate.is_a?(Symbol)
|
75
|
-
end
|
76
|
-
|
77
|
-
def delegate_to_class_variable(test_delegate)
|
78
|
-
actual_delegate = delegator.class.class_variable_get(delegate)
|
79
|
-
delegator.class.class_variable_set(delegate, test_delegate)
|
80
|
-
call
|
81
|
-
ensure
|
82
|
-
delegator.class.class_variable_set(delegate, actual_delegate)
|
83
|
-
end
|
84
|
-
|
85
|
-
def delegate_to_instance_variable(test_delegate)
|
86
|
-
actual_delegate = delegator.instance_variable_get(delegate)
|
87
|
-
delegator.instance_variable_set(delegate, test_delegate)
|
88
|
-
call
|
89
|
-
ensure
|
90
|
-
delegator.instance_variable_set(delegate, actual_delegate)
|
91
|
-
end
|
92
|
-
|
93
|
-
def delegate_to_constant
|
94
|
-
ensure_allow_nil_is_not_specified_for('a constant')
|
95
|
-
stub_delegation(delegator.class.const_get(delegate))
|
96
|
-
call
|
97
|
-
end
|
47
|
+
expected.method_name = method_name
|
48
|
+
expected.subject = subject
|
98
49
|
|
99
|
-
|
100
|
-
|
101
|
-
allow(delegator).to receive(delegate) { test_delegate }
|
102
|
-
call
|
103
|
-
end
|
104
|
-
|
105
|
-
def delegate_to_object
|
106
|
-
ensure_allow_nil_is_not_specified_for('an object')
|
107
|
-
stub_delegation(delegate)
|
108
|
-
call
|
109
|
-
end
|
110
|
-
|
111
|
-
def ensure_allow_nil_is_not_specified_for(target)
|
112
|
-
fail %(cannot verify "allow_nil" expectations when delegating to #{target}) unless expected_nil_check.nil?
|
113
|
-
end
|
114
|
-
|
115
|
-
def ensure_delegate_method_is_valid
|
116
|
-
fail "#{delegator} does not respond to #{delegate}" unless delegator.respond_to?(delegate, true)
|
117
|
-
fail "#{delegator}'s' #{delegate} method expects parameters" unless [0, -1].include?(delegator.method(delegate).arity)
|
118
|
-
end
|
119
|
-
|
120
|
-
def delegator_method
|
121
|
-
@delegator_method || (prefix ? :"#{prefix}_#{method}" : method)
|
122
|
-
end
|
123
|
-
|
124
|
-
def delegate_method
|
125
|
-
@delegate_method || method
|
126
|
-
end
|
127
|
-
|
128
|
-
def call
|
129
|
-
@actual_return_value = delegator.send(delegator_method, *args, &block)
|
130
|
-
end
|
131
|
-
|
132
|
-
def block
|
133
|
-
@block ||= proc {}
|
134
|
-
end
|
135
|
-
|
136
|
-
def delegate_double
|
137
|
-
double('delegate').tap { |delegate| stub_delegation(delegate) }
|
138
|
-
end
|
139
|
-
|
140
|
-
def stub_delegation(delegate)
|
141
|
-
@delegated = false
|
142
|
-
allow(delegate).to(receive(delegate_method)) do |*args, &block|
|
143
|
-
@actual_args = args
|
144
|
-
@actual_block = block
|
145
|
-
@delegated = true
|
146
|
-
expected_return_value
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def expected_return_value
|
151
|
-
self
|
152
|
-
end
|
153
|
-
|
154
|
-
def allow_nil_ok?
|
155
|
-
return true if expected_nil_check.nil?
|
156
|
-
return true unless delegate.is_a?(String) || delegate.is_a?(Symbol)
|
157
|
-
|
158
|
-
begin
|
159
|
-
actual_nil_check = true
|
160
|
-
delegate?(nil)
|
161
|
-
@return_value_when_delegate_nil = actual_return_value
|
162
|
-
rescue NoMethodError
|
163
|
-
actual_nil_check = false
|
164
|
-
end
|
165
|
-
|
166
|
-
expected_nil_check == actual_nil_check && @return_value_when_delegate_nil.nil?
|
167
|
-
end
|
168
|
-
|
169
|
-
def arguments_ok?
|
170
|
-
expected_args.nil? || actual_args.eql?(expected_args)
|
171
|
-
end
|
172
|
-
|
173
|
-
def block_ok?
|
174
|
-
case
|
175
|
-
when expected_block.nil?
|
176
|
-
true
|
177
|
-
when expected_block
|
178
|
-
actual_block == block
|
179
|
-
else
|
180
|
-
actual_block.nil?
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def return_value_ok?
|
185
|
-
actual_return_value == expected_return_value
|
186
|
-
end
|
187
|
-
|
188
|
-
def delegator_description
|
189
|
-
"#{delegator_method}#{argument_description(args)}"
|
190
|
-
end
|
191
|
-
|
192
|
-
def delegate_description
|
193
|
-
case
|
194
|
-
when !args.eql?(expected_args)
|
195
|
-
"#{delegate}.#{delegate_method}#{argument_description(expected_args)}"
|
196
|
-
when delegate_method.eql?(delegator_method)
|
197
|
-
"#{delegate}"
|
198
|
-
else
|
199
|
-
"#{delegate}.#{delegate_method}"
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def argument_description(args)
|
204
|
-
args ? "(#{args.map { |a| format('%p', a) }.join(', ')})" : ''
|
205
|
-
end
|
206
|
-
|
207
|
-
def nil_description
|
208
|
-
case
|
209
|
-
when expected_nil_check.nil?
|
210
|
-
''
|
211
|
-
when expected_nil_check
|
212
|
-
' with nil allowed'
|
213
|
-
else
|
214
|
-
' with nil not allowed'
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
def block_description
|
219
|
-
case
|
220
|
-
when expected_block.nil?
|
221
|
-
''
|
222
|
-
when expected_block
|
223
|
-
' with a block'
|
224
|
-
else
|
225
|
-
' without a block'
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
def failure_message_details(negated)
|
230
|
-
message = [
|
231
|
-
argument_failure_message(negated),
|
232
|
-
block_failure_message(negated),
|
233
|
-
return_value_failure_message(negated),
|
234
|
-
allow_nil_failure_message(negated)
|
235
|
-
].reject(&:empty?).join(' and ')
|
236
|
-
message.empty? ? nil : message
|
237
|
-
end
|
238
|
-
|
239
|
-
def argument_failure_message(negated)
|
240
|
-
case
|
241
|
-
when expected_args.nil? || negated ^ arguments_ok?
|
242
|
-
''
|
243
|
-
else
|
244
|
-
"was called with #{argument_description(actual_args)}"
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
def block_failure_message(negated)
|
249
|
-
case
|
250
|
-
when expected_block.nil? || (negated ^ block_ok?)
|
251
|
-
''
|
252
|
-
when negated
|
253
|
-
"a block was #{expected_block ? '' : 'not '}passed"
|
254
|
-
when expected_block
|
255
|
-
actual_block.nil? ? 'a block was not passed' : "a different block #{actual_block} was passed"
|
256
|
-
else
|
257
|
-
'a block was passed'
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
def return_value_failure_message(_negated)
|
262
|
-
case
|
263
|
-
when !@delegated || return_value_ok?
|
264
|
-
''
|
265
|
-
else
|
266
|
-
format('a return value of %p was returned instead of the delegate return value', actual_return_value)
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
def allow_nil_failure_message(negated)
|
271
|
-
case
|
272
|
-
when expected_nil_check.nil? || negated ^ allow_nil_ok?
|
273
|
-
''
|
274
|
-
when !@return_value_when_delegate_nil.nil?
|
275
|
-
'did not return nil'
|
276
|
-
when negated
|
277
|
-
"#{delegate} was #{expected_nil_check ? '' : 'not '}allowed to be nil"
|
278
|
-
else
|
279
|
-
"#{delegate} was #{expected_nil_check ? 'not ' : ''}allowed to be nil"
|
50
|
+
delegation.ok?
|
51
|
+
end
|
280
52
|
end
|
281
53
|
end
|
282
54
|
end
|
55
|
+
|
56
|
+
# TODO: Handle delegation to a class method?
|
57
|
+
# TODO: How to handle delegation if delegate_double is called with something else
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'rspec/matchers'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Matchers
|
5
|
+
module DelegateMatcher
|
6
|
+
class Delegation
|
7
|
+
attr_accessor :expected
|
8
|
+
attr_accessor :dispatcher
|
9
|
+
attr_accessor :delegate
|
10
|
+
|
11
|
+
def initialize(expected)
|
12
|
+
self.expected = expected
|
13
|
+
self.dispatcher = DelegateMatcher::Dispatcher.new(expected)
|
14
|
+
self.delegate = StubDelegate.new(expected)
|
15
|
+
end
|
16
|
+
|
17
|
+
def delegation_ok?
|
18
|
+
dispatcher.call
|
19
|
+
delegate.received
|
20
|
+
end
|
21
|
+
|
22
|
+
def ok?
|
23
|
+
allow_nil_ok? && delegation_ok? && arguments_ok? && block_ok? && return_value_ok?
|
24
|
+
end
|
25
|
+
|
26
|
+
def allow_nil_ok?
|
27
|
+
return true if expected.allow_nil.nil?
|
28
|
+
|
29
|
+
begin
|
30
|
+
NilDelegate.new(expected) { dispatcher.call }
|
31
|
+
allow_nil = true
|
32
|
+
rescue NoMethodError
|
33
|
+
allow_nil = false
|
34
|
+
end
|
35
|
+
|
36
|
+
allow_nil == expected.allow_nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def arguments_ok?
|
40
|
+
expected.as_args.nil? || delegate.args.eql?(expected.as_args)
|
41
|
+
end
|
42
|
+
|
43
|
+
def block_ok?
|
44
|
+
case
|
45
|
+
when expected.block.nil?
|
46
|
+
true
|
47
|
+
when expected.block
|
48
|
+
delegate.block == dispatcher.block
|
49
|
+
else
|
50
|
+
delegate.block.nil?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def return_value_ok?
|
55
|
+
!expected.check_return || dispatcher.return_value == delegate.return_value
|
56
|
+
end
|
57
|
+
|
58
|
+
def failure_message(negated)
|
59
|
+
message = [
|
60
|
+
argument_failure_message(negated),
|
61
|
+
block_failure_message(negated),
|
62
|
+
return_value_failure_message(negated),
|
63
|
+
allow_nil_failure_message(negated)
|
64
|
+
].reject(&:empty?).join(' and ')
|
65
|
+
message.empty? ? nil : message
|
66
|
+
end
|
67
|
+
|
68
|
+
def argument_failure_message(negated)
|
69
|
+
case
|
70
|
+
when expected.as_args.nil? || negated ^ arguments_ok?
|
71
|
+
''
|
72
|
+
else
|
73
|
+
"was called with #{delegate.argument_description}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def block_failure_message(negated)
|
78
|
+
case
|
79
|
+
when expected.block.nil? || (negated ^ block_ok?)
|
80
|
+
''
|
81
|
+
when negated
|
82
|
+
"a block was #{expected.block ? '' : 'not '}passed"
|
83
|
+
when expected.block
|
84
|
+
delegate.block.nil? ? 'a block was not passed' : "a different block #{delegate.block} was passed"
|
85
|
+
else
|
86
|
+
'a block was passed'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def return_value_failure_message(_negated)
|
91
|
+
case
|
92
|
+
when !delegate.received || return_value_ok?
|
93
|
+
''
|
94
|
+
else
|
95
|
+
format('a return value of %p was returned instead of the delegate return value', dispatcher.return_value)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def allow_nil_failure_message(negated)
|
100
|
+
case
|
101
|
+
when expected.allow_nil.nil? || negated ^ allow_nil_ok?
|
102
|
+
''
|
103
|
+
when negated
|
104
|
+
"#{expected.to} was #{expected.allow_nil ? '' : 'not '}allowed to be nil"
|
105
|
+
else
|
106
|
+
"#{expected.to} was #{expected.allow_nil ? 'not ' : ''}allowed to be nil"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# TODO: use default prefix with constants - lower case method prefix
|
115
|
+
# TODO: How to handle delegation is delegate_double is called with something else
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
module DelegateMatcher
|
4
|
+
class Dispatcher
|
5
|
+
attr_reader :return_value
|
6
|
+
|
7
|
+
def initialize(expected)
|
8
|
+
self.expected = expected
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
self.return_value = expected.subject.send(expected.delegator_method_name, *expected.args, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def block
|
16
|
+
@block ||= proc {}
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_accessor :expected
|
22
|
+
attr_writer :return_value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
module DelegateMatcher
|
4
|
+
class Expected
|
5
|
+
attr_accessor :subject, :to, :method_name, :block, :as, :allow_nil, :check_return
|
6
|
+
attr_reader :args
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
self.check_return = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def prefix=(prefix)
|
13
|
+
@has_prefix = true
|
14
|
+
@prefix = prefix
|
15
|
+
end
|
16
|
+
|
17
|
+
def prefix
|
18
|
+
case
|
19
|
+
when !@has_prefix
|
20
|
+
''
|
21
|
+
when @prefix
|
22
|
+
"#{@prefix}_"
|
23
|
+
when to.is_a?(String) || to.is_a?(Symbol)
|
24
|
+
to.to_s.delete('@').downcase + '_'
|
25
|
+
else
|
26
|
+
''
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def args=(args)
|
31
|
+
@args_set ? @as_args = args : @args = args
|
32
|
+
@args_set = true
|
33
|
+
end
|
34
|
+
|
35
|
+
def as_args
|
36
|
+
@as_args || args
|
37
|
+
end
|
38
|
+
|
39
|
+
def as
|
40
|
+
@as || method_name
|
41
|
+
end
|
42
|
+
|
43
|
+
def delegator_method_name
|
44
|
+
"#{prefix}#{method_name}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def description
|
48
|
+
"delegate #{delegator_description} to #{delegate_description}#{options_description}"
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def delegator_description
|
54
|
+
"#{delegator_method_name}#{argument_description}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def delegate_description
|
58
|
+
case
|
59
|
+
when !args.eql?(as_args)
|
60
|
+
"#{to}.#{as}#{as_argument_description}"
|
61
|
+
when as.to_s.eql?(delegator_method_name)
|
62
|
+
"#{to}"
|
63
|
+
else
|
64
|
+
"#{to}.#{as}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def as_argument_description
|
69
|
+
argument_description(as_args)
|
70
|
+
end
|
71
|
+
|
72
|
+
def argument_description(arguments = args)
|
73
|
+
arguments ? "(#{arguments.map { |a| format('%p', a) }.join(', ')})" : ''
|
74
|
+
end
|
75
|
+
|
76
|
+
def options_description
|
77
|
+
"#{nil_description}#{block_description}#{return_value_description}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def nil_description
|
81
|
+
case
|
82
|
+
when allow_nil.nil?
|
83
|
+
''
|
84
|
+
when allow_nil
|
85
|
+
' with nil allowed'
|
86
|
+
else
|
87
|
+
' with nil not allowed'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def block_description
|
92
|
+
case
|
93
|
+
when block.nil?
|
94
|
+
''
|
95
|
+
when block
|
96
|
+
' with a block'
|
97
|
+
else
|
98
|
+
' without a block'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def return_value_description
|
103
|
+
check_return ? '' : ' without using delegate return value'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
module DelegateMatcher
|
4
|
+
class NilDelegate < Delegate
|
5
|
+
def initialize(expected, &block)
|
6
|
+
super
|
7
|
+
original_receiver = receiver
|
8
|
+
self.receiver = nil
|
9
|
+
block.call
|
10
|
+
ensure
|
11
|
+
self.receiver = original_receiver
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# rubocop:disable Metrics/AbcSize
|
17
|
+
def receiver=(value)
|
18
|
+
case
|
19
|
+
when a_class_variable?
|
20
|
+
subject.class.class_variable_set(name, value)
|
21
|
+
when an_instance_variable?
|
22
|
+
subject.instance_variable_set(name, value)
|
23
|
+
when a_constant?
|
24
|
+
silence_warnings { subject.class.const_set(name, value) }
|
25
|
+
when a_method?
|
26
|
+
allow(subject).to receive(name) { value }
|
27
|
+
else # is an object
|
28
|
+
fail 'cannot verify "allow_nil" expectations when delegating to an object' if value.nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def silence_warnings(&block)
|
33
|
+
warn_level = $VERBOSE
|
34
|
+
$VERBOSE = nil
|
35
|
+
block.call
|
36
|
+
$VERBOSE = warn_level
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|