Files
openfoodnetwork/spec/controllers/api/shipments_controller_spec.rb
2020-06-08 19:17:11 +01:00

235 lines
7.5 KiB
Ruby

require 'spec_helper'
describe Api::ShipmentsController, type: :controller do
render_views
let!(:shipment) { create(:shipment) }
let!(:attributes) do
[:id, :tracking, :number, :cost, :shipped_at, :stock_location_name, :order_id]
end
let(:current_api_user) { build(:user) }
before do
allow(controller).to receive(:spree_current_user) { current_api_user }
end
context "as a non-admin" do
it "cannot make a shipment ready" do
api_put :ready, order_id: shipment.order.to_param, id: shipment.to_param
assert_unauthorized!
end
it "cannot make a shipment shipped" do
api_put :ship, order_id: shipment.order.to_param, id: shipment.to_param
assert_unauthorized!
end
end
context "as an admin" do
let(:current_api_user) { build(:admin_user) }
let!(:order) { shipment.order }
let(:order_ship_address) { create(:address) }
let!(:stock_location) { create(:stock_location_with_items) }
let!(:variant) { create(:variant) }
let(:params) do
{ quantity: 2,
variant_id: variant.to_param,
order_id: order.number,
stock_location_id: stock_location.to_param,
format: :json }
end
let(:error_message) { "broken shipments creation" }
before do
order.update_attribute :ship_address_id, order_ship_address.id
order.update_attribute :distributor, variant.product.supplier
shipment.shipping_method.distributors << variant.product.supplier
end
context '#create' do
it 'creates a shipment if order does not have a shipment' do
order.shipment.destroy
order.reload
spree_post :create, params
expect_valid_response
expect(order.shipment.reload.inventory_units.size).to eq 2
expect(order.reload.line_items.first.variant.price).to eq(variant.price)
end
it 'updates and returns exiting shipment, if order already has a shipment' do
original_shipment_id = order.shipment.id
spree_post :create, params
expect(json_response["id"]). to eq(original_shipment_id)
expect_valid_response
expect(order.shipment.reload.inventory_units.size).to eq 2
expect(order.reload.line_items.first.variant.price).to eq(variant.price)
end
it 'updates existing shipment with variant override if an VO is sent' do
hub = create(:distributor_enterprise)
order.update_attribute(:distributor, hub)
shipment.shipping_method.distributors << hub
variant_override = create(:variant_override, hub: hub, variant: variant)
spree_post :create, params
expect_valid_response
expect(order.shipment.reload.inventory_units.size).to eq 2
expect(order.reload.line_items.first.price).to eq(variant_override.price)
end
it 'returns error code when adding to order contents fails' do
make_order_contents_fail
spree_post :create, params
expect_error_response
end
end
it "can make a shipment ready" do
allow_any_instance_of(Spree::Order).to receive_messages(paid?: true, complete?: true)
api_put :ready, order_id: shipment.order.to_param, id: shipment.to_param
expect(attributes.all?{ |attr| json_response.key? attr.to_s }).to be_truthy
expect(json_response["state"]).to eq("ready")
expect(shipment.reload.state).to eq("ready")
end
it "cannot make a shipment ready if the order is unpaid" do
allow_any_instance_of(Spree::Order).to receive_messages(paid?: false)
api_put :ready, order_id: shipment.order.to_param, id: shipment.to_param
expect(json_response["error"]).to eq("Cannot ready shipment.")
expect(response.status).to eq(422)
end
context 'for completed shipments' do
let(:order) { create :completed_order_with_totals }
it 'adds a variant to a shipment' do
api_put :add, variant_id: variant.to_param,
quantity: 2,
order_id: order.to_param,
id: order.shipments.first.to_param
expect(response.status).to eq(200)
expect(inventory_units_for(variant).size).to eq 2
end
it 'removes a variant from a shipment' do
order.contents.add(variant, 2)
api_put :remove, variant_id: variant.to_param,
quantity: 1,
order_id: order.to_param,
id: order.shipments.first.to_param
expect(response.status).to eq(200)
expect(inventory_units_for(variant).size).to eq(1)
end
end
context "can transition a shipment from ready to ship" do
before do
allow_any_instance_of(Spree::Order).to receive_messages(paid?: true, complete?: true)
# For the shipment notification email
Spree::Config[:mails_from] = "ofn@example.com"
shipment.update!(shipment.order)
expect(shipment.state).to eq("ready")
allow_any_instance_of(Spree::ShippingRate).to receive_messages(cost: 5)
end
it "can transition a shipment from ready to ship" do
shipment.reload
api_put :ship, order_id: shipment.order.to_param,
id: shipment.to_param,
shipment: { tracking: "123123" }
expect(attributes.all?{ |attr| json_response.key? attr.to_s }).to be_truthy
expect(json_response["state"]).to eq("shipped")
end
end
context 'for a completed order with shipment' do
let(:order) { create :completed_order_with_totals }
before { params[:id] = order.shipments.first.to_param }
context '#add' do
it 'adds a variant to the shipment' do
spree_put :add, params
expect_valid_response
expect(inventory_units_for(variant).size).to eq 2
end
it 'returns error code when adding to order contents fails' do
make_order_contents_fail
spree_put :add, params
expect_error_response
end
it 'adds a variant override to the shipment' do
hub = create(:distributor_enterprise)
order.update_attribute(:distributor, hub)
variant_override = create(:variant_override, hub: hub, variant: variant)
spree_put :add, params
expect_valid_response
expect(inventory_units_for(variant).size).to eq 2
expect(order.reload.line_items.last.price).to eq(variant_override.price)
end
end
context '#remove' do
before do
params[:variant_id] = order.line_items.first.variant.to_param
params[:quantity] = 1
end
it 'removes a variant from the shipment' do
spree_put :remove, params
expect_valid_response
expect(inventory_units_for(variant).size).to eq 0
end
it 'returns error code when removing from order contents fails' do
make_order_contents_fail
spree_put :remove, params
expect_error_response
end
end
end
def inventory_units_for(variant)
order.shipment.reload.inventory_units.select { |unit| unit['variant_id'] == variant.id }
end
def expect_valid_response
expect(response.status).to eq 200
attributes.all?{ |attr| json_response.key? attr.to_s }
end
def make_order_contents_fail
expect(Spree::Order).to receive(:find_by!).with({ number: order.number }) { order }
expect(order).to receive(:contents) { raise error_message }
end
def expect_error_response
expect(response.status).to eq 422
expect(json_response["exception"]).to eq error_message
end
end
end