How to test LiveView behind AshAuthentication?
I have some LiveViews that require an authenticated user to access (AshAuthentication). How do I simulate login for the user?
I saw that there are a few tests in the AshHQ repo and I did try to copy all of the relevant stuff, but I still can't get it to work. Here's what I have so far:
defmodule MyAppWeb.BookLiveTest do
use MyAppWeb.ConnCase
import Phoenix.LiveViewTest
describe "with existing books" do
setup %{conn: conn} do
result = register_and_log_in_user(%{conn: conn})
book = book_fixture(result[:user], %{name: "Test Book"})
%{
conn: result[:conn],
user: result[:user],
book: book
}
end
test "lists all books", %{conn: conn, book: book} do
{:ok, _index_live, html} = live(conn, ~p"/books")
assert html =~ "Listing Books"
assert html =~ book.name
end
end
end
defmodule MyAppWeb.BookLiveTest do
use MyAppWeb.ConnCase
import Phoenix.LiveViewTest
describe "with existing books" do
setup %{conn: conn} do
result = register_and_log_in_user(%{conn: conn})
book = book_fixture(result[:user], %{name: "Test Book"})
%{
conn: result[:conn],
user: result[:user],
book: book
}
end
test "lists all books", %{conn: conn, book: book} do
{:ok, _index_live, html} = live(conn, ~p"/books")
assert html =~ "Listing Books"
assert html =~ book.name
end
end
end
defmodule MyAppWeb.LoginTestHelpers do
alias MyApp.AccountsFixtures
def register_and_log_in_user(%{conn: conn}) do
user = AccountsFixtures.user_fixture()
%{conn: log_in_user(conn, user), user: user}
end
def register_user(_context) do
%{
user: AccountsFixtures.user_fixture()
}
end
def log_in_user(conn, user) do
conn
|> Phoenix.ConnTest.init_test_session(%{})
|> Plug.Conn.put_session(:user_token, user.__metadata__.token)
end
end
defmodule MyAppWeb.LoginTestHelpers do
alias MyApp.AccountsFixtures
def register_and_log_in_user(%{conn: conn}) do
user = AccountsFixtures.user_fixture()
%{conn: log_in_user(conn, user), user: user}
end
def register_user(_context) do
%{
user: AccountsFixtures.user_fixture()
}
end
def log_in_user(conn, user) do
conn
|> Phoenix.ConnTest.init_test_session(%{})
|> Plug.Conn.put_session(:user_token, user.__metadata__.token)
end
end
3 Replies
I hit the character limit in my initial post. This is the continuation:
I'm getting this error when running the test:
defmodule MyApp.AccountsFixtures do
alias Terrible.Authentication.User
def user_fixture(attrs \\ %{}) do
password = Map.get(attrs, :password, "password123")
user =
User.register_with_password!(
Map.get(attrs, :email, "[email protected]"),
password,
password,
authorize?: false
)
receive do
{:email, _} -> :ok
after
0 -> :ok
end
user
end
end
defmodule MyApp.AccountsFixtures do
alias Terrible.Authentication.User
def user_fixture(attrs \\ %{}) do
password = Map.get(attrs, :password, "password123")
user =
User.register_with_password!(
Map.get(attrs, :email, "[email protected]"),
password,
password,
authorize?: false
)
receive do
{:email, _} -> :ok
after
0 -> :ok
end
user
end
end
defmodule MyAppWeb.Router do
use MyAppWeb, :router
use AshAuthentication.Phoenix.Router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, {MyAppWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session
end
pipeline :api do
plug :accepts, ["json"]
plug :load_from_bearer
end
scope "/", MyAppWeb do
pipe_through :browser
get "/", PageController, :home
sign_in_route()
sign_out_route(AuthenticationController)
auth_routes_for(MyApp.Accounts.User, to: AuthenticationController)
reset_route([])
live_session :authenticated,
on_mount: [
AshAuthentication.Phoenix.LiveSession,
{MyAppWeb.LiveUserAssigns, :live_user_required}
],
session: {AshAuthentication.Phoenix.LiveSession, :generate_session, []} do
live "/books", BookLive.Index, :index
end
end
end
defmodule MyAppWeb.Router do
use MyAppWeb, :router
use AshAuthentication.Phoenix.Router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, {MyAppWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session
end
pipeline :api do
plug :accepts, ["json"]
plug :load_from_bearer
end
scope "/", MyAppWeb do
pipe_through :browser
get "/", PageController, :home
sign_in_route()
sign_out_route(AuthenticationController)
auth_routes_for(MyApp.Accounts.User, to: AuthenticationController)
reset_route([])
live_session :authenticated,
on_mount: [
AshAuthentication.Phoenix.LiveSession,
{MyAppWeb.LiveUserAssigns, :live_user_required}
],
session: {AshAuthentication.Phoenix.LiveSession, :generate_session, []} do
live "/books", BookLive.Index, :index
end
end
end
** (MatchError) no match of right hand side value: {:error, {:redirect, %{flash: %{}, to: "/sign-in"}}}
code: {:ok, _index_live, html} = live(conn, ~p"/books")
** (MatchError) no match of right hand side value: {:error, {:redirect, %{flash: %{}, to: "/sign-in"}}}
code: {:ok, _index_live, html} = live(conn, ~p"/books")
Hey @Terryble , replace
Plug.Conn.put_session(:user_token, user.__metadata__.token)
with AshAuthentication.Phoenix.Plug.store_in_session(user)
in your log_in_user helperHoly crap, that worked! I wonder why the AshHQ repo didn't have to do that to make it work on the tests.