Files
openfoodnetwork/spec/models/exchange_spec.rb
Maikel Linke 73372a58ef Remove unused and dangerous Exchange#eql? override
The `eql?` override has been added in very early commits but was
actually not used except in a test. It also caused performance problems
since each call to `eql?` would issue two database queries. A developer
would unknowingly trigger these when using `exchanges.uniq`. A mistake
that could have happened again in the future.

I moved the implementation to the test that was actually using it and
made a second test a bit more explicit.
2019-07-02 18:42:02 +10:00

300 lines
10 KiB
Ruby

require 'spec_helper'
describe Exchange do
it "should be valid when built from factory" do
expect(build(:exchange)).to be_valid
end
[:order_cycle, :sender, :receiver].each do |attr|
it "should not be valid without #{attr}" do
e = build(:exchange)
e.send("#{attr}=", nil)
expect(e).not_to be_valid
end
end
it "should not be valid when (sender, receiver, direction) set are not unique for its order cycle" do
e1 = create(:exchange)
e2 = build(:exchange,
order_cycle: e1.order_cycle, sender: e1.sender, receiver: e1.receiver, incoming: e1.incoming)
expect(e2).not_to be_valid
e2.incoming = !e2.incoming
expect(e2).to be_valid
e2.incoming = !e2.incoming
e2.receiver = create(:enterprise)
expect(e2).to be_valid
e2.sender = e2.receiver
e2.receiver = e1.receiver
expect(e2).to be_valid
end
it "has exchange variants" do
e = create(:exchange)
p = create(:product)
e.exchange_variants.create(variant: p.master)
expect(e.variants.count).to eq(1)
end
it "has exchange fees" do
e = create(:exchange)
f = create(:enterprise_fee)
e.exchange_fees.create(enterprise_fee: f)
expect(e.enterprise_fees.count).to eq(1)
end
describe "exchange directionality" do
let(:supplier) { create(:supplier_enterprise) }
let(:coordinator) { create(:distributor_enterprise) }
let(:distributor) { create(:distributor_enterprise) }
let(:oc) { create(:simple_order_cycle, coordinator: coordinator) }
let(:incoming_exchange) { oc.exchanges.create! sender: supplier, receiver: coordinator, incoming: true }
let(:outgoing_exchange) { oc.exchanges.create! sender: coordinator, receiver: distributor, incoming: false }
describe "reporting whether it is an incoming exchange" do
it "returns true for incoming exchanges" do
expect(incoming_exchange).to be_incoming
end
it "returns false for outgoing exchanges" do
expect(outgoing_exchange).not_to be_incoming
end
end
describe "finding the exchange participant (the enterprise other than the coordinator)" do
it "returns the sender for incoming exchanges" do
expect(incoming_exchange.participant).to eq(supplier)
end
it "returns the receiver for outgoing exchanges" do
expect(outgoing_exchange.participant).to eq(distributor)
end
end
end
describe "reporting its role" do
it "returns 'supplier' when it is an incoming exchange" do
e = Exchange.new
allow(e).to receive(:incoming?) { true }
expect(e.role).to eq('supplier')
end
it "returns 'distributor' when it is an outgoing exchange" do
e = Exchange.new
allow(e).to receive(:incoming?) { false }
expect(e.role).to eq('distributor')
end
end
describe "products caching" do
let!(:exchange) { create(:exchange) }
it "refreshes the products cache on change" do
expect(OpenFoodNetwork::ProductsCache).to receive(:exchange_changed).with(exchange)
exchange.pickup_time = 'asdf'
exchange.save
end
it "refreshes the products cache on destruction" do
expect(OpenFoodNetwork::ProductsCache).to receive(:exchange_destroyed).with(exchange)
exchange.destroy
end
end
describe "scopes" do
let(:supplier) { create(:supplier_enterprise) }
let(:coordinator) { create(:distributor_enterprise, is_primary_producer: true) }
let(:distributor) { create(:distributor_enterprise) }
let(:oc) { create(:simple_order_cycle, coordinator: coordinator) }
describe "finding exchanges managed by a particular user" do
let(:user) do
user = create(:user)
user.spree_roles = []
user
end
before { Exchange.destroy_all }
it "returns exchanges where the user manages both the sender and the receiver" do
exchange = create(:exchange, order_cycle: oc)
exchange.sender.users << user
exchange.receiver.users << user
expect(Exchange.managed_by(user)).to eq([exchange])
end
it "does not return exchanges where the user manages only the sender" do
exchange = create(:exchange, order_cycle: oc)
exchange.sender.users << user
expect(Exchange.managed_by(user)).to be_empty
end
it "does not return exchanges where the user manages only the receiver" do
exchange = create(:exchange, order_cycle: oc)
exchange.receiver.users << user
expect(Exchange.managed_by(user)).to be_empty
end
it "does not return exchanges where the user manages neither enterprise" do
exchange = create(:exchange, order_cycle: oc)
expect(Exchange.managed_by(user)).to be_empty
end
end
it "finds exchanges in a particular order cycle" do
ex = create(:exchange, order_cycle: oc)
expect(Exchange.in_order_cycle(oc)).to eq([ex])
end
describe "finding exchanges by direction" do
let!(:incoming_exchange) { oc.exchanges.create! sender: supplier, receiver: coordinator, incoming: true }
let!(:outgoing_exchange) { oc.exchanges.create! sender: coordinator, receiver: distributor, incoming: false }
it "finds incoming exchanges" do
expect(Exchange.incoming).to eq([incoming_exchange])
end
it "finds outgoing exchanges" do
expect(Exchange.outgoing).to eq([outgoing_exchange])
end
it "correctly determines direction of exchanges between the same enterprise" do
incoming_exchange.update_attributes sender: coordinator, incoming: true
outgoing_exchange.update_attributes receiver: coordinator, incoming: false
expect(Exchange.incoming).to eq([incoming_exchange])
expect(Exchange.outgoing).to eq([outgoing_exchange])
end
it "finds exchanges coming from an enterprise" do
expect(Exchange.from_enterprise(supplier)).to eq([incoming_exchange])
expect(Exchange.from_enterprise(coordinator)).to eq([outgoing_exchange])
end
it "finds exchanges going to an enterprise" do
expect(Exchange.to_enterprise(coordinator)).to eq([incoming_exchange])
expect(Exchange.to_enterprise(distributor)).to eq([outgoing_exchange])
end
it "finds exchanges coming from any of a number of enterprises" do
expect(Exchange.from_enterprises([coordinator])).to eq([outgoing_exchange])
expect(Exchange.from_enterprises([supplier, coordinator])).to match_array [incoming_exchange, outgoing_exchange]
end
it "finds exchanges going to any of a number of enterprises" do
expect(Exchange.to_enterprises([coordinator])).to eq([incoming_exchange])
expect(Exchange.to_enterprises([coordinator, distributor])).to match_array [incoming_exchange, outgoing_exchange]
end
it "finds exchanges involving any of a number of enterprises" do
expect(Exchange.involving([supplier])).to eq([incoming_exchange])
expect(Exchange.involving([coordinator])).to match_array [incoming_exchange, outgoing_exchange]
expect(Exchange.involving([distributor])).to eq([outgoing_exchange])
end
end
describe "finding exchanges supplying to a distributor" do
it "returns incoming exchanges" do
d = create(:distributor_enterprise)
ex = create(:exchange, order_cycle: oc, incoming: true)
expect(oc.exchanges.supplying_to(d)).to eq([ex])
end
it "returns outgoing exchanges to the distributor" do
d = create(:distributor_enterprise)
ex = create(:exchange, order_cycle: oc, receiver: d, incoming: false)
expect(oc.exchanges.supplying_to(d)).to eq([ex])
end
it "does not return outgoing exchanges to a different distributor" do
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
ex = create(:exchange, order_cycle: oc, receiver: d1, incoming: false)
expect(oc.exchanges.supplying_to(d2)).to be_empty
end
end
it "finds exchanges with a particular variant" do
v = create(:variant)
ex = create(:exchange)
ex.variants << v
expect(Exchange.with_variant(v)).to eq([ex])
end
it "finds exchanges with any of a number of variants, without returning duplicates" do
v1 = create(:variant)
v2 = create(:variant)
v3 = create(:variant)
ex = create(:exchange)
ex.variants << v1
ex.variants << v2
expect(Exchange.with_any_variant([v1.id, v2.id, v3.id])).to eq([ex])
end
it "finds exchanges with a particular product's master variant" do
p = create(:simple_product)
ex = create(:exchange)
ex.variants << p.master
p.reload
expect(Exchange.with_product(p)).to eq([ex])
end
it "finds exchanges with a particular product's non-master variant" do
p = create(:simple_product)
v = create(:variant, product: p)
ex = create(:exchange)
ex.variants << v
p.reload
expect(Exchange.with_product(p)).to eq([ex])
end
describe "sorting exchanges by primary enterprise name" do
let(:e1) { create(:supplier_enterprise, name: 'ZZZ') }
let(:e2) { create(:distributor_enterprise, name: 'AAA') }
let(:e3) { create(:supplier_enterprise, name: 'CCC') }
let!(:ex1) { create(:exchange, sender: e1, incoming: true) }
let!(:ex2) { create(:exchange, receiver: e2, incoming: false) }
let!(:ex3) { create(:exchange, sender: e3, incoming: true) }
it "sorts" do
expect(Exchange.by_enterprise_name).to eq([ex2, ex3, ex1])
end
end
end
it "clones itself" do
oc = create(:order_cycle)
new_oc = create(:simple_order_cycle)
ex1 = oc.exchanges.last
ex1.update_attribute(:tag_list, "wholesale")
ex2 = ex1.clone! new_oc
expect(ex1.sender_id).to eq ex2.sender_id
expect(ex1.receiver_id).to eq ex2.receiver_id
expect(ex1.pickup_time).to eq ex2.pickup_time
expect(ex1.pickup_instructions).to eq ex2.pickup_instructions
expect(ex1.incoming).to eq ex2.incoming
expect(ex1.receival_instructions).to eq ex2.receival_instructions
expect(ex1.variant_ids).to eq ex2.variant_ids
expect(ex1.enterprise_fee_ids).to eq ex2.enterprise_fee_ids
expect(ex2.reload.tag_list).to eq ["wholesale"]
end
end