Registration LiveView
I’m looking through the files generated by mix phx.gen.auth
and see the entire browser interface for authentication uses live views except for the session management which can’t be done with web sockets alone.
The current authentication system for Minotaur uses controllers and “dead” views for all pages.
I will copy the generated live views to my application to replace the existing authentication interface.
I start with the registration live view by copying the first test case from the generated user_registration_live_test.exs
.
defmodule MinotaurWeb.UserRegistrationLiveTest do
@moduledoc false
use MinotaurWeb.ConnCase, async: true
import Phoenix.LiveViewTest
import Minotaur.AccountsFixtures
describe "Registration page" do
test "renders registration page", %{conn: conn} do
{:ok, _lv, html} = live(conn, ~p"/users/register")
assert html =~ "Register"
assert html =~ "Log in"
end
end
end
I have not configured a route for /users/register
so the test fails with:
** (FunctionClauseError) no function clause matching in Phoenix.LiveViewTest.connect_from_static_token/2
I add the minimal code needed to get past this error by updating the Router
module with a route to a non-existent UserRegistrationLive
module.
defmodule MinotaurWeb.Router do
use MinotaurWeb, :router
# …
scope "/", MinotaurWeb do
pipe_through [:browser]
live "/users/register", UserRegistrationLive, :new
end
end
The test now complains about the undefined module as expected.
** (UndefinedFunctionError) function MinotaurWeb.UserRegistrationLive.__live__/0 is undefined (module MinotaurWeb.UserRegistrationLive is not available)
I create the missing module and define a placeholder render
function to check that requests are being routed correctly through the application.
defmodule MinotaurWeb.UserRegistrationLive do
use MinotaurWeb, :live_view
def render(assigns) do
~H"""
OK
"""
end
end
Now the test is compiling and failing at the first assert statement since it does not find “Register” anywhere in rendered string.
I replace the render function with the render
from the generated auth live view and methodically work through the cycle of running the test and adding any missing references the new render depends on.
def render(assigns) do
~H"""
<div class="mx-auto max-w-sm">
<.header class="text-center">
Register for an account
<:subtitle>
Already registered?
<.link navigate={~p"/users/log_in"} class="font-semibold text-brand hover:underline">
Log in
</.link>
to your account now.
</:subtitle>
</.header>
<.simple_form
for={@form}
id="registration_form"
phx-submit="save"
phx-change="validate"
phx-trigger-action={@trigger_submit}
action={~p"/users/log_in?_action=registered"}
method="post"
>
<.error :if={@check_errors}>
Oops, something went wrong! Please check the errors below.
</.error>
<.input field={@form[:email]} type="email" label="Email" required />
<.input field={@form[:password]} type="password" label="Password" required />
<:actions>
<.button phx-disable-with="Creating account..." class="w-full">Create an account</.button>
</:actions>
</.simple_form>
</div>
"""
end
Once the test is passing, I continue the same cycle with the remaining tests to build out the registration live view. I skip any logic involving account confirmations since I don’t plan to implement this feature at this stage.