rspec-collection_matchers 0.0.1.pre → 0.0.1
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 +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 [](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
|