rr 1.1.2.rc1 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +5 -5
  2. data/Appraisals +3 -43
  3. data/CHANGES.md +98 -6
  4. data/CREDITS.md +5 -0
  5. data/Gemfile +1 -17
  6. data/README.md +29 -32
  7. data/Rakefile +42 -40
  8. data/doc/02_syntax_comparison.md +1 -0
  9. data/lib/rr/class_instance_method_defined.rb +1 -1
  10. data/lib/rr/core_ext/array.rb +2 -0
  11. data/lib/rr/core_ext/hash.rb +2 -0
  12. data/lib/rr/deprecations.rb +97 -0
  13. data/lib/rr/double.rb +28 -10
  14. data/lib/rr/double_definitions/double_definition.rb +39 -16
  15. data/lib/rr/double_definitions/double_definition_create.rb +5 -5
  16. data/lib/rr/double_definitions/double_definition_create_blank_slate.rb +10 -4
  17. data/lib/rr/double_definitions/double_injections/any_instance_of.rb +1 -1
  18. data/lib/rr/double_definitions/double_injections/instance.rb +2 -2
  19. data/lib/rr/double_definitions/strategies/strategy.rb +27 -8
  20. data/lib/rr/double_definitions/strategies/verification/mock.rb +8 -2
  21. data/lib/rr/double_matches.rb +4 -3
  22. data/lib/rr/dsl.rb +152 -0
  23. data/lib/rr/expectations/any_argument_expectation.rb +4 -4
  24. data/lib/rr/expectations/argument_equality_expectation.rb +43 -5
  25. data/lib/rr/injections/double_injection.rb +67 -19
  26. data/lib/rr/injections/method_missing_injection.rb +37 -6
  27. data/lib/rr/integrations/minitest_4.rb +1 -1
  28. data/lib/rr/integrations/minitest_4_active_support.rb +1 -1
  29. data/lib/rr/integrations/rspec/invocation_matcher.rb +0 -8
  30. data/lib/rr/integrations/rspec_2.rb +28 -8
  31. data/lib/rr/keyword_arguments.rb +15 -0
  32. data/lib/rr/method_dispatches/base_method_dispatch.rb +22 -5
  33. data/lib/rr/method_dispatches/method_dispatch.rb +21 -10
  34. data/lib/rr/method_dispatches/method_missing_dispatch.rb +14 -5
  35. data/lib/rr/recorded_call.rb +35 -0
  36. data/lib/rr/recorded_calls.rb +23 -9
  37. data/lib/rr/space.rb +15 -5
  38. data/lib/rr/spy_verification.rb +13 -5
  39. data/lib/rr/version.rb +1 -1
  40. data/lib/rr/wildcard_matchers.rb +10 -10
  41. data/lib/rr/without_autohook.rb +7 -14
  42. data/rr.gemspec +8 -3
  43. data/spec/defines_spec_suite_tasks.rb +12 -0
  44. data/spec/global_helper.rb +5 -0
  45. data/spec/spec_suite_configuration.rb +1 -7
  46. data/spec/suites.yml +0 -14
  47. data/spec/suites/rspec_2/functional/any_instance_of_spec.rb +133 -33
  48. data/spec/suites/rspec_2/functional/dont_allow_spec.rb +13 -8
  49. data/spec/suites/rspec_2/functional/mock_bang_spec.rb +20 -0
  50. data/spec/suites/rspec_2/functional/mock_instance_of_spec.rb +14 -0
  51. data/spec/suites/rspec_2/functional/mock_instance_of_strong_spec.rb +15 -0
  52. data/spec/suites/rspec_2/functional/mock_proxy_instance_of_spec.rb +15 -0
  53. data/spec/suites/rspec_2/functional/mock_proxy_spec.rb +14 -0
  54. data/spec/suites/rspec_2/functional/mock_spec.rb +8 -232
  55. data/spec/suites/rspec_2/functional/mock_strong_spec.rb +14 -0
  56. data/spec/suites/rspec_2/functional/received_spec.rb +16 -0
  57. data/spec/suites/rspec_2/functional/spy_spec.rb +89 -28
  58. data/spec/suites/rspec_2/functional/stub_bang_spec.rb +20 -0
  59. data/spec/suites/rspec_2/functional/stub_instance_of_spec.rb +15 -0
  60. data/spec/suites/rspec_2/functional/stub_instance_of_strong_spec.rb +15 -0
  61. data/spec/suites/rspec_2/functional/stub_proxy_instance_of_spec.rb +16 -0
  62. data/spec/suites/rspec_2/functional/stub_proxy_spec.rb +45 -0
  63. data/spec/suites/rspec_2/functional/stub_spec.rb +42 -161
  64. data/spec/suites/rspec_2/functional/stub_strong_spec.rb +15 -0
  65. data/spec/suites/rspec_2/helper.rb +2 -2
  66. data/spec/suites/rspec_2/support/mixins/double_definition_creator_helpers.rb +173 -0
  67. data/spec/suites/rspec_2/support/mixins/mock_definition_creator_helpers.rb +45 -0
  68. data/spec/suites/rspec_2/support/mixins/proxy_definition_creator_helpers.rb +33 -0
  69. data/spec/suites/rspec_2/support/mixins/stub_creator_helpers.rb +43 -0
  70. data/spec/suites/rspec_2/support/mixins/stub_definition_creator_helpers.rb +45 -0
  71. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_with_never_called_qualifier.rb +39 -0
  72. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_with_times_called_qualifier.rb +50 -0
  73. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/argument_expectations_without_qualifiers.rb +131 -0
  74. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/dont_allow.rb +148 -0
  75. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_instance_of.rb +26 -0
  76. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_instance_of_strong.rb +28 -0
  77. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_proxy.rb +11 -0
  78. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mock_strong.rb +37 -0
  79. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/mocking.rb +107 -0
  80. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_instance_of.rb +32 -0
  81. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_instance_of_strong.rb +39 -0
  82. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_proxy.rb +11 -0
  83. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stub_strong.rb +37 -0
  84. data/spec/suites/rspec_2/support/shared_contexts/double_definition_creators/stubbing.rb +57 -0
  85. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/array_flatten_bug.rb +35 -0
  86. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/block_form.rb +31 -0
  87. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/comparing_arity.rb +63 -0
  88. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/object_is_proxy.rb +43 -0
  89. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/sequential_invocations.rb +26 -0
  90. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/setting_implementation.rb +51 -0
  91. data/spec/suites/rspec_2/support/shared_examples/double_definition_creators/yields.rb +81 -0
  92. data/spec/suites/rspec_2/unit/core_ext/enumerable_spec.rb +0 -28
  93. data/spec/suites/rspec_2/unit/deprecations_spec.rb +27 -0
  94. data/spec/suites/rspec_2/unit/double_definitions/double_definition_create_spec.rb +18 -18
  95. data/spec/suites/rspec_2/unit/dsl/double_creators_spec.rb +133 -0
  96. data/spec/suites/rspec_2/unit/dsl/space_spec.rb +99 -0
  97. data/spec/suites/rspec_2/unit/dsl/wildcard_matchers_spec.rb +67 -0
  98. data/spec/suites/rspec_2/unit/expectations/any_argument_expectation_spec.rb +9 -9
  99. data/spec/suites/rspec_2/unit/expectations/argument_equality_expectation_spec.rb +21 -21
  100. data/spec/suites/rspec_2/unit/expectations/boolean_argument_equality_expectation_spec.rb +4 -4
  101. data/spec/suites/rspec_2/unit/expectations/hash_including_argument_equality_expectation_spec.rb +31 -21
  102. data/spec/suites/rspec_2/unit/injections/double_injection/double_injection_spec.rb +0 -12
  103. data/spec/suites/rspec_2/unit/integrations/rspec_spec.rb +4 -19
  104. data/spec/suites/rspec_2/unit/space_spec.rb +7 -4
  105. data/spec/suites/rspec_2/unit/spy_verification_spec.rb +1 -1
  106. data/spec/support/adapter.rb +1 -1
  107. data/spec/support/adapter_tests/rspec.rb +19 -15
  108. data/spec/support/project/generator.rb +0 -4
  109. metadata +113 -58
  110. data/gemfiles/ruby_18_rspec_1.gemfile +0 -14
  111. data/gemfiles/ruby_18_rspec_1.gemfile.lock +0 -38
  112. data/gemfiles/ruby_18_rspec_1_rails_2.gemfile +0 -18
  113. data/gemfiles/ruby_18_rspec_1_rails_2.gemfile.lock +0 -64
  114. data/gemfiles/ruby_19_rspec_2_rails_3.gemfile +0 -15
  115. data/gemfiles/ruby_19_rspec_2_rails_3.gemfile.lock +0 -123
  116. data/lib/rr/adapters.rb +0 -34
  117. data/lib/rr/adapters/rr_methods.rb +0 -142
  118. data/lib/rr/integrations/rspec_1.rb +0 -46
  119. data/lib/rr/integrations/test_unit_1.rb +0 -63
  120. data/lib/rr/integrations/test_unit_2.rb +0 -17
  121. data/lib/rr/integrations/test_unit_200.rb +0 -27
  122. data/lib/rr/integrations/test_unit_200_active_support.rb +0 -25
  123. data/lib/rr/integrations/test_unit_2_active_support.rb +0 -38
  124. data/lib/rr/proc_from_block.rb +0 -11
  125. data/spec/suites/rspec_1/helper.rb +0 -24
  126. data/spec/suites/rspec_1/integration/rspec_1_spec.rb +0 -93
  127. data/spec/suites/rspec_1/integration/test_unit_1_spec.rb +0 -102
  128. data/spec/suites/rspec_1/integration/test_unit_2_spec.rb +0 -109
  129. data/spec/suites/rspec_1/spec_helper.rb +0 -3
  130. data/spec/suites/rspec_1_rails_2/integration/astc_rails_2_spec.rb +0 -141
  131. data/spec/suites/rspec_1_rails_2/integration/rspec_1_rails_2_spec.rb +0 -132
  132. data/spec/suites/rspec_1_rails_2/integration/test_unit_1_rails_2_spec.rb +0 -141
  133. data/spec/suites/rspec_1_rails_2/integration/test_unit_2_rails_2_spec.rb +0 -148
  134. data/spec/suites/rspec_1_rails_2/spec_helper.rb +0 -3
  135. data/spec/suites/rspec_2/functional/dsl_spec.rb +0 -13
  136. data/spec/suites/rspec_2/functional/instance_of_spec.rb +0 -14
  137. data/spec/suites/rspec_2/functional/proxy_spec.rb +0 -136
  138. data/spec/suites/rspec_2/functional/strong_spec.rb +0 -79
  139. data/spec/suites/rspec_2/integration/rspec_2_spec.rb +0 -133
  140. data/spec/suites/rspec_2/integration/test_unit_200_spec.rb +0 -102
  141. data/spec/suites/rspec_2/integration/test_unit_2_spec.rb +0 -109
  142. data/spec/suites/rspec_2/unit/adapters/rr_methods/double_creators_spec.rb +0 -135
  143. data/spec/suites/rspec_2/unit/adapters/rr_methods/space_spec.rb +0 -101
  144. data/spec/suites/rspec_2/unit/adapters/rr_methods/wildcard_matchers_spec.rb +0 -69
  145. data/spec/suites/rspec_2/unit/proc_from_block_spec.rb +0 -14
  146. data/spec/suites/rspec_2_rails_3/integration/astc_rails_3_spec.rb +0 -141
  147. data/spec/suites/rspec_2_rails_3/integration/minitest_4_rails_3_spec.rb +0 -148
  148. data/spec/suites/rspec_2_rails_3/integration/rspec_2_rails_3_spec.rb +0 -172
  149. data/spec/suites/rspec_2_rails_3/integration/test_unit_200_rails_3_spec.rb +0 -141
  150. data/spec/suites/rspec_2_rails_3/integration/test_unit_2_rails_3_spec.rb +0 -148
  151. data/spec/suites/rspec_2_rails_3/spec_helper.rb +0 -3
  152. data/spec/suites/rspec_2_rails_4/integration/astc_rails_4_spec.rb +0 -142
  153. data/spec/suites/rspec_2_rails_4/integration/minitest_4_rails_4_spec.rb +0 -149
  154. data/spec/suites/rspec_2_rails_4/integration/rspec_2_rails_4_spec.rb +0 -173
  155. data/spec/suites/rspec_2_rails_4/integration/test_unit_200_rails_4_spec.rb +0 -142
  156. data/spec/suites/rspec_2_rails_4/integration/test_unit_2_rails_4_spec.rb +0 -149
  157. data/spec/suites/rspec_2_rails_4/spec_helper.rb +0 -3
