rr 1.2.1 → 3.0.4

Sign up to get free protection for your applications and to get access to all the features.
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