Files
openfoodnetwork/spec/models/spree/shipping_method_spec.rb
Cillian O'Ruanaidh fc4f951a1a Only require OrderCycleShippingMethod records if people want to override the default shipping methods
It makes things much simpler if we return all shipping methods by default without needing OrderCycleShippingMethod records to be added to the database.

Co-authored-by: Maikel <maikel@email.org.au>
2022-09-30 13:13:39 +01:00

322 lines
11 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
module Spree
describe ShippingMethod do
it "is valid when built from factory" do
expect(
build(
:shipping_method,
shipping_categories: [Spree::ShippingCategory.new(name: 'Test')]
)
).to be_valid
end
it "can have distributors" do
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
sm = create(:shipping_method)
sm.distributors.clear
sm.distributors << d1
sm.distributors << d2
expect(sm.reload.distributors).to match_array [d1, d2]
end
describe "scope" do
describe "filtering to specified distributors" do
let!(:distributor_a) { create(:distributor_enterprise) }
let!(:distributor_b) { create(:distributor_enterprise) }
let!(:distributor_c) { create(:distributor_enterprise) }
let!(:shipping_method_a) {
create(:shipping_method, distributors: [distributor_a, distributor_b])
}
let!(:shipping_method_b) { create(:shipping_method, distributors: [distributor_b]) }
let!(:shipping_method_c) { create(:shipping_method, distributors: [distributor_c]) }
it "includes only unique records under specified distributors" do
result = described_class.for_distributors([distributor_a, distributor_b])
expect(result.length).to eq(2)
expect(result).to include(shipping_method_a)
expect(result).to include(shipping_method_b)
end
end
it "finds shipping methods for a particular distributor" do
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
sm1 = create(:shipping_method, distributors: [d1])
sm2 = create(:shipping_method, distributors: [d2])
expect(ShippingMethod.for_distributor(d1)).to eq([sm1])
end
end
it "orders shipping methods by name" do
sm1 = create(:shipping_method, name: 'ZZ')
sm2 = create(:shipping_method, name: 'AA')
sm3 = create(:shipping_method, name: 'BB')
expect(ShippingMethod.by_name).to eq([sm2, sm3, sm1])
end
describe "finding services offered by all distributors" do
let!(:d1) { create(:distributor_enterprise) }
let!(:d2) { create(:distributor_enterprise) }
let!(:d3) { create(:distributor_enterprise) }
let!(:d4) { create(:distributor_enterprise) }
let!(:d1_pickup) { create(:shipping_method, require_ship_address: false, distributors: [d1]) }
let!(:d1_delivery) {
create(:shipping_method, require_ship_address: true, distributors: [d1])
}
let!(:d2_pickup) { create(:shipping_method, require_ship_address: false, distributors: [d2]) }
let!(:d3_delivery) {
create(:shipping_method, require_ship_address: true, distributors: [d3])
}
it "reports when the services are available" do
expect(ShippingMethod.services[d1.id]).to eq(pickup: true, delivery: true)
end
it "reports when only pickup is available" do
expect(ShippingMethod.services[d2.id]).to eq(pickup: true, delivery: false)
end
it "reports when only delivery is available" do
expect(ShippingMethod.services[d3.id]).to eq(pickup: false, delivery: true)
end
it "returns no entry when no service is available" do
expect(ShippingMethod.services[d4.id]).to be_nil
end
end
describe '#delivery?' do
context 'when the shipping method requires an address' do
let(:shipping_method) { build(:shipping_method, require_ship_address: true) }
it { expect(shipping_method.delivery?).to be true }
end
context 'when the shipping method does not require address' do
let(:shipping_method) { build(:shipping_method, require_ship_address: false) }
it { expect(shipping_method.delivery?).to be false }
end
end
describe "#include?" do
let(:shipping_method) { build_stubbed(:shipping_method) }
it "does not include a nil address" do
expect(shipping_method.include?(nil)).to be false
end
it "includes an address that is not included in the zones of the shipping method" do
address = create(:address)
zone_mock = instance_double(Spree::Zone)
allow(zone_mock).to receive(:include?).with(address).and_return(false)
allow(shipping_method).to receive(:zones) { [zone_mock] }
expect(shipping_method.include?(address)).to be true
end
end
describe "touches" do
let!(:distributor) { create(:distributor_enterprise) }
let!(:shipping_method) { create(:shipping_method) }
let(:add_distributor) { shipping_method.distributors << distributor }
it "is touched when applied to a distributor" do
expect{ add_distributor }.to change { shipping_method.reload.updated_at }
end
end
context "validations" do
it "validates presence of name" do
shipping_method = build_stubbed(
:shipping_method,
name: ''
)
expect(shipping_method).not_to be_valid
expect(shipping_method.errors[:name].first).to eq "can't be blank"
end
describe "#display_on" do
it "is valid when it's set to nil, an empty string or 'back_end'" do
shipping_method = build_stubbed(:shipping_method)
[nil, "", "back_end"].each do |display_on_option|
shipping_method.display_on = display_on_option
shipping_method.valid?
expect(shipping_method.errors[:display_on]).to be_empty
end
end
it "is not valid when it's set to an unknown value" do
shipping_method = build_stubbed(:shipping_method, display_on: "front_end")
expect(shipping_method).not_to be_valid
expect(shipping_method.errors[:display_on]).to eq ["is not included in the list"]
end
end
context "shipping category" do
it "validates presence of at least one" do
shipping_method = build_stubbed(
:shipping_method,
shipping_categories: []
)
expect(shipping_method).not_to be_valid
expect(shipping_method.errors[:base].first).to eq "You need to select at least one shipping category"
end
context "one associated" do
let(:shipping_method) do
build_stubbed(
:shipping_method,
shipping_categories: [Spree::ShippingCategory.new(name: 'Test')]
)
end
it { expect(shipping_method).to be_valid }
end
end
context "when it is being changed to backoffice only" do
let!(:order_cycle) { create(:distributor_order_cycle, distributors: [distributor]) }
let(:distributor) { create(:distributor_enterprise, shipping_methods: [shipping_method]) }
let(:shipping_method) { create(:shipping_method) }
context "when one of its distributors has no other shipping methods available
on an active or upcoming order cycle" do
it "should not be valid" do
shipping_method.display_on = "back_end"
expect(shipping_method).not_to be_valid
expect(shipping_method.errors.to_a).to eq [
"Unable to switch to backoffice only, some open or upcoming order cycles would be " \
"left without any shipping methods"
]
end
end
context "when one of its distributors has no other shipping methods available
on an order cycle which isn't active or upcoming" do
it "is valid" do
order_cycle.update!(orders_open_at: 2.weeks.ago, orders_close_at: 1.week.ago)
shipping_method.display_on = "back_end"
expect(shipping_method).to be_valid
end
end
context "when one of its distributors has other shipping methods available
on an active or upcoming order cycle" do
it "is valid" do
create(:shipping_method, distributors: [distributor])
shipping_method.display_on = "back_end"
expect(shipping_method).to be_valid
end
end
end
end
# Regression test for Spree #4320
context "soft deletion" do
let(:shipping_method) { create(:shipping_method) }
it "soft-deletes when destroy is called" do
shipping_method.destroy
expect(shipping_method.deleted_at).to_not be_blank
end
end
context 'factory' do
let(:shipping_method){ create :shipping_method }
it "should set calculable correctly" do
expect(shipping_method.calculator.calculable).to eq(shipping_method)
end
end
# Regression test for Spree #4492
context "#shipments" do
let!(:shipping_method) { create(:shipping_method) }
let!(:shipment) do
shipment = create(:shipment)
shipment.shipping_rates.create!(shipping_method: shipping_method)
shipment
end
it "can gather all the related shipments" do
expect(shipping_method.shipments).to include(shipment)
end
end
context "#destroy" do
let(:shipping_method) { create(:shipping_method) }
let(:distributor) { create(:distributor_enterprise, shipping_methods: [shipping_method]) }
let!(:order_cycle) { create(:distributor_order_cycle, distributors: [distributor]) }
context "when its distributors are part of some order cycles
and have no other shipping methods available" do
it "can be deleted if the order cycle is closed" do
order_cycle.update!(orders_close_at: 1.minute.ago)
shipping_method.destroy
expect(shipping_method).to be_deleted
end
it "cannot be deleted if the order cycle is active" do
order_cycle.update!(orders_open_at: 1.day.ago, orders_close_at: 1.week.from_now)
shipping_method.destroy
expect(shipping_method).not_to be_deleted
expect(shipping_method.errors.to_a).to eq [
"Unable to delete, some open or upcoming order cycles would be left without any " \
"shipping methods"
]
end
it "cannot be deleted if the order cycle is upcoming" do
order_cycle.update!(orders_open_at: 1.day.from_now, orders_close_at: 1.week.from_now)
shipping_method.destroy
expect(shipping_method).not_to be_deleted
expect(shipping_method.errors.to_a).to eq [
"Unable to delete, some open or upcoming order cycles would be left without any " \
"shipping methods"
]
end
end
context "when its distributors are part of some active or upcoming order cycles
and have other shipping methods available" do
it "can be deleted" do
create(:shipping_method, distributors: [distributor])
shipping_method.destroy
expect(shipping_method).to be_deleted
end
end
context "when its distributors have no other shipping methods available
but aren't part of active/upcoming order cycles" do
it "can be deleted" do
order_cycle.update!(orders_open_at: 2.weeks.ago, orders_close_at: 1.week.ago)
shipping_method.destroy
expect(shipping_method).to be_deleted
end
end
end
end
end