@@ -2,14 +2,14 @@ module RR
2
2
  module Expectations
3
3
  class AnyArgumentExpectation < ArgumentEqualityExpectation #:nodoc:
4
4
  def initialize
5
- super
5
+ super([], {})
6
6
  end
7
7
 
8
- def exact_match?(*arguments)
8
+ def exact_match?(arguments, keyword_arguments)
9
9
  false
10
10
  end
11
11
 
12
- def wildcard_match?(*arguments)
12
+ def wildcard_match?(arguments, keyword_arguments)
13
13
  true
14
14
  end
15
15
 
@@ -18,4 +18,4 @@ module RR
18
18
  end
19
19
  end
20
20
  end
21
- end
21
+ end
@@ -10,20 +10,37 @@ module RR
10
10
  end
11
11
 
12
12
  attr_reader :expected_arguments
13
+ attr_reader :expected_keyword_arguments
13
14
 
14
- def initialize(*expected_arguments)
15
+ def initialize(expected_arguments,
16
+ expected_keyword_arguments)
15
17
  @expected_arguments = expected_arguments
18
+ @expected_keyword_arguments = expected_keyword_arguments
16
19
  end
17
20
 
18
- def exact_match?(*arguments)
21
+ def exact_match?(arguments, keyword_arguments)
19
22
  return false unless arguments.length == expected_arguments.length
