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
Terryble
TerrybleOP3y ago
I hit the character limit in my initial post. This is the continuation:
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
I'm getting this error when running the test:
** (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")
dblack
dblack3y ago
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 helper
Terryble
TerrybleOP3y ago
Holy crap, that worked! I wonder why the AshHQ repo didn't have to do that to make it work on the tests.

Did you find this page helpful?