mitgliederverwaltung/test/membership/member_group_test.exs
2026-02-09 13:34:57 +01:00

121 lines
3.9 KiB
Elixir

defmodule Mv.Membership.MemberGroupTest do
@moduledoc """
Tests for MemberGroup join table resource - validations and cascade delete behavior.
Uses async: true; no shared DB state or sandbox constraints.
"""
use Mv.DataCase, async: true
alias Mv.Membership
require Ash.Query
import Ash.Expr
setup do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
%{actor: system_actor}
end
describe "Validations & Associations" do
test "create association between member and group", %{actor: actor} do
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
{:ok, group} = Membership.create_group(%{name: "Test Group"}, actor: actor)
assert {:ok, member_group} =
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
actor: actor
)
assert member_group.member_id == member.id
assert member_group.group_id == group.id
end
test "prevent duplicate associations (same member + same group)", %{actor: actor} do
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
{:ok, group} = Membership.create_group(%{name: "Test Group"}, actor: actor)
{:ok, _mg1} =
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
actor: actor
)
# Try to create duplicate
assert {:error, %Ash.Error.Invalid{errors: errors}} =
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
actor: actor
)
assert Enum.any?(errors, fn err ->
field = Map.get(err, :field)
message = Map.get(err, :message, "")
(field == :member_id or field == :group_id) and
(String.contains?(message, "already been taken") or
String.contains?(message, "already exists") or
String.contains?(message, "duplicate") or
String.contains?(message, "already in this group"))
end)
end
end
describe "Cascade Delete Behavior" do
test "cascade delete when member deleted (MemberGroup deleted, Group remains)", %{
actor: actor
} do
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
{:ok, group} = Membership.create_group(%{name: "Test Group"}, actor: actor)
{:ok, _mg} =
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
actor: actor
)
# Delete member
:ok = Membership.destroy_member(member, actor: actor)
# Group should still exist
{:ok, group_reloaded} = Ash.get(Mv.Membership.Group, group.id, actor: actor)
assert group_reloaded != nil
# MemberGroup should be deleted
{:ok, mgs} =
Ash.read(
Mv.Membership.MemberGroup
|> Ash.Query.filter(expr(member_id == ^member.id)),
actor: actor,
domain: Mv.Membership
)
assert mgs == []
end
test "cascade delete when group deleted (MemberGroup deleted, Member remains)", %{
actor: actor
} do
{:ok, member} = Membership.create_member(%{email: "test@test.com"}, actor: actor)
{:ok, group} = Membership.create_group(%{name: "Test Group"}, actor: actor)
{:ok, _mg} =
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
actor: actor
)
# Delete group
:ok = Membership.destroy_group(group, actor: actor)
# Member should still exist
{:ok, member_reloaded} = Ash.get(Mv.Membership.Member, member.id, actor: actor)
assert member_reloaded != nil
# MemberGroup should be deleted
{:ok, mgs} =
Ash.read(
Mv.Membership.MemberGroup
|> Ash.Query.filter(expr(group_id == ^group.id)),
actor: actor,
domain: Mv.Membership
)
assert mgs == []
end
end
end