20
23
  arguments.each_with_index do |arg, index|
21
- return false unless self.class.recursive_safe_eq(expected_arguments[index], arg)
24
+ expected_arg = expected_arguments[index]
25
+ return false unless self.class.recursive_safe_eq(expected_arg, arg)
26
+ end
27
+ keywords = keyword_arguments.keys
28
+ expected_keywords = expected_keyword_arguments.keys
29
+ unless keywords.length == expected_keywords.length
30
+ return false
31
+ end
32
+ keywords.each do |keyword|
33
+ keyword_argument = keyword_arguments[keyword]
34
+ expected_keyword_argument = expected_keyword_arguments[keyword]
35
+ unless self.class.recursive_safe_eq(expected_keyword_argument,
36
+ keyword_argument)
37
+ return false
38
+ end
22
39
  end
23
40
  true
24
41
  end
25
42
 
26
- def wildcard_match?(*arguments)
43
+ def wildcard_match?(arguments, keyword_arguments)
27
44
  return false unless arguments.length == expected_arguments.length
28
45
  arguments.each_with_index do |arg, index|
29
46
  expected_argument = expected_arguments[index]
@@ -33,11 +50,32 @@ module RR
33
50
  return false unless self.class.recursive_safe_eq(expected_argument, arg)
34
51
  end
