169 lines
6.3 KiB
Elixir
169 lines
6.3 KiB
Elixir
defmodule Mv.Accounts.User.Changes.AssignDefaultRoleTest do
|
|
@moduledoc """
|
|
Tests for AssignDefaultRole change module.
|
|
|
|
Tests cover:
|
|
- Automatic role assignment when no role is set
|
|
- Skipping assignment when role is already set (changeset, data, or argument)
|
|
- Handling missing "Mitglied" role gracefully
|
|
- Error handling for unexpected failures
|
|
"""
|
|
use Mv.DataCase, async: true
|
|
|
|
alias Mv.Accounts.User
|
|
alias Mv.Authorization.Role
|
|
|
|
setup do
|
|
# Ensure "Mitglied" role exists
|
|
Mv.DataCase.ensure_default_role()
|
|
|
|
# Get "Mitglied" role for assertions
|
|
{:ok, mitglied_role} = Role.get_mitglied_role()
|
|
|
|
%{mitglied_role: mitglied_role}
|
|
end
|
|
|
|
describe "change/3" do
|
|
test "assigns Mitglied role when no role is set", %{mitglied_role: mitglied_role} do
|
|
email = "test#{System.unique_integer([:positive])}@example.com"
|
|
|
|
# Create user - AssignDefaultRole change runs automatically via :create_user action
|
|
{:ok, user} =
|
|
User
|
|
|> Ash.Changeset.for_create(:create_user, %{email: email})
|
|
|> Ash.create(authorize?: false, domain: Mv.Accounts)
|
|
|
|
# Load user with role
|
|
{:ok, user_with_role} = Ash.load(user, :role, domain: Mv.Accounts, authorize?: false)
|
|
|
|
# Verify role was assigned
|
|
assert user_with_role.role != nil
|
|
assert user_with_role.role.id == mitglied_role.id
|
|
assert user_with_role.role.name == "Mitglied"
|
|
end
|
|
|
|
test "skips assignment when role relationship is already set in changeset", %{
|
|
mitglied_role: _mitglied_role
|
|
} do
|
|
# Create a different role
|
|
other_role =
|
|
Role
|
|
|> Ash.Changeset.for_create(:create_role, %{
|
|
name: "Test Role #{System.unique_integer([:positive])}",
|
|
description: "Test role",
|
|
permission_set_name: "own_data"
|
|
})
|
|
|> Ash.create!(authorize?: false, domain: Mv.Authorization)
|
|
|
|
# Test that AssignDefaultRole skips when role relationship is already set
|
|
# Create a changeset with role relationship already set BEFORE the change runs
|
|
changeset =
|
|
User
|
|
|> Ash.Changeset.for_create(:create_user, %{
|
|
email: "test#{System.unique_integer([:positive])}@example.com"
|
|
})
|
|
|> Ash.Changeset.manage_relationship(:role, other_role, type: :append_and_remove)
|
|
|
|
# Manually call the change to test it
|
|
result_changeset = Mv.Accounts.User.Changes.AssignDefaultRole.change(changeset, [], %{})
|
|
|
|
# The change should detect that role relationship is already set and skip assignment
|
|
# Verify by creating the user and checking the role
|
|
{:ok, user} = Ash.create(result_changeset, authorize?: false, domain: Mv.Accounts)
|
|
|
|
# Load user with role
|
|
{:ok, user_with_role} = Ash.load(user, :role, domain: Mv.Accounts, authorize?: false)
|
|
|
|
# Verify the explicitly set role was used, not "Mitglied"
|
|
assert user_with_role.role != nil
|
|
assert user_with_role.role.id == other_role.id
|
|
assert user_with_role.role.name != "Mitglied"
|
|
end
|
|
|
|
test "skips assignment when role_id is already set in data (upsert scenario)" do
|
|
# Create user with role
|
|
role =
|
|
Role
|
|
|> Ash.Changeset.for_create(:create_role, %{
|
|
name: "Test Role #{System.unique_integer([:positive])}",
|
|
description: "Test role",
|
|
permission_set_name: "own_data"
|
|
})
|
|
|> Ash.create!(authorize?: false, domain: Mv.Authorization)
|
|
|
|
{:ok, existing_user} =
|
|
User
|
|
|> Ash.Changeset.for_create(:create_user, %{
|
|
email: "existing#{System.unique_integer([:positive])}@example.com"
|
|
})
|
|
|> Ash.create(authorize?: false, domain: Mv.Accounts)
|
|
|
|
# Update user to have role
|
|
{:ok, user_with_role} =
|
|
existing_user
|
|
|> Ash.Changeset.for_update(:update, %{})
|
|
|> Ash.Changeset.manage_relationship(:role, role, type: :append_and_remove)
|
|
|> Ash.update(authorize?: false, domain: Mv.Accounts)
|
|
|
|
# Reload to get role_id in data
|
|
{:ok, user_with_role} =
|
|
Ash.load(user_with_role, :role, domain: Mv.Accounts, authorize?: false)
|
|
|
|
# Verify user has the explicitly set role
|
|
assert user_with_role.role != nil
|
|
assert user_with_role.role.id == role.id
|
|
|
|
# Now update user again - AssignDefaultRole should skip (role already set)
|
|
{:ok, updated_user} =
|
|
user_with_role
|
|
|> Ash.Changeset.for_update(:update, %{})
|
|
|> Ash.update(authorize?: false, domain: Mv.Accounts)
|
|
|
|
# Reload to verify role didn't change
|
|
{:ok, updated_user_with_role} =
|
|
Ash.load(updated_user, :role, domain: Mv.Accounts, authorize?: false)
|
|
|
|
# Role should still be the same (not changed to "Mitglied")
|
|
assert updated_user_with_role.role.id == role.id
|
|
assert updated_user_with_role.role.name != "Mitglied"
|
|
end
|
|
|
|
test "handles missing Mitglied role gracefully" do
|
|
# Test that change handles nil role gracefully
|
|
# Since we can't easily delete the system role, we test the code path
|
|
# by verifying that when get_mitglied_role returns nil, changeset is unchanged
|
|
changeset =
|
|
User
|
|
|> Ash.Changeset.for_create(:create_user, %{
|
|
email: "test#{System.unique_integer([:positive])}@example.com"
|
|
})
|
|
|
|
# The change should handle nil role gracefully
|
|
# If role exists, it will be assigned; if not, changeset remains unchanged
|
|
result_changeset = Mv.Accounts.User.Changes.AssignDefaultRole.change(changeset, [], %{})
|
|
|
|
# Changeset should be valid regardless
|
|
assert result_changeset.valid?
|
|
|
|
# If role exists, it should be assigned (we check this in other tests)
|
|
# If role doesn't exist, changeset should be unchanged (no error)
|
|
end
|
|
|
|
test "assigns role correctly in integration test" do
|
|
email = "integration#{System.unique_integer([:positive])}@example.com"
|
|
|
|
{:ok, user} =
|
|
User
|
|
|> Ash.Changeset.for_create(:create_user, %{email: email})
|
|
|> Ash.create(authorize?: false, domain: Mv.Accounts)
|
|
|
|
# Load user with role
|
|
{:ok, user_with_role} = Ash.load(user, :role, domain: Mv.Accounts, authorize?: false)
|
|
|
|
# Verify role was assigned
|
|
assert user_with_role.role != nil
|
|
assert user_with_role.role.name == "Mitglied"
|
|
assert user_with_role.role.permission_set_name == "own_data"
|
|
end
|
|
end
|
|
end
|