- Add comprehensive tests for UserLive.Show - Add comprehensive tests for RoleLive.Show - Cover mount, display, navigation, and error handling
274 lines
7.9 KiB
Elixir
274 lines
7.9 KiB
Elixir
defmodule MvWeb.RoleLive.ShowTest do
|
|
@moduledoc """
|
|
Tests for the role show page.
|
|
|
|
Tests cover:
|
|
- Displaying role information
|
|
- System role badge display
|
|
- User count display
|
|
- Navigation
|
|
- Error handling
|
|
- Delete functionality
|
|
"""
|
|
use MvWeb.ConnCase, async: false
|
|
import Phoenix.LiveViewTest
|
|
require Ash.Query
|
|
use Gettext, backend: MvWeb.Gettext
|
|
|
|
alias Mv.Authorization
|
|
alias Mv.Authorization.Role
|
|
|
|
# Helper to create a role
|
|
defp create_role(attrs \\ %{}) do
|
|
default_attrs = %{
|
|
name: "Test Role #{System.unique_integer([:positive])}",
|
|
description: "Test description",
|
|
permission_set_name: "read_only"
|
|
}
|
|
|
|
attrs = Map.merge(default_attrs, attrs)
|
|
|
|
case Authorization.create_role(attrs) do
|
|
{:ok, role} -> role
|
|
{:error, error} -> raise "Failed to create role: #{inspect(error)}"
|
|
end
|
|
end
|
|
|
|
# Helper to create admin user with admin role
|
|
defp create_admin_user(conn) do
|
|
# Create admin role
|
|
admin_role =
|
|
case Authorization.list_roles() do
|
|
{:ok, roles} ->
|
|
case Enum.find(roles, &(&1.name == "Admin")) do
|
|
nil ->
|
|
# Create admin role if it doesn't exist
|
|
create_role(%{
|
|
name: "Admin",
|
|
description: "Administrator with full access",
|
|
permission_set_name: "admin"
|
|
})
|
|
|
|
role ->
|
|
role
|
|
end
|
|
|
|
_ ->
|
|
# Create admin role if list_roles fails
|
|
create_role(%{
|
|
name: "Admin",
|
|
description: "Administrator with full access",
|
|
permission_set_name: "admin"
|
|
})
|
|
end
|
|
|
|
# Create user
|
|
{:ok, user} =
|
|
Mv.Accounts.User
|
|
|> Ash.Changeset.for_create(:register_with_password, %{
|
|
email: "admin#{System.unique_integer([:positive])}@mv.local",
|
|
password: "testpassword123"
|
|
})
|
|
|> Ash.create()
|
|
|
|
# Assign admin role using manage_relationship
|
|
{:ok, user} =
|
|
user
|
|
|> Ash.Changeset.for_update(:update, %{})
|
|
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
|
|> Ash.update()
|
|
|
|
# Load role for authorization checks (must be loaded for can?/3 to work)
|
|
user_with_role = Ash.load!(user, :role, domain: Mv.Accounts)
|
|
|
|
# Store user with role in session for LiveView
|
|
conn = conn_with_password_user(conn, user_with_role)
|
|
{conn, user_with_role, admin_role}
|
|
end
|
|
|
|
describe "mount and display" do
|
|
setup %{conn: conn} do
|
|
{conn, _user, _admin_role} = create_admin_user(conn)
|
|
%{conn: conn}
|
|
end
|
|
|
|
test "mounts successfully with valid role ID", %{conn: conn} do
|
|
role = create_role()
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
assert html =~ role.name
|
|
end
|
|
|
|
test "displays role name", %{conn: conn} do
|
|
role = create_role(%{name: "Test Role Name"})
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
assert html =~ "Test Role Name"
|
|
assert html =~ gettext("Name")
|
|
end
|
|
|
|
test "displays role description when present", %{conn: conn} do
|
|
role = create_role(%{description: "This is a test description"})
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
assert html =~ "This is a test description"
|
|
assert html =~ gettext("Description")
|
|
end
|
|
|
|
test "displays 'No description' when description is missing", %{conn: conn} do
|
|
role = create_role(%{description: nil})
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
assert html =~ gettext("No description")
|
|
end
|
|
|
|
test "displays permission set name", %{conn: conn} do
|
|
role = create_role(%{permission_set_name: "read_only"})
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
assert html =~ "read_only"
|
|
assert html =~ gettext("Permission Set")
|
|
end
|
|
|
|
test "displays system role badge when is_system_role is true", %{conn: conn} do
|
|
system_role =
|
|
Role
|
|
|> Ash.Changeset.for_create(:create_role, %{
|
|
name: "System Role",
|
|
permission_set_name: "own_data"
|
|
})
|
|
|> Ash.Changeset.force_change_attribute(:is_system_role, true)
|
|
|> Ash.create!()
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{system_role.id}")
|
|
|
|
assert html =~ gettext("System Role")
|
|
assert html =~ gettext("Yes")
|
|
end
|
|
|
|
test "displays non-system role badge when is_system_role is false", %{conn: conn} do
|
|
role = create_role()
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
assert html =~ gettext("System Role")
|
|
assert html =~ gettext("No")
|
|
end
|
|
|
|
test "displays user count", %{conn: conn} do
|
|
role = create_role()
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
# User count should be displayed (might be 0 or more)
|
|
assert html =~ gettext("User") || html =~ "0" || html =~ "users"
|
|
end
|
|
end
|
|
|
|
describe "navigation" do
|
|
setup %{conn: conn} do
|
|
{conn, _user, _admin_role} = create_admin_user(conn)
|
|
%{conn: conn}
|
|
end
|
|
|
|
test "back button navigates to role list", %{conn: conn} do
|
|
role = create_role()
|
|
|
|
{:ok, view, _html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
assert {:error, {:live_redirect, %{to: to}}} =
|
|
view
|
|
|> element(
|
|
"a[aria-label='#{gettext("Back to roles list")}'], button[aria-label='#{gettext("Back to roles list")}']"
|
|
)
|
|
|> render_click()
|
|
|
|
assert to == "/admin/roles"
|
|
end
|
|
|
|
test "edit button navigates to edit form", %{conn: conn} do
|
|
role = create_role()
|
|
|
|
{:ok, view, _html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
assert {:error, {:live_redirect, %{to: to}}} =
|
|
view
|
|
|> element(
|
|
"a[href='/admin/roles/#{role.id}/edit'], button[href='/admin/roles/#{role.id}/edit']"
|
|
)
|
|
|> render_click()
|
|
|
|
assert to == "/admin/roles/#{role.id}/edit"
|
|
end
|
|
end
|
|
|
|
describe "error handling" do
|
|
setup %{conn: conn} do
|
|
{conn, _user, _admin_role} = create_admin_user(conn)
|
|
%{conn: conn}
|
|
end
|
|
|
|
test "redirects to role list with error for invalid role ID", %{conn: conn} do
|
|
invalid_id = Ecto.UUID.generate()
|
|
|
|
# Should redirect to index with error message
|
|
result = live(conn, "/admin/roles/#{invalid_id}")
|
|
|
|
assert match?({:error, {:redirect, %{to: "/admin/roles"}}}, result) or
|
|
match?({:error, {:live_redirect, %{to: "/admin/roles"}}}, result)
|
|
end
|
|
end
|
|
|
|
describe "delete functionality" do
|
|
setup %{conn: conn} do
|
|
{conn, _user, _admin_role} = create_admin_user(conn)
|
|
%{conn: conn}
|
|
end
|
|
|
|
test "delete button is not shown for system roles", %{conn: conn} do
|
|
system_role =
|
|
Role
|
|
|> Ash.Changeset.for_create(:create_role, %{
|
|
name: "System Role",
|
|
permission_set_name: "own_data"
|
|
})
|
|
|> Ash.Changeset.force_change_attribute(:is_system_role, true)
|
|
|> Ash.create!()
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{system_role.id}")
|
|
|
|
# Delete button should not be visible for system roles
|
|
refute html =~ ~r/Delete.*Role.*#{system_role.id}/i
|
|
end
|
|
|
|
test "delete button is shown for non-system roles", %{conn: conn} do
|
|
role = create_role()
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
# Delete button should be visible for non-system roles
|
|
assert html =~ gettext("Delete Role") || html =~ "delete"
|
|
end
|
|
end
|
|
|
|
describe "page title" do
|
|
setup %{conn: conn} do
|
|
{conn, _user, _admin_role} = create_admin_user(conn)
|
|
%{conn: conn}
|
|
end
|
|
|
|
test "sets correct page title", %{conn: conn} do
|
|
role = create_role()
|
|
|
|
{:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
|
|
|
|
# Check that page title is set (might be in title tag or header)
|
|
assert html =~ gettext("Show Role") || html =~ role.name
|
|
end
|
|
end
|
|
end
|