delegate_matcher 0.0.3 → 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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
|