rework email settings for true progressive enhancement
All checks were successful
deploy / deploy (push) Successful in 1m19s

Render all adapter field sections in the form with CSS :has(:checked)
controlling visibility. Selecting a provider instantly shows its config
fields — no JS, no page reload, no server round-trip needed.

- Render all 6 adapter configs with data-adapter attribute
- CSS :has(:checked) show/hide rules per adapter in admin stylesheet
- Namespace field names per adapter (email[brevo][api_key] etc)
- Drop 4 transactional-only providers (Resend, Postmark, Mailgun, MailPace)
- Remove noscript "Switch provider" button and controller redirect workaround
- Remove configured_adapter hidden input tracking
- Hide JS-only test email button for no-JS users via noscript style
- LiveView progressively enhances with async save and test email

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-03-04 23:10:37 +00:00
parent dd20ea824f
commit db130a7155
12 changed files with 213 additions and 456 deletions

View File

@@ -33,27 +33,17 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
# 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
test "shows providers and advanced section", %{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"
@@ -64,10 +54,20 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest 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
test "renders all adapter field sections in the form", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/admin/settings/email")
# All adapters have their config sections rendered (CSS controls visibility)
assert html =~ ~s(data-adapter="brevo")
assert html =~ ~s(data-adapter="sendgrid")
assert html =~ ~s(data-adapter="mailjet")
assert html =~ ~s(data-adapter="smtp")
assert html =~ ~s(data-adapter="postal")
end
test "selecting a provider updates via phx-change", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
# Select SMTP via form change (radio inputs fire phx-change)
@@ -76,35 +76,9 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "smtp"}})
|> render_change()
# SMTP fields are always rendered; check the step title changes
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
@@ -115,11 +89,11 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
|> form("form[phx-change=\"form_change\"]", %{email: %{adapter: "brevo"}})
|> render_change()
# Submit with an API key
# Submit with namespaced fields: email[brevo][api_key]
html =
view
|> form("form[phx-submit=\"save\"]", %{
email: %{adapter: "brevo", api_key: "xkeysib-abc123def456"}
email: %{adapter: "brevo", brevo: %{api_key: "xkeysib-abc123def456"}}
})
|> render_submit()
@@ -138,7 +112,9 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
# Submit without API key
html =
view
|> form("form[phx-submit=\"save\"]", %{email: %{adapter: "brevo", api_key: ""}})
|> form("form[phx-submit=\"save\"]", %{
email: %{adapter: "brevo", brevo: %{api_key: ""}}
})
|> render_submit()
assert html =~ "API key is required"
@@ -154,7 +130,7 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
html =
view
|> form("form[phx-submit=\"save\"]", %{
email: %{adapter: "smtp", relay: "smtp.example.com", port: "abc"}
email: %{adapter: "smtp", smtp: %{relay: "smtp.example.com", port: "abc"}}
})
|> render_submit()
@@ -162,8 +138,8 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
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")
Settings.put_setting("email_adapter", "brevo")
Settings.put_secret("email_brevo_api_key", "xkeysib-test-abc")
{:ok, _view, html} = live(conn, ~p"/admin/settings/email")
@@ -182,8 +158,8 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
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")
Settings.put_setting("email_adapter", "brevo")
Settings.put_secret("email_brevo_api_key", "xkeysib-test-abc")
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
@@ -205,14 +181,14 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
{:ok, view, _html} = live(conn, ~p"/admin/settings/email")
# Switch to Brevo and save
# Switch to Brevo and save (namespaced fields)
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"}
email: %{adapter: "brevo", brevo: %{api_key: "xkeysib-switch-test"}}
})
|> render_submit()
@@ -236,7 +212,7 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
view
|> form("form[phx-submit=\"save\"]", %{
email: %{adapter: "brevo", api_key: "xkeysib-def789ghi012"}
email: %{adapter: "brevo", brevo: %{api_key: "xkeysib-def789ghi012"}}
})
|> render_submit()
@@ -262,13 +238,6 @@ defmodule BerrypodWeb.Admin.EmailSettingsTest do
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")