Add tests for System Actor helper
Test system actor retrieval, caching, fallback behavior, and auto-creation in test environment.
This commit is contained in:
parent
cf9e6e91fd
commit
481e82d541
1 changed files with 193 additions and 0 deletions
193
test/mv/helpers/system_actor_test.exs
Normal file
193
test/mv/helpers/system_actor_test.exs
Normal file
|
|
@ -0,0 +1,193 @@
|
||||||
|
defmodule Mv.Helpers.SystemActorTest do
|
||||||
|
@moduledoc """
|
||||||
|
Tests for the SystemActor helper module.
|
||||||
|
"""
|
||||||
|
use Mv.DataCase, async: false
|
||||||
|
|
||||||
|
alias Mv.Helpers.SystemActor
|
||||||
|
alias Mv.Authorization
|
||||||
|
alias Mv.Accounts
|
||||||
|
|
||||||
|
require Ash.Query
|
||||||
|
|
||||||
|
setup do
|
||||||
|
# Ensure admin role exists
|
||||||
|
admin_role =
|
||||||
|
case Authorization.list_roles() do
|
||||||
|
{:ok, roles} ->
|
||||||
|
case Enum.find(roles, &(&1.permission_set_name == "admin")) do
|
||||||
|
nil ->
|
||||||
|
{:ok, role} =
|
||||||
|
Authorization.create_role(%{
|
||||||
|
name: "Admin",
|
||||||
|
description: "Administrator with full access",
|
||||||
|
permission_set_name: "admin"
|
||||||
|
})
|
||||||
|
|
||||||
|
role
|
||||||
|
|
||||||
|
role ->
|
||||||
|
role
|
||||||
|
end
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:ok, role} =
|
||||||
|
Authorization.create_role(%{
|
||||||
|
name: "Admin",
|
||||||
|
description: "Administrator with full access",
|
||||||
|
permission_set_name: "admin"
|
||||||
|
})
|
||||||
|
|
||||||
|
role
|
||||||
|
end
|
||||||
|
|
||||||
|
# Ensure system user exists
|
||||||
|
system_user =
|
||||||
|
case Accounts.User
|
||||||
|
|> Ash.Query.filter(email == ^"system@mila.local")
|
||||||
|
|> Ash.read_one(domain: Mv.Accounts) do
|
||||||
|
{:ok, user} when not is_nil(user) ->
|
||||||
|
user
|
||||||
|
|> Ash.Changeset.for_update(:update, %{})
|
||||||
|
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
||||||
|
|> Ash.update!()
|
||||||
|
|> Ash.load!(:role, domain: Mv.Accounts)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Accounts.create_user!(%{email: "system@mila.local"},
|
||||||
|
upsert?: true,
|
||||||
|
upsert_identity: :unique_email
|
||||||
|
)
|
||||||
|
|> Ash.Changeset.for_update(:update, %{})
|
||||||
|
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
||||||
|
|> Ash.update!()
|
||||||
|
|> Ash.load!(:role, domain: Mv.Accounts)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Ensure admin user exists (for fallback)
|
||||||
|
admin_email = System.get_env("ADMIN_EMAIL") || "admin@localhost"
|
||||||
|
|
||||||
|
admin_user =
|
||||||
|
case Accounts.User
|
||||||
|
|> Ash.Query.filter(email == ^admin_email)
|
||||||
|
|> Ash.read_one(domain: Mv.Accounts) do
|
||||||
|
{:ok, user} when not is_nil(user) ->
|
||||||
|
user
|
||||||
|
|> Ash.Changeset.for_update(:update, %{})
|
||||||
|
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
||||||
|
|> Ash.update!()
|
||||||
|
|> Ash.load!(:role, domain: Mv.Accounts)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Accounts.create_user!(%{email: admin_email}, upsert?: true, upsert_identity: :unique_email)
|
||||||
|
|> Ash.Changeset.for_update(:update, %{})
|
||||||
|
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
||||||
|
|> Ash.update!()
|
||||||
|
|> Ash.load!(:role, domain: Mv.Accounts)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Invalidate cache to ensure fresh load
|
||||||
|
SystemActor.invalidate_cache()
|
||||||
|
|
||||||
|
%{admin_role: admin_role, system_user: system_user, admin_user: admin_user}
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "get_system_actor/0" do
|
||||||
|
test "returns system user with admin role", %{system_user: _system_user} do
|
||||||
|
system_actor = SystemActor.get_system_actor()
|
||||||
|
|
||||||
|
assert %Mv.Accounts.User{} = system_actor
|
||||||
|
assert to_string(system_actor.email) == "system@mila.local"
|
||||||
|
assert system_actor.role != nil
|
||||||
|
assert system_actor.role.permission_set_name == "admin"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "falls back to admin user if system user doesn't exist", %{admin_user: _admin_user} do
|
||||||
|
# Delete system user if it exists
|
||||||
|
case Accounts.User
|
||||||
|
|> Ash.Query.filter(email == ^"system@mila.local")
|
||||||
|
|> Ash.read_one(domain: Mv.Accounts) do
|
||||||
|
{:ok, user} when not is_nil(user) ->
|
||||||
|
Ash.destroy!(user, domain: Mv.Accounts)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
# Invalidate cache to force reload
|
||||||
|
SystemActor.invalidate_cache()
|
||||||
|
|
||||||
|
# Should fall back to admin user
|
||||||
|
system_actor = SystemActor.get_system_actor()
|
||||||
|
|
||||||
|
assert %Mv.Accounts.User{} = system_actor
|
||||||
|
assert system_actor.role != nil
|
||||||
|
assert system_actor.role.permission_set_name == "admin"
|
||||||
|
# Should be admin user, not system user
|
||||||
|
assert to_string(system_actor.email) != "system@mila.local"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "caches system actor for performance" do
|
||||||
|
# First call
|
||||||
|
actor1 = SystemActor.get_system_actor()
|
||||||
|
|
||||||
|
# Second call should return cached actor (same struct)
|
||||||
|
actor2 = SystemActor.get_system_actor()
|
||||||
|
|
||||||
|
# Should be the same struct (cached)
|
||||||
|
assert actor1.id == actor2.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "creates system user in test environment if none exists", %{admin_role: _admin_role} do
|
||||||
|
# In test environment, system actor should auto-create if missing
|
||||||
|
# Delete all users to test auto-creation
|
||||||
|
case Accounts.User
|
||||||
|
|> Ash.Query.filter(email == ^"system@mila.local")
|
||||||
|
|> Ash.read_one(domain: Mv.Accounts) do
|
||||||
|
{:ok, user} when not is_nil(user) ->
|
||||||
|
Ash.destroy!(user, domain: Mv.Accounts)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
admin_email = System.get_env("ADMIN_EMAIL") || "admin@localhost"
|
||||||
|
case Accounts.User
|
||||||
|
|> Ash.Query.filter(email == ^admin_email)
|
||||||
|
|> Ash.read_one(domain: Mv.Accounts) do
|
||||||
|
{:ok, user} when not is_nil(user) ->
|
||||||
|
Ash.destroy!(user, domain: Mv.Accounts)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
# Invalidate cache
|
||||||
|
SystemActor.invalidate_cache()
|
||||||
|
|
||||||
|
# Should auto-create system user in test environment
|
||||||
|
system_actor = SystemActor.get_system_actor()
|
||||||
|
|
||||||
|
assert %Mv.Accounts.User{} = system_actor
|
||||||
|
assert to_string(system_actor.email) == "system@mila.local"
|
||||||
|
assert system_actor.role != nil
|
||||||
|
assert system_actor.role.permission_set_name == "admin"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "invalidate_cache/0" do
|
||||||
|
test "forces reload of system actor on next call" do
|
||||||
|
# Get initial actor
|
||||||
|
actor1 = SystemActor.get_system_actor()
|
||||||
|
|
||||||
|
# Invalidate cache
|
||||||
|
:ok = SystemActor.invalidate_cache()
|
||||||
|
|
||||||
|
# Next call should reload (but should be same user)
|
||||||
|
actor2 = SystemActor.get_system_actor()
|
||||||
|
|
||||||
|
# Should be same user (same ID)
|
||||||
|
assert actor1.id == actor2.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Add table
Add a link
Reference in a new issue