feat: add transactional emails for order confirmation and shipping
Plain text emails via Swoosh OrderNotifier module. Order confirmation triggered from Stripe webhook after payment, shipping notification from Printify shipment webhook with polling fallback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
161
test/simpleshop_theme/orders/order_notifier_test.exs
Normal file
161
test/simpleshop_theme/orders/order_notifier_test.exs
Normal file
@@ -0,0 +1,161 @@
|
||||
defmodule SimpleshopTheme.Orders.OrderNotifierTest do
|
||||
use SimpleshopTheme.DataCase, async: true
|
||||
|
||||
import Swoosh.TestAssertions
|
||||
import SimpleshopTheme.OrdersFixtures
|
||||
|
||||
alias SimpleshopTheme.Orders
|
||||
alias SimpleshopTheme.Orders.OrderNotifier
|
||||
|
||||
describe "deliver_order_confirmation/1" do
|
||||
test "sends confirmation with order details" do
|
||||
order =
|
||||
order_fixture(%{
|
||||
customer_email: "buyer@example.com",
|
||||
payment_status: "paid",
|
||||
shipping_address: %{
|
||||
"name" => "Jane Doe",
|
||||
"line1" => "42 Test Street",
|
||||
"city" => "London",
|
||||
"postal_code" => "SW1A 1AA",
|
||||
"country" => "GB"
|
||||
}
|
||||
})
|
||||
|
||||
assert {:ok, _email} = OrderNotifier.deliver_order_confirmation(order)
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
assert email.to == [{"", "buyer@example.com"}]
|
||||
assert email.subject =~ "Order confirmed"
|
||||
assert email.subject =~ order.order_number
|
||||
assert email.text_body =~ order.order_number
|
||||
assert email.text_body =~ "Test product"
|
||||
assert email.text_body =~ "Jane Doe"
|
||||
assert email.text_body =~ "42 Test Street"
|
||||
assert email.text_body =~ "London"
|
||||
end)
|
||||
end
|
||||
|
||||
test "includes item quantities and prices" do
|
||||
order =
|
||||
order_fixture(%{
|
||||
customer_email: "buyer@example.com",
|
||||
payment_status: "paid",
|
||||
quantity: 2,
|
||||
unit_price: 1500
|
||||
})
|
||||
|
||||
assert {:ok, _email} = OrderNotifier.deliver_order_confirmation(order)
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
assert email.text_body =~ "2x Test product"
|
||||
end)
|
||||
end
|
||||
|
||||
test "includes order total" do
|
||||
order =
|
||||
order_fixture(%{
|
||||
customer_email: "buyer@example.com",
|
||||
payment_status: "paid",
|
||||
unit_price: 2500
|
||||
})
|
||||
|
||||
assert {:ok, _email} = OrderNotifier.deliver_order_confirmation(order)
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
assert email.text_body =~ "Total:"
|
||||
end)
|
||||
end
|
||||
|
||||
test "skips when customer_email is nil" do
|
||||
order = order_fixture(%{customer_email: nil})
|
||||
|
||||
# Override to nil since fixture sets a default
|
||||
{:ok, order} = Orders.update_order(order, %{customer_email: nil})
|
||||
|
||||
assert {:ok, :no_email} = OrderNotifier.deliver_order_confirmation(order)
|
||||
assert_no_email_sent()
|
||||
end
|
||||
|
||||
test "skips when customer_email is empty string" do
|
||||
order = order_fixture()
|
||||
{:ok, order} = Orders.update_order(order, %{customer_email: ""})
|
||||
|
||||
assert {:ok, :no_email} = OrderNotifier.deliver_order_confirmation(order)
|
||||
assert_no_email_sent()
|
||||
end
|
||||
|
||||
test "handles missing shipping address" do
|
||||
order = order_fixture(%{customer_email: "buyer@example.com", payment_status: "paid"})
|
||||
|
||||
assert {:ok, _email} = OrderNotifier.deliver_order_confirmation(order)
|
||||
assert_email_sent(subject: "Order confirmed - #{order.order_number}")
|
||||
end
|
||||
end
|
||||
|
||||
describe "deliver_shipping_notification/1" do
|
||||
test "sends notification with tracking info" do
|
||||
{order, _v, _p, _c} = submitted_order_fixture(%{customer_email: "buyer@example.com"})
|
||||
|
||||
{:ok, order} =
|
||||
Orders.update_fulfilment(order, %{
|
||||
fulfilment_status: "shipped",
|
||||
tracking_number: "1Z999AA1",
|
||||
tracking_url: "https://ups.com/track/1Z999AA1",
|
||||
shipped_at: DateTime.utc_now() |> DateTime.truncate(:second)
|
||||
})
|
||||
|
||||
assert {:ok, _email} = OrderNotifier.deliver_shipping_notification(order)
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
assert email.to == [{"", "buyer@example.com"}]
|
||||
assert email.subject =~ "Your order has shipped"
|
||||
assert email.subject =~ order.order_number
|
||||
assert email.text_body =~ "1Z999AA1"
|
||||
assert email.text_body =~ "https://ups.com/track/1Z999AA1"
|
||||
end)
|
||||
end
|
||||
|
||||
test "handles missing tracking info gracefully" do
|
||||
{order, _v, _p, _c} = submitted_order_fixture(%{customer_email: "buyer@example.com"})
|
||||
|
||||
{:ok, order} =
|
||||
Orders.update_fulfilment(order, %{
|
||||
fulfilment_status: "shipped",
|
||||
shipped_at: DateTime.utc_now() |> DateTime.truncate(:second)
|
||||
})
|
||||
|
||||
assert {:ok, _email} = OrderNotifier.deliver_shipping_notification(order)
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
assert email.text_body =~ "Tracking details will follow"
|
||||
end)
|
||||
end
|
||||
|
||||
test "includes tracking number without URL" do
|
||||
{order, _v, _p, _c} = submitted_order_fixture(%{customer_email: "buyer@example.com"})
|
||||
|
||||
{:ok, order} =
|
||||
Orders.update_fulfilment(order, %{
|
||||
fulfilment_status: "shipped",
|
||||
tracking_number: "RM123456789GB",
|
||||
shipped_at: DateTime.utc_now() |> DateTime.truncate(:second)
|
||||
})
|
||||
|
||||
assert {:ok, _email} = OrderNotifier.deliver_shipping_notification(order)
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
assert email.text_body =~ "RM123456789GB"
|
||||
assert not (email.text_body =~ "Tracking details will follow")
|
||||
end)
|
||||
end
|
||||
|
||||
test "skips when customer_email is nil" do
|
||||
{order, _v, _p, _c} = submitted_order_fixture()
|
||||
{:ok, order} = Orders.update_order(order, %{customer_email: nil})
|
||||
|
||||
assert {:ok, :no_email} = OrderNotifier.deliver_shipping_notification(order)
|
||||
assert_no_email_sent()
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user