rspec-eventually 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.rubocop.yml +15 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +52 -0
- data/Rakefile +8 -0
- data/lib/rspec/eventually/version.rb +5 -0
- data/lib/rspec/eventually.rb +90 -0
- data/rspec-eventually.gemspec +25 -0
- data/spec/eventually_spec.rb +102 -0
- data/spec/spec_helper.rb +43 -0
- metadata +115 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 992247ed8e9a18a6a7e7f9f29c7a280f85a47661
|
4
|
+
data.tar.gz: e953bbb93dacf3c94e34b094c193323a44b49c82
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a71003af10bfc2782af1320b628c4bf3ed81af1ff9d2edf032b52fbcbbb9ab60f5e73522ceb25332748ea948e6bdf05a2cc7669291c3a81dd47c7f4ff555c1dc
|
7
|
+
data.tar.gz: 91de91764868bbbca2ccf45e2bd19c508d06ea0f6c1a54dcc8a304a50179720ca264cdba092920a4e7e5b19723bb307b131cf7a672e351accf45ba73518596fa
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
+
# on 2015-01-08 10:47:58 -0800 using RuboCop version 0.27.1.
|
3
|
+
# The point is for the user to remove these configuration records
|
4
|
+
# one by one as the offenses are removed from the code base.
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
6
|
+
#
|
7
|
+
Metrics/LineLength:
|
8
|
+
Max: 100
|
9
|
+
|
10
|
+
Style/Documentation:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Style/DotPosition:
|
14
|
+
Enabled: true
|
15
|
+
EnforcedStyle: trailing
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Hawk Newton
|
2
|
+
|
3
|
+
MIT License
|
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:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/hawknewton/rspec-eventually.svg?branch=master)](https://travis-ci.org/hawknewton/rspec-eventually)
|
2
|
+
# Rspec::Eventually
|
3
|
+
|
4
|
+
I want to be able to do something like this:
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
it 'eventually matches' do
|
8
|
+
value = 0
|
9
|
+
Thread.new do
|
10
|
+
sleep 1
|
11
|
+
value = 1
|
12
|
+
end
|
13
|
+
|
14
|
+
expect { value }.to eventually eq 1
|
15
|
+
expect { value }.to eventually_not eq 0
|
16
|
+
|
17
|
+
# Ignore errors raised by the block and retry
|
18
|
+
expect { client.get 'ABC' }.to eventually(eq 1).by_suppressing_errors
|
19
|
+
|
20
|
+
# Change the timeout
|
21
|
+
expect { client.get 'ZYX' }.to eventually(eq 1).within 5
|
22
|
+
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
## Installation
|
27
|
+
|
28
|
+
Add this line to your application's Gemfile:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
gem 'rspec-eventually'
|
32
|
+
```
|
33
|
+
|
34
|
+
And then execute:
|
35
|
+
|
36
|
+
$ bundle
|
37
|
+
|
38
|
+
Or install it yourself as:
|
39
|
+
|
40
|
+
$ gem install rspec-eventually
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
TODO: Write usage instructions here
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
|
48
|
+
1. Fork it ( https://github.com/[my-github-username]/rspec-eventually/fork )
|
49
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
50
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
51
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
52
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'rspec/eventually/version'
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
module Rspec
|
5
|
+
module Eventually
|
6
|
+
class << self
|
7
|
+
attr_accessor :timeout
|
8
|
+
end
|
9
|
+
self.timeout = 5
|
10
|
+
|
11
|
+
class FailedMatcherError < StandardError; end
|
12
|
+
|
13
|
+
class Eventually
|
14
|
+
def by_suppressing_errors
|
15
|
+
tap { @suppress_errors = true }
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(target)
|
19
|
+
@target = target
|
20
|
+
@tries = 0
|
21
|
+
@negative = false
|
22
|
+
end
|
23
|
+
|
24
|
+
def matches?(expected_block)
|
25
|
+
Timeout.timeout(timeout) { eventually_matches? expected_block }
|
26
|
+
rescue Timeout::Error
|
27
|
+
@tries == 0 && raise('Timeout before first evaluation, use a longer `eventually` timeout')
|
28
|
+
end
|
29
|
+
|
30
|
+
def does_not_match?
|
31
|
+
fail 'Use eventually_not instead of expect(...).to_not'
|
32
|
+
end
|
33
|
+
|
34
|
+
def failure_message
|
35
|
+
"After #{@tries} tries, the last failure message was:\n#{@target.failure_message}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def not
|
39
|
+
tap { @negative = true }
|
40
|
+
end
|
41
|
+
|
42
|
+
def supports_block_expectations?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def suppress_errors
|
47
|
+
@suppress_errors || false
|
48
|
+
end
|
49
|
+
|
50
|
+
def within(timeout)
|
51
|
+
tap { @timeout = timeout }
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def eventually_matches?(expected_block)
|
57
|
+
target_matches?(expected_block) || fail(FailedMatcherError)
|
58
|
+
rescue => e
|
59
|
+
if suppress_errors || e.is_a?(FailedMatcherError)
|
60
|
+
sleep 0.1
|
61
|
+
@tries += 1
|
62
|
+
retry
|
63
|
+
else
|
64
|
+
raise
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def target_matches?(expected_block)
|
69
|
+
result = @target.matches? expected_block.call
|
70
|
+
@negative ? !result : result
|
71
|
+
end
|
72
|
+
|
73
|
+
def timeout
|
74
|
+
@timeout || Rspec::Eventually.timeout
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def eventually(target)
|
79
|
+
Eventually.new target
|
80
|
+
end
|
81
|
+
|
82
|
+
def eventually_not(target)
|
83
|
+
Eventually.new(target).not
|
84
|
+
end
|
85
|
+
|
86
|
+
RSpec.configure do |config|
|
87
|
+
config.include ::Rspec::Eventually
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rspec/eventually/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rspec-eventually'
|
8
|
+
spec.version = Rspec::Eventually::VERSION
|
9
|
+
spec.authors = ['Hawk Newton']
|
10
|
+
spec.email = ['hawk.newton@gmail.com']
|
11
|
+
spec.summary = 'Make your matchers match eventually'
|
12
|
+
spec.description = 'Enhances rspec DSL to include `eventually` and `eventually_not`'
|
13
|
+
spec.homepage = 'https://github.com/hawknewton/rspec-eventually'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
|
+
spec.add_development_dependency 'rspec', '~> 3.2'
|
24
|
+
spec.add_development_dependency 'rubocop', '~> 0.27.1'
|
25
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Eventually
|
3
|
+
describe Eventually do
|
4
|
+
|
5
|
+
it 'eventually matches' do
|
6
|
+
value = 0
|
7
|
+
Thread.new do
|
8
|
+
sleep 0.5
|
9
|
+
value = 1
|
10
|
+
end
|
11
|
+
|
12
|
+
expect(Eventually.new(eq 1).matches? -> { value }).to be true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'eventually_not matches' do
|
16
|
+
value = 0
|
17
|
+
Thread.new do
|
18
|
+
sleep 0.5
|
19
|
+
value = 1
|
20
|
+
end
|
21
|
+
|
22
|
+
expect(Eventually.new(eq 0).not.matches? -> { value }).to be true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'eventually fails' do
|
26
|
+
expect(Eventually.new(eq 1).matches? -> { 0 }).to be false
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'eventually_not fails' do
|
30
|
+
expect(Eventually.new(eq 1).not.matches? -> { 1 }).to be false
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'has a configurable default timeout' do
|
34
|
+
begin
|
35
|
+
::Rspec::Eventually.timeout = 1
|
36
|
+
expect(::Rspec::Eventually.timeout).to eq 1
|
37
|
+
|
38
|
+
before = Time.now
|
39
|
+
Eventually.new(eq 1).matches? -> { 0 }
|
40
|
+
took = Time.now - before
|
41
|
+
expect(took).to be_within(0.5).of 1
|
42
|
+
ensure
|
43
|
+
::Rspec::Eventually.timeout = 5
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'can have a specific timeout' do
|
48
|
+
before = Time.now
|
49
|
+
Eventually.new(eq 1).within(0.5).matches? -> { 0 }
|
50
|
+
took = Time.now - before
|
51
|
+
expect(took).to be_within(0.1).of 0.5
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'raises errors by default' do
|
55
|
+
block = lambda do
|
56
|
+
Eventually.new(eq 1).matches? -> { fail 'I am throwing an error' }
|
57
|
+
end
|
58
|
+
|
59
|
+
expect { block.call }.to raise_error(/I am throwing an error/)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'can suppress errors' do
|
63
|
+
first = false
|
64
|
+
block = lambda do
|
65
|
+
|
66
|
+
one_eventually = lambda do
|
67
|
+
if first
|
68
|
+
first = false
|
69
|
+
fail 'I am throwing an error'
|
70
|
+
end
|
71
|
+
1
|
72
|
+
end
|
73
|
+
|
74
|
+
Eventually.new(eq 1).by_suppressing_errors.matches? one_eventually
|
75
|
+
end
|
76
|
+
|
77
|
+
expect { block.call }.to_not raise_error
|
78
|
+
expect(block.call).to be true
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'produces a coherent failure message' do
|
82
|
+
(matcher = Eventually.new(eq 1).within(0.5)).matches? -> { 0 }
|
83
|
+
message = matcher.failure_message
|
84
|
+
expect(message).to match(/After [0-9]+ tries, the last failure message was/)
|
85
|
+
expect(message).to match(/expected: 1/)
|
86
|
+
expect(message).to match(/got: 0/)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'raises an error when negated' do
|
90
|
+
expect { Eventually.new(eq 1).does_not_match? }.to raise_error(/Use eventually_not/)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'raises an error when timeout occurs before the first evaluation' do
|
94
|
+
block = lambda do
|
95
|
+
Eventually.new(eq 1).within(0.5).matches? -> { sleep 5 }
|
96
|
+
end
|
97
|
+
|
98
|
+
expect { block.call }.to raise_error(/Timeout before first evaluation/)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rspec/eventually'
|
2
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
3
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
4
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
5
|
+
# this file to always be loaded, without a need to explicitly require it in any
|
6
|
+
# files.
|
7
|
+
#
|
8
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
9
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
10
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
11
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
12
|
+
# a separate helper file that requires the additional dependencies and performs
|
13
|
+
# the additional setup, and require it from the spec files that actually need
|
14
|
+
# it.
|
15
|
+
#
|
16
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
17
|
+
# users commonly want.
|
18
|
+
#
|
19
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
20
|
+
RSpec.configure do |config|
|
21
|
+
# rspec-expectations config goes here. You can use an alternate
|
22
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
23
|
+
# assertions if you prefer.
|
24
|
+
config.expect_with :rspec do |expectations|
|
25
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
26
|
+
# and `failure_message` of custom matchers include text for helper methods
|
27
|
+
# defined using `chain`, e.g.:
|
28
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
29
|
+
# # => "be bigger than 2 and smaller than 4"
|
30
|
+
# ...rather than:
|
31
|
+
# # => "be bigger than 2"
|
32
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
33
|
+
end
|
34
|
+
|
35
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
36
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
37
|
+
config.mock_with :rspec do |mocks|
|
38
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
39
|
+
# a real object. This is generally recommended, and will default to
|
40
|
+
# `true` in RSpec 4.
|
41
|
+
mocks.verify_partial_doubles = true
|
42
|
+
end
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec-eventually
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hawk Newton
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.27.1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.27.1
|
69
|
+
description: Enhances rspec DSL to include `eventually` and `eventually_not`
|
70
|
+
email:
|
71
|
+
- hawk.newton@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".rubocop.yml"
|
79
|
+
- ".travis.yml"
|
80
|
+
- Gemfile
|
81
|
+
- LICENSE.txt
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- lib/rspec/eventually.rb
|
85
|
+
- lib/rspec/eventually/version.rb
|
86
|
+
- rspec-eventually.gemspec
|
87
|
+
- spec/eventually_spec.rb
|
88
|
+
- spec/spec_helper.rb
|
89
|
+
homepage: https://github.com/hawknewton/rspec-eventually
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.4.5
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Make your matchers match eventually
|
113
|
+
test_files:
|
114
|
+
- spec/eventually_spec.rb
|
115
|
+
- spec/spec_helper.rb
|