spec/limit_detectors_spec.rb
# frozen_string_literal: true
require 'set'
Array.include LimitDetectors
describe '#at_most' do
it 'is true for an empty Array' do
expect(Kernel).to_not receive(:warn)
expect([].at_most?(5) { true }).to be_truthy
expect([].at_most?(0) { true }).to be_truthy
expect([].at_most?(1) { true }).to be_truthy
expect([].at_most?(5) { :foo }).to be_truthy
end
it 'is true if the criterion is met once' do
expect(["it's there"].at_most?(1) { |el| el == "it's there" }).to be_truthy
end
it 'is true if all elements meet the criterion and the size is the given maximum number' do
expect([1, 1, 1].at_most?(3) { |e| e == 1 })
end
it 'is false if not enough elements meet the criterion' do
expect([1, 2, 4].at_most?(1, &:even?)).to be_falsey
end
it 'is true if 0 elements are expected to match' do
r = Array.new(10) { rand }
expect(r.at_most?(0) { |i| i > 2 }).to be_truthy
end
describe 'Hash#at_most' do
Hash.include LimitDetectors
it 'detects a condition based on key as well as value properties' do
h = { 'foo' => 1, 'bar' => 4, 'baz' => 5, 'bum' => 1, 'fum' => 0 }
expect(h.at_most?(3) { |ky, vl| ky.match(/^b/) || vl > 1 }).to be_truthy
end
end
end
describe '#at_least' do
it 'is false for an empty Array, if at least one is expected' do
expect(Kernel).to_not receive(:warn)
expect([].at_least?(1) { true }).to be_falsey
end
it 'is true if the expected number is 0 and Array is empty' do
expect([].at_least?(0) { true }).to be_truthy
expect({}.at_least?(0) { false }).to be_truthy
end
it 'is false if the container ist smaller than the expected number' do
size = 10
expect(Array.new(10).at_least?(size + 1) { true }).to be_falsey
end
it 'is true if the criterion is met and expected once' do
expect(["it's there"].at_least?(1) { |el| el == "it's there" }).to be_truthy
end
it 'is false for an empty Array if you expect at least 1' do
expect([].at_least?(1) { true }).to be_falsey
end
it 'is true for an empty Array if you expect at least 0' do
expect([].at_least?(0) {}).to be_truthy
end
it 'is true if the criterion is met once' do
expect(["it's there"].at_least?(1) { |el| el == "it's there" }).to be_truthy
end
it 'is true if all elements meet the criterion and the size is the given minimum number' do
expect([1, 1, 1].at_least?(3) { |e| e == 1 }).to be_truthy
end
it 'is true if enough elements meet the criterion' do
expect([1, 2, 4, 8].at_least?(2, &:even?)).to be_truthy
end
it 'is true if there are enough elements to match' do
r = Array.new(10) { |i| i }
expect(r.at_least?(7) { |i| i > 2 }).to be_truthy
expect(r.at_least?(8) { |i| i > 2 }).to be_falsey
end
end
describe '#ocurrences_of' do
context 'collection with content' do
Set.include LimitDetectors
subject { Set.new([1, 2, 3, 4, 5, 6, 7]) }
it('counts 3 even numbers') { expect(subject.occurrences_of(&:even?)).to be 3 }
it('counts 4 odd numbers') { expect(subject.occurrences_of(&:odd?)).to be 4 }
it('counts no number < 0') { expect(subject.occurrences_of { |e| e < 0 }).to be 0 }
it('counts 7 positive numbers') { expect(subject.occurrences_of { |e| e > 0 }).to be 7 }
end
context 'empty collection' do
it 'counts 0 for any empty collection' do
[[], Set.new, {}].each do |obj|
expect(obj.occurrences_of { true }).to be(0), "Expected to count 0, for an empty #{obj.class}"
end
end
end
it("doesn't return nil") { expect([1].occurrences_of {}).not_to be_nil }
end
describe "Using an object that doesn't respond to #inject" do
object = Object.new
object.extend LimitDetectors
it 'will raise an exception, if it\'s sent #at_most' do
expect { object.at_most?(1, &:condition?) }.to raise_exception(NoMethodError, /undefined method .inject./)
end
end
describe 'Give a warning, if non-predicate versions are used' do
it 'yields a warning for old-style at_most' do
expect(Kernel).to receive(:warn).with(/'at_most'.+deprecated.+'at_most\?'/)
[1, 2, 4, 8].at_most(2, &:even?)
end
it 'yields a warning for old-style at_least' do
expect(Kernel).to receive(:warn).with(/'at_least'.+deprecated.+'at_least\?'/)
[1, 2, 4, 8].at_least(2, &:even?)
end
end
describe 'When the provided block raises an exception' do
subject { [1] }
it 'passes up the stack unchanged' do
expect { subject.at_most?(1) { raise ArgumentError, 'BoomError' } }.to raise_error(ArgumentError, 'BoomError')
expect { subject.occurrences_of { raise ArgumentError, 'BoomError' } }.to raise_error(ArgumentError, 'BoomError')
end
end