120 lines
3.9 KiB
Elixir
120 lines
3.9 KiB
Elixir
defmodule Mv.Membership.MemberGroupTest do
|
|
@moduledoc """
|
|
Tests for MemberGroup join table resource - validations and cascade delete behavior.
|
|
"""
|
|
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
|