prop/test/microwaveprop_web/controllers/user_settings_controller_test.exs
Graham McIntire b4b8d4ec47
Some checks failed
Build base image / Build and push base image (push) Successful in 12s
Build and Push / Build CI test image (push) Successful in 14s
Build and Push / Build and Push Docker Image (push) Failing after 14m7s
simplify: DRY up shared changesets, context helpers, LiveView helpers, and structural extraction
- Create MaidenheadChangesetHelpers: consolidate grid validation, callsign
  normalization, lat/lon validation, grid/latlon derivation across 6 schemas
- Create ContextHelpers: shared fetch_owned with admin bypass, safe_enqueue
  for Oban workers, UUID casting to replace CastError rescues
- Extend LiveHelpers: add current_user/1 (removes 7 duplicate definitions),
  subscribe/2 (replaces 13 inline PubSub sites), assign_url_params/2
- Extract Propagation.ScoreStore (528 lines): separate file I/O and cache
  management from scoring logic, 13 defdelegate passthroughs
- Split SubmitLive (942->475 lines): extract CSV/ADIF upload rendering into
  3 function component modules (csv_upload, adif_upload, preview)
- Update 16 LiveViews to use shared helpers
2026-08-06 18:06:50 -05:00

177 lines
5.7 KiB
Elixir

defmodule MicrowavepropWeb.UserSettingsControllerTest do
use MicrowavepropWeb.ConnCase, async: true
import Microwaveprop.AccountsFixtures
alias Microwaveprop.Accounts
setup :register_and_log_in_user
describe "GET /users/settings" do
test "renders settings page", %{conn: conn} do
conn = get(conn, ~p"/users/settings")
response = html_response(conn, 200)
assert response =~ "Settings"
end
test "redirects if user is not logged in" do
conn = build_conn()
conn = get(conn, ~p"/users/settings")
assert redirected_to(conn) == ~p"/users/log-in"
end
@tag token_authenticated_at: DateTime.shift(DateTime.utc_now(:second), hour: -25)
test "redirects if user is not in sudo mode", %{conn: conn} do
conn = get(conn, ~p"/users/settings")
assert redirected_to(conn) == ~p"/users/log-in"
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
"You must re-authenticate to access this page."
end
end
describe "PUT /users/settings (change password form)" do
test "updates the user password and resets tokens", %{conn: conn, user: user} do
new_password_conn =
put(conn, ~p"/users/settings", %{
"action" => "update_password",
"user" => %{
"password" => "new valid password",
"password_confirmation" => "new valid password"
}
})
assert redirected_to(new_password_conn) == ~p"/users/settings"
assert get_session(new_password_conn, :user_token) != get_session(conn, :user_token)
assert Phoenix.Flash.get(new_password_conn.assigns.flash, :info) =~
"Password updated successfully"
assert Accounts.get_user_by_email_and_password(user.email, "new valid password")
end
test "does not update password on invalid data", %{conn: conn} do
old_password_conn =
put(conn, ~p"/users/settings", %{
"action" => "update_password",
"user" => %{
"password" => "short",
"password_confirmation" => "nope"
}
})
response = html_response(old_password_conn, 200)
assert response =~ "Settings"
assert response =~ "should be at least 8 character(s)"
assert response =~ "does not match password"
assert get_session(old_password_conn, :user_token) == get_session(conn, :user_token)
end
end
describe "PUT /users/settings (home QTH form)" do
test "updates the user home QTH from a grid", %{conn: conn, user: user} do
conn =
put(conn, ~p"/users/settings", %{
"action" => "update_home_qth",
"user" => %{"home_grid" => "EM13qc"}
})
assert redirected_to(conn) == ~p"/users/settings"
reloaded = Microwaveprop.Repo.reload(user)
assert reloaded.home_grid == "EM13qc"
assert reloaded.home_lat >= -90 and reloaded.home_lat <= 90
assert reloaded.home_lon >= -180 and reloaded.home_lon <= 180
end
test "rejects an invalid grid", %{conn: conn} do
conn =
put(conn, ~p"/users/settings", %{
"action" => "update_home_qth",
"user" => %{"home_grid" => "ZZ99zz"}
})
response = html_response(conn, 200)
assert response =~ "Home QTH"
assert response =~ "is not a valid Maidenhead"
end
end
describe "PUT /users/settings (change email form)" do
@tag :capture_log
test "updates the user email", %{conn: conn, user: user} do
conn =
put(conn, ~p"/users/settings", %{
"action" => "update_email",
"user" => %{"email" => unique_user_email()}
})
assert redirected_to(conn) == ~p"/users/settings"
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
"A link to confirm your email"
assert Accounts.get_user_by_email(user.email)
end
test "does not update email on invalid data", %{conn: conn} do
conn =
put(conn, ~p"/users/settings", %{
"action" => "update_email",
"user" => %{"email" => "with spaces"}
})
response = html_response(conn, 200)
assert response =~ "Settings"
assert response =~ "must have the @ sign and no spaces"
end
end
describe "GET /users/settings/confirm-email/:token" do
setup %{user: user} do
email = unique_user_email()
token =
extract_user_token(fn url ->
Accounts.deliver_user_update_email_instructions(%{user | email: email}, user.email, url)
end)
%{token: token, email: email}
end
test "updates the user email once", %{conn: conn, user: user, token: token, email: email} do
conn = get(conn, ~p"/users/settings/confirm-email/#{token}")
assert redirected_to(conn) == ~p"/users/settings"
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~
"Email changed successfully"
refute Accounts.get_user_by_email(user.email)
assert Accounts.get_user_by_email(email)
conn = get(conn, ~p"/users/settings/confirm-email/#{token}")
assert redirected_to(conn) == ~p"/users/settings"
assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
"Email change link is invalid or it has expired"
end
test "does not update email with invalid token", %{conn: conn, user: user} do
conn = get(conn, ~p"/users/settings/confirm-email/oops")
assert redirected_to(conn) == ~p"/users/settings"
assert Phoenix.Flash.get(conn.assigns.flash, :error) =~
"Email change link is invalid or it has expired"
assert Accounts.get_user_by_email(user.email)
end
test "redirects if user is not logged in", %{token: token} do
conn = build_conn()
conn = get(conn, ~p"/users/settings/confirm-email/#{token}")
assert redirected_to(conn) == ~p"/users/log-in"
end
end
end