defmodule Mv.Accounts.UserMemberRelationshipTest do # Using async: true for faster test execution # This is safe because all database operations are sandboxed per test use Mv.DataCase, async: true alias Mv.Accounts alias Mv.Membership describe "User-Member Relationship - Basic Tests" do @valid_user_attrs %{ email: "test@example.com" } @valid_member_attrs %{ first_name: "John", last_name: "Doe", email: "john@example.com" } test "user can exist without member" do {:ok, user} = Accounts.create_user(@valid_user_attrs) assert user.member_id == nil # Load the relationship to test it {:ok, user_with_member} = Ash.get(Mv.Accounts.User, user.id, load: [:member]) assert user_with_member.member == nil end test "member can exist without user" do {:ok, member} = Membership.create_member(@valid_member_attrs) assert member.id != nil assert member.first_name == "John" # Load the relationship to test it {:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user]) assert member_with_user.user == nil end end describe "User-Member Relationship - Linking Tests" do @valid_user_attrs %{ email: "test1@example.com" } @valid_member_attrs %{ first_name: "Alice", last_name: "Johnson", email: "alice@example.com" } test "user can be linked to member during user creation" do {:ok, member} = Membership.create_member(@valid_member_attrs) user_attrs = Map.put(@valid_user_attrs, :member, %{id: member.id}) {:ok, user} = Accounts.create_user(user_attrs) # Load the relationship to test it {:ok, user_with_member} = Ash.get(Mv.Accounts.User, user.id, load: [:member]) assert user_with_member.member.id == member.id end test "member can be linked to user during member creation using manage_relationship" do {:ok, user} = Accounts.create_user(@valid_user_attrs) member_attrs = Map.put(@valid_member_attrs, :user, %{id: user.id}) {:ok, member} = Membership.create_member(member_attrs) # Load the relationship to test it {:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user]) assert member_with_user.user.id == user.id end test "user can be linked to member during update" do {:ok, user} = Accounts.create_user(@valid_user_attrs) {:ok, member} = Membership.create_member(@valid_member_attrs) {:ok, updated_user} = Accounts.update_user(user, %{member: %{id: member.id}}) # Load the relationship to test it {:ok, user_with_member} = Ash.get(Mv.Accounts.User, updated_user.id, load: [:member]) assert user_with_member.member.id == member.id end test "member can be linked to user during update using manage_relationship" do {:ok, user} = Accounts.create_user(@valid_user_attrs) {:ok, member} = Membership.create_member(@valid_member_attrs) {:ok, _updated_member} = Membership.update_member(member, %{user: %{id: user.id}}) # Load the relationship to test it {:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user]) assert member_with_user.user.id == user.id end end describe "User-Member Relationship - Inverse Relationship Tests" do @valid_user_attrs %{ email: "test2@example.com" } @valid_member_attrs %{ first_name: "Bob", last_name: "Smith", email: "bob@example.com" } test "ash resolves inverse relationship automatically" do {:ok, member} = Membership.create_member(@valid_member_attrs) user_attrs = Map.put(@valid_user_attrs, :member, %{id: member.id}) {:ok, user} = Accounts.create_user(user_attrs) # Load relationships {:ok, user_with_member} = Ash.get(Mv.Accounts.User, user.id, load: [:member]) {:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user]) assert user_with_member.member.id == member.id assert member_with_user.user.id == user.id end test "member can find associated user" do {:ok, member} = Membership.create_member(@valid_member_attrs) {:ok, user} = Accounts.create_user(%{email: "test3@example.com", member: %{id: member.id}}) {:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user]) assert member_with_user.user.id == user.id end end describe "User-Member Relationship - Preventing Duplicates" do @valid_user_attrs %{ email: "test4@example.com" } @valid_member_attrs %{ first_name: "Charlie", last_name: "Brown", email: "charlie@example.com" } test "prevents overwriting a member of already linked user on update" do {:ok, existing_member} = Membership.create_member(@valid_member_attrs) user_attrs = Map.put(@valid_user_attrs, :member, %{id: existing_member.id}) {:ok, user} = Accounts.create_user(user_attrs) {:ok, member2} = Membership.create_member(%{ first_name: "Dave", last_name: "Wilson", email: "dave@example.com" }) assert {:error, %Ash.Error.Invalid{}} = Accounts.update_user(user, %{member: %{id: member2.id}}) end test "prevents linking user to already linked member on update" do {:ok, existing_user} = Accounts.create_user(@valid_user_attrs) {:ok, member} = Membership.create_member(@valid_member_attrs) {:ok, _updated_user} = Accounts.update_user(existing_user, %{member: %{id: member.id}}) {:ok, user2} = Accounts.create_user(%{email: "test5@example.com"}) assert {:error, %Ash.Error.Invalid{}} = Accounts.update_user(user2, %{member: %{id: member.id}}) end test "prevents linking member to already linked user on creation" do {:ok, existing_member} = Membership.create_member(@valid_member_attrs) user_attrs = Map.put(@valid_user_attrs, :member, %{id: existing_member.id}) {:ok, user} = Accounts.create_user(user_attrs) assert {:error, %Ash.Error.Invalid{}} = Membership.create_member(%{ first_name: "Dave", last_name: "Wilson", email: "dave@example.com", user: %{id: user.id} }) end test "prevents linking user to already linked member on creation" do {:ok, existing_user} = Accounts.create_user(@valid_user_attrs) {:ok, member} = Membership.create_member(@valid_member_attrs) {:ok, _updated_user} = Accounts.update_user(existing_user, %{member: %{id: member.id}}) assert {:error, %Ash.Error.Invalid{}} = Accounts.create_user(%{ email: "test5@example.com", member: %{id: member.id} }) end end end