rspec-collection_matchers 0.0.1.pre → 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 +16 -15
- data/.rspec +2 -0
- data/.travis.yml +17 -0
- data/Gemfile +15 -1
- data/LICENSE.txt +7 -2
- data/README.md +49 -11
- data/Rakefile +18 -1
- data/features/have.feature +113 -0
- data/features/support/env.rb +21 -0
- data/lib/rspec/collection_matchers.rb +3 -0
- data/lib/rspec/collection_matchers/have.rb +122 -0
- data/lib/rspec/collection_matchers/matchers.rb +62 -0
- data/lib/rspec/collection_matchers/version.rb +5 -0
- data/rspec-collection_matchers.gemspec +19 -14
- data/script/test_all +21 -0
- data/spec/rspec/collection_matchers/have_spec.rb +487 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/classes.rb +56 -0
- data/spec/support/matchers.rb +23 -0
- data/spec/support/shared_examples.rb +12 -0
- metadata +66 -21
- data/lib/rspec-collection_matchers.rb +0 -7
- data/lib/rspec-collection_matchers/version.rb +0 -5
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1bd9e9e6cead5be254467961d97df52cfdae0316
|
4
|
+
data.tar.gz: e36762e51754850cbec1da1f81cc3d0237187dfa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e32cdb9c067ada99bdf5357a7aab08fe0ab014db5c54821ea53da740ed5764aec7db13ae2bdace551855f7b0854945642240c1f6fbe77cbff6a1853956414187
|
7
|
+
data.tar.gz: 0a0934bac819f8a0b17031de14c0d56e43e77dd25ba77fc0b371f9d053560530d0b5f195115837a3a83151a58557b188aab5a1e4705caaed850d727b44d6cb22
|
data/.gitignore
CHANGED
@@ -1,17 +1,18 @@
|
|
1
|
-
*.
|
2
|
-
|
3
|
-
|
4
|
-
.config
|
5
|
-
.yardoc
|
6
|
-
Gemfile.lock
|
7
|
-
InstalledFiles
|
8
|
-
_yardoc
|
9
|
-
coverage
|
10
|
-
doc/
|
11
|
-
lib/bundler/man
|
12
|
-
pkg
|
1
|
+
*.sw?
|
2
|
+
.DS_Store
|
3
|
+
coverage*
|
13
4
|
rdoc
|
14
|
-
|
15
|
-
|
16
|
-
test/version_tmp
|
5
|
+
pkg
|
6
|
+
doc
|
17
7
|
tmp
|
8
|
+
rerun.txt
|
9
|
+
Gemfile.lock
|
10
|
+
.bundle
|
11
|
+
*.rbc
|
12
|
+
.yardoc
|
13
|
+
bin
|
14
|
+
.rbx
|
15
|
+
Gemfile-custom
|
16
|
+
bundle
|
17
|
+
.rspec-local
|
18
|
+
Guardfile
|
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
language: ruby
|
2
|
+
script: "script/test_all"
|
3
|
+
bundler_args: "--standalone --binstubs --without documentation"
|
4
|
+
rvm:
|
5
|
+
- 1.8.7
|
6
|
+
- 1.9.2
|
7
|
+
- 1.9.3
|
8
|
+
- ree
|
9
|
+
- jruby-18mode
|
10
|
+
- jruby-19mode
|
11
|
+
- rbx-18mode
|
12
|
+
- rbx-19mode
|
13
|
+
- 2.0.0
|
14
|
+
matrix:
|
15
|
+
allow_failures:
|
16
|
+
- rvm: rbx-19mode
|
17
|
+
- rvm: rbx-18mode
|
data/Gemfile
CHANGED
@@ -1,4 +1,18 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in rspec-collection_matchers.gemspec
|
4
3
|
gemspec
|
4
|
+
|
5
|
+
%w[rspec rspec-core rspec-expectations rspec-mocks].each do |lib|
|
6
|
+
library_path = File.expand_path("../../#{lib}", __FILE__)
|
7
|
+
if File.exist?(library_path)
|
8
|
+
gem lib, :path => library_path
|
9
|
+
else
|
10
|
+
gem lib, :git => "git://github.com/rspec/#{lib}.git", :branch => "2-99-maintenance"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
gem "cucumber", "~> 1.1.9"
|
15
|
+
gem "aruba", "~> 0.5"
|
16
|
+
gem "rake", "~> 10.0.0"
|
17
|
+
|
18
|
+
eval File.read('Gemfile-custom') if File.exist?('Gemfile-custom')
|
data/LICENSE.txt
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Hugo Barauna
|
4
|
+
Copyright (c) 2012 David Chelimsky, Myron Marston
|
5
|
+
Copyright (c) 2006 David Chelimsky, The RSpec Development Team
|
6
|
+
Copyright (c) 2005 Steven Baker
|
2
7
|
|
3
8
|
MIT License
|
4
9
|
|
@@ -19,4 +24,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
24
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
25
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
26
|
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.
|
27
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# RSpec::CollectionMatchers [![Build Status](https://secure.travis-ci.org/rspec/rspec-collection_matchers.png?branch=master)](http://travis-ci.org/rspec/rspec-collection_matchers)
|
2
2
|
|
3
|
-
|
3
|
+
RSpec::CollectionMatchers lets you express expected outcomes on collections
|
4
|
+
of an object in an example.
|
4
5
|
|
5
|
-
|
6
|
+
expect(account.shopping_cart).to have_exactly(3).items
|
7
|
+
|
8
|
+
## Install
|
6
9
|
|
7
10
|
Add this line to your application's Gemfile:
|
8
11
|
|
@@ -16,14 +19,49 @@ Or install it yourself as:
|
|
16
19
|
|
17
20
|
$ gem install rspec-collection_matchers
|
18
21
|
|
19
|
-
##
|
22
|
+
## Basic usage
|
23
|
+
|
24
|
+
Using `rspec-collection_matchers` you can match the number of items in a
|
25
|
+
collection directly, e.g.:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
it 'matches number of items in a collection' do
|
29
|
+
expect([1,2,3]).to have_at_least(3).items
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
You can also match the number of items returned by a method on an object, e.g.:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
class Cart
|
37
|
+
def initialize(*products)
|
38
|
+
@products = products
|
39
|
+
end
|
40
|
+
attr_reader :products
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'matches number of items returned from a method' do
|
44
|
+
cart = Cart.new('product a', 'product b')
|
45
|
+
expect(cart).to have_at_most(2).products
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
The last line of the example expresses an expected outcome:
|
50
|
+
if `cart.products.size <= 2` then the example passes, otherwise it fails with a message like:
|
51
|
+
|
52
|
+
expected at most 2 products, got 3
|
53
|
+
|
54
|
+
## Available matchers
|
20
55
|
|
21
|
-
|
56
|
+
```ruby
|
57
|
+
expect(collection).to have(n).items
|
58
|
+
expect(collection).to have_exactly(n).items
|
59
|
+
expect(collection).to have_at_most(n).items
|
60
|
+
expect(collection).to have_at_least(n).items
|
61
|
+
```
|
22
62
|
|
23
|
-
##
|
63
|
+
## See also
|
24
64
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
65
|
+
* [http://github.com/rspec/rspec](http://github.com/rspec/rspec)
|
66
|
+
* [http://github.com/rspec/rspec-core](http://github.com/rspec/rspec-core)
|
67
|
+
* [http://github.com/rspec/rspec-expectations](http://github.com/rspec/rspec-expectations)
|
data/Rakefile
CHANGED
@@ -1 +1,18 @@
|
|
1
|
-
require "bundler
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup
|
3
|
+
Bundler::GemHelper.install_tasks
|
4
|
+
|
5
|
+
require "rake"
|
6
|
+
|
7
|
+
require "rspec/core/rake_task"
|
8
|
+
require "rspec/core/version"
|
9
|
+
|
10
|
+
require "cucumber/rake/task"
|
11
|
+
Cucumber::Rake::Task.new(:cucumber)
|
12
|
+
|
13
|
+
desc "Run all examples"
|
14
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
15
|
+
t.ruby_opts = %w[-w]
|
16
|
+
end
|
17
|
+
|
18
|
+
task :default => [:spec, :cucumber]
|
@@ -0,0 +1,113 @@
|
|
1
|
+
Feature: have(n).items matcher
|
2
|
+
|
3
|
+
RSpec provides several matchers that make it easy to set expectations about the
|
4
|
+
size of a collection. There are three basic forms:
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
collection.should have(x).items
|
8
|
+
collection.should have_at_least(x).items
|
9
|
+
collection.should have_at_most(x).items
|
10
|
+
```
|
11
|
+
|
12
|
+
In addition, #have_exactly is provided as an alias to #have.
|
13
|
+
|
14
|
+
These work on any collection-like object--the object just needs to respond to #size
|
15
|
+
or #length (or both). When the matcher is called directly on a collection object,
|
16
|
+
the #items call is pure syntactic sugar. You can use anything you want here. These
|
17
|
+
are equivalent:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
collection.should have(x).items
|
21
|
+
collection.should have(x).things
|
22
|
+
```
|
23
|
+
|
24
|
+
You can also use this matcher on a non-collection object that returns a collection
|
25
|
+
from one of its methods. For example, Dir#entries returns an array, so you could
|
26
|
+
set an expectation using the following:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
Dir.new("my/directory").should have(7).entries
|
30
|
+
```
|
31
|
+
|
32
|
+
Scenario: have(x).items on a collection
|
33
|
+
Given a file named "have_items_spec.rb" with:
|
34
|
+
"""ruby
|
35
|
+
require 'rspec/collection_matchers'
|
36
|
+
|
37
|
+
describe [1, 2, 3] do
|
38
|
+
it { should have(3).items }
|
39
|
+
it { should_not have(2).items }
|
40
|
+
it { should_not have(4).items }
|
41
|
+
|
42
|
+
it { should have_exactly(3).items }
|
43
|
+
it { should_not have_exactly(2).items }
|
44
|
+
it { should_not have_exactly(4).items }
|
45
|
+
|
46
|
+
it { should have_at_least(2).items }
|
47
|
+
it { should have_at_most(4).items }
|
48
|
+
|
49
|
+
# deliberate failures
|
50
|
+
it { should_not have(3).items }
|
51
|
+
it { should have(2).items }
|
52
|
+
it { should have(4).items }
|
53
|
+
|
54
|
+
it { should_not have_exactly(3).items }
|
55
|
+
it { should have_exactly(2).items }
|
56
|
+
it { should have_exactly(4).items }
|
57
|
+
|
58
|
+
it { should have_at_least(4).items }
|
59
|
+
it { should have_at_most(2).items }
|
60
|
+
end
|
61
|
+
"""
|
62
|
+
When I run `rspec have_items_spec.rb`
|
63
|
+
Then the output should contain "16 examples, 8 failures"
|
64
|
+
And the output should contain "expected target not to have 3 items, got 3"
|
65
|
+
And the output should contain "expected 2 items, got 3"
|
66
|
+
And the output should contain "expected 4 items, got 3"
|
67
|
+
And the output should contain "expected at least 4 items, got 3"
|
68
|
+
And the output should contain "expected at most 2 items, got 3"
|
69
|
+
|
70
|
+
Scenario: have(x).words on a String when String#words is defined
|
71
|
+
Given a file named "have_words_spec.rb" with:
|
72
|
+
"""ruby
|
73
|
+
require 'rspec/collection_matchers'
|
74
|
+
|
75
|
+
class String
|
76
|
+
def words
|
77
|
+
split(' ')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "a sentence with some words" do
|
82
|
+
it { should have(5).words }
|
83
|
+
it { should_not have(4).words }
|
84
|
+
it { should_not have(6).words }
|
85
|
+
|
86
|
+
it { should have_exactly(5).words }
|
87
|
+
it { should_not have_exactly(4).words }
|
88
|
+
it { should_not have_exactly(6).words }
|
89
|
+
|
90
|
+
it { should have_at_least(4).words }
|
91
|
+
it { should have_at_most(6).words }
|
92
|
+
|
93
|
+
# deliberate failures
|
94
|
+
it { should_not have(5).words }
|
95
|
+
it { should have(4).words }
|
96
|
+
it { should have(6).words }
|
97
|
+
|
98
|
+
it { should_not have_exactly(5).words }
|
99
|
+
it { should have_exactly(4).words }
|
100
|
+
it { should have_exactly(6).words }
|
101
|
+
|
102
|
+
it { should have_at_least(6).words }
|
103
|
+
it { should have_at_most(4).words }
|
104
|
+
end
|
105
|
+
"""
|
106
|
+
When I run `rspec have_words_spec.rb`
|
107
|
+
Then the output should contain "16 examples, 8 failures"
|
108
|
+
And the output should contain "expected target not to have 5 words, got 5"
|
109
|
+
And the output should contain "expected 4 words, got 5"
|
110
|
+
And the output should contain "expected 6 words, got 5"
|
111
|
+
And the output should contain "expected at least 6 words, got 5"
|
112
|
+
And the output should contain "expected at most 4 words, got 5"
|
113
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'aruba/cucumber'
|
2
|
+
|
3
|
+
Before do
|
4
|
+
if RUBY_PLATFORM =~ /java/
|
5
|
+
@aruba_timeout_seconds = 30
|
6
|
+
else
|
7
|
+
@aruba_timeout_seconds = 10
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Aruba.configure do |config|
|
12
|
+
config.before_cmd do |cmd|
|
13
|
+
set_env('JRUBY_OPTS', "-X-C #{ENV['JRUBY_OPTS']}") # disable JIT since these processes are so short lived
|
14
|
+
end
|
15
|
+
end if RUBY_PLATFORM == 'java'
|
16
|
+
|
17
|
+
Aruba.configure do |config|
|
18
|
+
config.before_cmd do |cmd|
|
19
|
+
set_env('RBXOPT', "-Xint=true #{ENV['RBXOPT']}") # disable JIT since these processes are so short lived
|
20
|
+
end
|
21
|
+
end if defined?(Rubinius)
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module RSpec
|
2
|
+
module CollectionMatchers
|
3
|
+
class Have
|
4
|
+
QUERY_METHODS = [:size, :length, :count].freeze
|
5
|
+
|
6
|
+
def initialize(expected, relativity=:exactly)
|
7
|
+
@expected = case expected
|
8
|
+
when :no then 0
|
9
|
+
when String then expected.to_i
|
10
|
+
else expected
|
11
|
+
end
|
12
|
+
@relativity = relativity
|
13
|
+
@actual = @collection_name = @plural_collection_name = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def relativities
|
17
|
+
@relativities ||= {
|
18
|
+
:exactly => "",
|
19
|
+
:at_least => "at least ",
|
20
|
+
:at_most => "at most "
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def matches?(collection_or_owner)
|
25
|
+
collection = determine_collection(collection_or_owner)
|
26
|
+
case collection
|
27
|
+
when enumerator_class
|
28
|
+
for query_method in QUERY_METHODS
|
29
|
+
next unless collection.respond_to?(query_method)
|
30
|
+
@actual = collection.__send__(query_method)
|
31
|
+
break unless @actual.nil?
|
32
|
+
end
|
33
|
+
raise not_a_collection if @actual.nil?
|
34
|
+
else
|
35
|
+
query_method = determine_query_method(collection)
|
36
|
+
raise not_a_collection unless query_method
|
37
|
+
@actual = collection.__send__(query_method)
|
38
|
+
end
|
39
|
+
case @relativity
|
40
|
+
when :at_least then @actual >= @expected
|
41
|
+
when :at_most then @actual <= @expected
|
42
|
+
else @actual == @expected
|
43
|
+
end
|
44
|
+
end
|
45
|
+
alias == matches?
|
46
|
+
|
47
|
+
def determine_collection(collection_or_owner)
|
48
|
+
if collection_or_owner.respond_to?(@collection_name)
|
49
|
+
collection_or_owner.__send__(@collection_name, *@args, &@block)
|
50
|
+
elsif (@plural_collection_name && collection_or_owner.respond_to?(@plural_collection_name))
|
51
|
+
collection_or_owner.__send__(@plural_collection_name, *@args, &@block)
|
52
|
+
elsif determine_query_method(collection_or_owner)
|
53
|
+
collection_or_owner
|
54
|
+
else
|
55
|
+
collection_or_owner.__send__(@collection_name, *@args, &@block)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def determine_query_method(collection)
|
60
|
+
QUERY_METHODS.detect {|m| collection.respond_to?(m)}
|
61
|
+
end
|
62
|
+
|
63
|
+
def not_a_collection
|
64
|
+
"expected #{@collection_name} to be a collection but it does not respond to #length, #size or #count"
|
65
|
+
end
|
66
|
+
|
67
|
+
def failure_message_for_should
|
68
|
+
"expected #{relative_expectation} #{@collection_name}, got #{@actual}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def failure_message_for_should_not
|
72
|
+
if @relativity == :exactly
|
73
|
+
return "expected target not to have #{@expected} #{@collection_name}, got #{@actual}"
|
74
|
+
elsif @relativity == :at_most
|
75
|
+
return <<-EOF
|
76
|
+
Isn't life confusing enough?
|
77
|
+
Instead of having to figure out the meaning of this:
|
78
|
+
#{Expectations::Syntax.negative_expression("actual", "have_at_most(#{@expected}).#{@collection_name}")}
|
79
|
+
We recommend that you use this instead:
|
80
|
+
#{Expectations::Syntax.positive_expression("actual", "have_at_least(#{@expected + 1}).#{@collection_name}")}
|
81
|
+
EOF
|
82
|
+
elsif @relativity == :at_least
|
83
|
+
return <<-EOF
|
84
|
+
Isn't life confusing enough?
|
85
|
+
Instead of having to figure out the meaning of this:
|
86
|
+
#{Expectations::Syntax.negative_expression("actual", "have_at_least(#{@expected}).#{@collection_name}")}
|
87
|
+
We recommend that you use this instead:
|
88
|
+
#{Expectations::Syntax.positive_expression("actual", "have_at_most(#{@expected - 1}).#{@collection_name}")}
|
89
|
+
EOF
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def description
|
94
|
+
"have #{relative_expectation} #{@collection_name}"
|
95
|
+
end
|
96
|
+
|
97
|
+
def respond_to?(m)
|
98
|
+
@expected.respond_to?(m) || super
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def method_missing(method, *args, &block)
|
104
|
+
@collection_name = method
|
105
|
+
if inflector = (defined?(ActiveSupport::Inflector) && ActiveSupport::Inflector.respond_to?(:pluralize) ? ActiveSupport::Inflector : (defined?(Inflector) ? Inflector : nil))
|
106
|
+
@plural_collection_name = inflector.pluralize(method.to_s)
|
107
|
+
end
|
108
|
+
@args = args
|
109
|
+
@block = block
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
def relative_expectation
|
114
|
+
"#{relativities[@relativity]}#{@expected}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def enumerator_class
|
118
|
+
RUBY_VERSION < '1.9' ? Enumerable::Enumerator : Enumerator
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|