require 'spec_helper' module RSpec::Matchers::BuiltIn describe BeBetween do class SizeMatters include Comparable attr :str def <=>(other) str.size <=> other.str.size end def initialize(str) @str = str end def inspect @str end end shared_examples_for "be_between" do |mode| it "passes if target is between min and max" do expect(5).to matcher(1, 10) end it "fails if target is not between min and max" do expect { # It does not go to 11 expect(11).to matcher(1, 10) }.to fail_with("expected 11 to be between 1 and 10 (#{mode})") end it "works with strings" do expect("baz").to matcher("bar", "foo") expect { expect("foo").to matcher("bar", "baz") }.to fail_with("expected \"foo\" to be between \"bar\" and \"baz\" (#{mode})") end it "works with other Comparable objects" do expect(SizeMatters.new("--")).to matcher(SizeMatters.new("-"), SizeMatters.new("---")) expect { expect(SizeMatters.new("---")).to matcher(SizeMatters.new("-"), SizeMatters.new("--")) }.to fail_with("expected --- to be between - and -- (#{mode})") end end shared_examples_for "not_to be_between" do |mode| it "passes if target is not between min and max" do expect(11).not_to matcher(1, 10) end it "fails if target is between min and max" do expect { expect(5).not_to matcher(1, 10) }.to fail_with("expected 5 not to be between 1 and 10 (#{mode})") end end shared_examples_for "composing with other matchers" do |mode| it "passes when the matchers both match" do expect([nil, 3]).to include(matcher(2, 4), a_nil_value) end it "works with mixed types" do expect(["baz", Math::PI]).to include(matcher(3.1, 3.2), matcher("bar", "foo")) expect { expect(["baz", 2.14]).to include(matcher(3.1, 3.2), matcher("bar", "foo") ) }.to fail_with("expected [\"baz\", 2.14] to include (a value between 3.1 and 3.2 (#{mode})) and (a value between \"bar\" and \"foo\" (#{mode}))") end it "provides a description" do description = include(matcher(2, 4), an_instance_of(Float)).description expect(description).to eq("include (a value between 2 and 4 (#{mode})) and (an instance of Float)") end it "fails with a clear error message when the matchers do not match" do expect { expect([nil, 1]).to include(matcher(2, 4), a_nil_value) }.to fail_with("expected [nil, 1] to include (a value between 2 and 4 (#{mode})) and (a nil value)") end end it_behaves_like "an RSpec matcher", :valid_value => (10), :invalid_value => (11) do let(:matcher) { be_between(1, 10) } end describe "expect(...).to be_between(min, max) (inclusive)" do it_behaves_like "be_between", :inclusive do def matcher(min, max) be_between(min, max) end end it "is inclusive" do expect(1).to be_between(1, 10) expect(10).to be_between(1, 10) end it "indicates it was not comparable if it does not respond to `<=` and `>=`" do expect { expect(nil).to be_between(0, 10) }.to fail_with("expected nil to be between 0 and 10 (inclusive), but it does not respond to `<=` and `>=`") end end describe "expect(...).to be_between(min, max) (exclusive)" do it_behaves_like "be_between", :exclusive do def matcher(min, max) be_between(min, max).exclusive end end it "indicates it was not comparable if it does not respond to `<` and `>`" do expect { expect(nil).to be_between(0, 10).exclusive }.to fail_with("expected nil to be between 0 and 10 (exclusive), but it does not respond to `<` and `>`") end it "is exclusive" do expect { expect(1).to be_between(1, 10).exclusive }.to fail expect { expect(10).to be_between(1, 10).exclusive }.to fail end end describe "expect(...).not_to be_between(min, max) (inclusive)" do it_behaves_like "not_to be_between", :inclusive do def matcher(min, max) be_between(min, max) end end end describe "expect(...).not_to be_between(min, max) (exclusive)" do it_behaves_like "not_to be_between", :exclusive do def matcher(min, max) be_between(min, max).exclusive end end end describe "composing with other matchers (inclusive)" do it_behaves_like "composing with other matchers", :inclusive do def matcher(min, max) a_value_between(min, max) end end end describe "composing with other matchers (exclusive)" do it_behaves_like "composing with other matchers", :exclusive do def matcher(min, max) a_value_between(min, max).exclusive end end end end end