rr 1.2.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +25 -0
  3. data/Gemfile +1 -8
  4. data/README.md +8 -13
  5. data/Rakefile +16 -6
  6. data/lib/rr/class_instance_method_defined.rb +1 -1
  7. data/lib/rr/double.rb +28 -10
  8. data/lib/rr/double_definitions/double_definition.rb +39 -16
  9. data/lib/rr/double_definitions/double_definition_create.rb +5 -5
  10. data/lib/rr/double_definitions/double_definition_create_blank_slate.rb +10 -4
  11. data/lib/rr/double_definitions/strategies/strategy.rb +27 -8
  12. data/lib/rr/double_definitions/strategies/verification/mock.rb +8 -2
  13. data/lib/rr/double_matches.rb +4 -3
  14. data/lib/rr/expectations/any_argument_expectation.rb +4 -4
  15. data/lib/rr/expectations/argument_equality_expectation.rb +43 -5
  16. data/lib/rr/injections/double_injection.rb +65 -18
  17. data/lib/rr/injections/method_missing_injection.rb +36 -9
  18. data/lib/rr/keyword_arguments.rb +15 -0
  19. data/lib/rr/method_dispatches/base_method_dispatch.rb +22 -5
  20. data/lib/rr/method_dispatches/method_dispatch.rb +21 -10
  21. data/lib/rr/method_dispatches/method_missing_dispatch.rb +14 -5
  22. data/lib/rr/recorded_call.rb +9 -3
  23. data/lib/rr/recorded_calls.rb +17 -7
  24. data/lib/rr/space.rb +15 -5
  25. data/lib/rr/version.rb +1 -1
  26. data/lib/rr/without_autohook.rb +2 -1
  27. data/rr.gemspec +5 -0
  28. data/spec/suites.yml +1 -15
  29. data/spec/suites/rspec_2/unit/double_definitions/double_definition_create_spec.rb +18 -18
  30. data/spec/suites/rspec_2/unit/expectations/any_argument_expectation_spec.rb +9 -9
  31. data/spec/suites/rspec_2/unit/expectations/argument_equality_expectation_spec.rb +21 -21
  32. data/spec/suites/rspec_2/unit/expectations/boolean_argument_equality_expectation_spec.rb +4 -4
  33. data/spec/suites/rspec_2/unit/expectations/hash_including_argument_equality_expectation_spec.rb +31 -21
  34. data/spec/suites/rspec_2/unit/space_spec.rb +4 -3
  35. metadata +61 -10
  36. data/lib/rr/proc_from_block.rb +0 -11
  37. data/spec/suites/rspec_2/unit/proc_from_block_spec.rb +0 -14
  38. data/spec/suites/rspec_2_rails_4/integration/astc_rails_4_spec.rb +0 -142
  39. data/spec/suites/rspec_2_rails_4/integration/minitest_4_rails_4_spec.rb +0 -149
  40. data/spec/suites/rspec_2_rails_4/spec_helper.rb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 35d55fd0d14916ec412865fa0093c5c3ecf6af07
4
- data.tar.gz: e5dd7d9dbddb7c2dfe272de8a0fb9e3c18ffbf9b
2
+ SHA256:
3
+ metadata.gz: a67997dc1e6efa65e6b99101306915242163d3d6b65f73cec7a1ba2e3dbb3229
4
+ data.tar.gz: 34ed2995cdf97291cb5f1334737d8fc93dbd9078a420197635a307414d61255c
5
5
  SHA512:
