1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
module Mocha
class Cardinality
INFINITY = 1 / 0.0
def initialize(required = 0, maximum = INFINITY)
update(required, maximum)
@invocations = []
end
def exactly(count)
update(count, count)
end
def at_least(count)
update(count, INFINITY)
end
def at_most(count)
update(0, count)
end
def times(range_or_count)
case range_or_count
when Range then update(range_or_count.first, range_or_count.last)
else update(range_or_count, range_or_count)
end
end
def <<(invocation)
@invocations << invocation
end
def invocations_allowed?
@invocations.size < maximum
end
def satisfied?
@invocations.size >= required
end
def needs_verifying?
!allowed_any_number_of_times?
end
def verified?
(@invocations.size >= required) && (@invocations.size <= maximum)
end
def allowed_any_number_of_times?
required.zero? && infinite?(maximum)
end
def used?
@invocations.any? || maximum.zero?
end
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
def anticipated_times
if allowed_any_number_of_times?
'allowed any number of times'
elsif required.zero? && maximum.zero?
"expected #{count(maximum)}"
elsif required == maximum
"expected exactly #{count(required)}"
elsif infinite?(maximum)
"expected at least #{count(required)}"
elsif required.zero?
"expected at most #{count(maximum)}"
else
"expected between #{required} and #{count(maximum)}"
end
end
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
def invoked_times
"invoked #{count(@invocations.size)}"
end
def actual_invocations
@invocations.map(&:full_description).join
end
protected
attr_reader :required, :maximum
def count(number)
case number
when 0 then 'never'
when 1 then 'once'
when 2 then 'twice'
else "#{number} times"
end
end
def update(required, maximum)
@required = required
@maximum = maximum
self
end
def infinite?(number)
number.respond_to?(:infinite?) && number.infinite?
end
end
end
|