35
52
  end
53
+ keywords = keyword_arguments.keys
54
+ expected_keywords = expected_keyword_arguments.keys
55
+ unless keywords.length == expected_keywords.length
56
+ return false
57
+ end
58
+ keywords.each do |keyword|
59
+ keyword_argument = keyword_arguments[keyword]
60
+ expected_keyword_argument = expected_keyword_arguments[keyword]
61
+ if expected_keyword_argument.respond_to?(:wildcard_match?)
62
+ unless expected_keyword_argument.wildcard_match?(keyword_argument)
63
+ return false
64
+ end
65
+ else
66
+ unless self.class.recursive_safe_eq(expected_keyword_argument,
67
+ keyword_argument)
68
+ return false
69
+ end
70
+ end
71
+ end
36
72
  true
37
73
  end
38
74
 
39
75
  def ==(other)
40
- expected_arguments == other.expected_arguments
76
+ other.is_a?(self.class) and
77
+ expected_arguments == other.expected_arguments and
78
+ expected_keyword_arguments == other.expected_keyword_arguments
41
79
  end
42
80
  end
43
81
  end
@@ -31,15 +31,20 @@ module RR
31
31
  exists?((class << subject; self; end), method_name)
32
32
  end
33
33
 
34
- def dispatch_method(subject, subject_class, method_name, arguments, block)
34
+ def dispatch_method(subject,
35
+ subject_class,
36
+ method_name,
37
+ arguments,
38
+ keyword_arguments,
39
+ block)
35
40
  subject_eigenclass = (class << subject; self; end)