6
- metadata.gz: 3013497ba6d79be17044b1da4efa0806f8c608840d46603fc05ec255aebdc701946cd097d9032a017f88ff2e672c5a065d0a4a4a14431bb5d0b0c6c431a3c9d3
7
- data.tar.gz: 066dc64081fc2b385185e25bd4f56612b90f14c9788ab8ca78fb17b5593542fb601b33108703ce637770d28c2a90a4dd00edac809447b59f09755e7bbe73588f
6
+ metadata.gz: 0bb271fe1108d5b1fc1b35c8c14d1d38bcf2254e9863a7cc48d8e20ca67aabc3ee6d02e8cb9bcd30875c285a3b5c14e3386faa31b7907f04be501678025a5278
7
+ data.tar.gz: 85641d68043365de3f062ef34164492ba69c5be725b14a12eef75f06895df73a05dbea3d53d196e6f3402d1f4ce108bcc2bdc2b8c65e2bfb015d2f7d7f6bff7c
data/CHANGES.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.0.0 - 2021-03-31
4
+
5
+ ### Improvements
6
+
7
+ * Added support for Ruby 3.0's keyword arguments.
8
+ [GitHub#17][Reported by Takuro Ashie]
9
+
10
+ ### Fixes
11
+
12
+ * Fixed a bug that `any_instance_of` doesn't work with class
13
+ hierarchies. [GitHub#12][Reported by Étienne Barrié]
14
+
15
+ ### Thanks
16
+
17
+ * Étienne Barrié
18
+
19
+ * Takuro Ashie
20
+
21
+ ## 1.2.1 - 2017-06-22
22
+
23
+ ### Fixes
24
+
25
+ * Fixed a bug that `RR.reset` resets newly created methods.
26
+ [GitHub#8]
27
+
3
28
  ## 1.2.0 - 2016-05-30
4
29
 
5
30
  ### Improvements
data/Gemfile CHANGED
@@ -1,10 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'rake', '~> 10.0'
4
- gem 'simplecov', '~> 0.7'
5
- gem 'appraisal', '~> 0.5'
6
- gem 'posix-spawn', :platforms => :mri
7
- gem 'open4', :platforms => :mri
8
- gem 'test-unit'
9
- gem 'test-unit-rr'
10
- gem 'rspec', '~> 2.14'
3
+ gemspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RR [![Gem Version](https://badge.fury.io/rb/rr.png)](http://badge.fury.io/rb/rr) [![Build Status](https://travis-ci.org/rr/rr.png?branch=master)](https://travis-ci.org/rr/rr) [![Code Climate GPA](https://codeclimate.com/github/rr/rr.png)](https://codeclimate.com/github/rr/rr)
1
+ # RR [![Gem Version](https://badge.fury.io/rb/rr.svg)](https://badge.fury.io/rb/rr) [![Build Status](https://travis-ci.org/rr/rr.svg?branch=master)](https://travis-ci.org/rr/rr) [![Code Climate GPA](https://codeclimate.com/github/rr/rr.svg)](https://codeclimate.com/github/rr/rr)
2
2
 
3
3
  RR is a test double framework for Ruby that features a rich selection of double
4
4
  techniques and a terse syntax.
@@ -147,35 +147,30 @@ require 'rr'
147
147
 
148
148
  RR is designed and tested to work against the following Ruby versions:
149
149
 
150
- * 2.1
151
- * 2.2
152
- * 2.3
150
+ * 2.4
151
+ * 2.5
152
+ * 2.6
153
+ * 2.7
153
154
  * JRuby 1.7.4
154
155
 
155
156
  as well as the following test frameworks:
156
157
 
157
- * RSpec 2
158
158
  * Test::Unit via [test-unit-rr](https://test-unit.github.io/#test-unit-rr)
159
+ * RSpec 2
159
160
  * MiniTest 4
160
161
  * Minitest 5
161
162
 
162
- and the following Rails versions:
163
-
164
- * Rails 4
165
-
166
-
167
163
  ## Help!
168
164
 
169
165
  If you have a question or are having trouble, simply [post it as an
170
- issue](http://github.com/rr/rr/issues) and I'll respond as soon as I can.
166
+ issue](https://github.com/rr/rr/issues) and I'll respond as soon as I can.
171
167
 
172
168
 
173
169
  ## Contributing
174
170
 
175
171
  Want to contribute a bug fix or new feature to RR? Great! Follow these steps:
176
172
 
177
- 1. Make sure you have Ruby 2.0.0-p195 installed (this is the primary Ruby
178
- version that RR targets).
173
+ 1. Make sure you have a recent Ruby (check the compatibility table above).
179
174
  2. Clone the repo (you probably knew that already).
180
175
  3. Make a new branch off of `master` with a descriptive name.
181
176
  4. Work on your patch.
data/Rakefile CHANGED
@@ -7,10 +7,13 @@ require 'pp'
7
7
  # build, install, release
8
8
  require 'bundler/gem_tasks'
9
9
 
10
+ default_tasks = []
11
+
10
12
  begin
11
13
  # appraisal
12
14
  require 'appraisal'
13
-
15
+ rescue LoadError
16
+ else
14
17
  # appraisals
15
18
  Appraisal::File.each do |appraisal|
16
19
  desc "Resolve and install dependencies for the #{appraisal.name} appraisal"
@@ -18,16 +21,23 @@ begin
18
21
  appraisal.install
19
22
  end
20
23
  end
21
- rescue LoadError
24
+ default_tasks << 'appraisal:install'
22
25
  end
23
26
 
24
- # spec
25
- require File.expand_path('../spec/defines_spec_suite_tasks', __FILE__)
26
- DefinesSpecSuiteTasks.call
27
+ begin
28
+ # spec
29
+ require 'rspec/core/rake_task'
30
+ rescue LoadError
31
+ else
32
+ require File.expand_path('../spec/defines_spec_suite_tasks', __FILE__)
33
+ DefinesSpecSuiteTasks.call
34
+ default_tasks << :spec
35
+ end
27
36
 
28
37
  desc "Run tests"
29
38
  task :test do
30
39
  ruby("test/run-test.rb")
31
40
  end
41
+ default_tasks << :test
32
42
 
33
- task :default => ['appraisal:install', :spec, :test]
43
+ task :default => default_tasks
@@ -6,4 +6,4 @@ module RR
6
6
  klass.private_instance_methods(include_super).detect {|method_name| method_name.to_sym == instance_method.to_sym}
7
7
  end
8
8
  end
9
- end
9
+ end
data/lib/rr/double.rb CHANGED
@@ -4,14 +4,20 @@ module RR
4
4
  # and the implementation.
5
5
  class Double
6
6
  extend(Module.new do
7
- def formatted_name(method_name, args)
8
- formatted_errors = args.collect {|arg| arg.inspect}.join(', ')
7
+ def formatted_name(method_name, args, kwargs)
8
+ formatted_arguments =
9
+ args.collect {|arg| arg.inspect} +
10
+ kwargs.collect {|keyword, value| "#{keyword}: #{value.inspect}"}
11
+ formatted_errors = formatted_arguments.join(', ')
9
12
  "#{method_name}(#{formatted_errors})"
10
13
  end
11
14
 
12
15
  def list_message_part(doubles)
13
16
  doubles.collect do |double|
14
- "- #{formatted_name(double.method_name, double.expected_arguments)}"
17
+ name = formatted_name(double.method_name,
18
+ double.expected_arguments,
19
+ double.expected_keyword_arguments)
20
+ "- #{name}"
15
21
  end.join("\n")
16
22
  end
17
23
  end)
@@ -32,14 +38,14 @@ module RR
32
38
 
33
39
  # Double#exact_match? returns true when the passed in arguments
34
40
  # exactly match the ArgumentEqualityExpectation arguments.
35
- def exact_match?(*arguments)
36
- definition.exact_match?(*arguments)
41
+ def exact_match?(arguments, keyword_arguments)
42
+ definition.exact_match?(arguments, keyword_arguments)
37
43
  end
38
44
 
39
45
  # Double#wildcard_match? returns true when the passed in arguments
40
46
  # wildcard match the ArgumentEqualityExpectation arguments.
41
- def wildcard_match?(*arguments)
42
- definition.wildcard_match?(*arguments)
47
+ def wildcard_match?(arguments, keyword_arguments)
48
+ definition.wildcard_match?(arguments, keyword_arguments)
43
49
  end
44
50
 
45
51
  # Double#attempt? returns true when the
@@ -74,18 +80,26 @@ module RR
74
80
  argument_expectation.expected_arguments
75
81
  end
76
82
 
83
+ # The keyword arguments that this Double expects
84
+ def expected_keyword_arguments
85
+ verify_argument_expectation_is_set
86
+ argument_expectation.expected_keyword_arguments
87
+ end
88
+
77
89
  # The TimesCalledMatcher for the TimesCalledExpectation
78
90
  def times_matcher
79
91
  definition.times_matcher
80
92
  end
81
93
 
82
94
  def formatted_name
83
- self.class.formatted_name(method_name, expected_arguments)
95
+ self.class.formatted_name(method_name,
96
+ expected_arguments,
97
+ expected_keyword_arguments)
84
98
  end
85
99
 
86
- def method_call(args)
100
+ def method_call(args, kwargs)
87
101
  if verbose?
88
- puts Double.formatted_name(method_name, args)
102
+ puts Double.formatted_name(method_name, args, kwargs)
89
103
  end
90
104
  times_called_expectation.attempt if definition.times_matcher
91
105
  space.verify_ordered_double(self) if ordered?
@@ -148,6 +162,10 @@ module RR
148
162
  definition.argument_expectation.expected_arguments
149
163
  end
150
164
 
165
+ def kwargs
166
+ definition.argument_expectation.expected_keyword_arguments
167
+ end
168
+
151
169
  def argument_expectation
152
170
  definition.argument_expectation
153
171
  end
@@ -36,16 +36,26 @@ module RR
36
36
  end
37
37
 
38
38
  module ArgumentDefinitionConstructionMethods
39
- # Double#with sets the expectation that the Double will receive
40
- # the passed in arguments.
41
- #
42
- # Passing in a block sets the return value.
43
- #
44
- # mock(subject).method_name.with(1, 2) {:return_value}
45
- def with(*args, &return_value_block)
46
- @argument_expectation = Expectations::ArgumentEqualityExpectation.new(*args)
47
- install_method_callback return_value_block
48
- self
39
+ if KeywordArguments.fully_supported?
40
+ # Double#with sets the expectation that the Double will receive
41
+ # the passed in arguments.
42
+ #
43
+ # Passing in a block sets the return value.
44
+ #
45
+ # mock(subject).method_name.with(1, 2) {:return_value}
46
+ def with(*args, **kwargs, &return_value_block)
47
+ @argument_expectation =
48
+ Expectations::ArgumentEqualityExpectation.new(args, kwargs)
49
+ install_method_callback return_value_block
50
+ self
51
+ end
52
+ else
53
+ def with(*args, &return_value_block)
54
+ @argument_expectation =
55
+ Expectations::ArgumentEqualityExpectation.new(args, {})
56
+ install_method_callback return_value_block
57
+ self
58
+ end
49
59
  end
50
60
 
51
61
  # Double#with_any_args sets the expectation that the Double can receive
@@ -67,7 +77,8 @@ module RR
67
77
  #
68
78
  # mock(subject).method_name.with_no_args {:return_value}
69
79
  def with_no_args(&return_value_block)
70
- @argument_expectation = Expectations::ArgumentEqualityExpectation.new()
80
+ @argument_expectation =
81
+ Expectations::ArgumentEqualityExpectation.new([], {})
71
82
  install_method_callback return_value_block
72
83
  self
73
84
  end
@@ -298,18 +309,18 @@ module RR
298
309
  @verbose ? true : false
299
310
  end
300
311
 
301
- def exact_match?(*arguments)
312
+ def exact_match?(arguments, keyword_arguments)
302
313
  unless @argument_expectation
303
314
  raise RR::Errors.build_error(:DoubleDefinitionError, "#argument_expectation must be defined on #{inspect}")
304
315
  end
305
- @argument_expectation.exact_match?(*arguments)
316
+ @argument_expectation.exact_match?(arguments, keyword_arguments)
306
317
  end
307
318
 
308
- def wildcard_match?(*arguments)
319
+ def wildcard_match?(arguments, keyword_arguments)
309
320
  unless @argument_expectation
310
321
  raise RR::Errors.build_error(:DoubleDefinitionError, "#argument_expectation must be defined on #{inspect}")
311
322
  end
312
- @argument_expectation.wildcard_match?(*arguments)
323
+ @argument_expectation.wildcard_match?(arguments, keyword_arguments)
313
324
  end
314
325
 
315
326
  def terminal?
@@ -320,7 +331,19 @@ module RR
320
331
  end
321
332
 
322
333
  def expected_arguments
323
- argument_expectation ? argument_expectation.expected_arguments : []
334
+ if argument_expectation
335
+ argument_expectation.expected_arguments
336
+ else
337
+ []
338
+ end
339
+ end
340
+
341
+ def expected_keyword_arguments
342
+ if argument_expectation
343
+ argument_expectation.expected_keyword_arguments
344
+ else
345
+ {}
346
+ end
324
347
  end
325
348
 
326
349
  def implementation_is_original_method?
@@ -30,11 +30,11 @@ module RR
30
30
  @double_injection_strategy = self.class.default_double_injection_strategy.call(self)
31
31
  end
32
32
 
33
- def call(method_name, *args, &handler)
33
+ def call(method_name, args, kwargs, &handler)
34
34
  definition = DoubleDefinition.new(self)
35
- verification_strategy.call(definition, method_name, args, handler)
36
- implementation_strategy.call(definition, method_name, args, handler)
37
- double_injection_strategy.call(definition, method_name, args, handler)
35
+ verification_strategy.call(definition, method_name, args, kwargs, handler)
36
+ implementation_strategy.call(definition, method_name, args, kwargs, handler)
37
+ double_injection_strategy.call(definition, method_name, args, kwargs, handler)
38
38
  definition
39
39
  end
40
40
 
@@ -81,7 +81,7 @@ module RR
81
81
  self
82
82
  elsif method_name
83
83
  # TODO: Pass in arguments.
84
- call(method_name)
84
+ call(method_name, [], {})
85
85
  else
86
86
  DoubleDefinitionCreateBlankSlate.new(self, &definition_eval_block)
87
87
  end
@@ -14,13 +14,19 @@ module RR
14
14
  end
15
15
  end
16
16
 
17
- def method_missing(method_name, *args, &block)
18
- @double_definition_create.call(method_name, *args, &block)
17
+ if KeywordArguments.fully_supported?
18
+ def method_missing(method_name, *args, **kwargs, &block)
19
+ @double_definition_create.call(method_name, args, kwargs, &block)
20
+ end
21
+ else
22
+ def method_missing(method_name, *args, &block)
23
+ @double_definition_create.call(method_name, args, {}, &block)
24
+ end
19
25
  end
20
26
 
21
27
  def __double_definition_create__
22
28
  @double_definition_create
23
29
  end
24
- end
30
+ end
25
31
  end
26
- end
32
+ end
@@ -2,7 +2,12 @@ module RR
2
2
  module DoubleDefinitions
3
3
  module Strategies
4
4
  class Strategy
5
- attr_reader :double_definition_create, :definition, :method_name, :args, :handler
5
+ attr_reader :double_definition_create
6
+ attr_reader :definition
7
+ attr_reader :method_name
8
+ attr_reader :args
9
+ attr_reader :kwargs
10
+ attr_reader :handler
6
11
 
7
12
  include Space::Reader
8
13
 
@@ -10,8 +15,12 @@ module RR
10
15
  @double_definition_create = double_definition_create
11
16
  end
12
17
 
13
- def call(definition, method_name, args, handler)
14
- @definition, @method_name, @args, @handler = definition, method_name, args, handler
18
+ def call(definition, method_name, args, kwargs, handler)
19
+ @definition = definition
20
+ @method_name = method_name
21
+ @args = args
22
+ @kwargs = kwargs
23
+ @handler = handler
15
24
  do_call
16
25
  end
17
26
 
@@ -23,11 +32,21 @@ module RR
23
32
  raise NotImplementedError
24
33
  end
25
34
 
26
- def permissive_argument
27
- if args.empty?
28
- definition.with_any_args
29
- else
30
- definition.with(*args)
35
+ if KeywordArguments.fully_supported?
36
+ def permissive_argument
37
+ if args.empty? and kwargs.empty?
38
+ definition.with_any_args
39
+ else
40
+ definition.with(*args, **kwargs)
41
+ end
42
+ end
43
+ else
44
+ def permissive_argument
45
+ if args.empty?
46
+ definition.with_any_args
47
+ else
48
+ definition.with(*args)
49
+ end
31
50
  end
32
51
  end
33
52
 
@@ -32,8 +32,14 @@ module RR
32
32
  # end
33
33
  class Mock < VerificationStrategy
34
34
  protected
35
- def do_call
36
- definition.with(*args).once
35
+ if KeywordArguments.fully_supported?
36
+ def do_call
37
+ definition.with(*args, **kwargs).once
38
+ end
39
+ else
40
+ def do_call
41
+ definition.with(*args).once
42
+ end
37
43
  end
38
44
  end
39
45
  end