rspec-wait 0.0.8 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cedad41775bb1aea029cd5e62f48d9e118f16762
4
- data.tar.gz: 7714b1b6a2542f4478432ee487ed07a4acdafe34
2
+ SHA256:
3
+ metadata.gz: f3063b52ebd279697ad6513ff3086284b4de74646b923b26eac4063eda6a230d
4
+ data.tar.gz: a1e2a15ea600566d77c946bb53662907885a1b5491ef1f17bb7735352340b03d
5
5
  SHA512:
6
- metadata.gz: ffbafc5d55897cf050e5ac748fe277baebd705c793c2acd72397eddcf7846207c2c350ca36ecfbc452e73586c64f2b73f87c6a236854643ab7fa6d865cd2ad99
7
- data.tar.gz: 82460c250ae79582f699f607f2a9263f6d901755450d953b1fda0d41482eff955d497974b8c6471dc39ee5f78656ae591968e95da248b4bf3f2ded5e8bbe545e
6
+ metadata.gz: 8c5675ecf53888f5e0a82de31a819be2e1ec2d051beade97169361344210dc067a4f9b84f8faf97f19b397d431fc6a215637fa5e3c7cf16e8830b5d81556c940
7
+ data.tar.gz: c0d8d730ead4d2dad8bbe3412c02357276b13734b2befe3c184aa5e62b1bedb680d66a561a76b99bb8c9debb1bc62f214591a2ddcd0d98cd346b585ab565a64f
data/LICENSE.txt CHANGED
@@ -1,22 +1,21 @@
1
- Copyright (c) 2014 Steve Richert
1
+ The MIT License (MIT)
2
2
 
3
- MIT License
3
+ Copyright (c) 2014 Steve Richert
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
12
11
 
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
15
14
 
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -2,11 +2,9 @@
2
2
 
3
3
  Wait for conditions in RSpec
4
4
 
