Finalize join request feature #472

Merged
simon merged 18 commits from feature/308-web-form into main 2026-03-13 20:51:11 +01:00
Showing only changes of commit 1866c79461 - Show all commits

View file

@ -9,12 +9,11 @@ defmodule MvWeb.JoinLiveTest do
Honeypot: form param `"website"` (legit-sounding name per best practice; not "honeypot"). Honeypot: form param `"website"` (legit-sounding name per best practice; not "honeypot").
Field is hidden via CSS class in app.css (off-screen, no inline styles), type="text". Field is hidden via CSS class in app.css (off-screen, no inline styles), type="text".
""" """
# async: false so LiveView and test share sandbox (submit creates JoinRequest in LiveView process). # async: false → shared sandbox; all processes (including LiveView) share the DB connection.
use MvWeb.ConnCase, async: false use MvWeb.ConnCase, async: false
import Phoenix.LiveViewTest import Phoenix.LiveViewTest
import Ecto.Query import Ecto.Query
alias Ecto.Adapters.SQL.Sandbox
alias Mv.Membership alias Mv.Membership
alias Mv.Repo alias Mv.Repo
@ -35,20 +34,18 @@ defmodule MvWeb.JoinLiveTest do
end end
describe "submit join form" do describe "submit join form" do
setup :enable_join_form_for_test setup context do
reset_rate_limiter()
enable_join_form_for_test(context)
end
@tag role: :unauthenticated @tag role: :unauthenticated
test "submit with valid allowlist data creates one JoinRequest and shows success copy", %{ test "submit with valid allowlist data creates one JoinRequest and shows success copy", %{
conn: conn conn: conn
} do } do
# Re-apply allowlist so this test is robust when run in parallel with others (Settings singleton).
enable_join_form_for_test(%{})
count_before = count_join_requests() count_before = count_join_requests()
{:ok, view, _html} = live(conn, "/join") {:ok, view, _html} = live(conn, "/join")
# Allow LiveView process to use the same Ecto sandbox so the test sees the created JoinRequest.
Sandbox.allow(Repo, conn.private[:ecto_sandbox], view.pid)
view view
|> form("#join-form", %{ |> form("#join-form", %{
"email" => "newuser#{System.unique_integer([:positive])}@example.com", "email" => "newuser#{System.unique_integer([:positive])}@example.com",
@ -92,23 +89,6 @@ defmodule MvWeb.JoinLiveTest do
test "after rate limit exceeded submit returns 429 or error and no new JoinRequest", %{ test "after rate limit exceeded submit returns 429 or error and no new JoinRequest", %{
conn: conn conn: conn
} do } do
# Reset rate limit state so this test is independent of others (same key in test)
try do
:ets.delete_all_objects(MvWeb.JoinRateLimit)
rescue
ArgumentError -> :ok
end
enable_join_form(true)
# Set allowlist so form has email, first_name, last_name
{:ok, settings} = Membership.get_settings()
Membership.update_settings(settings, %{
join_form_field_ids: ["email", "first_name", "last_name"],
join_form_field_required: %{"email" => true, "first_name" => false, "last_name" => false}
})
# Rely on test config: join rate limit low (e.g. 2 per window)
base_email = "ratelimit#{System.unique_integer([:positive])}@example.com" base_email = "ratelimit#{System.unique_integer([:positive])}@example.com"
count_before = count_join_requests() count_before = count_join_requests()
sandbox = conn.private[:ecto_sandbox] sandbox = conn.private[:ecto_sandbox]
@ -176,4 +156,10 @@ defmodule MvWeb.JoinLiveTest do
defp count_join_requests do defp count_join_requests do
Repo.one(from j in "join_requests", select: count(j.id)) || 0 Repo.one(from j in "join_requests", select: count(j.id)) || 0
end end
defp reset_rate_limiter do
:ets.delete_all_objects(MvWeb.JoinRateLimit)
rescue
ArgumentError -> :ok
end
end end