From d77eb4d55e1e853cf42fa5274a4aa87e5117b487 Mon Sep 17 00:00:00 2001 From: Moritz Date: Sat, 24 Jan 2026 19:13:15 +0100 Subject: [PATCH] Add test support for default role assignment --- test/support/data_case.ex | 34 ++++++++++++++++++++++++++ test/support/fixtures.ex | 50 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/test/support/data_case.ex b/test/support/data_case.ex index 4ba75ef..e39568b 100644 --- a/test/support/data_case.ex +++ b/test/support/data_case.ex @@ -16,6 +16,8 @@ defmodule Mv.DataCase do use ExUnit.CaseTemplate + require Ash.Query + using do quote do alias Mv.Repo @@ -29,6 +31,8 @@ defmodule Mv.DataCase do setup tags do Mv.DataCase.setup_sandbox(tags) + # Ensure "Mitglied" role exists for AssignDefaultRole to work in tests + Mv.DataCase.ensure_default_role() :ok end @@ -42,6 +46,36 @@ defmodule Mv.DataCase do pid end + @doc """ + Ensures the default "Mitglied" role exists in the test database. + + This is necessary because AssignDefaultRole expects this role to exist. + Tests run in sandbox mode, so the role needs to be created for each test. + """ + def ensure_default_role do + # Check if "Mitglied" role already exists + case Mv.Authorization.Role.get_mitglied_role() do + {:ok, nil} -> + # Create the role if it doesn't exist + Mv.Authorization.Role + |> Ash.Changeset.for_create(:create_role_with_system_flag, %{ + name: "Mitglied", + description: "Default member role with access to own data only", + permission_set_name: "own_data", + is_system_role: true + }) + |> Ash.create!(authorize?: false, domain: Mv.Authorization) + + {:ok, _role} -> + # Role already exists, do nothing + :ok + + {:error, _error} -> + # Ignore errors (e.g., in tests that don't need roles) + :ok + end + end + @doc """ A helper that transforms changeset errors into a map of messages. diff --git a/test/support/fixtures.ex b/test/support/fixtures.ex index 29726ef..23d4aa7 100644 --- a/test/support/fixtures.ex +++ b/test/support/fixtures.ex @@ -182,6 +182,56 @@ defmodule Mv.Fixtures do user_with_role end + @doc """ + Creates a user with password authentication and a specific role. + + This is useful for tests that need to use password-based registration + but also require the user to have a role for authorization. + + ## Parameters + - `email` - User email (defaults to unique generated email) + - `password` - User password (defaults to "testpassword123") + - `permission_set_name` - The permission set name (defaults to "own_data") + + ## Returns + - User struct with role preloaded + + ## Examples + + iex> user = password_user_with_role_fixture() + iex> user.role.permission_set_name + "own_data" + + """ + def password_user_with_role_fixture(opts \\ %{}) do + email = Map.get(opts, :email, "user#{System.unique_integer([:positive])}@example.com") + password = Map.get(opts, :password, "testpassword123") + permission_set_name = Map.get(opts, :permission_set_name, "own_data") + + # Create role with permission set + role = role_fixture(permission_set_name) + + # Create user with password (without password_confirmation as it's optional) + {:ok, user} = + Mv.Accounts.User + |> Ash.Changeset.for_create(:register_with_password, %{ + email: email, + password: password + }) + |> Ash.create() + + # Assign role to user + {:ok, user} = + user + |> Ash.Changeset.for_update(:update, %{}) + |> Ash.Changeset.manage_relationship(:role, role, type: :append_and_remove) + |> Ash.update() + + # Reload user with role preloaded + {:ok, user_with_role} = Ash.load(user, :role, domain: Mv.Accounts) + user_with_role + end + @doc """ Creates a member with an actor (for use in tests with policies).