rspec-collection_matchers-1.2.0/0000755000004100000410000000000013543411216016675 5ustar www-datawww-datarspec-collection_matchers-1.2.0/.travis.yml0000644000004100000410000000104713543411216021010 0ustar www-datawww-datalanguage: ruby script: "script/test_all" bundler_args: "--standalone --binstubs --without documentation" before_install: - gem update --system --conservative || (gem i "rubygems-update:~>2.7" --no-document && update_rubygems) - gem update bundler --conservative # In order to install old Rubies, we need to use old Ubuntu distibution. dist: trusty rvm: - 1.8.7 - 1.9.2 - 1.9.3 - 2.0.0 - 2.1 - 2.2.10 - 2.3.8 - 2.4.6 - 2.5.5 - 2.6.3 - ree - jruby-19mode - jruby-18mode env: - BRANCH=master - BRANCH=2-99-maintenance rspec-collection_matchers-1.2.0/.rspec0000644000004100000410000000003713543411216020012 0ustar www-datawww-data--format documentation --color rspec-collection_matchers-1.2.0/README.md0000644000004100000410000000360413543411216020157 0ustar www-datawww-data# RSpec::CollectionMatchers [![Build Status](https://secure.travis-ci.org/rspec/rspec-collection_matchers.svg?branch=master)](http://travis-ci.org/rspec/rspec-collection_matchers) RSpec::CollectionMatchers lets you express expected outcomes on collections of an object in an example. ```ruby expect(account.shopping_cart).to have_exactly(3).items ``` ## Install Add this line to your application's Gemfile: gem 'rspec-collection_matchers' And then execute: $ bundle Or install it yourself as: $ gem install rspec-collection_matchers ## Basic usage First of all, you need to require rspec-collection matchers. Add the following line to your `spec_helper.rb`: ```ruby require 'rspec/collection_matchers' ``` Using `rspec-collection_matchers` you can match the number of items in a collection directly, e.g.: ```ruby it 'matches number of items in a collection' do expect([1,2,3]).to have_at_least(3).items end ``` You can also match the number of items returned by a method on an object, e.g.: ```ruby class Cart def initialize(*products) @products = products end attr_reader :products end it 'matches number of items returned from a method' do cart = Cart.new('product a', 'product b') expect(cart).to have_at_most(2).products end ``` The last line of the example expresses an expected outcome: if `cart.products.size <= 2` then the example passes, otherwise it fails with a message like: expected at most 2 products, got 3 ## Available matchers ```ruby expect(collection).to have(n).items expect(collection).to have_exactly(n).items expect(collection).to have_at_most(n).items expect(collection).to have_at_least(n).items ``` ## See also * [http://github.com/rspec/rspec](http://github.com/rspec/rspec) * [http://github.com/rspec/rspec-core](http://github.com/rspec/rspec-core) * [http://github.com/rspec/rspec-expectations](http://github.com/rspec/rspec-expectations) rspec-collection_matchers-1.2.0/spec/0000755000004100000410000000000013543411216017627 5ustar www-datawww-datarspec-collection_matchers-1.2.0/spec/rspec/0000755000004100000410000000000013543411216020743 5ustar www-datawww-datarspec-collection_matchers-1.2.0/spec/rspec/collection_matchers/0000755000004100000410000000000013543411216024764 5ustar www-datawww-datarspec-collection_matchers-1.2.0/spec/rspec/collection_matchers/have_spec.rb0000644000004100000410000005526613543411216027264 0ustar www-datawww-datarequire 'spec_helper' require 'stringio' describe "have matcher" do let(:inflector) do Class.new do def self.pluralize(string) string.to_s + 's' end end end before(:each) { stub_const("ActiveSupport::Inflector", inflector) } def create_collection_owner_with(n) owner = RSpec::Expectations::Helper::CollectionOwner.new (1..n).each do |number| owner.add_to_collection_with_length_method(number) owner.add_to_collection_with_size_method(number) owner.add_to_collection_with_count_method(number) end owner end describe "expect(...).to have(n).items" do it_behaves_like "an RSpec matcher", :valid_value => [1, 2], :invalid_value => [1] do let(:matcher) { have(2).items } end it "passes if target has a collection of items with n members" do owner = create_collection_owner_with(3) expect(owner).to have(3).items_in_collection_with_length_method expect(owner).to have(3).items_in_collection_with_size_method expect(owner).to have(3).items_in_collection_with_count_method end it "converts :no to 0" do owner = create_collection_owner_with(0) expect(owner).to have(:no).items_in_collection_with_length_method expect(owner).to have(:no).items_in_collection_with_size_method expect(owner).to have(:no).items_in_collection_with_count_method end it "converts a String argument to Integer" do owner = create_collection_owner_with(3) expect(owner).to have('3').items_in_collection_with_length_method expect(owner).to have('3').items_in_collection_with_size_method expect(owner).to have('3').items_in_collection_with_count_method end it "fails if target has a collection of items with < n members" do owner = create_collection_owner_with(3) expect { expect(owner).to have(4).items_in_collection_with_length_method }.to fail_with("expected 4 items_in_collection_with_length_method, got 3") expect { expect(owner).to have(4).items_in_collection_with_size_method }.to fail_with("expected 4 items_in_collection_with_size_method, got 3") expect { expect(owner).to have(4).items_in_collection_with_count_method }.to fail_with("expected 4 items_in_collection_with_count_method, got 3") end it "fails if target has a collection of items with > n members" do owner = create_collection_owner_with(3) expect { expect(owner).to have(2).items_in_collection_with_length_method }.to fail_with("expected 2 items_in_collection_with_length_method, got 3") expect { expect(owner).to have(2).items_in_collection_with_size_method }.to fail_with("expected 2 items_in_collection_with_size_method, got 3") expect { expect(owner).to have(2).items_in_collection_with_count_method }.to fail_with("expected 2 items_in_collection_with_count_method, got 3") end end describe 'expect(...).to have(1).item when ActiveSupport::Inflector is defined' do it 'pluralizes the collection name' do owner = create_collection_owner_with(1) expect(owner).to have(1).item end context "when ActiveSupport::Inflector is partially loaded without its inflectors" do it "does not pluralize the collection name" do stub_const("ActiveSupport::Inflector", Module.new) owner = create_collection_owner_with(1) expect { expect(owner).to have(1).item }.to raise_error(NoMethodError) end end end describe 'expect(...).to have(1).item when Inflector is defined' do before { stub_const("Inflector", inflector) } it 'pluralizes the collection name' do owner = create_collection_owner_with(1) expect(owner).to have(1).item end end describe "expect(...).to have(n).items where result responds to items but returns something other than a collection" do it "provides a meaningful error" do owner = Class.new do def items 1 end end.new expect do expect(owner).to have(3).items end.to raise_error("expected items to be a collection but it does not respond to #length, #size or #count") end it "provides a meaningful error" do owner = Class.new do def items Object.new end end.new expect do expect(owner).to have(3).items end.to raise_error("expected items to be a collection but it does not respond to #length, #size or #count") end end describe "expect(...).not_to have(n).items" do it "passes if target has a collection of items with < n members" do owner = create_collection_owner_with(3) expect(owner).not_to have(4).items_in_collection_with_length_method expect(owner).not_to have(4).items_in_collection_with_size_method expect(owner).not_to have(4).items_in_collection_with_count_method end it "passes if target has a collection of items with > n members" do owner = create_collection_owner_with(3) expect(owner).not_to have(2).items_in_collection_with_length_method expect(owner).not_to have(2).items_in_collection_with_size_method expect(owner).not_to have(2).items_in_collection_with_count_method end it "fails if target has a collection of items with n members" do owner = create_collection_owner_with(3) expect { expect(owner).not_to have(3).items_in_collection_with_length_method }.to fail_with("expected target not to have 3 items_in_collection_with_length_method, got 3") expect { expect(owner).not_to have(3).items_in_collection_with_size_method }.to fail_with("expected target not to have 3 items_in_collection_with_size_method, got 3") expect { expect(owner).not_to have(3).items_in_collection_with_count_method }.to fail_with("expected target not to have 3 items_in_collection_with_count_method, got 3") end end describe "expect(...).to have_exactly(n).items" do it "passes if target has a collection of items with n members" do owner = create_collection_owner_with(3) expect(owner).to have_exactly(3).items_in_collection_with_length_method expect(owner).to have_exactly(3).items_in_collection_with_size_method expect(owner).to have_exactly(3).items_in_collection_with_count_method end it "converts :no to 0" do owner = create_collection_owner_with(0) expect(owner).to have_exactly(:no).items_in_collection_with_length_method expect(owner).to have_exactly(:no).items_in_collection_with_size_method expect(owner).to have_exactly(:no).items_in_collection_with_count_method end it "fails if target has a collection of items with < n members" do owner = create_collection_owner_with(3) expect { expect(owner).to have_exactly(4).items_in_collection_with_length_method }.to fail_with("expected 4 items_in_collection_with_length_method, got 3") expect { expect(owner).to have_exactly(4).items_in_collection_with_size_method }.to fail_with("expected 4 items_in_collection_with_size_method, got 3") expect { expect(owner).to have_exactly(4).items_in_collection_with_count_method }.to fail_with("expected 4 items_in_collection_with_count_method, got 3") end it "fails if target has a collection of items with > n members" do owner = create_collection_owner_with(3) expect { expect(owner).to have_exactly(2).items_in_collection_with_length_method }.to fail_with("expected 2 items_in_collection_with_length_method, got 3") expect { expect(owner).to have_exactly(2).items_in_collection_with_size_method }.to fail_with("expected 2 items_in_collection_with_size_method, got 3") expect { expect(owner).to have_exactly(2).items_in_collection_with_count_method }.to fail_with("expected 2 items_in_collection_with_count_method, got 3") end end describe "expect(...).to have_at_least(n).items" do it "passes if target has a collection of items with n members" do owner = create_collection_owner_with(3) expect(owner).to have_at_least(3).items_in_collection_with_length_method expect(owner).to have_at_least(3).items_in_collection_with_size_method expect(owner).to have_at_least(3).items_in_collection_with_count_method end it "passes if target has a collection of items with > n members" do owner = create_collection_owner_with(3) expect(owner).to have_at_least(2).items_in_collection_with_length_method expect(owner).to have_at_least(2).items_in_collection_with_size_method expect(owner).to have_at_least(2).items_in_collection_with_count_method end it "fails if target has a collection of items with < n members" do owner = create_collection_owner_with(3) expect { expect(owner).to have_at_least(4).items_in_collection_with_length_method }.to fail_with("expected at least 4 items_in_collection_with_length_method, got 3") expect { expect(owner).to have_at_least(4).items_in_collection_with_size_method }.to fail_with("expected at least 4 items_in_collection_with_size_method, got 3") expect { expect(owner).to have_at_least(4).items_in_collection_with_count_method }.to fail_with("expected at least 4 items_in_collection_with_count_method, got 3") end it "provides educational negative failure messages" do #given owner = create_collection_owner_with(3) length_matcher = have_at_least(3).items_in_collection_with_length_method size_matcher = have_at_least(3).items_in_collection_with_size_method count_matcher = have_at_least(3).items_in_collection_with_count_method #when length_matcher.matches?(owner) size_matcher.matches?(owner) count_matcher.matches?(owner) #then expect(length_matcher.failure_message_for_should_not).to eq <<-EOF Isn't life confusing enough? Instead of having to figure out the meaning of this: expect(actual).not_to have_at_least(3).items_in_collection_with_length_method We recommend that you use this instead: expect(actual).to have_at_most(2).items_in_collection_with_length_method EOF expect(size_matcher.failure_message_for_should_not).to eq <<-EOF Isn't life confusing enough? Instead of having to figure out the meaning of this: expect(actual).not_to have_at_least(3).items_in_collection_with_size_method We recommend that you use this instead: expect(actual).to have_at_most(2).items_in_collection_with_size_method EOF expect(count_matcher.failure_message_for_should_not).to eq <<-EOF Isn't life confusing enough? Instead of having to figure out the meaning of this: expect(actual).not_to have_at_least(3).items_in_collection_with_count_method We recommend that you use this instead: expect(actual).to have_at_most(2).items_in_collection_with_count_method EOF end end describe "expect(...).to have_at_most(n).items" do it "passes if target has a collection of items with n members" do owner = create_collection_owner_with(3) expect(owner).to have_at_most(3).items_in_collection_with_length_method expect(owner).to have_at_most(3).items_in_collection_with_size_method expect(owner).to have_at_most(3).items_in_collection_with_count_method end it "fails if target has a collection of items with > n members" do owner = create_collection_owner_with(3) expect { expect(owner).to have_at_most(2).items_in_collection_with_length_method }.to fail_with("expected at most 2 items_in_collection_with_length_method, got 3") expect { expect(owner).to have_at_most(2).items_in_collection_with_size_method }.to fail_with("expected at most 2 items_in_collection_with_size_method, got 3") expect { expect(owner).to have_at_most(2).items_in_collection_with_count_method }.to fail_with("expected at most 2 items_in_collection_with_count_method, got 3") end it "passes if target has a collection of items with < n members" do owner = create_collection_owner_with(3) expect(owner).to have_at_most(4).items_in_collection_with_length_method expect(owner).to have_at_most(4).items_in_collection_with_size_method expect(owner).to have_at_most(4).items_in_collection_with_count_method end it "provides educational negative failure messages" do #given owner = create_collection_owner_with(3) length_matcher = have_at_most(3).items_in_collection_with_length_method size_matcher = have_at_most(3).items_in_collection_with_size_method count_matcher = have_at_most(3).items_in_collection_with_count_method #when length_matcher.matches?(owner) size_matcher.matches?(owner) count_matcher.matches?(owner) #then expect(length_matcher.failure_message_for_should_not).to eq <<-EOF Isn't life confusing enough? Instead of having to figure out the meaning of this: expect(actual).not_to have_at_most(3).items_in_collection_with_length_method We recommend that you use this instead: expect(actual).to have_at_least(4).items_in_collection_with_length_method EOF expect(size_matcher.failure_message_for_should_not).to eq <<-EOF Isn't life confusing enough? Instead of having to figure out the meaning of this: expect(actual).not_to have_at_most(3).items_in_collection_with_size_method We recommend that you use this instead: expect(actual).to have_at_least(4).items_in_collection_with_size_method EOF expect(count_matcher.failure_message_for_should_not).to eq <<-EOF Isn't life confusing enough? Instead of having to figure out the meaning of this: expect(actual).not_to have_at_most(3).items_in_collection_with_count_method We recommend that you use this instead: expect(actual).to have_at_least(4).items_in_collection_with_count_method EOF end end describe "have(n).items(args, block)" do it "passes args to target" do target = double("target") expect(target).to receive(:items).with("arg1","arg2").and_return([1,2,3]) expect(target).to have(3).items("arg1","arg2") end it "passes block to target" do target = double("target") block = Proc.new { 5 } expect(target).to receive(:items).with("arg1","arg2", block).and_return([1,2,3]) expect(target).to have(3).items("arg1","arg2", block) end end describe "have(n).items where target IS a collection" do it "references the number of items IN the collection" do expect([1,2,3]).to have(3).items end it "fails when the number of items IN the collection is not as expected" do expect { expect([1,2,3]).to have(7).items }.to fail_with("expected 7 items, got 3") end end describe "have(n).characters where target IS a String" do it "passes if the length is correct" do expect("this string").to have(11).characters end it "fails if the length is incorrect" do expect { expect("this string").to have(12).characters }.to fail_with("expected 12 characters, got 11") end end describe "have(n).things on an object which is not a collection nor contains one" do it "fails" do expect { expect(Object.new).to have(2).things }.to raise_error(NoMethodError) { |e| expect(e.name).to eq :things } end end describe "expectations compounded with RSpec::Matchers::Composable", :if => defined?(RSpec::Matchers::Composable) do context "using #and" do it "fails with relevant error when only first expectation fails" do expect { expect([1, 2, 3]).to be_falsey.and have(3).items }.to fail_matching "expected: falsey value" end it "fails with relevant error when only second expectation fails" do expect { expect([1, 2, 3]).to have(3).items.and be_falsey }.to fail_matching "expected: falsey value" end it "fails with relevant error when both expectations fail" do expect { expect([1, 2, 3]).to be_falsey.and have(0).items }.to fail_matching "...and:" end it "passes when both expectations are met" do expect([1, 2, 3]).to have(3).items.and be_truthy end end context "using #or" do it "fails with relevant error when neither expectation is met" do expect { expect([1, 2, 3]).to be_falsey.or have(0).items }.to fail_matching "...or:" end it "passes when only first expectation is met" do expect([1, 2, 3]).to have(3).items.or be_falsey end it "passes when only second expectation is met" do expect([1, 2, 3]).to be_falsey.or have(3).items end it "passes when both expectations are met" do expect([1, 2, 3]).to be_truthy.or have(3).items end end context "using the have matcher as an argument of another matcher" do it "has an alias for the have matcher" do word = "hi" expect { word = "hey" }.to change { word }. from( a_collection_having(2).letters ). to( a_collection_having(3).letters ) end it "has an alias for the have_at_most matcher" it "has an alias for the have_at_least matcher" end end describe RSpec::CollectionMatchers::Have, "for a collection owner that implements #send" do before(:each) do @collection = Object.new def @collection.floozles; [1,2] end def @collection.send; :sent; end end it "works in the straightforward case" do expect(@collection).to have(2).floozles end it "works when doing automatic pluralization" do expect(@collection).to have_at_least(1).floozle end it "blows up when the owner doesn't respond to that method" do expect { expect(@collection).to have(99).problems }.to raise_error(NoMethodError, /problems/) end it 'works when #send is defined directly on an array' do array = [1, 2] def array.send; :sent; end expect(array).to have(2).items end end if RUBY_VERSION >= '2.0' describe RSpec::CollectionMatchers::Have, "for an Enumerator whose size is nil but count is supplied" do let(:enumerator) { %w[a b c d].to_enum(:each) } it 'works fine' do expect(enumerator).to have(4).items end end end describe RSpec::CollectionMatchers::Have do it "has method_missing as private" do expect(described_class.private_instance_methods).to include_method(:method_missing) end it "does not respond_to? method_missing (because it's private)" do formatter = described_class.new(0, StringIO.new) expect(formatter).not_to respond_to(:method_missing) end describe "respond_to?" do before :each do @have = described_class.new(:foo) @a_method_which_have_defines = described_class.instance_methods.first @a_method_which_object_defines = Object.instance_methods.first end it "is true for a method which Have defines" do expect(@have).to respond_to(@a_method_which_have_defines) end it "is true for a method that it's superclass (Object) defines" do expect(@have).to respond_to(@a_method_which_object_defines) end it "is false for a method which neither Object nor nor Have defines" do expect(@have).not_to respond_to(:foo_bar_baz) end it "is false if the owner doesn't respond to the method" do have = described_class.new(99) expect(have).not_to respond_to(:problems) end it "is true if the owner responds to the method" do have = described_class.new(:a_symbol) expect(have).to respond_to(:to_sym) end end end context "description generation" do let(:team) do Class.new do def players [1,2,3] end end.new end describe "the have matcher" do it "generates its own description" do expect(team).to have(3).players expect(RSpec::Matchers.generated_description).to match /have 3 players$/ end end describe "the have_at_least matcher"do it "generates its own description" do expect(team).to have_at_least(2).players expect(RSpec::Matchers.generated_description).to match /have at least 2 players$/ end end describe "the have_at_most matcher" do it "generates its own description" do expect(team).to have_at_most(4).players expect(RSpec::Matchers.generated_description).to match /have at most 4 players$/ end end end end module RSpec module CollectionMatchers describe Syntax do describe "expression generation" do let(:target) { "foo" } let(:expectation) { "eq('bar')" } let(:positive_expect_example) { "expect(foo).to eq('bar')" } let(:positive_should_example) { "foo.should eq('bar')" } let(:negative_expect_example) { "expect(foo).not_to eq('bar')" } let(:negative_should_example) { "foo.should_not eq('bar')" } def positive_expression Syntax.positive_expression(target, expectation) end def negative_expression Syntax.negative_expression(target, expectation) end context "when only :expect is enabled", :uses_only_expect do before do expect(Expectations::Syntax.should_enabled?).to be_falsey expect(Expectations::Syntax.expect_enabled?).to be_truthy end it 'generates a positive expression using the expect syntax' do expect(positive_expression).to eq(positive_expect_example) end it 'generates a negative expression using the expect syntax' do expect(negative_expression).to eq(negative_expect_example) end end context "when both :should and :expect are enabled", :uses_should do before do expect(Expectations::Syntax.should_enabled?).to be_truthy expect(Expectations::Syntax.expect_enabled?).to be_truthy end it 'generates a positive expression using the expect syntax' do expect(positive_expression).to eq(positive_expect_example) end it 'generates a negative expression using the expect syntax' do expect(negative_expression).to eq(negative_expect_example) end end context "when only :should is enabled", :uses_only_should do before do Expectations::Syntax.should_enabled?.should be_truthy Expectations::Syntax.expect_enabled?.should be_falsey end it 'generates a positive expression using the expect syntax' do positive_expression.should eq(positive_should_example) end it 'generates a negative expression using the expect syntax' do negative_expression.should eq(negative_should_example) end end end end end end rspec-collection_matchers-1.2.0/spec/rspec/collection_matchers/rails_extensions_spec.rb0000644000004100000410000000523113543411216031715 0ustar www-datawww-datarequire "spec_helper" require 'active_model' module RSpec::CollectionMatchers describe "Have extensions for rails" do describe "error_on" do it "provides a description including the name of what the error is on" do expect(have(1).error_on(:whatever).description).to eq "have 1 error on :whatever" end it "provides a failure message including the number actually given" do expect { expect([]).to have(1).error_on(:whatever) }.to raise_error("expected 1 error on :whatever, got 0") end end describe "errors_on" do it "provides a description including the name of what the error is on" do expect(have(2).errors_on(:whatever).description).to eq "have 2 errors on :whatever" end it "provides a failure message including the number actually given" do expect { expect([1]).to have(3).errors_on(:whatever) }.to raise_error("expected 3 errors on :whatever, got 1") end let(:klass) do Class.new do include ActiveModel::Validations end end it "calls valid?" do model = klass.new expect(model).to receive(:valid?) model.errors_on(:foo) end it "returns the errors on that attribute" do model = klass.new allow(model).to receive(:errors) do { :foo => ['a', 'b'] } end expect(model.errors_on(:foo)).to eq(['a','b']) end context "ActiveModel class that takes no arguments to valid?" do let(:klass) { Class.new do include ActiveModel::Validations def self.name "ActiveModelValidationsFake" end def valid? super end attr_accessor :name validates_presence_of :name end } context "with nil name" do it "has one error" do object = klass.new object.name = "" expect(object).to have(1).error_on(:name) end end context "with non-blank name" do it "has no error" do object = klass.new object.name = "Ywen" expect(object).to have(:no).error_on(:name) end end end end describe "have something other than error_on or errors_on" do it "has a standard rspec failure message" do expect { expect([1,2,3]).to have(2).elements }.to raise_error("expected 2 elements, got 3") end it "has a standard rspec description" do expect(have(2).elements.description).to eq "have 2 elements" end end end end rspec-collection_matchers-1.2.0/spec/spec_helper.rb0000644000004100000410000000324113543411216022445 0ustar www-datawww-datarequire 'active_model' # to avoid deprecation warning: # [deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message. I18n.enforce_available_locales = false require 'rspec/collection_matchers' Dir['./spec/support/**/*'].each {|f| require f} RSpec.configure do |config| config.treat_symbols_as_metadata_keys_with_true_values = true if RSpec::Expectations::Version::STRING < "3.0" config.run_all_when_everything_filtered = true config.filter_run :focus config.order = 'random' config.expect_with :rspec do |rspec| rspec.syntax = :expect end config.mock_with :rspec do |rspec| rspec.syntax = :expect end end shared_context "with #should enabled", :uses_should do orig_syntax = nil before(:all) do orig_syntax = RSpec::Matchers.configuration.syntax RSpec::Matchers.configuration.syntax = [:expect, :should] end after(:all) do RSpec::Matchers.configuration.syntax = orig_syntax end end shared_context "with #should exclusively enabled", :uses_only_should do orig_syntax = nil before(:all) do orig_syntax = RSpec::Matchers.configuration.syntax RSpec::Matchers.configuration.syntax = :should end after(:all) do RSpec::Matchers.configuration.syntax = orig_syntax end end shared_context "with #expect exclusively enabled", :uses_only_expect do orig_syntax = nil before(:all) do orig_syntax = RSpec::Matchers.configuration.syntax RSpec::Matchers.configuration.syntax = :expect end after(:all) do RSpec::Matchers.configuration.syntax = orig_syntax end end rspec-collection_matchers-1.2.0/spec/support/0000755000004100000410000000000013543411216021343 5ustar www-datawww-datarspec-collection_matchers-1.2.0/spec/support/matchers.rb0000644000004100000410000000076713543411216023510 0ustar www-datawww-dataRSpec::Matchers.define :include_method do |expected| match do |actual| actual.map { |m| m.to_s }.include?(expected.to_s) end end module RSpec module Matchers def fail raise_error(RSpec::Expectations::ExpectationNotMetError) end def fail_with(message) raise_error(RSpec::Expectations::ExpectationNotMetError, message) end def fail_matching(message) raise_error(RSpec::Expectations::ExpectationNotMetError, /#{Regexp.escape(message)}/) end end end rspec-collection_matchers-1.2.0/spec/support/classes.rb0000644000004100000410000000313613543411216023330 0ustar www-datawww-data# various classes used by the specs module RSpec module Expectations module Helper class CollectionWithSizeMethod def initialize; @list = []; end def size; @list.size; end def push(item); @list.push(item); end end class CollectionWithLengthMethod def initialize; @list = []; end def length; @list.size; end def push(item); @list.push(item); end end class CollectionWithCountMethod def initialize; @list = []; end def count; @list.count; end def push(item); @list.push(item); end end class CollectionOwner attr_reader :items_in_collection_with_size_method, :items_in_collection_with_length_method, :items_in_collection_with_count_method def initialize @items_in_collection_with_size_method = CollectionWithSizeMethod.new @items_in_collection_with_length_method = CollectionWithLengthMethod.new @items_in_collection_with_count_method = CollectionWithCountMethod.new end def add_to_collection_with_size_method(item) @items_in_collection_with_size_method.push(item) end def add_to_collection_with_length_method(item) @items_in_collection_with_length_method.push(item) end def add_to_collection_with_count_method(item) @items_in_collection_with_count_method.push(item) end def items_for(arg) return [1, 2, 3] if arg == 'a' [1] end def items @items_in_collection_with_size_method end end end end end rspec-collection_matchers-1.2.0/spec/support/shared_examples.rb0000644000004100000410000000063413543411216025037 0ustar www-datawww-datashared_examples_for "an RSpec matcher" do |options| let(:valid_value) { options.fetch(:valid_value) } let(:invalid_value) { options.fetch(:invalid_value) } it 'matches a valid value when using #== so it can be composed' do expect(matcher).to eq(valid_value) end it 'does not match an invalid value when using #== so it can be composed' do expect(matcher).not_to eq(invalid_value) end end rspec-collection_matchers-1.2.0/.gitignore0000644000004100000410000000021613543411216020664 0ustar www-datawww-data*.sw? .DS_Store coverage* rdoc pkg doc tmp rerun.txt Gemfile.lock .bundle *.rbc .yardoc bin .rbx Gemfile-custom bundle .rspec-local Guardfile rspec-collection_matchers-1.2.0/script/0000755000004100000410000000000013543411216020201 5ustar www-datawww-datarspec-collection_matchers-1.2.0/script/test_all0000755000004100000410000000147513543411216021745 0ustar www-datawww-data#!/bin/bash set -e -x # idea taken from: http://blog.headius.com/2010/03/jruby-startup-time-tips.html export JRUBY_OPTS='-X-C' # disable JIT since these processes are so short lived # force jRuby to use client mode JVM or a compilation mode thats as close as possible, # idea taken from https://github.com/jruby/jruby/wiki/Improving-startup-time export JAVA_OPTS='-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' echo "Running rspec specs" bin/rspec spec --format progress --profile echo "Running cucumber specs" # TODO: it would be nice to figure out how to run the cukes w/o the overhead of # bundler, but just running `bin/cucumber` can fail due to the fact that it # shells out (via aruba) and executes `rspec`--which can pick up the wrong # rspec version if we're not running with bundler. bundle exec cucumber rspec-collection_matchers-1.2.0/Rakefile0000644000004100000410000000052113543411216020340 0ustar www-datawww-datarequire "bundler" Bundler.setup Bundler::GemHelper.install_tasks require "rake" require "rspec/core/rake_task" require "rspec/core/version" require "cucumber/rake/task" Cucumber::Rake::Task.new(:cucumber) desc "Run all examples" RSpec::Core::RakeTask.new(:spec) do |t| t.ruby_opts = %w[-w] end task :default => [:spec, :cucumber] rspec-collection_matchers-1.2.0/lib/0000755000004100000410000000000013543411216017443 5ustar www-datawww-datarspec-collection_matchers-1.2.0/lib/rspec/0000755000004100000410000000000013543411216020557 5ustar www-datawww-datarspec-collection_matchers-1.2.0/lib/rspec/collection_matchers.rb0000644000004100000410000000032313543411216025123 0ustar www-datawww-datarequire 'rspec/expectations' require 'rspec/collection_matchers/version' require 'rspec/collection_matchers/matchers' require 'rspec/collection_matchers/have' require 'rspec/collection_matchers/rails_extensions'rspec-collection_matchers-1.2.0/lib/rspec/collection_matchers/0000755000004100000410000000000013543411216024600 5ustar www-datawww-datarspec-collection_matchers-1.2.0/lib/rspec/collection_matchers/matchers.rb0000644000004100000410000000364413543411216026742 0ustar www-datawww-datarequire 'rspec/matchers' module RSpec module Matchers # Passes if receiver is a collection with the submitted number of items OR # if the receiver OWNS a collection with the submitted number of items. # # If the receiver OWNS the collection, you must use the name of the # collection. So if a `Team` instance has a collection named `#players`, # you must use that name to set the expectation. # # If the receiver IS the collection, you can use any name you like for # `named_collection`. We'd recommend using either "elements", "members", or # "items" as these are all standard ways of describing the things IN a # collection. # # This also works for Strings, letting you set expectations about their # lengths. # # @example # # # Passes if team.players.size == 11 # expect(team).to have(11).players # # # Passes if [1,2,3].length == 3 # expect([1,2,3]).to have(3).items #"items" is pure sugar # # # Passes if ['a', 'b', 'c'].count == 3 # expect([1,2,3]).to have(3).items #"items" is pure sugar # # # Passes if "this string".length == 11 # expect("this string").to have(11).characters #"characters" is pure sugar def have(n) RSpec::CollectionMatchers::Have.new(n) end alias :have_exactly :have alias :a_collection_having :have # Exactly like have() with >=. # # @example # expect("this").to have_at_least(3).letters # # ### Warning: # # `expect(..).not_to have_at_least` is not supported def have_at_least(n) RSpec::CollectionMatchers::Have.new(n, :at_least) end # Exactly like have() with <=. # # @example # expect("this").to have_at_most(4).letters # # ### Warning: # # `expect(..).not_to have_at_most` is not supported def have_at_most(n) RSpec::CollectionMatchers::Have.new(n, :at_most) end end end rspec-collection_matchers-1.2.0/lib/rspec/collection_matchers/version.rb0000644000004100000410000000011113543411216026603 0ustar www-datawww-datamodule RSpec module CollectionMatchers VERSION = "1.2.0" end end rspec-collection_matchers-1.2.0/lib/rspec/collection_matchers/have.rb0000644000004100000410000001576613543411216026067 0ustar www-datawww-datamodule RSpec module CollectionMatchers class Have include RSpec::Matchers::Composable unless RSpec::Expectations::Version::STRING.to_f < 3.0 QUERY_METHODS = [:size, :length, :count].freeze IGNORED_CLASSES = [Integer].freeze def initialize(expected, relativity=:exactly) @expected = case expected when :no then 0 when String then expected.to_i else expected end @relativity = relativity @actual = @collection_name = @plural_collection_name = nil end def relativities @relativities ||= { :exactly => "", :at_least => "at least ", :at_most => "at most " } end if RUBY_VERSION == '1.9.2' # On Ruby 1.9.2 items that don't return an array for `to_ary` # can't be flattened in arrays, we need to be able to do this # to produce diffs for compound matchers, so this corrects the # default implementation. Note that rspec-support has code that # directly checks for pattern and prevents infinite recursion. def to_ary [self] end end def matches?(collection_or_owner) collection = determine_collection(collection_or_owner) case collection when enumerator_class for query_method in QUERY_METHODS next unless collection.respond_to?(query_method) @actual = collection.__send__(query_method) break unless @actual.nil? end raise not_a_collection if @actual.nil? else query_method = determine_query_method(collection) raise not_a_collection if !query_method || is_ignored_class?(collection) @actual = collection.__send__(query_method) end case @relativity when :at_least then @actual >= @expected when :at_most then @actual <= @expected else @actual == @expected end end alias == matches? def determine_collection(collection_or_owner) if collection_or_owner.respond_to?(@collection_name) collection_or_owner.__send__(@collection_name, *@args, &@block) elsif (@plural_collection_name && collection_or_owner.respond_to?(@plural_collection_name)) collection_or_owner.__send__(@plural_collection_name, *@args, &@block) elsif determine_query_method(collection_or_owner) collection_or_owner else collection_or_owner.__send__(@collection_name, *@args, &@block) end end def determine_query_method(collection) QUERY_METHODS.detect {|m| collection.respond_to?(m)} end def is_ignored_class?(collection) IGNORED_CLASSES.any? {|klass| klass === collection} end def not_a_collection "expected #{@collection_name} to be a collection but it does not respond to #length, #size or #count" end def failure_message return errors_on_message(:expected, ", got #{@actual}") if is_errors_on? "expected #{relative_expectation} #{@collection_name}, got #{@actual}" end alias failure_message_for_should failure_message def failure_message_when_negated if @relativity == :exactly return "expected target not to have #{@expected} #{@collection_name}, got #{@actual}" elsif @relativity == :at_most return <<-EOF Isn't life confusing enough? Instead of having to figure out the meaning of this: #{Syntax.negative_expression("actual", "have_at_most(#{@expected}).#{@collection_name}")} We recommend that you use this instead: #{Syntax.positive_expression("actual", "have_at_least(#{@expected + 1}).#{@collection_name}")} EOF elsif @relativity == :at_least return <<-EOF Isn't life confusing enough? Instead of having to figure out the meaning of this: #{Syntax.negative_expression("actual", "have_at_least(#{@expected}).#{@collection_name}")} We recommend that you use this instead: #{Syntax.positive_expression("actual", "have_at_most(#{@expected - 1}).#{@collection_name}")} EOF end end alias failure_message_for_should_not failure_message_when_negated def description return errors_on_message(:have) if is_errors_on? "have #{relative_expectation} #{@collection_name}" end def respond_to?(m, include_all = false) @expected.respond_to?(m, include_all) || super end private def method_missing(method, *args, &block) @collection_name = method if inflector = (defined?(ActiveSupport::Inflector) && ActiveSupport::Inflector.respond_to?(:pluralize) ? ActiveSupport::Inflector : (defined?(Inflector) ? Inflector : nil)) @plural_collection_name = inflector.pluralize(method.to_s) end @args = args @block = block self end def relative_expectation "#{relativities[@relativity]}#{@expected}" end def enumerator_class RUBY_VERSION < '1.9' ? Enumerable::Enumerator : Enumerator end def is_errors_on? [:errors_on, :error_on].include? @collection_name end def errors_on_message(prefix, suffix = nil) "#{prefix} #{relative_expectation} #{@collection_name.to_s.gsub('_', ' ')} :#{@args[0]}#{suffix}" end end module Syntax # @api private # Generates a positive expectation expression. def self.positive_expression(target_expression, matcher_expression) expression_generator.positive_expression(target_expression, matcher_expression) end # @api private # Generates a negative expectation expression. def self.negative_expression(target_expression, matcher_expression) expression_generator.negative_expression(target_expression, matcher_expression) end # @api private # Selects which expression generator to use based on the configured syntax. def self.expression_generator if RSpec::Expectations::Syntax.expect_enabled? ExpectExpressionGenerator else ShouldExpressionGenerator end end # @api private # Generates expectation expressions for the `should` syntax. module ShouldExpressionGenerator def self.positive_expression(target_expression, matcher_expression) "#{target_expression}.should #{matcher_expression}" end def self.negative_expression(target_expression, matcher_expression) "#{target_expression}.should_not #{matcher_expression}" end end # @api private # Generates expectation expressions for the `expect` syntax. module ExpectExpressionGenerator def self.positive_expression(target_expression, matcher_expression) "expect(#{target_expression}).to #{matcher_expression}" end def self.negative_expression(target_expression, matcher_expression) "expect(#{target_expression}).not_to #{matcher_expression}" end end end end end rspec-collection_matchers-1.2.0/lib/rspec/collection_matchers/rails_extensions.rb0000644000004100000410000000163113543411216030517 0ustar www-datawww-dataif defined?(::ActiveModel) module ::ActiveModel::Validations # Extension to enhance `to have` on AR Model instances. Calls # model.valid? in order to prepare the object's errors object. Accepts # a :context option to specify the validation context. # # You can also use this to specify the content of the error messages. # # @example # # expect(model).to have(:no).errors_on(:attribute) # expect(model).to have(1).error_on(:attribute) # expect(model).to have(n).errors_on(:attribute) # expect(model).to have(n).errors_on(:attribute, :context => :create) # # expect(model.errors_on(:attribute)).to include("can't be blank") def errors_on(attribute, options = {}) valid_args = [options[:context]].compact self.valid?(*valid_args) [self.errors[attribute]].flatten.compact end alias :error_on :errors_on end end rspec-collection_matchers-1.2.0/Gemfile0000644000004100000410000000304613543411216020173 0ustar www-datawww-datasource 'https://rubygems.org' gemspec %w[rspec rspec-core rspec-expectations rspec-mocks].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) && !ENV['USE_GIT_REPOS'] gem lib, :path => library_path else gem lib, :git => "git://github.com/rspec/#{lib}.git", :branch => ENV.fetch('BRANCH',"master") end end # only the master branch is supported on rspec-support gem "rspec-support", :git => "git://github.com/rspec/rspec-support.git" gem "aruba" gem "rake", "~> 10.0.0" version_file = File.expand_path("../.rails-version", __FILE__) rails_gem_args = case version = ENV['RAILS_VERSION'] || (File.exist?(version_file) && File.read(version_file).chomp) when /master/ { :git => "git://github.com/rails/rails.git" } when /stable$/ { :git => "git://github.com/rails/rails.git", :branch => version } when nil, false, "" if RUBY_VERSION < '1.9.3' # Rails 4+ requires 1.9.3+, so on earlier versions default to the last 3.x release. "3.2.17" else "4.0.4" end else version end gem "activesupport", *rails_gem_args gem "activemodel", *rails_gem_args if RUBY_VERSION.to_f < 2 gem "cucumber", "~> 1.3.20" gem "contracts", "0.15.0" # doesn't work on Ruby 1.9.3 gem 'json', '< 2' gem 'term-ansicolor', '< 1.4.0' # used by cucumber gem 'tins', '~> 1.6.0' # used by term-ansicolor else gem "cucumber" end if RUBY_VERSION < '1.9.3' gem 'i18n', '< 0.7.0' end platform :rbx do gem 'rubysl' end eval File.read('Gemfile-custom') if File.exist?('Gemfile-custom') rspec-collection_matchers-1.2.0/features/0000755000004100000410000000000013543411216020513 5ustar www-datawww-datarspec-collection_matchers-1.2.0/features/have.feature0000644000004100000410000000746313543411216023025 0ustar www-datawww-dataFeature: have(n).items matcher RSpec provides several matchers that make it easy to set expectations about the size of a collection. There are three basic forms: ```ruby collection.should have(x).items collection.should have_at_least(x).items collection.should have_at_most(x).items ``` In addition, #have_exactly is provided as an alias to #have. These work on any collection-like object--the object just needs to respond to #size or #length (or both). When the matcher is called directly on a collection object, the #items call is pure syntactic sugar. You can use anything you want here. These are equivalent: ```ruby collection.should have(x).items collection.should have(x).things ``` You can also use this matcher on a non-collection object that returns a collection from one of its methods. For example, Dir#entries returns an array, so you could set an expectation using the following: ```ruby Dir.new("my/directory").should have(7).entries ``` Scenario: have(x).items on a collection Given a file named "have_items_spec.rb" with: """ruby require 'rspec/collection_matchers' describe [1, 2, 3] do it { should have(3).items } it { should_not have(2).items } it { should_not have(4).items } it { should have_exactly(3).items } it { should_not have_exactly(2).items } it { should_not have_exactly(4).items } it { should have_at_least(2).items } it { should have_at_most(4).items } # deliberate failures it { should_not have(3).items } it { should have(2).items } it { should have(4).items } it { should_not have_exactly(3).items } it { should have_exactly(2).items } it { should have_exactly(4).items } it { should have_at_least(4).items } it { should have_at_most(2).items } end """ When I run `rspec have_items_spec.rb` Then the output should contain "16 examples, 8 failures" And the output should contain "expected target not to have 3 items, got 3" And the output should contain "expected 2 items, got 3" And the output should contain "expected 4 items, got 3" And the output should contain "expected at least 4 items, got 3" And the output should contain "expected at most 2 items, got 3" Scenario: have(x).words on a String when String#words is defined Given a file named "have_words_spec.rb" with: """ruby require 'rspec/collection_matchers' class String def words split(' ') end end describe "a sentence with some words" do it { should have(5).words } it { should_not have(4).words } it { should_not have(6).words } it { should have_exactly(5).words } it { should_not have_exactly(4).words } it { should_not have_exactly(6).words } it { should have_at_least(4).words } it { should have_at_most(6).words } # deliberate failures it { should_not have(5).words } it { should have(4).words } it { should have(6).words } it { should_not have_exactly(5).words } it { should have_exactly(4).words } it { should have_exactly(6).words } it { should have_at_least(6).words } it { should have_at_most(4).words } end """ When I run `rspec have_words_spec.rb` Then the output should contain "16 examples, 8 failures" And the output should contain "expected target not to have 5 words, got 5" And the output should contain "expected 4 words, got 5" And the output should contain "expected 6 words, got 5" And the output should contain "expected at least 6 words, got 5" And the output should contain "expected at most 4 words, got 5" rspec-collection_matchers-1.2.0/features/support/0000755000004100000410000000000013543411216022227 5ustar www-datawww-datarspec-collection_matchers-1.2.0/features/support/env.rb0000644000004100000410000000147513543411216023353 0ustar www-datawww-dataunless defined?(RSpec::Matchers.all) module RSpec module Matchers # aruba assumes this is defined def all end # aruba doesn't alias this itself on 2.99 def an_output_string_including(partial) match partial end end end end require 'aruba/cucumber' Before do if RUBY_PLATFORM =~ /java/ @aruba_timeout_seconds = 30 else @aruba_timeout_seconds = 10 end end Aruba.configure do |config| config.before_cmd do |cmd| set_env('JRUBY_OPTS', "-X-C #{ENV['JRUBY_OPTS']}") # disable JIT since these processes are so short lived end end if RUBY_PLATFORM == 'java' Aruba.configure do |config| config.before_cmd do |cmd| set_env('RBXOPT', "-Xint=true #{ENV['RBXOPT']}") # disable JIT since these processes are so short lived end end if defined?(Rubinius) rspec-collection_matchers-1.2.0/rspec-collection_matchers.gemspec0000644000004100000410000000302113543411216025371 0ustar www-datawww-data# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'rspec/collection_matchers/version' Gem::Specification.new do |spec| spec.name = "rspec-collection_matchers" spec.version = RSpec::CollectionMatchers::VERSION spec.authors = ["Hugo Baraúna"] spec.email = ["hugo.barauna@plataformatec.com.br"] spec.summary = "rspec-collection_matchers-#{RSpec::CollectionMatchers::VERSION}" spec.description = "Collection cardinality matchers, extracted from rspec-expectations" spec.homepage = "https://github.com/rspec/rspec-collection_matchers" spec.license = "MIT" spec.metadata = { 'bug_tracker_uri' => 'https://github.com/rspec/rspec-collection_matchers/issues', 'changelog_uri' => "https://github.com/rspec/rspec-collection_matchers/blob/v#{spec.version}/Changelog.md", 'documentation_uri' => 'https://rspec.info/documentation/', 'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/rspec', 'source_code_uri' => 'https://github.com/rspec/rspec-collection_matchers', } spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(spec|features)/}) spec.require_paths = ["lib"] spec.add_runtime_dependency "rspec-expectations", ">= 2.99.0.beta1" spec.add_development_dependency "bundler", ">= 1.3" spec.add_development_dependency "activemodel", ">= 3.0" end rspec-collection_matchers-1.2.0/LICENSE.txt0000644000004100000410000000232113543411216020516 0ustar www-datawww-data(The MIT License) Copyright (c) 2013 Hugo Barauna Copyright (c) 2012 David Chelimsky, Myron Marston Copyright (c) 2006 David Chelimsky, The RSpec Development Team Copyright (c) 2005 Steven Baker MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rspec-collection_matchers-1.2.0/Changelog.md0000644000004100000410000000312413543411216021106 0ustar www-datawww-data### 1.2.0 / 2019-09-18 Enhancements: * Add a `have` matcher alias for `a_collection_having` (Hugo Baraúna, #25) Bug Fixes: * Define `to_ary` on Ruby 1.9.2 to fix issue when diffing in compound expectations (Jon Rowe, #34) * Prevent warning being issued due to incorrect definition of `respond_to`. (Matt Whipple, #33) ### 1.1.2 / 2014-11-11 [full changelog](http://github.com/rspec/rspec-collection_matchers/compare/v1.1.1...v1.1.2) Bug Fixes: * Fix bug of uninitialized constant RSpec::Expectations (Related to #20) ### 1.1.1 / 2014-11-10 [full changelog](http://github.com/rspec/rspec-collection_matchers/compare/v1.1.0...v1.1.1) Bug Fixes: * Remove virtual dependency on rspec-core (Thanks @jscheid for reporting that, #20) ### 1.1.0 / 2014-11-10 [full changelog](http://github.com/rspec/rspec-collection_matchers/compare/v1.0.0...v1.1.0) Enhancements: * Make matchers composable on RSpec 3 and above. (Johnson Denen, #19) ### 1.0.0 / 2014-06-09 [full changelog](http://github.com/rspec/rspec-collection_matchers/compare/v0.0.4...v1.0.0) ### 0.0.4 / 2014-04-24 [full changelog](http://github.com/rspec/rspec-collection_matchers/compare/v0.0.3...v0.0.4) Enhancements: * Add Rails extension `have(n).errors_on(:whatever)` (Bradley Schaefer) ### 0.0.3 / 2014-02-16 [full changelog](http://github.com/rspec/rspec-collection_matchers/compare/v0.0.2...v0.0.3) Enhancements: * Update to latest RSpec 3 matcher API. (Myron Marston) Bug Fixes: * Raise an error when you attempt to use matcher against an `Integer` which previously would have incorrectly used a `#size` of 8. (Kassio Borges)