36
41
  if (
37
42
  exists?(subject_class, method_name) &&
38
- (subject_class == subject_eigenclass) || !subject.is_a?(Class)
43
+ ((subject_class == subject_eigenclass) || !subject.is_a?(Class))
39
44
  )
40
- find(subject_class, method_name.to_sym).dispatch_method(subject, arguments, block)
45
+ find(subject_class, method_name.to_sym).dispatch_method(subject, arguments, keyword_arguments, block)
41
46
  else
42
- new(subject_class, method_name.to_sym).dispatch_original_method(subject, arguments, block)
47
+ new(subject_class, method_name.to_sym).dispatch_original_method(subject, arguments, keyword_arguments, block)
43
48
  end
44
49
  end
45
50
 
@@ -91,7 +96,9 @@ module RR
91
96
 
92
97
  attr_reader :subject_class, :method_name, :doubles
93
98
 
94
- MethodArguments = Struct.new(:arguments, :block)
99
+ MethodArguments = Struct.new(:arguments,
100
+ :keyword_arguments,
101
+ :block)
95
102
 
96
103
  def initialize(subject_class, method_name)
97
104
  @subject_class = subject_class
@@ -111,7 +118,11 @@ module RR
111
118
  # is called.
112
119
  def bind
113
120
  if subject_has_method_defined?(method_name)
114
- bind_method_with_alias
121
+ if subject_has_original_method?
122
+ bind_method
123
+ else
124
+ bind_method_with_alias
125
+ end
115
126
  else
116
127
  Injections::MethodMissingInjection.find_or_create(subject_class)
117
128
  Injections::SingletonMethodAddedInjection.find_or_create(subject_class)
@@ -141,13 +152,37 @@ module RR
141
152
  id = BoundObjects.size
142
153
  BoundObjects[id] = subject_class
143
154
 
