mitgliederverwaltung/test/mv_web/controllers/join_confirm_controller_test.exs

97 lines
3.1 KiB
Elixir

defmodule MvWeb.JoinConfirmControllerTest do
@moduledoc """
Unit tests for JoinConfirmController (Subtask 2).
Stubs the join-confirm callback via Application config so no DB or domain is used.
Uses unauthenticated conn; route is public (/confirm*).
"""
use MvWeb.ConnCase, async: false
# Stub modules for configurable callback (unit test: no real Membership calls)
defmodule JoinConfirmValidStub do
def confirm_join_request(_token, _opts), do: {:ok, %{}}
end
defmodule JoinConfirmExpiredStub do
def confirm_join_request(_token, _opts), do: {:error, :token_expired}
end
defmodule JoinConfirmInvalidStub do
def confirm_join_request(_token, _opts) do
{:error, Ash.Error.Query.NotFound.exception(resource: Mv.Membership.JoinRequest)}
end
end
setup %{conn: conn} do
# Restore callback after each test so env does not leak
on_exit(fn ->
Application.delete_env(:mv, :join_confirm_callback)
end)
# Build unauthenticated conn for public confirm route
unauth_conn =
build_conn()
|> init_test_session(%{})
|> fetch_flash()
|> Plug.Conn.put_private(:ecto_sandbox, conn.private[:ecto_sandbox])
{:ok, conn: unauth_conn}
end
describe "GET /confirm_join/:token" do
@tag role: :unauthenticated
test "valid token returns 200 and success message", %{conn: conn} do
Application.put_env(:mv, :join_confirm_callback, JoinConfirmValidStub)
conn = get(conn, "/confirm_join/any-valid-token")
assert response(conn, 200) =~ "received your request"
end
@tag role: :unauthenticated
test "second request with same token still returns 200 (idempotent)", %{conn: conn} do
Application.put_env(:mv, :join_confirm_callback, JoinConfirmValidStub)
first = get(conn, "/confirm_join/same-token")
second = get(conn, "/confirm_join/same-token")
assert response(first, 200) =~ "received your request"
assert response(second, 200) =~ "received your request"
end
@tag role: :unauthenticated
test "expired token returns 200 with expired message and instructs to submit form again", %{
conn: conn
} do
Application.put_env(:mv, :join_confirm_callback, JoinConfirmExpiredStub)
conn = get(conn, "/confirm_join/expired-token")
body = response(conn, 200)
assert body =~ "expired"
assert body =~ "submit"
# Concept §2.5: clear message + "submit form again"
assert body =~ "form" or body =~ "again"
end
@tag role: :unauthenticated
test "unknown or invalid token returns 404 with error message", %{conn: conn} do
Application.put_env(:mv, :join_confirm_callback, JoinConfirmInvalidStub)
conn = get(conn, "/confirm_join/nonexistent-token")
assert response(conn, 404) =~ "Invalid"
end
@tag role: :unauthenticated
test "route is public (unauthenticated request returns 200, not redirect to sign-in)", %{
conn: conn
} do
Application.put_env(:mv, :join_confirm_callback, JoinConfirmValidStub)
conn = get(conn, "/confirm_join/public-test-token")
assert conn.status == 200
end
end
end