rr 1.2.1 → 3.0.4

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 +69 -0
  3. data/Gemfile +1 -8
  4. data/README.md +9 -13
  5. data/Rakefile +30 -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 +29 -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 +83 -25
  17. data/lib/rr/injections/method_missing_injection.rb +36 -9
  18. data/lib/rr/keyword_arguments.rb +21 -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: 303d118de2a2762d0b82b84ce5074540e77008a95805fb0b3b8df64872e3bb26
4
+ data.tar.gz: 84a6e68fae515e2c5c1e6bed26dd55cbfba98e846e54d03b353266acb681a056
5
5
  SHA512:
6
- metadata.gz: 3013497ba6d79be17044b1da4efa0806f8c608840d46603fc05ec255aebdc701946cd097d9032a017f88ff2e672c5a065d0a4a4a14431bb5d0b0c6c431a3c9d3
7
- data.tar.gz: 066dc64081fc2b385185e25bd4f56612b90f14c9788ab8ca78fb17b5593542fb601b33108703ce637770d28c2a90a4dd00edac809447b59f09755e7bbe73588f
6
+ metadata.gz: c5b89becb9e9df041c472826206c92e0c9b9b6755246ce8e0c6bd84b81b5cb498c77222aaf22dbaa20f55b3315483dff85dd3b910f2ef16a0b4405d51c697dc9
7
+ data.tar.gz: f590f980d6fb93a5c173efe8a0f85676402262bd4fcec944e9804602f2372426b2a78cd9e2120569520667e9eaf213e72cb70c5db08d62373bee831a2f75387e
data/CHANGES.md CHANGED
@@ -1,5 +1,74 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.0.4 - 2021-06-23
4
+
5
+ ### Fixes
6
+
7
+ * Fix inverted condition in keyword arguments related code.
8
+ [GitHub#84][Patch by akira yamada]
9
+
10
+ ### Thanks
11
+
12
+ * akira yamada
13
+
14
+ ## 3.0.3 - 2021-06-22
15
+
16
+ ### Improvements
17
+
18
+ * Improved keyword arguments support.
19
+ [GitHub#83][Patch by akira yamada]
20
+
21
+ ### Thanks
22
+
23
+ * akira yamada
24
+
25
+ ## 3.0.2 - 2021-06-18
26
+
27
+ ### Improvements
28
+
29
+ * `stub`: Added support for Ruby 3.0's keyword arguments.
30
+ [GitHub#82][Reported by akira yamada]
31
+
32
+ ### Thanks
33
+
34
+ * akira yamada
35
+
36
+ ## 3.0.1 - 2021-06-18
37
+
38
+ ### Improvements
39
+
40
+ * Suppressed keyword arguments related warnings on Ruby 2.7.
41
+ [GitHub#81][Reported by akira yamada]
42
+
43
+ ### Thanks
44
+
45
+ * akira yamada
46
+
47
+ ## 3.0.0 - 2021-03-31
48
+
49
+ ### Improvements
50
+
51
+ * Added support for Ruby 3.0's keyword arguments.
52
+ [GitHub#17][Reported by Takuro Ashie]
53
+
54
+ ### Fixes
55
+
56
+ * Fixed a bug that `any_instance_of` doesn't work with class
57
+ hierarchies. [GitHub#12][Reported by Étienne Barrié]
58
+
59
+ ### Thanks
60
+
61
+ * Étienne Barrié
62
+
63
+ * Takuro Ashie
64
+
65
+ ## 1.2.1 - 2017-06-22
66
+
67
+ ### Fixes
68
+
69
+ * Fixed a bug that `RR.reset` resets newly created methods.
70
+ [GitHub#8]
71
+
3
72
  ## 1.2.0 - 2016-05-30
4
73
 
5
74
  ### 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,31 @@ 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
154
+ * 3.0
153
155
  * JRuby 1.7.4
154
156
 
155
157
  as well as the following test frameworks:
156
158
 
157
- * RSpec 2
158
159
  * Test::Unit via [test-unit-rr](https://test-unit.github.io/#test-unit-rr)
160
+ * RSpec 2
159
161
  * MiniTest 4
160
162
  * Minitest 5
161
163
 
162
- and the following Rails versions:
163
-
164
- * Rails 4
165
-
166
-
167
164
  ## Help!
168
165
 
169
166
  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.
167
+ issue](https://github.com/rr/rr/issues) and I'll respond as soon as I can.
171
168
 
172
169
 
173
170
  ## Contributing
174
171
 
175
172
  Want to contribute a bug fix or new feature to RR? Great! Follow these steps:
176
173
 
177
- 1. Make sure you have Ruby 2.0.0-p195 installed (this is the primary Ruby
178
- version that RR targets).
174
+ 1. Make sure you have a recent Ruby (check the compatibility table above).
179
175
  2. Clone the repo (you probably knew that already).
180
176
  3. Make a new branch off of `master` with a descriptive name.
181
177
  4. Work on your patch.
data/Rakefile CHANGED
@@ -7,10 +7,15 @@ require 'pp'
7
7
  # build, install, release
8
8
  require 'bundler/gem_tasks'
9
9
 
10
+ require_relative "lib/rr/version"
11
+
12
+ default_tasks = []
13
+
10
14
  begin
11
15
  # appraisal
12
16
  require 'appraisal'
13
-
17
+ rescue LoadError
18
+ else
14
19
  # appraisals
15
20
  Appraisal::File.each do |appraisal|
16
21
  desc "Resolve and install dependencies for the #{appraisal.name} appraisal"
@@ -18,16 +23,35 @@ begin
18
23
  appraisal.install
19
24
  end
20
25
  end
21
- rescue LoadError
26
+ default_tasks << 'appraisal:install'
22
27
  end
23
28
 
24
- # spec
25
- require File.expand_path('../spec/defines_spec_suite_tasks', __FILE__)
26
- DefinesSpecSuiteTasks.call
29
+ begin
30
+ # spec
31
+ require 'rspec/core/rake_task'
32
+ rescue LoadError
33
+ else
34
+ require File.expand_path('../spec/defines_spec_suite_tasks', __FILE__)
35
+ DefinesSpecSuiteTasks.call
36
+ default_tasks << :spec
37
+ end
27
38
 
28
39
  desc "Run tests"
29
40
  task :test do
30
41
  ruby("test/run-test.rb")
31
42
  end
43
+ default_tasks << :test
44
+
45
+ namespace :"gh-pages" do
46
+ namespace :version do
47
+ desc "Update version"
48
+ task :update do
49
+ config_yml_path = "gh-pages/_config.yml"
50
+ config_yml = File.read(config_yml_path)
51
+ config_yml = config_yml.gsub(/^version: .*$/, "version: #{RR::VERSION}")
52
+ File.write(config_yml_path, config_yml)
53
+ end
54
+ end
55
+ end
32
56
 
33
- task :default => ['appraisal:install', :spec, :test]
57
+ 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,23 @@ 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
+ elsif kwargs.empty?
40
+ definition.with(*args)
41
+ else
42
+ definition.with(*args, **kwargs)
43
+ end
44
+ end
45
+ else
46
+ def permissive_argument
47
+ if args.empty?
48
+ definition.with_any_args
49
+ else
50
+ definition.with(*args)
51
+ end
31
52
  end
32
53
  end
33
54