Files
openfoodnetwork/spec/models/spree/variant_stock_spec.rb
2025-07-09 13:43:18 +10:00

130 lines
3.9 KiB
Ruby

# frozen_string_literal: false
require 'spec_helper'
RSpec.describe Spree::Variant do
# These methods are defined in app/models/concerns/variant_stock.rb.
# There is a separate spec for that concern but here I want to test
# the interplay of Spree::Variant and VariantOverride.
#
# A variant can be scoped to a hub which means that all stock methods
# like this one get overridden. Future calls to `variant.move` are then
# handled by the ScopeVariantToHub module which may call the
# VariantOverride.
describe "#fill_status" do
subject(:variant) { create(:variant, on_hand: 15) }
it 'is all on_hand if variant is on_demand' do
variant.on_demand = true
on_hand, backordered = subject.fill_status(25)
expect(on_hand).to eq 25
expect(backordered).to eq 0
end
it 'is all on_hand if on_hand is enough' do
on_hand, backordered = subject.fill_status(5)
expect(on_hand).to eq 5
expect(backordered).to eq 0
end
it 'is some on_hand if not all available' do
on_hand, backordered = subject.fill_status(20)
expect(on_hand).to eq 15
expect(backordered).to eq 0
end
it 'is zero on_hand if none available' do
variant.on_hand = 0
on_hand, backordered = subject.fill_status(20)
expect(on_hand).to eq 0
expect(backordered).to eq 0
end
end
describe "#move" do
subject(:variant) { create(:variant, on_hand: 5) }
it "changes stock" do
expect { variant.move(-2) }.to change { variant.on_hand }.from(5).to(3)
end
it "reduces stock even when on demand" do
variant.on_demand = true
expect { variant.move(-2) }.to change { variant.on_hand }.from(5).to(3)
end
it "rejects negative stock" do
expect { variant.move(-7) }.to raise_error(
ActiveRecord::RecordInvalid,
"Validation failed: Count on hand must be greater than or equal to 0"
)
end
describe "with VariantOverride", feature: :inventory do
subject(:hub_variant) {
Spree::Variant.find(variant.id).tap { |v| scoper.scope(v) }
}
let(:override) {
VariantOverride.create!(
variant:,
hub: create(:distributor_enterprise),
count_on_hand: 7,
on_demand: false,
)
}
let(:scoper) { OpenFoodNetwork::ScopeVariantToHub.new(override.hub) }
it "changes stock only on the variant override" do
expect {
hub_variant.move(-3)
override.reload
}
.to change { override.count_on_hand }.from(7).to(4)
.and change { hub_variant.on_hand }.from(7).to(4)
.and change { variant.on_hand }.by(0)
end
it "reduces stock when on demand" do
override.update!(on_demand: true, count_on_hand: 7)
expect {
hub_variant.move(-3)
override.reload
}
.to change { override.count_on_hand }.from(7).to(4)
.and change { hub_variant.on_hand }.from(7).to(4)
.and change { variant.on_hand }.by(0)
end
it "doesn't prevent negative stock" do
# VariantOverride relies on other stock checks during checkout. :-(
expect {
hub_variant.move(-8)
override.reload
}
.to change { override.count_on_hand }.from(7).to(-1)
.and change { hub_variant.on_hand }.from(7).to(-1)
.and change { variant.on_hand }.by(0)
# The update didn't run validations and now it's invalid:
expect(override).not_to be_valid
end
it "doesn't fail on negative stock when on demand" do
override.update!(on_demand: true, count_on_hand: nil)
expect {
hub_variant.move(-8)
override.reload
}
.to change { override.count_on_hand }.from(nil).to(-8)
.and change { hub_variant.on_hand }.from(nil).to(-8)
.and change { variant.on_hand }.by(0)
end
end
end
end