berrypod/test/berrypod_web/live/admin/email_settings_test.exs

295 lines
9.0 KiB
Elixir
Raw Normal View History

defmodule BerrypodWeb.Admin.EmailSettingsTest do
use BerrypodWeb.ConnCase, async: false
import Phoenix.LiveViewTest
import Berrypod.AccountsFixtures
alias Berrypod.{Mailer, Settings}
setup do
# Ensure mailer starts as test adapter and restore on exit
original = Application.get_env(:berrypod, Berrypod.Mailer)
Application.put_env(:berrypod, Berrypod.Mailer, adapter: Swoosh.Adapters.Test)
on_exit(fn ->
Application.put_env(:berrypod, Berrypod.Mailer, original)
end)
user = user_fixture()
%{user: user}
end
describe "authenticated" do
setup %{conn: conn, user: user} do
conn = log_in_user(conn, user)
%{conn: conn}
end
test "renders email settings page with provider cards", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/admin/settings/email")
assert html =~ "Email settings"
assert html =~ "Choose a provider"
# Provider names rendered as radio cards
assert html =~ "Brevo"
assert html =~ "Mailjet"
assert html =~ "MailPace"
assert html =~ "Postal"
end
test "shows all three provider groups", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/admin/settings/email")
# All-email providers
assert html =~ "Popular providers"
assert html =~ "Brevo"
assert html =~ "SendGrid"
assert html =~ "Mailjet"
assert html =~ "MailerSend"
# Transactional providers
assert html =~ "Transactional only"
assert html =~ "Resend"
assert html =~ "Postmark"
assert html =~ "Mailgun"
assert html =~ "MailPace"
# Advanced in details
assert html =~ "Already have your own email server?"
assert html =~ "SMTP"
assert html =~ "Postal"
end
test "shows setup guidance", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/admin/settings/email")
assert html =~ "needs an email provider"
assert html =~ "300 emails/day free"
end
test "selecting a provider shows its config fields", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
# Select SMTP via form change (radio inputs fire phx-change)
html =
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "smtp"}})
|> render_change()
assert html =~ "Server host"
assert html =~ "Port"
assert html =~ "Username"
assert html =~ "Password"
end
test "selecting a different provider shows different fields", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
# Select Brevo which needs just an api_key
html =
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "brevo"}})
|> render_change()
assert html =~ "API key"
assert html =~ "Brevo"
end
test "selecting a transactional provider shows its config", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
html =
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "resend"}})
|> render_change()
assert html =~ "API key"
assert html =~ "Resend"
end
test "saving config persists settings", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
# Select Brevo via form change
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "brevo"}})
|> render_change()
# Submit with an API key
html =
view
|> form("form[phx-submit=\"save\"]", %{
email: %{adapter: "brevo", api_key: "xkeysib-abc123def456"}
})
|> render_submit()
assert html =~ "Settings saved"
assert Settings.get_setting("email_adapter") == "brevo"
end
test "saving without required fields shows error", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
# Select Brevo
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "brevo"}})
|> render_change()
# Submit without API key
html =
view
|> form("form[phx-submit=\"save\"]", %{email: %{adapter: "brevo", api_key: ""}})
|> render_submit()
assert html =~ "API key is required"
end
test "saving with invalid port shows error", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "smtp"}})
|> render_change()
html =
view
|> form("form[phx-submit=\"save\"]", %{
email: %{adapter: "smtp", relay: "smtp.example.com", port: "abc"}
})
|> render_submit()
assert html =~ "must be a number"
end
test "shows test email section when configured", %{conn: conn} do
Settings.put_setting("email_adapter", "postmark")
Settings.put_secret("email_postmark_api_key", "pm_test_abc")
{:ok, _view, html} = live(conn, ~p"/admin/settings/email")
assert html =~ "Send a test email"
assert html =~ "Send test email"
end
test "hides test email section when not configured", %{conn: conn} do
# Ensure clean state — no adapter configured
Settings.delete_setting("email_adapter")
Application.put_env(:berrypod, Berrypod.Mailer, adapter: Swoosh.Adapters.Local)
{:ok, _view, html} = live(conn, ~p"/admin/settings/email")
refute html =~ "Send test email"
end
test "sending test email shows success and sets verified flag", %{conn: conn} do
Settings.put_setting("email_adapter", "postmark")
Settings.put_secret("email_postmark_api_key", "pm_test_abc")
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
# send_test is now async — click triggers the event, then handle_info completes it
render_click(view, "send_test")
# Wait for the async handle_info to complete
html = render(view)
assert html =~ "Email is working"
assert html =~ "Send again"
assert Mailer.email_verified?()
end
test "switching provider clears old provider settings", %{conn: conn} do
# Save Mailjet config first
Settings.put_setting("email_adapter", "mailjet")
Settings.put_secret("email_mailjet_api_key", "mj-key-123")
Settings.put_secret("email_mailjet_secret", "mj-secret-456")
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
# Switch to Brevo and save
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "brevo"}})
|> render_change()
view
|> form("form[phx-submit=\"save\"]", %{
email: %{adapter: "brevo", api_key: "xkeysib-switch-test"}
})
|> render_submit()
# Old Mailjet settings should be deleted
assert Settings.get_setting("email_adapter") == "brevo"
refute Settings.has_secret?("email_mailjet_api_key")
refute Settings.has_secret?("email_mailjet_secret")
# New Brevo key should exist
assert Settings.has_secret?("email_brevo_api_key")
end
test "saving config clears verified flag", %{conn: conn} do
Mailer.mark_email_verified()
assert Mailer.email_verified?()
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "brevo"}})
|> render_change()
view
|> form("form[phx-submit=\"save\"]", %{
email: %{adapter: "brevo", api_key: "xkeysib-def789ghi012"}
})
|> render_submit()
refute Mailer.email_verified?()
end
test "phx-change is no-op when adapter hasn't changed", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
# Select Brevo
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "brevo"}})
|> render_change()
# Trigger another change with the same adapter (simulates text field input)
html =
view
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "brevo"}})
|> render_change()
# Should still show Brevo config
assert html =~ "Brevo"
assert html =~ "API key"
end
test "adapter query param preselects provider", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/admin/settings/email?adapter=resend")
assert html =~ "Resend"
assert html =~ "API key"
end
test "from_checklist param shows checklist banner", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/admin/settings/email?from=checklist")
assert html =~ "setting up email"
assert html =~ "Back to checklist"
end
test "has fieldset legend for accessibility", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/admin/settings/email")
assert html =~ "Email provider"
assert html =~ "sr-only"
end
end
describe "unauthenticated" do
test "redirects to login", %{conn: conn} do
{:error, redirect} = live(conn, ~p"/admin/settings/email")
assert {:redirect, %{to: path}} = redirect
assert path == ~p"/users/log-in"
end
end
end