144
- subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
145
- def #{method_name}(*args, &block)
146
- arguments = MethodArguments.new(args, block)
147
- obj = ::RR::Injections::DoubleInjection::BoundObjects[#{id}]
148
- ::RR::Injections::DoubleInjection.dispatch_method(self, obj, :#{method_name}, arguments.arguments, arguments.block)
149
- end
150
- RUBY
155
+ if KeywordArguments.fully_supported?
156
+ subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
157
+ def #{method_name}(*args, **kwargs, &block)
158
+ arguments = MethodArguments.new(args, kwargs, block)
159
+ obj = ::RR::Injections::DoubleInjection::BoundObjects[#{id}]
160
+ ::RR::Injections::DoubleInjection.dispatch_method(
161
+ self,
162
+ obj,
163
+ :#{method_name},
164
+ arguments.arguments,
165
+ arguments.keyword_arguments,
166
+ arguments.block
167
+ )
168
+ end
169
+ RUBY
170
+ else
171
+ subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
172
+ def #{method_name}(*args, &block)
173
+ arguments = MethodArguments.new(args, {}, block)
174
+ obj = ::RR::Injections::DoubleInjection::BoundObjects[#{id}]
175
+ ::RR::Injections::DoubleInjection.dispatch_method(
176
+ self,
177
+ obj,
178
+ :#{method_name},
179
+ arguments.arguments,
180
+ arguments.keyword_arguments,
181
+ arguments.block
182
+ )
183
+ end
184
+ RUBY
185
+ end
151
186
  self
152
187
  end
153
188
 
@@ -175,17 +210,29 @@ module RR
175
210
  end
176
211
  end
177
212
 
178
- def dispatch_method(subject, args, block)
213
+ def dispatch_method(subject, args, kwargs, block)
179
214
  if @dispatch_method_delegates_to_dispatch_original_method
180
- dispatch_original_method(subject, args, block)
215
+ dispatch_original_method(subject, args, kwargs, block)
181
216
  else
182
- dispatch = MethodDispatches::MethodDispatch.new(self, subject, args, block)
217
+ dispatch = MethodDispatches::MethodDispatch.new(
218
+ self,
219
+ subject,
220
+ args,
221
+ kwargs,
222
+ block
223
+ )
183
224
  dispatch.call
184
225
  end
185
226
  end
186
227
 
187
- def dispatch_original_method(subject, args, block)
188
- dispatch = MethodDispatches::MethodDispatch.new(self, subject, args, block)
228
+ def dispatch_original_method(subject, args, kwargs, block)
229
+ dispatch = MethodDispatches::MethodDispatch.new(
230
+ self,
231
+ subject,
232
+ args,
233
+ kwargs,
234
+ block
235
+ )
189
236
  dispatch.call_original_method
190
237
  end
191
238
 
@@ -206,7 +253,8 @@ module RR
206
253
 
207
254
  protected
208
255
  def deferred_bind_method
209
- unless subject_has_method_defined?(original_method_alias_name)
256
+ if respond_to?(method_name) and
257
+ not subject_has_method_defined?(original_method_alias_name)
210
258
  bind_method_with_alias
211
259
  end
212
260
  @performed_deferred_bind = true
@@ -71,12 +71,43 @@ module RR
71
71
  id = BoundObjects.size
72
72
  BoundObjects[id] = subject_class
73
73
 
74
- subject_class.class_eval((<<-METHOD), __FILE__, __LINE__ + 1)
75
- def method_missing(method_name, *args, &block)
76
- obj = ::RR::Injections::MethodMissingInjection::BoundObjects[#{id}]
77
- MethodDispatches::MethodMissingDispatch.new(self, obj, method_name, args, block).call
78
- end
79
- METHOD
74
+ if KeywordArguments.fully_supported?
75
+ subject_class.class_eval((<<-METHOD), __FILE__, __LINE__ + 1)
76
+ def method_missing(method_name, *args, **kwargs, &block)
77
+ if respond_to_missing?(method_name, true)
78
+ super(method_name, *args, **kwargs, &block)
79
+ else
80
+ obj = ::RR::Injections::MethodMissingInjection::BoundObjects[#{id}]
81
+ MethodDispatches::MethodMissingDispatch.new(
82
+ self,
83
+ obj,
84
+ method_name,
85
+ args,
86
+ kwargs,
87
+ block
88
+ ).call
89
+ end
90
+ end
91
+ METHOD
92
+ else
93
+ subject_class.class_eval((<<-METHOD), __FILE__, __LINE__ + 1)
94
+ def method_missing(method_name, *args, &block)
95
+ if respond_to_missing?(method_name, true)
96
+ super(method_name, *args, &block)
97
+ else
98
+ obj = ::RR::Injections::MethodMissingInjection::BoundObjects[#{id}]
99
+ MethodDispatches::MethodMissingDispatch.new(
100
+ self,
101
+ obj,
102
+ method_name,
103
+ args,
104
+ {},
105
+ block
106
+ ).call
107
+ end
108
+ end
109
+ METHOD
110
+ end
80
111
  end
81
112
 
82
113
  def original_method_alias_name
@@ -36,7 +36,7 @@ module RR
36
36
  def hook
37
37
  assertion_error_class = self.assertion_error_class
38
38
  test_case_class.class_eval do
39
- include RR::Adapters::RRMethods
39
+ include RR::DSL
40
40
  include Mixin
41
41
 
42
42
  unless instance_methods.any? { |method_name| method_name.to_sym == :setup_with_rr }
@@ -20,7 +20,7 @@ module RR
20
20
  def hook
21
21
  parent_adapter_class = self.parent_adapter_class
22
22
  ::ActiveSupport::TestCase.class_eval do
23
- include RR::Adapters::RRMethods
23
+ include RR::DSL
24
24
  include parent_adapter_class::Mixin
25
25
 
26
26
  setup do
@@ -37,11 +37,3 @@ module RR
37
37
  end
38
38
  end
39
39
  end
40
-
41
- module RR
42
- module Adapters
43
- module Rspec
44
- InvocationMatcher = RR::Integrations::RSpec::InvocationMatcher
45
- end
46
- end
47
- end
@@ -1,6 +1,24 @@
1
1
  module RR
2
2
  module Integrations
3
- class RSpec2 < RSpec1
3
+ class RSpec2
4
+ module Mixin
5
+ def setup_mocks_for_rspec
6
+ RR.reset
7
+ end
8
+
9
+ def verify_mocks_for_rspec
10
+ RR.verify
11
+ end
12
+
13
+ def teardown_mocks_for_rspec
14
+ RR.reset
15
+ end
16
+
17
+ def have_received(method = nil)
18
+ RSpec::InvocationMatcher.new(method)
19
+ end
20
+ end
21
+
4
22
  def name
5
23
  'RSpec 2'
6
24
  end
@@ -14,14 +32,16 @@ module RR
14
32
  def hook
15
33
  ::RSpec.configure do |config|
16
34
  config.mock_with Mixin
17
- config.include RR::Adapters::RRMethods
18
- end
19
- patterns =
20
- if ::RSpec.configuration.respond_to?(:backtrace_exclusion_patterns)
21
- ::RSpec.configuration.backtrace_exclusion_patterns
22
- else
23
- ::RSpec.configuration.backtrace_clean_patterns
35
+ config.include RR::DSL
24
36
  end
37
+
38
+ patterns =
39
+ if ::RSpec.configuration.respond_to?(:backtrace_exclusion_patterns)
40
+ ::RSpec.configuration.backtrace_exclusion_patterns
41
+ else
42
+ ::RSpec.configuration.backtrace_clean_patterns
43
+ end
44
+
25
45
  unless patterns.include?(RR::Errors::BACKTRACE_IDENTIFIER)
26
46
  patterns.push(RR::Errors::BACKTRACE_IDENTIFIER)
27
47
  end
@@ -0,0 +1,15 @@
1
+ module RR
2
+ module KeywordArguments
3
+ class << self
4
+ if (RUBY_VERSION <=> "2.7.0") >= 0
5
+ def fully_supported?
6
+ true
7
+ end
8
+ else
9
+ def fully_supported?
10
+ false
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -4,7 +4,7 @@ module RR
4
4
  extend Forwardable
5
5
  include Space::Reader
6
6
 
7
- attr_reader :args, :block, :double
7
+ attr_reader :args, :kwargs, :block, :double
8
8
 
9
9
  def call
10
10
  raise NotImplementedError
@@ -12,7 +12,7 @@ module RR
12
12
 
13
13
  protected
14
14
  def find_double_to_attempt
15
- matches = DoubleMatches.new(doubles).find_all_matches(args)
15
+ matches = DoubleMatches.new(doubles).find_all_matches(args, kwargs)
16
16
 
17
17
  unless matches.exact_terminal_doubles_to_attempt.empty?
18
18
  return matches.exact_terminal_doubles_to_attempt.first
@@ -47,8 +47,25 @@ module RR
47
47
  end
48
48
  end
49
49
 
50
- def call_original_method_missing
51
- subject.__send__(MethodMissingDispatch.original_method_missing_alias_name, method_name, *args, &block)
50
+ if KeywordArguments.fully_supported?
51
+ def call_original_method_missing
52
+ subject.__send__(
53
+ MethodMissingDispatch.original_method_missing_alias_name,
54
+ method_name,
55
+ *args,
56
+ **kwargs,
57
+ &block
58
+ )
59
+ end
60
+ else
61
+ def call_original_method_missing
62
+ subject.__send__(
63
+ MethodMissingDispatch.original_method_missing_alias_name,
64
+ method_name,
65
+ *args,
66
+ &block
67
+ )
68
+ end
52
69
  end
53
70
 
54
71
  def implementation_is_original_method?
@@ -70,7 +87,7 @@ module RR
70
87
  message =
71
88
  "On subject #{subject},\n" <<
72
89
  "unexpected method invocation:\n" <<
73
- " #{Double.formatted_name(method_name, args)}\n" <<
90
+ " #{Double.formatted_name(method_name, args, kwargs)}\n" <<
74
91
  "expected invocations:\n" <<
75
92
  Double.list_message_part(doubles)
76
93
  raise RR::Errors.build_error(:DoubleNotFoundError, message)
@@ -3,15 +3,19 @@ module RR
3
3
  class MethodDispatch < BaseMethodDispatch
4
4
  attr_reader :double_injection, :subject
5
5
 
6
- def initialize(double_injection, subject, args, block)
7
- @double_injection, @subject, @args, @block = double_injection, subject, args, block
6
+ def initialize(double_injection, subject, args, kwargs, block)
7
+ @double_injection = double_injection
8
+ @subject = subject
9
+ @args = args
10
+ @kwargs = kwargs
11
+ @block = block
8
12
  @double = find_double_to_attempt
9
13
  end
10
14
 
11
15
  def call
12
- space.record_call(subject, method_name, args, block)
16
+ space.record_call(subject, method_name, args, kwargs, block)
13
17
  if double
14
- double.method_call(args)
18
+ double.method_call(args, kwargs)
15
19
  call_yields
16
20
  return_value_1 = call_implementation
17
21
  return_value_2 = extract_subject_from_return_value(return_value_1)
@@ -27,11 +31,19 @@ module RR
27
31
 
28
32
  def call_original_method
29
33
  if subject_has_original_method?
30
- subject.__send__(original_method_alias_name, *args, &block)
34
+ if KeywordArguments.fully_supported?
35
+ subject.__send__(original_method_alias_name, *args, **kwargs, &block)
36
+ else
37
+ subject.__send__(original_method_alias_name, *args, &block)
38
+ end
31
39
  elsif subject_has_original_method_missing?
32
40
  call_original_method_missing
33
41
  else
34
- subject.__send__(:method_missing, method_name, *args, &block)
42
+ if KeywordArguments.fully_supported?
43
+ subject.__send__(:method_missing, method_name, *args, **kwargs, &block)
44
+ else
45
+ subject.__send__(:method_missing, method_name, *args, &block)
46
+ end
35
47
  end
36
48
  end
37
49
 
@@ -41,11 +53,10 @@ module RR
41
53
  call_original_method
42
54
  else
43
55
  if implementation
44
- if implementation.is_a?(Method)
45
- implementation.call(*args, &block)
56
+ if KeywordArguments.fully_supported?
57
+ implementation.call(*args, **kwargs, &block)
46
58
  else
47
- call_args = block ? args + [ProcFromBlock.new(&block)] : args
48
- implementation.call(*call_args)
59
+ implementation.call(*args, &block)
49
60
  end
50
61
  else
51
62
  nil