rspec-wait 0.0.8 → 1.0.0.rc1

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
- 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