test: add tests for user-member linking and fuzzy search (#168)

This commit is contained in:
Moritz 2025-11-20 15:51:44 +01:00
parent 70b3875154
commit 173f522da5
Signed by: moritz
GPG key ID: 1020A035E5DD0824
4 changed files with 679 additions and 0 deletions

View file

@ -0,0 +1,169 @@
defmodule Mv.Accounts.UserMemberLinkingEmailTest do
@moduledoc """
Tests email validation during user-member linking.
Implements rules from docs/email-sync.md.
Tests for Issue #168, specifically Problem #4: Email validation bug.
"""
use Mv.DataCase, async: false
alias Mv.Accounts
alias Mv.Membership
describe "link with same email" do
test "succeeds when user.email == member.email" do
# Create member with specific email
{:ok, member} =
Membership.create_member(%{
first_name: "Alice",
last_name: "Johnson",
email: "alice@example.com"
})
# Create user with same email and link to member
result =
Accounts.create_user(%{
email: "alice@example.com",
member: %{id: member.id}
})
# Should succeed without errors
assert {:ok, user} = result
assert to_string(user.email) == "alice@example.com"
# Reload to verify link
user = Ash.load!(user, [:member], domain: Mv.Accounts)
assert user.member.id == member.id
assert user.member.email == "alice@example.com"
end
test "no validation error triggered when updating linked pair with same email" do
# Create member
{:ok, member} =
Membership.create_member(%{
first_name: "Bob",
last_name: "Smith",
email: "bob@example.com"
})
# Create user and link
{:ok, user} =
Accounts.create_user(%{
email: "bob@example.com",
member: %{id: member.id}
})
# Update user (should not trigger email validation error)
result = Accounts.update_user(user, %{email: "bob@example.com"})
assert {:ok, updated_user} = result
assert to_string(updated_user.email) == "bob@example.com"
end
end
describe "link with different emails" do
test "fails if member.email is used by a DIFFERENT linked user" do
# Create first user and link to a different member
{:ok, other_member} =
Membership.create_member(%{
first_name: "Other",
last_name: "Member",
email: "other@example.com"
})
{:ok, _user1} =
Accounts.create_user(%{
email: "user1@example.com",
member: %{id: other_member.id}
})
# Reload to ensure email sync happened
_other_member = Ash.reload!(other_member)
# Create a NEW member with different email
{:ok, member} =
Membership.create_member(%{
first_name: "Charlie",
last_name: "Brown",
email: "charlie@example.com"
})
# Try to create user2 with email that matches the linked other_member
result =
Accounts.create_user(%{
email: "user1@example.com",
member: %{id: member.id}
})
# Should fail because user1@example.com is already used by other_member (which is linked to user1)
assert {:error, _error} = result
end
test "succeeds for unique emails" do
# Create member
{:ok, member} =
Membership.create_member(%{
first_name: "David",
last_name: "Wilson",
email: "david@example.com"
})
# Create user with different but unique email
result =
Accounts.create_user(%{
email: "user@example.com",
member: %{id: member.id}
})
# Should succeed
assert {:ok, user} = result
# Email sync should update member's email to match user's
user = Ash.load!(user, [:member], domain: Mv.Accounts)
assert user.member.email == "user@example.com"
end
end
describe "edge cases" do
test "unlinking and relinking with same email works (Problem #4)" do
# This is the exact scenario from Problem #4:
# 1. Link user and member (both have same email)
# 2. Unlink them (member keeps the email)
# 3. Try to relink (validation should NOT fail)
# Create member
{:ok, member} =
Membership.create_member(%{
first_name: "Emma",
last_name: "Davis",
email: "emma@example.com"
})
# Create user and link
{:ok, user} =
Accounts.create_user(%{
email: "emma@example.com",
member: %{id: member.id}
})
# Verify they are linked
user = Ash.load!(user, [:member], domain: Mv.Accounts)
assert user.member.id == member.id
assert user.member.email == "emma@example.com"
# Unlink
{:ok, unlinked_user} = Accounts.update_user(user, %{member: nil})
assert is_nil(unlinked_user.member_id)
# Member still has the email after unlink
member = Ash.reload!(member)
assert member.email == "emma@example.com"
# Relink (should work - this is Problem #4)
result = Accounts.update_user(unlinked_user, %{member: %{id: member.id}})
assert {:ok, relinked_user} = result
assert relinked_user.member_id == member.id
end
end
end