spy 1.0.3 → 1.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb02855e84ed97ae778d5983b8bba3e5839a6593416336a18240beb759f82b7f
4
- data.tar.gz: df92498cacaab913d6d71d6d3e34778140d7367f741a1f1d750e96cbc2353a19
3
+ metadata.gz: 46c870bafa6e5402e585dc44ea855f5e22a8087b4c14f70fad8794b39ac425a0
4
+ data.tar.gz: c9552993d8b0e335defead206a238c0342ea461102722f6702f04ae8a823f100
5
5
  SHA512:
6
- metadata.gz: 72e822dfc3517b8bcc4d26d9ffc0db333acd4526673a765de0a19f4396292834bd0402a307d31d6ba226c5f9017a2813fba53738d5784dc00fc0aa0e66720869
7
- data.tar.gz: 35b2c58f79ef8da6c462ba1a5739ddc2705df1544a2f75c14ecb9731c60b5f33337f94056dbf1803480699d6729f0410985194cbfe4d376852cf5417d352b8c2
6
+ metadata.gz: 5b476de3ea3a4f01a85ed3f99d51ed7c38785f67c9c7b565607e6e0edd027eeb643bc2fe43a92b8bdcfc7054e149c6e75022489bccaa3b7678f4239263152094
7
+ data.tar.gz: 16d976fa766805c685f7198fe219a55802d29a4d560ec7f984c229c751905c81fe0622a8887fc71c0c87845a48d40d283fdb4f0411d2c3ded2d72673bddfe1e1
@@ -0,0 +1,38 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ "master" ]
13
+ pull_request:
14
+ branches: [ "master" ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ ruby-version: ['2.7', '3.0', '3.1']
26
+
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - name: Set up Ruby
30
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
31
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
32
+ # uses: ruby/setup-ruby@v1
33
+ uses: ruby/setup-ruby@0a29871fe2b0200a17a4497bae54fe5df0d973aa # v1.115.3
34
+ with:
35
+ ruby-version: ${{ matrix.ruby-version }}
36
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
37
+ - name: Run tests
38
+ run: bundle exec rake
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 2.7.0
1
+ ruby 3.1.2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## Spy 1.0.4 (December 21th, 2022) ##
2
+
3
+ * remove usage of #present? (@ryanong)
4
+
5
+ ## Spy 1.0.4 (December 21th, 2022) ##
6
+
7
+ * Hash as argument got turned into keyword arguments (@svenpl)
8
+ * drop support for ruby older than 2.7 (@ryanong)
9
+
10
+ ## Spy 1.0.3 (September 15, 2022) ##
11
+
12
+ * Fix private method call errors for older ruby versions (@dylanahsmith)
13
+ * `Spy.on_instance_method` and `and_call_through` on `#to_ary-able` class causes an error (@mizukami234)
14
+ * Fix `and_return` on class method (@jfirebaugh)
15
+
16
+ ## Spy 1.0.2 (January 10, 2022) ##
17
+
18
+ * Fix subroutine call with hash as last arg (@dtheo-ad)
19
+ * Ruby 2.7+ support (@casperisfine)
20
+
1
21
  ## Spy 1.0.1 (August 20th, 2020) ##
2
22
 
3
23
  * Fix call_through w/ instance methods (@lreeves)
data/README.md CHANGED
@@ -9,8 +9,7 @@
9
9
 
10
10
  Spy is a lightweight stubbing framework with support for method spies, constant stubs, and object mocks.
11
11
 
12
- Spy supports ruby 2.1.0+.
13
- For versions less than 2.1 use v0.4.5
12
+ Spy supports ruby 2.7.0+.
14
13
 
15
14
  Spy features that were completed were tested against the rspec-mocks tests so it covers all cases that rspec-mocks does.
16
15
 
@@ -47,7 +46,7 @@ Fail faster, code faster.
47
46
  * you can usually just check the call logs.
48
47
  * if you do need to use this. It is probably a code smell. You either need to abstract your method more or add separate tests.
49
48
  * you want to use dumb double, Spy has smart mocks, they are better
50
- * you use `mock_model` and `stub_model` (I want to impliment this soon)
49
+ * you use `mock_model` and `stub_model`
51
50
 
52
51
  ## Installation
53
52
 
@@ -87,7 +86,7 @@ Spy::Subroutine.new(book, :flamethrower).hook(force:true).and_return("burnninant
87
86
  ```
88
87
 
89
88
  You can also stub instance methods of Classes and Modules. This is equivalent to
90
- rspec-mock's `Module#any_instance`
89
+ rspec-mock's `allow_any_instance_of(Module)`
91
90
 
92
91
  ```ruby
93
92
  Spy.on_instance_method(Book, :title).and_return("Cannery Row")
data/lib/spy/call_log.rb CHANGED
@@ -10,6 +10,9 @@ module Spy
10
10
  # @!attribute [r] args
11
11
  # @return [Array] arguments were sent to the method
12
12
  #
13
+ # @!attribute [r] kwargs
14
+ # @return [Array] keyword arguments were sent to the method
15
+ #
13
16
  # @!attribute [r] block
14
17
  # @return [Proc] the block that was sent to the method
15
18
  #
@@ -17,10 +20,10 @@ module Spy
17
20
  # @return The result of the method of being stubbed, or called through
18
21
 
19
22
 
20
- attr_reader :object, :called_from, :args, :block, :result
23
+ attr_reader :object, :called_from, :args, :kwargs, :block, :result
21
24
 
22
- def initialize(object, called_from, args, block, result)
23
- @object, @called_from, @args, @block, @result = object, called_from, args, block, result
25
+ def initialize(object, called_from, args, kwargs, block, result)
26
+ @object, @called_from, @args, @kwargs, @block, @result = object, called_from, args, kwargs, block, result
24
27
  end
25
28
  end
26
29
  end
@@ -201,26 +201,28 @@ module Spy
201
201
  # check if the method was called with the exact arguments
202
202
  # @param args Arguments that should have been sent to the method
203
203
  # @return [Boolean]
204
- def has_been_called_with?(*args, &block)
204
+ def has_been_called_with?(*args, **kwargs, &block)
205
205
  raise NeverHookedError unless @was_hooked
206
- match = block_given? ? block : proc { |call| call.args == args }
206
+ match = block_given? ? block : proc { |call| call.args == args && call.kwargs == kwargs }
207
207
  calls.any?(&match)
208
208
  end
209
209
 
210
210
  # invoke that the method has been called. You really shouldn't use this
211
211
  # method.
212
- def invoke(object, args, block, called_from)
213
- check_arity!(args.size)
212
+ def invoke(object, args, kwargs, block, called_from)
213
+ arity = args.size
214
+ arity += 1 if !kwargs&.empty?
215
+ check_arity!(arity)
214
216
 
215
217
  result =
216
218
  if @call_through
217
- call_plan(build_call_through_plan(object), block, *args)
219
+ call_plan(build_call_through_plan(object), block, *args, **kwargs)
218
220
  elsif @plan
219
221
  check_for_too_many_arguments!(@plan)
220
- call_plan(@plan, block, *args)
222
+ call_plan(@plan, block, *args, **kwargs)
221
223
  end
222
224
  ensure
223
- calls << CallLog.new(object, called_from, args, block, result)
225
+ calls << CallLog.new(object, called_from, args, kwargs, block, result)
224
226
  end
225
227
 
226
228
  # reset the call log
@@ -237,11 +239,12 @@ module Spy
237
239
  # we use eval to set the spy object id as a parameter so it can be extracted
238
240
  # and looked up later using `Method#parameters`
239
241
  SPY_ARGS_PREFIX='__spy_args_'.freeze
242
+ SPY_KWARGS_PREFIX='__spy_kwargs_'.freeze
240
243
  def override_method
241
244
  eval <<-METHOD, binding, __FILE__, __LINE__ + 1
242
245
  __method_spy__ = self
243
- lambda do |*#{SPY_ARGS_PREFIX}#{self.object_id}, &block|
244
- __method_spy__.invoke(self, #{SPY_ARGS_PREFIX}#{self.object_id}, block, caller(1)[0])
246
+ lambda do |*#{SPY_ARGS_PREFIX}#{self.object_id}, **#{SPY_KWARGS_PREFIX}#{self.object_id}, &block|
247
+ __method_spy__.invoke(self, #{SPY_ARGS_PREFIX}#{self.object_id}, #{SPY_KWARGS_PREFIX}#{self.object_id}, block, caller(1)[0])
245
248
  end
246
249
  METHOD
247
250
  end
@@ -345,23 +348,8 @@ module Spy
345
348
  end
346
349
  end
347
350
 
348
- def call_plan(plan, block, *args)
349
- if ruby_27_last_arg_hash?(args)
350
- *prefix, last = args
351
- plan.call(*prefix, **last, &block)
352
- else
353
- plan.call(*args, &block)
354
- end
355
- end
356
-
357
- # Ruby 2.7 gives a deprecation warning about passing hash as last argument for a method
358
- # with a double-splat operator (**), and Ruby 3 raises an ArgumentError exception.
359
- # This checks if args has a hash as last element to extract it and pass it with double-splat to avoid an exception.
360
- def ruby_27_last_arg_hash?(args)
361
- last = args.last
362
- last.instance_of?(Hash) &&
363
- !last.empty? &&
364
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0")
351
+ def call_plan(plan, block, *args, **kwargs)
352
+ plan.call(*args, **kwargs, &block)
365
353
  end
366
354
 
367
355
  class << self
data/lib/spy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Spy
2
- VERSION = "1.0.3"
2
+ VERSION = "1.0.5"
3
3
  end
data/spy.gemspec CHANGED
@@ -6,7 +6,7 @@ require 'spy/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "spy"
8
8
  gem.version = Spy::VERSION
9
- gem.required_ruby_version = '>= 2.1.0'
9
+ gem.required_ruby_version = '>= 2.7.0'
10
10
  gem.license = 'MIT'
11
11
  gem.authors = ["Ryan Ong"]
12
12
  gem.email = ["ryanong@gmail.com"]
@@ -150,6 +150,14 @@ module Spy
150
150
  assert_equal string, result
151
151
  end
152
152
 
153
+ def test_spy_and_call_through_with_hash_and_keyword_args
154
+ spy_on(@pen, 'hash_and_keyword_arg').and_call_through
155
+ hsh = { hello: 'world' }
156
+
157
+ assert_equal [hsh, nil], @pen.hash_and_keyword_arg(hsh)
158
+ assert_equal [hsh, 'foo'], @pen.hash_and_keyword_arg(hsh, keyword: 'foo')
159
+ end
160
+
153
161
  def test_spy_and_call_through_returns_original_method_result
154
162
  string = "hello world"
155
163
 
@@ -237,6 +245,20 @@ module Spy
237
245
  assert pen_write_spy.has_been_called_with?("hello")
238
246
  end
239
247
 
248
+ def test_has_been_called_with_kwargs
249
+ pen_write_spy = spy_on(@pen, :opt_kwargs)
250
+ refute pen_write_spy.has_been_called_with?("hello")
251
+
252
+ @pen.opt_kwargs("hello")
253
+ assert pen_write_spy.has_been_called_with?("hello")
254
+
255
+ @pen.opt_kwargs("world", opt: "hello")
256
+ assert pen_write_spy.has_been_called_with?("world", opt: "hello")
257
+
258
+ @pen.opt_kwargs("hello world", opt: "world", opt2: "hello")
259
+ assert pen_write_spy.has_been_called_with?("hello world", opt: "world", opt2: "hello")
260
+ end
261
+
240
262
  def test_spy_hook_records_number_of_calls2
241
263
  args = ["hello world"]
242
264
  block = Proc.new {}
data/test/support/pen.rb CHANGED
@@ -37,6 +37,10 @@ class Pen
37
37
  write("#{hello} #{name}")
38
38
  end
39
39
 
40
+ def hash_and_keyword_arg(hsh, keyword: nil)
41
+ [hsh, keyword]
42
+ end
43
+
40
44
  def public_method
41
45
  end
42
46
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Ong
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-15 00:00:00.000000000 Z
11
+ date: 2022-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -117,9 +117,9 @@ executables: []
117
117
  extensions: []
118
118
  extra_rdoc_files: []
119
119
  files:
120
+ - ".github/workflows/ruby.yml"
120
121
  - ".gitignore"
121
122
  - ".tool-versions"
122
- - ".travis.yml"
123
123
  - ".yardopts"
124
124
  - CHANGELOG.md
125
125
  - Gemfile
@@ -139,22 +139,6 @@ files:
139
139
  - lib/spy/nest.rb
140
140
  - lib/spy/subroutine.rb
141
141
  - lib/spy/version.rb
142
- - spec/spec_helper.rb
143
- - spec/spy/and_call_original_spec.rb
144
- - spec/spy/and_yield_spec.rb
145
- - spec/spy/any_instance_spec.rb
146
- - spec/spy/hash_excluding_matcher_spec.rb
147
- - spec/spy/hash_including_matcher_spec.rb
148
- - spec/spy/mutate_const_spec.rb
149
- - spec/spy/nil_expectation_warning_spec.rb
150
- - spec/spy/null_object_mock_spec.rb
151
- - spec/spy/partial_mock_spec.rb
152
- - spec/spy/passing_argument_matchers_spec.rb
153
- - spec/spy/serialization_spec.rb
154
- - spec/spy/stash_spec.rb
155
- - spec/spy/stub_implementation_spec.rb
156
- - spec/spy/stub_spec.rb
157
- - spec/spy/to_ary_spec.rb
158
142
  - spy.gemspec
159
143
  - test/integration/test_api.rb
160
144
  - test/integration/test_class_method.rb
@@ -179,7 +163,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
179
163
  requirements:
180
164
  - - ">="
181
165
  - !ruby/object:Gem::Version
182
- version: 2.1.0
166
+ version: 2.7.0
183
167
  required_rubygems_version: !ruby/object:Gem::Requirement
184
168
  requirements:
185
169
  - - ">="
@@ -192,22 +176,6 @@ specification_version: 4
192
176
  summary: A simple modern mocking library that uses the spy pattern and checks method's
193
177
  existence and arity.
194
178
  test_files:
195
- - spec/spec_helper.rb
196
- - spec/spy/and_call_original_spec.rb
197
- - spec/spy/and_yield_spec.rb
198
- - spec/spy/any_instance_spec.rb
199
- - spec/spy/hash_excluding_matcher_spec.rb
200
- - spec/spy/hash_including_matcher_spec.rb
201
- - spec/spy/mutate_const_spec.rb
202
- - spec/spy/nil_expectation_warning_spec.rb
203
- - spec/spy/null_object_mock_spec.rb
204
- - spec/spy/partial_mock_spec.rb
205
- - spec/spy/passing_argument_matchers_spec.rb
206
- - spec/spy/serialization_spec.rb
207
- - spec/spy/stash_spec.rb
208
- - spec/spy/stub_implementation_spec.rb
209
- - spec/spy/stub_spec.rb
210
- - spec/spy/to_ary_spec.rb
211
179
  - test/integration/test_api.rb
212
180
  - test/integration/test_class_method.rb
213
181
  - test/integration/test_constant_spying.rb
data/.travis.yml DELETED
@@ -1,13 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - '2.1'
4
- - '2.5'
5
- - '2.7'
6
- - jruby
7
- - ruby-head
8
- - rbx-3
9
- matrix:
10
- allow_failures:
11
- - rvm: ruby-head
12
- - rvm: rbx-3
13
- - rvm: jruby
data/spec/spec_helper.rb DELETED
@@ -1,41 +0,0 @@
1
- require "rspec/core"
2
- require "rspec/matchers"
3
- require "rspec/expectations"
4
- require "spy"
5
- require "pry"
6
- require "pry-nav"
7
-
8
- RSpec::Matchers.define :include_method do |expected|
9
- match do |actual|
10
- actual.map { |m| m.to_s }.include?(expected.to_s)
11
- end
12
- end
13
-
14
- RSpec.configure do |config|
15
- config.color_enabled = true
16
- config.order = :random
17
- config.run_all_when_everything_filtered = true
18
- config.treat_symbols_as_metadata_keys_with_true_values = true
19
- config.filter_run_including :focus
20
- config.filter_run_excluding :broken => true
21
- config.mock_with :absolutely_nothing
22
-
23
- config.expect_with :rspec do |expectations|
24
- expectations.syntax = :expect
25
- end
26
-
27
- old_verbose = nil
28
- config.before(:each, :silence_warnings) do
29
- old_verbose = $VERBOSE
30
- $VERBOSE = nil
31
- end
32
-
33
- config.after(:each, :silence_warnings) do
34
- $VERBOSE = old_verbose
35
- end
36
-
37
- config.after(:each) do
38
- Spy.teardown
39
- end
40
- end
41
-
@@ -1,152 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "and_call_through" do
4
- context "on a partial mock object" do
5
- let(:klass) do
6
- Class.new do
7
- def meth_1
8
- :original
9
- end
10
-
11
- def meth_2(x)
12
- yield x, :additional_yielded_arg
13
- end
14
-
15
- def self.new_instance
16
- new
17
- end
18
- end
19
- end
20
-
21
- let(:instance) { klass.new }
22
-
23
- it 'passes the received message through to the original method' do
24
- spy = Spy.on(instance, :meth_1).and_call_through
25
- expect(instance.meth_1).to eq(:original)
26
- expect(spy).to have_been_called
27
- end
28
-
29
- it 'passes args and blocks through to the original method' do
30
- spy = Spy.on(instance, :meth_2).and_call_through
31
- value = instance.meth_2(:submitted_arg) { |a, b| [a, b] }
32
- expect(value).to eq([:submitted_arg, :additional_yielded_arg])
33
- expect(spy).to have_been_called
34
- end
35
-
36
- it 'works for singleton methods' do
37
- def instance.foo; :bar; end
38
- spy = Spy.on(instance, :foo).and_call_through
39
- expect(instance.foo).to eq(:bar)
40
- expect(spy).to have_been_called
41
- end
42
-
43
- it 'works for methods added through an extended module' do
44
- instance.extend Module.new { def foo; :bar; end }
45
- spy = Spy.on(instance, :foo).and_call_through
46
- expect(instance.foo).to eq(:bar)
47
- expect(spy).to have_been_called
48
- end
49
-
50
- it "works for method added through an extended module onto a class's ancestor" do
51
- sub_sub_klass = Class.new(Class.new(klass))
52
- klass.extend Module.new { def foo; :bar; end }
53
- spy = Spy.on(sub_sub_klass, :foo).and_call_through
54
- expect(sub_sub_klass.foo).to eq(:bar)
55
- expect(spy).to have_been_called
56
- end
57
-
58
- it "finds the method on the most direct ancestor even if the method " +
59
- "is available on more distant ancestors" do
60
- klass.extend Module.new { def foo; :klass_bar; end }
61
- sub_klass = Class.new(klass)
62
- sub_klass.extend Module.new { def foo; :sub_klass_bar; end }
63
- spy = Spy.on(sub_klass, :foo).and_call_through
64
- expect(sub_klass.foo).to eq(:sub_klass_bar)
65
- expect(spy).to have_been_called
66
- end
67
-
68
- it 'works for class methods defined on a superclass' do
69
- subclass = Class.new(klass)
70
- spy = Spy.on(subclass, :new_instance).and_call_through
71
- expect(subclass.new_instance).to be_a(subclass)
72
- expect(spy).to have_been_called
73
- end
74
-
75
- it 'works for class methods defined on a grandparent class' do
76
- sub_subclass = Class.new(Class.new(klass))
77
- spy = Spy.on(sub_subclass, :new_instance).and_call_through
78
- expect(sub_subclass.new_instance).to be_a(sub_subclass)
79
- expect(spy).to have_been_called
80
- end
81
-
82
- it 'works for class methods defined on the Class class' do
83
- spy = Spy.on(klass, :new).and_call_through
84
- expect(klass.new).to be_an_instance_of(klass)
85
- expect(spy).to have_been_called
86
- end
87
-
88
- it "works for instance methods defined on the object's class's superclass" do
89
- subclass = Class.new(klass)
90
- inst = subclass.new
91
- spy = Spy.on(inst, :meth_1).and_call_through
92
- expect(inst.meth_1).to eq(:original)
93
- expect(spy).to have_been_called
94
- end
95
-
96
- it 'works for aliased methods' do
97
- klass = Class.new do
98
- class << self
99
- alias alternate_new new
100
- end
101
- end
102
-
103
- spy = Spy.on(klass, :alternate_new).and_call_through
104
- expect(klass.alternate_new).to be_an_instance_of(klass)
105
- expect(spy).to have_been_called
106
- end
107
-
108
- context 'on an object that defines method_missing' do
109
- before do
110
- klass.class_eval do
111
- def respond_to_missing?(name, _)
112
- if name.to_s == "greet_jack"
113
- true
114
- else
115
- super
116
- end
117
- end
118
-
119
- def method_missing(name, *args)
120
- if name.to_s == "greet_jack"
121
- "Hello, jack"
122
- else
123
- super
124
- end
125
- end
126
- end
127
- end
128
-
129
- it 'works when the method_missing definition handles the message' do
130
- spy = Spy.on(instance, :greet_jack).and_call_through
131
- expect(instance.greet_jack).to eq("Hello, jack")
132
- expect(spy).to have_been_called
133
- end
134
-
135
- it 'raises an error on invocation if method_missing does not handle the message' do
136
- Spy::Subroutine.new(instance, :not_a_handled_message).hook(force: true).and_call_through
137
-
138
- # Note: it should raise a NoMethodError (and usually does), but
139
- # due to a weird rspec-expectations issue (see #183) it sometimes
140
- # raises a `NameError` when a `be_xxx` predicate matcher has been
141
- # recently used. `NameError` is the superclass of `NoMethodError`
142
- # so this example will pass regardless.
143
- # If/when we solve the rspec-expectations issue, this can (and should)
144
- # be changed to `NoMethodError`.
145
- expect {
146
- instance.not_a_handled_message
147
- }.to raise_error(NameError, /not_a_handled_message/)
148
- end
149
- end
150
- end
151
- end
152
-
@@ -1,123 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Spy" do
4
-
5
- class Foo
6
- def method_that_accepts_a_block(&block)
7
- end
8
- end
9
-
10
- let(:obj) { Foo.new }
11
-
12
- describe "#and_yield" do
13
- context "with eval context as block argument" do
14
-
15
- it "evaluates the supplied block as it is read" do
16
- evaluated = false
17
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
18
- evaluated = true
19
- end
20
- expect(evaluated).to be_true
21
- end
22
-
23
- it "passes an eval context object to the supplied block" do
24
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
25
- expect(eval_context).not_to be_nil
26
- end
27
- end
28
-
29
- it "evaluates the block passed to the stubbed method in the context of the supplied eval context" do
30
- expected_eval_context = nil
31
- actual_eval_context = nil
32
-
33
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
34
- expected_eval_context = eval_context
35
- end
36
-
37
- obj.method_that_accepts_a_block do
38
- actual_eval_context = self
39
- end
40
-
41
- expect(actual_eval_context).to equal(expected_eval_context)
42
- end
43
-
44
- context "and no yielded arguments" do
45
-
46
- it "passes when expectations set on the eval context are met" do
47
- configured_eval_context = nil
48
- context_foo_spy = nil
49
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
50
- configured_eval_context = eval_context
51
- context_foo_spy = Spy::Subroutine.new(configured_eval_context, :foo).hook(force: true)
52
- end
53
-
54
- obj.method_that_accepts_a_block do
55
- foo
56
- end
57
-
58
- expect(context_foo_spy).to have_been_called
59
- end
60
-
61
- it "fails when expectations set on the eval context are not met" do
62
- configured_eval_context = nil
63
- context_foo_spy = nil
64
- Spy.on(obj, :method_that_accepts_a_block).and_yield do |eval_context|
65
- configured_eval_context = eval_context
66
- context_foo_spy = Spy::Subroutine.new(configured_eval_context, :foo).hook(force: true)
67
- end
68
-
69
- obj.method_that_accepts_a_block do
70
- # foo is not called here
71
- end
72
-
73
- expect(context_foo_spy).to_not have_been_called
74
- end
75
-
76
- end
77
-
78
- context "and yielded arguments" do
79
-
80
- it "passes when expectations set on the eval context and yielded arguments are met" do
81
- configured_eval_context = nil
82
- yielded_arg = Object.new
83
- context_foo_spy = nil
84
- Spy.on(obj, :method_that_accepts_a_block).and_yield(yielded_arg) do |eval_context|
85
- configured_eval_context = eval_context
86
- context_foo_spy = Spy::Subroutine.new(configured_eval_context, :foo).hook(force: true)
87
- Spy::Subroutine.new(yielded_arg, :bar).hook(force: true)
88
- end
89
-
90
- obj.method_that_accepts_a_block do |obj|
91
- obj.bar
92
- foo
93
- end
94
-
95
- expect(context_foo_spy).to have_been_called
96
- expect(Spy.get(yielded_arg, :bar)).to have_been_called
97
- end
98
-
99
- it "fails when expectations set on the eval context and yielded arguments are not met" do
100
- configured_eval_context = nil
101
- yielded_arg = Object.new
102
- context_foo_spy = nil
103
- Spy.on(obj, :method_that_accepts_a_block).and_yield(yielded_arg) do |eval_context|
104
- configured_eval_context = eval_context
105
- context_foo_spy = Spy::Subroutine.new(configured_eval_context, :foo).hook(force: true)
106
- Spy::Subroutine.new(yielded_arg, :bar).hook(force: true)
107
- end
108
-
109
- obj.method_that_accepts_a_block do |obj|
110
- # obj.bar is not called here
111
- # foo is not called here
112
- end
113
-
114
- expect(context_foo_spy).to_not have_been_called
115
- expect(Spy.get(yielded_arg, :bar)).to_not have_been_called
116
- end
117
-
118
- end
119
-
120
- end
121
- end
122
- end
123
-