# frozen_string_literal: true require 'spec_helper' RSpec.describe Spree::OrderInventory do let(:order) { create :completed_order_with_totals } let(:line_item) { order.line_items.first } subject { described_class.new(order) } it 'inventory_units_for should return array of units for a given variant' do units = subject.inventory_units_for(line_item.variant) expect(units.map(&:variant_id)).to eq [line_item.variant.id] end context "when order is missing inventory units" do before do line_item.update_column(:quantity, 2) end it 'should be a messed up order' do expect(order.shipments.first.inventory_units_for(line_item.variant).size).to eq 1 expect(line_item.reload.quantity).to eq 2 end it 'should increase the number of inventory units' do subject.verify(line_item) expect(order.reload.shipments.first.inventory_units_for(line_item.variant).size).to eq 2 end end context "#add_to_shipment" do let(:shipment) { order.shipments.first } let(:variant) { create :variant } context "order is not completed" do before { allow(order).to receive_messages completed?: false } it "doesn't unstock items" do expect(line_item.variant).not_to receive(:move) expect(subject.__send__(:add_to_shipment, shipment, variant, 5)).to eq 5 end end it 'should create inventory_units in the necessary states' do expect(variant).to receive(:fill_status).with(5).and_return([3, 2]) expect(subject.__send__(:add_to_shipment, shipment, variant, 5)).to eq 5 units = shipment.inventory_units.group_by(&:variant_id) units = units[variant.id].group_by(&:state) expect(units['backordered'].size).to eq 2 expect(units['on_hand'].size).to eq 3 end end context 'when order has too many inventory units' do before do line_item.quantity = 3 line_item.save! line_item.update_column(:quantity, 2) order.reload end it 'should be a messed up order' do expect(order.shipments.first.inventory_units_for(line_item.variant).size).to eq 3 expect(line_item.quantity).to eq 2 end it 'should decrease the number of inventory units' do subject.verify(line_item) expect(order.reload.shipments.first.inventory_units_for(line_item.variant).size).to eq 2 end context '#remove_from_shipment' do let(:shipment) { order.shipments.first } let(:variant) { order.line_items.first.variant } context "order is not completed" do before { allow(order).to receive_messages completed?: false } it "doesn't restock items" do expect(variant).not_to receive(:move) expect(subject.__send__(:remove_from_shipment, shipment, variant, 1, true)).to eq 1 end end context "order is completed" do before { allow(order).to receive_messages completed?: true } it "doesn't restock items" do expect(variant).not_to receive(:move) expect(subject.__send__(:remove_from_shipment, shipment, variant, 1, false)).to eq 1 end end it 'should destroy backordered units first' do allow(shipment).to receive_messages(inventory_units_for: [ build(:inventory_unit, variant_id: variant.id, state: 'backordered'), build(:inventory_unit, variant_id: variant.id, state: 'on_hand'), build(:inventory_unit, variant_id: variant.id, state: 'backordered') ] ) expect(shipment.inventory_units_for[0]).to receive(:destroy) expect(shipment.inventory_units_for[1]).not_to receive(:destroy) expect(shipment.inventory_units_for[2]).to receive(:destroy) expect(subject.__send__(:remove_from_shipment, shipment, variant, 2, true)).to eq 2 end it 'should destroy unshipped units first' do allow(shipment).to receive_messages(inventory_units_for: [ build(:inventory_unit, variant_id: variant.id, state: 'shipped'), build(:inventory_unit, variant_id: variant.id, state: 'on_hand') ] ) expect(shipment.inventory_units_for[0]).not_to receive(:destroy) expect(shipment.inventory_units_for[1]).to receive(:destroy) expect(subject.__send__(:remove_from_shipment, shipment, variant, 1, true)).to eq 1 end it 'only attempts to destroy as many units as are eligible, and return amount destroyed' do allow(shipment).to receive_messages(inventory_units_for: [ build(:inventory_unit, variant_id: variant.id, state: 'shipped'), build(:inventory_unit, variant_id: variant.id, state: 'on_hand') ] ) expect(shipment.inventory_units_for[0]).not_to receive(:destroy) expect(shipment.inventory_units_for[1]).to receive(:destroy) expect(subject.__send__(:remove_from_shipment, shipment, variant, 1, true)).to eq 1 end it 'should destroy self if not inventory units remain' do allow(shipment.inventory_units).to receive_messages(count: 0) expect(shipment).to receive(:destroy) expect(subject.__send__(:remove_from_shipment, shipment, variant, 1, true)).to eq 1 end end end end