5
- [![Gem Version](https://img.shields.io/gem/v/rspec-wait.svg?style=flat-square)](https://rubygems.org/gems/rspec-wait)
6
- [![Build Status](https://img.shields.io/travis/laserlemon/rspec-wait/master.svg?style=flat-square)](https://travis-ci.org/laserlemon/rspec-wait)
7
- [![Code Climate](https://img.shields.io/codeclimate/github/laserlemon/rspec-wait.svg?style=flat-square)](https://codeclimate.com/github/laserlemon/rspec-wait)
8
- [![Coverage Status](https://img.shields.io/codeclimate/coverage/github/laserlemon/rspec-wait.svg?style=flat-square)](https://codeclimate.com/github/laserlemon/rspec-wait)
9
- [![Dependency Status](https://img.shields.io/gemnasium/laserlemon/rspec-wait.svg?style=flat-square)](https://gemnasium.com/laserlemon/rspec-wait)
5
+ [![Gem Version](https://img.shields.io/gem/v/rspec-wait)](http://rubygems.org/gems/rspec-wait)
6
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/laserlemon/rspec-wait/rake.yml)](https://github.com/laserlemon/rspec-wait/actions/workflows/rake.yml)
7
+ [![License](https://img.shields.io/github/license/laserlemon/rspec-wait)](https://github.com/laserlemon/rspec-wait/blob/-/LICENSE.txt)
10
8
 
11
9
  ## Why does RSpec::Wait exist?
12
10
 
@@ -24,16 +22,15 @@ syntactic sugar that you already know and love.
24
22
 
25
23
  RSpec::Wait will keep trying until your assertion passes or times out.
26
24
 
27
- ### Example
25
+ ### Examples
28
26
 
29
27
  RSpec::Wait's `wait_for` assertions are nearly drop-in replacements for RSpec's
30
- `expect` assertions. The major difference is that the `wait_for` method only
31
- works with non-block matchers. However, `wait_for` will still accept a block
32
- because it may need to evaluate the content of that block multiple times while
33
- waiting.
28
+ `expect` assertions. The major difference is that the `wait_for` method
29
+ requires a block because it may need to evaluate the content of that block
30
+ multiple times while it's waiting.
34
31
 
35
32
  ```ruby
36
- describe Ticker do
33
+ RSpec.describe Ticker do
37
34
  subject(:ticker) { Ticker.new("foo") }
38
35
 
39
36
  describe "#start" do
@@ -41,21 +38,21 @@ describe Ticker do
41
38
  ticker.start
42
39
  end
43
40
 
44
- it "starts a blank tape" do
41
+ it "starts with a blank tape" do
45
42
  expect(ticker.tape).to eq("")
46
43
  end
47
44
 
48
- it "writes the message one letter at a time" do
49
- wait_for(ticker.tape).to eq("··-·")
50
- wait_for(ticker.tape).to eq("··-· ---")
51
- wait_for(ticker.tape).to eq("··-· --- ---")
45
+ it "sends the message in Morse code one letter at a time" do
46
+ wait_for { ticker.tape }.to eq("··-·")
47
+ wait_for { ticker.tape }.to eq("··-· ---")
48
+ wait_for { ticker.tape }.to eq("··-· --- ---")
52
49
  end
53
50
  end
54
51
  end
55
52
  ```
56
53
 
57
- This can be especially useful for testing user interfaces with tricky timing
58
- elements like JavaScript interactions or remote requests.
54
+ RSpec::Wait can be especially useful for testing user interfaces with tricky
55
+ timing elements like JavaScript interactions or remote requests.
59
56
 
60
57
  ```ruby
61
58
  feature "User Login" do
@@ -74,31 +71,104 @@ feature "User Login" do
74
71
  end
75
72
  ```
76
73
 
74
+ ## Compatibility
75
+
76
+ ### Ruby Support
77
+
78
+ RSpec::Wait is tested against all [non-EOL Ruby versions](https://www.ruby-lang.org/en/downloads/branches/),
79
+ which as of this writing are versions 3.1, 3.2, and 3.3. If you find that
80
+ RSpec::Wait does not work or [is not tested](https://github.com/laserlemon/rspec-wait/blob/-/.github/workflows/rake.yml)
81
+ for a maintained Ruby version, please [open an issue](https://github.com/laserlemon/rspec-wait/issues/new)
82
+ or pull request to add support.
83
+
84
+ Additionally, RSpec::Wait is tested against Ruby head to surface future
85
+ compatibility issues, but no guarantees are made that RSpec::Wait will
86
+ function as expected on Ruby head. Proceed with caution!
87
+
88
+ ### RSpec Support
89
+
90
+ RSpec::Wait is tested against several [versions of RSpec](https://rubygems.org/gems/rspec/versions),
91
+ which as of this writing are versions 3.4 through 3.13. If you find that
92
+ RSpec::Wait does not work or [is not tested](https://github.com/laserlemon/rspec-wait/blob/-/.github/workflows/rake.yml)
93
+ for a newer RSpec version, please [open an issue](https://github.com/laserlemon/rspec-wait/issues/new)
94
+ or pull request to add support.
95
+
96
+ Additionally, RSpec::Wait is tested against unbounded RSpec to surface future
97
+ compatibility issues, but no guarantees are made that RSpec::Wait will
98
+ function as expected on any RSpec version that's not explicitly [tested](https://github.com/laserlemon/rspec-wait/blob/-/.github/workflows/rake.yml).
99
+ Proceed with caution!
100
+
77
101
  ### Matchers
78
102
 
79
103
  RSpec::Wait ties into RSpec's internals so it can take full advantage of any
80
- non-block matcher that you would use with RSpec's own `expect` method.
104
+ matcher that you would use with RSpec's own `expect` method.
105
+
106
+ If you discover a matcher that works with `expect` but not with `wait_for`,
107
+ please [open an issue](https://github.com/laserlemon/rspec-wait/issues/new)
108
+ and I'd be happy to take a look!
109
+
110
+ ## Installation
111
+
112
+ To get started with RSpec::Wait, simply add the dependency to your `Gemfile`
113
+ and `bundle install`:
114
+
115
+ ```ruby
116
+ gem "rspec-wait", "~> 1.0"
117
+ ```
118
+
119
+ If your codebase calls `Bundler.require` at boot time, you're all set and the
120
+ `wait_for` method is already available in your RSpec suite.
121
+
122
+ If you encounter the following error:
123
+
124
+ ```
125
+ NoMethodError:
126
+ undefined method `wait_for'
127
+ ```
128
+
129
+ You will need to explicitly require RSpec::Wait at boot time in your test
130
+ environment:
131
+
132
+ ```ruby
133
+ require "rspec/wait"
134
+ ```
135
+
136
+ ## Configuration
81
137
 
82
- ### Timeout
138
+ RSpec::Wait has three available configuration values:
83
139
 
84
- By default, RSpec::Wait will wait up to 10 seconds for an assertion to pass.
85
- That timeout value is configurable in three ways:
140
+ - `wait_timeout` - The maximum amount of time (in seconds) that RSpec::Wait
141
+ will continue to retry a failing assertion. Default: `10.0`
142
+ - `wait_delay` - How long (in seconds) RSpec::Wait will pause between retries.
143
+ Default: `0.1`
144
+ - `clone_wait_matcher` - Whether each retry will `clone` the given RSpec
145
+ matcher instance for each evaluation. Set to `true` if you have trouble with
146
+ a matcher holding onto stale state. Default: `false`
86
147
 
87
- #### RSpec Configuration
148
+ RSpec::Wait configurations can be set in three ways:
149
+
150
+ - Globally via `RSpec.configure`
151
+ - Per example or context via RSpec metadata
152
+ - Per assertion via the `wait` method
153
+
154
+ ### Global Configuration
88
155
 
89
156
  ```ruby
90
157
  RSpec.configure do |config|
91
158
  config.wait_timeout = 3 # seconds
159
+ config.wait_delay = 0.5 # seconds
160
+ config.clone_wait_matcher = true
92
161
  end
93
162
  ```
94
163
 
95
- #### RSpec Metadata
164
+ ### RSpec Metadata
96
165
 
97
- The timeout can also be specified via options added to a spec's or context's
98
- `:wait` metadata:
166
+ Any of RSpec::Wait's three configurations can be set on a per-example or
167
+ per-context basis using `wait` metadata. Provide a hash containing any
168
+ number of shorthand keys and values for RSpec::Wait's configurations.
99
169
 
100
170
  ```ruby
101
- scenario "A user can log in successfully", wait: { timeout: 3 } do
171
+ scenario "A user can log in successfully", wait: { timeout: 3, delay: 0.5, clone_wait_matcher: true } do
102
172
  visit new_session_path
103
173
 
104
174
  fill_in "Email", with: "john@example.com"
@@ -110,9 +180,12 @@ scenario "A user can log in successfully", wait: { timeout: 3 } do
110
180
  end
111
181
  ```
112
182
 
113
- #### The `wait` Method
183
+ ### The `wait` Method
114
184
 
115
- On a per-assertion basis, the timeout value can be passed to the `wait` method.
185
+ And on a per-assertion basis, the `wait` method accepts a hash of shorthand
186
+ keys and values for RSpec::Wait's configurations. The `wait` method must be
187
+ chained to the `for` method and aside from the ability to set RSpec::Wait
188
+ configuration for the single assertion, it behaves identically to `wait_for`.
116
189
 
117
190
  ```ruby
118
191
  scenario "A user can log in successfully" do
@@ -122,12 +195,47 @@ scenario "A user can log in successfully" do
122
195
  fill_in "Password", with: "secret"
123
196
  click_button "Log In"
124
197
 
125
- wait(3.seconds).for { current_path }.to eq(account_path)
198
+ wait(timeout: 3).for { current_path }.to eq(account_path)
126
199
  expect(page).to have_content("Welcome back!")
127
200
  end
128
201
  ```
129
202
 
130
- ### Use with Cucumber
203
+ The `wait` method will also accept `timeout` as a positional argument for
204
+ improved readability:
205
+
206
+ ```ruby
207
+ wait(3.seconds).for { current_path }.to eq(account_path)
208
+ ```
209
+
210
+ ## Use with RuboCop
211
+
212
+ If you use `rubocop` and `rubocop-rspec` in your codebase, an RSpec example
213
+ with a single `wait_for` assertion may cause RuboCop to complain:
214
+
215
+ ```
216
+ RSpec/NoExpectationExample: No expectation found in this example.
217
+ ```
218
+
219
+ By default, RuboCop sees only `expect*` and `assert*` methods as expectations.
220
+ You can configure RuboCop to recognize `wait_for` and `wait.for` as
221
+ expectations (in addition to the defaults) in your RuboCop configuration:
222
+
223
+ ```yaml
224
+ RSpec/NoExpectationExample:
225
+ AllowedPatterns:
226
+ - ^assert_
227
+ - ^expect_
228
+ - ^wait(_for)?$
229
+ ```
230
+
231
+ Of course, you can always disable this cop entirely:
232
+
233
+ ```yaml
234
+ RSpec/NoExpectationExample:
235
+ Enabled: false
236
+ ```
237
+
238
+ ## Use with Cucumber
131
239
 
132
240
  To enable RSpec::Wait in your Cucumber step definitions, add the following to
133
241
  `features/support/env.rb`:
@@ -147,7 +255,7 @@ and [contribution](https://github.com/laserlemon/rspec-wait/graphs/contributors)
147
255
  from the Ruby community, especially the [authors and maintainers](https://github.com/rspec/rspec-core/graphs/contributors)
148
256
  of RSpec.
149
257
 
150
- **Thank you!**
258
+ **Thank you!** :yellow_heart:
151
259
 
152
260
  ## How can I help?
153
261
 
@@ -156,3 +264,6 @@ No contribution is too small.
156
264
 
157
265
  See RSpec::Wait's [contribution guidelines](CONTRIBUTING.md) for more
158
266
  information.
267
+
268
+ If you're enjoying RSpec::Wait, please consider [sponsoring](https://github.com/sponsors/laserlemon)
269
+ my [open source work](https://github.com/laserlemon)! :green_heart:
@@ -1,34 +1,42 @@
1
- require "timeout"
1
+ # frozen_string_literal: true
2
2
 
3
3
  module RSpec
4
4
  module Wait
5
+ # The RSpec::Wait::Handler module is common functionality shared between
6
+ # the RSpec::Wait::PositiveHandler and RSpec::Wait::NegativeHandler classes
7
+ # defined below. The module overrides RSpec's handle_matcher method,
8
+ # allowing a block target to be repeatedly evaluated until the underlying
9
+ # matcher passes or the configured timeout elapses.
5
10
  module Handler
6
- def handle_matcher(target, *args, &block)
7
- failure = nil
11
+ def handle_matcher(target, initial_matcher, message, &block)
12
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
8
13
 
9
- Timeout.timeout(RSpec.configuration.wait_timeout) do
10
- loop do
11
- begin
12
- actual = target.respond_to?(:call) ? target.call : target
13
- super(actual, *args, &block)
14
- break
15
- rescue RSpec::Expectations::ExpectationNotMetError => failure
16
- sleep RSpec.configuration.wait_delay
17
- retry
18
- end
14
+ begin
15
+ matcher = RSpec.configuration.clone_wait_matcher ? initial_matcher.clone : initial_matcher
16
+
17
+ if matcher.supports_block_expectations?
18
+ super(target, matcher, message, &block)
19
+ else
20
+ super(target.call, matcher, message, &block)
19
21
  end
22
+ rescue RSpec::Expectations::ExpectationNotMetError
23
+ raise if RSpec.world.wants_to_quit
24
+
25
+ elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
26
+ raise if elapsed_time > RSpec.configuration.wait_timeout
27
+
28
+ sleep RSpec.configuration.wait_delay
29
+ retry
20
30
  end
21
- rescue Timeout::Error
22
- raise failure || TimeoutError
23
31
  end
24
32
  end
25
33
 
26
- # From: https://github.com/rspec/rspec-expectations/blob/v3.0.0/lib/rspec/expectations/handler.rb#L44-L63
34
+ # From: https://github.com/rspec/rspec-expectations/blob/v3.4.0/lib/rspec/expectations/handler.rb#L46-L65
27
35
  class PositiveHandler < RSpec::Expectations::PositiveExpectationHandler
28
36
  extend Handler
29
37
  end
30
38
 
31
- # From: https://github.com/rspec/rspec-expectations/blob/v3.0.0/lib/rspec/expectations/handler.rb#L66-L93
39
+ # From: https://github.com/rspec/rspec-expectations/blob/v3.4.0/lib/rspec/expectations/handler.rb#L68-L95
32
40
  class NegativeHandler < RSpec::Expectations::NegativeExpectationHandler
33
41
  extend Handler
34
42
  end
@@ -1,12 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RSpec
2
4
  module Wait
5
+ # The RSpec::Wait::Proxy class is capable of creating a small container
6
+ # object for RSpec::Wait options, returned by the top-level wait method,
7
+ # which allows chaining wait and for methods for more expectations that
8
+ # read more naturally, like:
9
+ #
10
+ # wait(3.seconds).for { this }.to eq(that)
11
+ #
3
12
  class Proxy
4
- def initialize(options)
13
+ def initialize(**options)
5
14
  @options = options
6
15
  end
7
16
 
8
- def for(value = Target::UndefinedValue, &block)
9
- Target.for(value, block, @options)
17
+ def for(*args, &block)
18
+ raise ArgumentError, "The `wait.for` method only accepts a block." if args.any?
19
+ raise ArgumentError, "The `wait.for` method requires a block." unless block
20
+
21
+ Target.new(block, @options)
10
22
  end
11
23
  end
12
24
  end
@@ -1,47 +1,41 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RSpec
2
4
  module Wait
5
+ # The RSpec::Wait::Target class inherits from RSpec's internal
6
+ # RSpec::Expectations::ExpectationTarget class and allows the inclusion of
7
+ # RSpec::Wait options via RSpec::Wait::Proxy.
3
8
  class Target < RSpec::Expectations::ExpectationTarget
4
- # From: https://github.com/rspec/rspec-expectations/blob/v3.0.0/lib/rspec/expectations/expectation_target.rb#L22
5
- UndefinedValue = Module.new
6
-
7
- # From: https://github.com/rspec/rspec-expectations/blob/v3.0.0/lib/rspec/expectations/expectation_target.rb#L30-L41
8
- def self.for(value, block, options = {})
9
- if UndefinedValue.equal?(value)
10
- unless block
11
- raise ArgumentError, "You must pass either an argument or a block to `wait_for`."
12
- end
13
- new(block, options)
14
- elsif block
15
- raise ArgumentError, "You cannot pass both an argument and a block to `wait_for`."
16
- else
17
- new(value, options)
18
- end
19
- end
20
-
21
- # From: https://github.com/rspec/rspec-expectations/blob/v3.0.0/lib/rspec/expectations/expectation_target.rb#L25-L27
22
- def initialize(target, options)
9
+ # From: https://github.com/rspec/rspec-expectations/blob/v3.4.0/lib/rspec/expectations/expectation_target.rb#L25-L27
10
+ def initialize(block, options = {})
23
11
  @wait_options = options
24
- super(target)
12
+ super(block)
25
13
  end
26
14
 
27
- # From: https://github.com/rspec/rspec-expectations/blob/v3.0.0/lib/rspec/expectations/expectation_target.rb#L53-L54
15
+ # From: https://github.com/rspec/rspec-expectations/blob/v3.4.0/lib/rspec/expectations/expectation_target.rb#L52-L55
28
16
  def to(matcher = nil, message = nil, &block)
29
- prevent_operator_matchers(:to, matcher) unless matcher
30
- with_wait { PositiveHandler.handle_matcher(@target, matcher, message, &block) }
17
+ prevent_operator_matchers(:to) unless matcher
18
+
19
+ with_wait do
20
+ PositiveHandler.handle_matcher(@target, matcher, message, &block)
21
+ end
31
22
  end
32
23
 
33
- # From: https://github.com/rspec/rspec-expectations/blob/v3.0.0/lib/rspec/expectations/expectation_target.rb#L66-L67
24
+ # From: https://github.com/rspec/rspec-expectations/blob/v3.4.0/lib/rspec/expectations/expectation_target.rb#L65-L68
34
25
  def not_to(matcher = nil, message = nil, &block)
35
- prevent_operator_matchers(:not_to, matcher) unless matcher
36
- with_wait { NegativeHandler.handle_matcher(@target, matcher, message, &block) }
26
+ prevent_operator_matchers(:not_to) unless matcher
27
+
28
+ with_wait do
29
+ NegativeHandler.handle_matcher(@target, matcher, message, &block)
30
+ end
37
31
  end
38
32
 
39
- alias_method :to_not, :not_to
33
+ alias to_not not_to
40
34
 
41
35
  private
42
36
 
43
- def with_wait
44
- Wait.with_wait(@wait_options) { yield }
37
+ def with_wait(&block)
38
+ Wait.with_wait(**@wait_options, &block)
45
39
  end
46
40
  end
47
41
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Wait
5
+ VERSION = ::Gem::Version.new("1.0.0.rc1")
6
+ end
7
+ end
data/lib/rspec/wait.rb CHANGED
@@ -1,34 +1,48 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rspec"
2
- require "rspec/wait/error"
3
- require "rspec/wait/handler"
4
- require "rspec/wait/proxy"
5
- require "rspec/wait/target"
4
+
5
+ require_relative "wait/handler"
6
+ require_relative "wait/proxy"
7
+ require_relative "wait/target"
8
+ require_relative "wait/version"
6
9
 
7
10
  module RSpec
11
+ # The RSpec::Wait module is included into RSpec's example environment, making
12
+ # the wait_for, wait, and with_wait methods available inside each spec.
8
13
  module Wait
14
+ DEFAULT_TIMEOUT = 10.0
15
+ DEFAULT_DELAY = 0.1
16
+ DEFAULT_CLONE_MATCHER = false
17
+
9
18
  module_function
10
19
 
11
- # From: https://github.com/rspec/rspec-expectations/blob/v3.0.0/lib/rspec/expectations/syntax.rb#L72-L74
12
- def wait_for(value = Target::UndefinedValue, &block)
13
- Target.for(value, block)
20
+ # From: https://github.com/rspec/rspec-expectations/blob/v3.4.0/lib/rspec/expectations/syntax.rb#L72-L74
21
+ def wait_for(*args, &block)
22
+ raise ArgumentError, "The `wait_for` method only accepts a block." if args.any?
23
+ raise ArgumentError, "The `wait_for` method requires a block." unless block
24
+
25
+ Target.new(block)
14
26
  end
15
27
 
16
- def wait(timeout = nil, options = {})
17
- options[:timeout] = timeout
18
- Proxy.new(options)
28
+ def wait(arg = nil, timeout: arg, delay: nil, clone_matcher: nil)
29
+ Proxy.new(timeout: timeout, delay: delay, clone_matcher: clone_matcher)
19
30
  end
20
31
 
21
- def with_wait(options)
32
+ def with_wait(timeout: nil, delay: nil, clone_matcher: nil)
22
33
  original_timeout = RSpec.configuration.wait_timeout
23
34
  original_delay = RSpec.configuration.wait_delay
35
+ original_clone_matcher = RSpec.configuration.clone_wait_matcher
24
36
 
25
- RSpec.configuration.wait_timeout = options[:timeout] if options[:timeout]
26
- RSpec.configuration.wait_delay = options[:delay] if options[:delay]
37
+ RSpec.configuration.wait_timeout = timeout unless timeout.nil?
38
+ RSpec.configuration.wait_delay = delay unless delay.nil?
39
+ RSpec.configuration.clone_wait_matcher = clone_matcher unless clone_matcher.nil?
27
40
 
28
41
  yield
29
42
  ensure
30
43
  RSpec.configuration.wait_timeout = original_timeout
31
44
  RSpec.configuration.wait_delay = original_delay
45
+ RSpec.configuration.clone_wait_matcher = original_clone_matcher
32
46
  end
33
47
  end
34
48
  end
@@ -36,14 +50,12 @@ end
36
50
  RSpec.configure do |config|
37
51
  config.include(RSpec::Wait)
38
52
 
39
- config.add_setting(:wait_timeout, default: 10)
40
- config.add_setting(:wait_delay, default: 0.1)
53
+ config.add_setting(:wait_timeout, default: RSpec::Wait::DEFAULT_TIMEOUT)
54
+ config.add_setting(:wait_delay, default: RSpec::Wait::DEFAULT_DELAY)
55
+ config.add_setting(:clone_wait_matcher, default: RSpec::Wait::DEFAULT_CLONE_MATCHER)
41
56
 
42
- config.around do |example|
43
- if options = example.metadata[:wait]
44
- with_wait(options) { example.run }
45
- else
46
- example.run
47
- end
57
+ config.around(wait: {}) do |example|
58
+ options = example.metadata.fetch(:wait)
59
+ with_wait(**options) { example.run }
48
60
  end
49
61
  end
data/lib/rspec-wait.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rspec/wait"
data/rspec-wait.gemspec CHANGED
@@ -1,21 +1,37 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rspec/wait/version"
2
4
 
3
5
  Gem::Specification.new do |spec|
4
- spec.name = "rspec-wait"
5
- spec.version = "0.0.8"
6
+ spec.name = "rspec-wait"
7
+ spec.summary = "Wait for conditions in RSpec"
8
+ spec.description = "RSpec::Wait enables time-resilient expectations in your RSpec test suite."
9
+ spec.version = RSpec::Wait::VERSION
10
+
11
+ spec.author = "Steve Richert"
12
+ spec.email = "steve.richert@hey.com"
13
+ spec.license = "MIT"
14
+ spec.homepage = "https://github.com/laserlemon/rspec-wait"
6
15
 
7
- spec.author = "Steve Richert"
8
- spec.email = "steve.richert@gmail.com"
9
- spec.summary = "Wait for conditions in RSpec"
10
- spec.description = spec.summary
11
- spec.homepage = "https://github.com/laserlemon/rspec-wait"
12
- spec.license = "MIT"
16
+ spec.metadata = {
17
+ "allowed_push_host" => "https://rubygems.org",
18
+ "bug_tracker_uri" => "https://github.com/laserlemon/rspec-wait/issues",
19
+ "funding_uri" => "https://github.com/sponsors/laserlemon",
20
+ "homepage_uri" => "https://github.com/laserlemon/rspec-wait",
21
+ "rubygems_mfa_required" => "true",
22
+ "source_code_uri" => "https://github.com/laserlemon/rspec-wait",
23
+ }
13
24
 
14
- spec.files = `git ls-files -z`.split("\x0")
15
- spec.test_files = spec.files.grep(/^spec/)
25
+ spec.required_ruby_version = ">= 3.0"
26
+ spec.add_dependency "rspec", ">= 3.4"
27
+ spec.add_development_dependency "bundler", ">= 2.0"
28
+ spec.add_development_dependency "rake", ">= 13.0"
16
29
 
17
- spec.add_dependency "rspec", ">= 2.11", "< 3.5"
30
+ spec.files = Dir.glob([
31
+ "rspec-wait.gemspec",
32
+ "lib/**/*.rb",
33
+ "LICENSE.txt",
34
+ ])
18
35
 
19
- spec.add_development_dependency "bundler", "~> 1.10"
20
- spec.add_development_dependency "rake", "~> 10.4"
36
+ spec.extra_rdoc_files = ["README.md"]
21
37
  end