berrypod/test/berrypod/shipping_test.exs
jamey 9528700862 rename project from SimpleshopTheme to Berrypod
All modules, configs, paths, and references updated.
836 tests pass, zero warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:23:15 +00:00

311 lines
8.3 KiB
Elixir

defmodule Berrypod.ShippingTest do
use Berrypod.DataCase, async: false
alias Berrypod.Shipping
alias Berrypod.Shipping.ShippingRate
import Berrypod.ProductsFixtures
describe "upsert_rates/2" do
test "inserts new rates" do
conn = provider_connection_fixture()
rates = [
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 450,
additional_item_cost: 100,
currency: "GBP"
},
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "US",
first_item_cost: 650,
additional_item_cost: 150,
currency: "USD"
}
]
assert {:ok, 2} = Shipping.upsert_rates(conn.id, rates)
assert Repo.aggregate(ShippingRate, :count) == 2
end
test "replaces existing rates on conflict" do
conn = provider_connection_fixture()
rates = [
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 450,
additional_item_cost: 100,
currency: "GBP"
}
]
{:ok, 1} = Shipping.upsert_rates(conn.id, rates)
updated_rates = [
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 550,
additional_item_cost: 200,
currency: "GBP"
}
]
{:ok, 1} = Shipping.upsert_rates(conn.id, updated_rates)
assert Repo.aggregate(ShippingRate, :count) == 1
rate = Repo.one(ShippingRate)
assert rate.first_item_cost == 550
assert rate.additional_item_cost == 200
end
end
describe "get_rate/3" do
test "returns rate when it exists" do
conn = provider_connection_fixture()
{:ok, _} =
Shipping.upsert_rates(conn.id, [
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 450,
additional_item_cost: 100,
currency: "GBP"
}
])
rate = Shipping.get_rate(100, 200, "GB")
assert rate.first_item_cost == 450
assert rate.country_code == "GB"
end
test "returns nil when no rate exists" do
assert Shipping.get_rate(999, 999, "XX") == nil
end
end
describe "calculate_for_cart/2" do
test "returns {:ok, 0} for empty cart" do
assert {:ok, 0} = Shipping.calculate_for_cart([], "GB")
end
test "calculates shipping for single item" do
conn = provider_connection_fixture()
product =
product_fixture(%{
provider_connection: conn,
provider_data: %{"blueprint_id" => 100, "print_provider_id" => 200}
})
variant = product_variant_fixture(%{product: product})
{:ok, _} =
Shipping.upsert_rates(conn.id, [
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 450,
additional_item_cost: 100,
currency: "GBP"
}
])
cart_items = [%{variant_id: variant.id, quantity: 1}]
assert {:ok, 450} = Shipping.calculate_for_cart(cart_items, "GB")
end
test "calculates shipping for multiple quantities" do
conn = provider_connection_fixture()
product =
product_fixture(%{
provider_connection: conn,
provider_data: %{"blueprint_id" => 100, "print_provider_id" => 200}
})
variant = product_variant_fixture(%{product: product})
{:ok, _} =
Shipping.upsert_rates(conn.id, [
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 450,
additional_item_cost: 100,
currency: "GBP"
}
])
cart_items = [%{variant_id: variant.id, quantity: 3}]
# first_item_cost + 2 * additional_item_cost = 450 + 200 = 650
assert {:ok, 650} = Shipping.calculate_for_cart(cart_items, "GB")
end
test "returns error when no rates found" do
conn = provider_connection_fixture()
product =
product_fixture(%{
provider_connection: conn,
provider_data: %{"blueprint_id" => 100, "print_provider_id" => 200}
})
variant = product_variant_fixture(%{product: product})
cart_items = [%{variant_id: variant.id, quantity: 1}]
assert {:error, :rates_not_found} = Shipping.calculate_for_cart(cart_items, "XX")
end
test "groups items by print provider" do
conn = provider_connection_fixture()
product1 =
product_fixture(%{
provider_connection: conn,
provider_data: %{"blueprint_id" => 100, "print_provider_id" => 200}
})
product2 =
product_fixture(%{
provider_connection: conn,
provider_data: %{"blueprint_id" => 101, "print_provider_id" => 200}
})
variant1 = product_variant_fixture(%{product: product1})
variant2 = product_variant_fixture(%{product: product2})
{:ok, _} =
Shipping.upsert_rates(conn.id, [
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 450,
additional_item_cost: 100,
currency: "GBP"
},
%{
blueprint_id: 101,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 500,
additional_item_cost: 150,
currency: "GBP"
}
])
cart_items = [
%{variant_id: variant1.id, quantity: 1},
%{variant_id: variant2.id, quantity: 1}
]
# Same provider: highest first_item_cost (500) + 1 additional item cost
assert {:ok, cost} = Shipping.calculate_for_cart(cart_items, "GB")
# 500 (highest first item) + one additional item cost (100 or 150)
assert cost in [600, 650]
end
end
describe "upsert_rates/3 with exchange rates" do
test "converts rates to GBP at sync time with buffer" do
conn = provider_connection_fixture()
exchange_rates = %{"USD" => 0.80}
rates = [
%{
blueprint_id: 100,
print_provider_id: 1,
country_code: "US",
first_item_cost: 1000,
additional_item_cost: 500,
currency: "USD"
}
]
{:ok, 1} = Shipping.upsert_rates(conn.id, rates, exchange_rates)
rate = Shipping.get_rate(100, 1, "US")
assert rate.currency == "GBP"
# 1000 USD cents * 0.80 rate * 1.05 buffer, ceil'd
assert rate.first_item_cost == 841
assert rate.additional_item_cost == 421
end
test "leaves GBP rates unconverted" do
conn = provider_connection_fixture()
exchange_rates = %{"USD" => 0.80}
rates = [
%{
blueprint_id: 100,
print_provider_id: 1,
country_code: "GB",
first_item_cost: 500,
additional_item_cost: 200,
currency: "GBP"
}
]
{:ok, 1} = Shipping.upsert_rates(conn.id, rates, exchange_rates)
rate = Shipping.get_rate(100, 1, "GB")
assert rate.currency == "GBP"
assert rate.first_item_cost == 500
assert rate.additional_item_cost == 200
end
end
describe "list_available_countries/0" do
test "returns distinct country codes" do
conn = provider_connection_fixture()
{:ok, _} =
Shipping.upsert_rates(conn.id, [
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 450,
additional_item_cost: 100,
currency: "GBP"
},
%{
blueprint_id: 100,
print_provider_id: 200,
country_code: "US",
first_item_cost: 650,
additional_item_cost: 150,
currency: "USD"
},
%{
blueprint_id: 101,
print_provider_id: 200,
country_code: "GB",
first_item_cost: 500,
additional_item_cost: 100,
currency: "GBP"
}
])
countries = Shipping.list_available_countries()
assert "GB" in countries
assert "US" in countries
assert length(countries) == 2
end
end
end