require 'rails_helper' RSpec.describe Spree::StockQuantities, type: :model do let(:variant1) { mock_model(Spree::Variant) } let(:variant2) { mock_model(Spree::Variant) } subject do described_class.new(quantities) end describe "#each" do def expect_each expect { |b| subject.each(&b) } end context "with no items" do let(:quantities) { {} } it "doesn't yield" do expect_each.not_to yield_control end end context "with one item" do let(:quantities) { { variant1 => 2 } } it "yields values" do expect_each.to yield_with_args([variant1, 2]) end end context "with two items" do let(:quantities) { { variant1 => 2, variant2 => 3 } } it "yields values" do expect_each.to yield_successive_args([variant1, 2], [variant2, 3]) end end end describe "#variants" do context "with one item" do let(:quantities) { { variant1 => 2 } } it "returns variant" do expect(subject.variants).to eq [variant1] end end context "with two items" do let(:quantities) { { variant1 => 2, variant2 => 3 } } it "returns both variants" do expect(subject.variants).to eq [variant1, variant2] end end end describe "#empty?" do context "no variants" do let(:quantities) { {} } it { is_expected.to be_empty } end context "only quantity 0" do let(:quantities) { { variant1 => 0 } } it { is_expected.to be_empty } end context "positive quantity" do let(:quantities) { { variant1 => 1 } } it { is_expected.not_to be_empty } end context "one variant positive one zero" do let(:quantities) { { variant1 => 1, variant2 => 0 } } it { is_expected.not_to be_empty } end context "negative quantity" do # empty? doesn't make a whole lot of sense in this case, but returning # false is probably more accurate. let(:quantities) { { variant1 => -1 } } it { is_expected.not_to be_empty } end end describe "==" do subject do described_class.new(quantity1) == described_class.new(quantity2) end context "when both empty" do let(:quantity1) { {} } let(:quantity2) { {} } it { is_expected.to be true } end context "when both equal" do let(:quantity1) { { variant1 => 1 } } let(:quantity2) { { variant1 => 1 } } it { is_expected.to be true } end context "with different order" do let(:quantity1) { { variant1 => 1, variant2 => 2 } } let(:quantity2) { { variant2 => 2, variant1 => 1 } } it { is_expected.to be true } end context "with different variant" do let(:quantity1) { { variant1 => 1 } } let(:quantity2) { { variant2 => 1 } } it { is_expected.to be false } end context "with different quantities" do let(:quantity1) { { variant1 => 1 } } let(:quantity2) { { variant1 => 2 } } it { is_expected.to be false } end context "nil != 0" do let(:quantity1) { { variant1 => 0 } } let(:quantity2) { {} } it { is_expected.to be false } end end describe "+" do subject do described_class.new(quantity1) + described_class.new(quantity2) end context "same variant" do let(:quantity1) { { variant1 => 20 } } let(:quantity2) { { variant1 => 22 } } it { is_expected.to eq described_class.new({ variant1 => 42 }) } end context "different variants" do let(:quantity1) { { variant1 => 1 } } let(:quantity2) { { variant2 => 2 } } it { is_expected.to eq described_class.new({ variant1 => 1, variant2 => 2 }) } end context "0 quantities" do let(:quantity1) { { variant1 => 0 } } let(:quantity2) { { variant2 => 1 } } it { is_expected.to eq described_class.new({ variant1 => 0, variant2 => 1 }) } end context "empty quantity" do let(:quantity1) { { variant1 => 1 } } let(:quantity2) { {} } it { is_expected.to eq described_class.new({ variant1 => 1 }) } end end describe "-" do subject do described_class.new(quantity1) - described_class.new(quantity2) end context "same variant" do let(:quantity1) { { variant1 => 22 } } let(:quantity2) { { variant1 => 20 } } it { is_expected.to eq described_class.new({ variant1 => 2 }) } end context "different variants" do let(:quantity1) { { variant1 => 1 } } let(:quantity2) { { variant2 => 2 } } it { is_expected.to eq described_class.new({ variant1 => 1, variant2 => -2 }) } end context "0 quantity" do let(:quantity1) { { variant1 => 0 } } let(:quantity2) { { variant1 => 1 } } it { is_expected.to eq described_class.new({ variant1 => -1 }) } end context "empty quantity RHS" do let(:quantity1) { { variant1 => 1 } } let(:quantity2) { {} } it { is_expected.to eq described_class.new({ variant1 => 1 }) } end context "empty quantity LHS" do let(:quantity1) { {} } let(:quantity2) { { variant1 => 1 } } it { is_expected.to eq described_class.new({ variant1 => -1 }) } end end # Common subset describe "&" do subject do described_class.new(quantity1) & described_class.new(quantity2) end context "same variant" do let(:quantity1) { { variant1 => 20 } } let(:quantity2) { { variant1 => 22 } } it { is_expected.to eq described_class.new({ variant1 => 20 }) } end context "multiple variants" do let(:quantity1) { { variant1 => 10, variant2 => 20 } } let(:quantity2) { { variant1 => 12, variant2 => 14 } } it { is_expected.to eq described_class.new({ variant1 => 10, variant2 => 14 }) } end context "different variants" do let(:quantity1) { { variant1 => 1 } } let(:quantity2) { { variant2 => 2 } } it { is_expected.to be_empty } it { is_expected.to eq described_class.new({}) } end context "0 quantities" do let(:quantity1) { { variant1 => 0 } } let(:quantity2) { { variant1 => 1 } } it { is_expected.to eq described_class.new({ variant1 => 0 }) } end context "empty quantity" do let(:quantity1) { { variant1 => 1 } } let(:quantity2) { {} } it { is_expected.to eq described_class.new({}) } end end end