aprs.me/test/aprsme/swoosh/resend_adapter_test.exs
Graham McIntire a377847122
chore: remove unused deps, replace resend with custom Swoosh adapter, fix test isolation
Remove faker, floki, igniter, ecto_psql_extras (zero usages), exvcr
(zero usages), and resend. Replace resend with Aprsme.Swoosh.ResendAdapter
using the already-present req dependency. Frees 23 packages total from
the lockfile including hackney, certifi, and the tesla dependency chain.

Fix two pre-existing test isolation bugs:
- signal_handler_test called the real ShutdownHandler.shutdown() via SIGTERM
  simulation without restoring state, causing page_controller_test to see
  shutting_down: true and return 503
- page_controller_test setup now resets ShutdownHandler state defensively
2026-04-24 13:04:18 -05:00

132 lines
4 KiB
Elixir

defmodule Aprsme.Swoosh.ResendAdapterTest do
use ExUnit.Case, async: true
alias Aprsme.Swoosh.ResendAdapter
alias Swoosh.Email
defp stub_config(plug_name) do
[api_key: "re_test_key", plug: {Req.Test, plug_name}]
end
defp new_email(opts \\ []) do
defaults = [
from: {"Sender Name", "sender@example.com"},
to: [{"Recipient", "recipient@example.com"}],
subject: "Test Subject",
html_body: "<p>Hello</p>",
text_body: "Hello"
]
Email.new(Keyword.merge(defaults, opts))
end
describe "deliver/2" do
test "posts to Resend API and returns id on success" do
Req.Test.stub(__MODULE__, fn conn ->
Req.Test.json(conn, %{"id" => "msg_abc123"})
end)
email = new_email()
assert {:ok, %{id: "msg_abc123"}} = ResendAdapter.deliver(email, stub_config(__MODULE__))
end
test "returns error on API error response" do
Req.Test.stub(__MODULE__, fn conn ->
conn
|> Plug.Conn.put_status(422)
|> Req.Test.json(%{"name" => "validation_error", "message" => "Invalid email"})
end)
email = new_email()
assert {:error, {"validation_error", "Invalid email"}} =
ResendAdapter.deliver(email, stub_config(__MODULE__))
end
test "returns error on network failure" do
Req.Test.stub(__MODULE__, fn conn ->
Req.Test.transport_error(conn, :econnrefused)
end)
email = new_email()
assert {:error, %Req.TransportError{reason: :econnrefused}} =
ResendAdapter.deliver(email, stub_config(__MODULE__))
end
test "formats named sender as 'Name <email>'" do
Req.Test.stub(__MODULE__, fn conn ->
{:ok, body, conn} = Plug.Conn.read_body(conn)
decoded = Jason.decode!(body)
send(self(), {:request_body, decoded})
Req.Test.json(conn, %{"id" => "msg_1"})
end)
email = new_email(from: {"My App", "noreply@example.com"})
ResendAdapter.deliver(email, stub_config(__MODULE__))
assert_received {:request_body, body}
assert body["from"] == "My App <noreply@example.com>"
end
test "formats bare email sender without name prefix" do
Req.Test.stub(__MODULE__, fn conn ->
{:ok, body, conn} = Plug.Conn.read_body(conn)
decoded = Jason.decode!(body)
send(self(), {:request_body, decoded})
Req.Test.json(conn, %{"id" => "msg_1"})
end)
email = new_email(from: {"", "noreply@example.com"})
ResendAdapter.deliver(email, stub_config(__MODULE__))
assert_received {:request_body, body}
assert body["from"] == "noreply@example.com"
end
test "formats list of recipients as list of email strings" do
Req.Test.stub(__MODULE__, fn conn ->
{:ok, body, conn} = Plug.Conn.read_body(conn)
decoded = Jason.decode!(body)
send(self(), {:request_body, decoded})
Req.Test.json(conn, %{"id" => "msg_1"})
end)
email =
new_email(to: [{"Alice", "alice@example.com"}, {"Bob", "bob@example.com"}])
ResendAdapter.deliver(email, stub_config(__MODULE__))
assert_received {:request_body, body}
assert body["to"] == ["alice@example.com", "bob@example.com"]
end
test "omits nil fields from request body" do
Req.Test.stub(__MODULE__, fn conn ->
{:ok, body, conn} = Plug.Conn.read_body(conn)
decoded = Jason.decode!(body)
send(self(), {:request_body, decoded})
Req.Test.json(conn, %{"id" => "msg_1"})
end)
email = new_email()
ResendAdapter.deliver(email, stub_config(__MODULE__))
assert_received {:request_body, body}
refute Map.has_key?(body, "cc")
refute Map.has_key?(body, "bcc")
refute Map.has_key?(body, "reply_to")
end
end
describe "validate_config/1" do
test "returns :ok when api_key is present" do
assert :ok = ResendAdapter.validate_config(api_key: "re_abc")
end
test "returns error when api_key is missing" do
assert {:error, _reason} = ResendAdapter.validate_config([])
end
end
end