427 lines
11 KiB
Elixir
427 lines
11 KiB
Elixir
defmodule MvWeb.GroupLive.ShowIntegrationTest do
|
|
@moduledoc """
|
|
Integration tests for Add/Remove Member functionality.
|
|
Tests data consistency, database operations, and multiple operations.
|
|
"""
|
|
|
|
use MvWeb.ConnCase, async: false
|
|
import Phoenix.LiveViewTest
|
|
use Gettext, backend: MvWeb.Gettext
|
|
|
|
alias Mv.Membership
|
|
alias Mv.Fixtures
|
|
|
|
describe "data consistency" do
|
|
test "member appears in group after add (verified in database)", %{conn: conn} do
|
|
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
|
group = Fixtures.group_fixture()
|
|
|
|
{:ok, member} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Alice",
|
|
last_name: "Smith",
|
|
email: "alice@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, view, _html} = live(conn, "/groups/#{group.slug}")
|
|
|
|
# Add member via UI
|
|
view
|
|
|> element("button", "Add Member")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_focus()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_change(%{"member_search" => "Alice"})
|
|
|
|
view
|
|
|> element("[data-member-id='#{member.id}']")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("button", "Add")
|
|
|> render_click()
|
|
|
|
# Verify in database
|
|
require Ash.Query
|
|
|
|
query =
|
|
Mv.Membership.Group
|
|
|> Ash.Query.filter(slug == ^group.slug)
|
|
|> Ash.Query.load([:members])
|
|
|
|
{:ok, updated_group} = Ash.read_one(query, actor: system_actor, domain: Mv.Membership)
|
|
|
|
# Member should be in group
|
|
assert Enum.any?(updated_group.members, &(&1.id == member.id))
|
|
end
|
|
|
|
test "member disappears from group after remove (verified in database)", %{conn: conn} do
|
|
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
|
group = Fixtures.group_fixture()
|
|
|
|
{:ok, member} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Bob",
|
|
last_name: "Jones",
|
|
email: "bob@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
# Add member to group
|
|
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, view, _html} = live(conn, "/groups/#{group.slug}")
|
|
|
|
# Remove member via UI
|
|
view
|
|
|> element("button[phx-click='remove_member']", "")
|
|
|> render_click()
|
|
|
|
# Verify in database
|
|
require Ash.Query
|
|
|
|
query =
|
|
Mv.Membership.Group
|
|
|> Ash.Query.filter(slug == ^group.slug)
|
|
|> Ash.Query.load([:members])
|
|
|
|
{:ok, updated_group} = Ash.read_one(query, actor: system_actor, domain: Mv.Membership)
|
|
|
|
# Member should NOT be in group
|
|
refute Enum.any?(updated_group.members, &(&1.id == member.id))
|
|
end
|
|
|
|
test "MemberGroup association is created correctly", %{conn: conn} do
|
|
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
|
group = Fixtures.group_fixture()
|
|
|
|
{:ok, member} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Charlie",
|
|
last_name: "Brown",
|
|
email: "charlie@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, view, _html} = live(conn, "/groups/#{group.slug}")
|
|
|
|
# Add member
|
|
view
|
|
|> element("button", "Add Member")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_focus()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_change(%{"member_search" => "Charlie"})
|
|
|
|
view
|
|
|> element("[data-member-id='#{member.id}']")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("button", "Add")
|
|
|> render_click()
|
|
|
|
# Verify MemberGroup association exists
|
|
require Ash.Query
|
|
|
|
{:ok, member_groups} =
|
|
Ash.read(
|
|
Mv.Membership.MemberGroup
|
|
|> Ash.Query.filter(member_id == ^member.id and group_id == ^group.id),
|
|
actor: system_actor,
|
|
domain: Mv.Membership
|
|
)
|
|
|
|
assert length(member_groups) == 1
|
|
assert hd(member_groups).member_id == member.id
|
|
assert hd(member_groups).group_id == group.id
|
|
end
|
|
|
|
test "MemberGroup association is deleted correctly", %{conn: conn} do
|
|
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
|
group = Fixtures.group_fixture()
|
|
|
|
{:ok, member} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "David",
|
|
last_name: "Wilson",
|
|
email: "david@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
# Add member first
|
|
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, view, _html} = live(conn, "/groups/#{group.slug}")
|
|
|
|
# Remove member
|
|
view
|
|
|> element("button[phx-click='remove_member']", "")
|
|
|> render_click()
|
|
|
|
# Verify MemberGroup association is deleted
|
|
require Ash.Query
|
|
|
|
{:ok, member_groups} =
|
|
Ash.read(
|
|
Mv.Membership.MemberGroup
|
|
|> Ash.Query.filter(member_id == ^member.id and group_id == ^group.id),
|
|
actor: system_actor,
|
|
domain: Mv.Membership
|
|
)
|
|
|
|
assert member_groups == []
|
|
end
|
|
|
|
test "member itself is NOT deleted (only association)", %{conn: conn} do
|
|
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
|
group = Fixtures.group_fixture()
|
|
|
|
{:ok, member} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Eve",
|
|
last_name: "Davis",
|
|
email: "eve@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
# Add member to group
|
|
Membership.create_member_group(%{member_id: member.id, group_id: group.id},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, view, _html} = live(conn, "/groups/#{group.slug}")
|
|
|
|
# Remove member from group
|
|
view
|
|
|> element("button[phx-click='remove_member']", "")
|
|
|> render_click()
|
|
|
|
# Verify member still exists
|
|
{:ok, member_after_remove} =
|
|
Ash.get(Mv.Membership.Member, member.id, actor: system_actor)
|
|
|
|
assert member_after_remove.id == member.id
|
|
assert member_after_remove.first_name == "Eve"
|
|
end
|
|
end
|
|
|
|
describe "multiple operations" do
|
|
test "multiple members can be added sequentially", %{conn: conn} do
|
|
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
|
group = Fixtures.group_fixture()
|
|
|
|
{:ok, member1} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Frank",
|
|
last_name: "Moore",
|
|
email: "frank@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, member2} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Grace",
|
|
last_name: "Taylor",
|
|
email: "grace@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, view, _html} = live(conn, "/groups/#{group.slug}")
|
|
|
|
# Add first member
|
|
view
|
|
|> element("button", "Add Member")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_focus()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_change(%{"member_search" => "Frank"})
|
|
|
|
view
|
|
|> element("[data-member-id='#{member1.id}']")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("button", "Add")
|
|
|> render_click()
|
|
|
|
# Add second member
|
|
view
|
|
|> element("button", "Add Member")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_focus()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_change(%{"member_search" => "Grace"})
|
|
|
|
view
|
|
|> element("[data-member-id='#{member2.id}']")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("button", "Add")
|
|
|> render_click()
|
|
|
|
# Both members should be in list
|
|
html = render(view)
|
|
assert html =~ "Frank"
|
|
assert html =~ "Grace"
|
|
end
|
|
|
|
test "multiple members can be removed sequentially", %{conn: conn} do
|
|
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
|
group = Fixtures.group_fixture()
|
|
|
|
{:ok, member1} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Henry",
|
|
last_name: "Anderson",
|
|
email: "henry@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, member2} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Isabel",
|
|
last_name: "Martinez",
|
|
email: "isabel@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
# Add both members
|
|
Membership.create_member_group(%{member_id: member1.id, group_id: group.id},
|
|
actor: system_actor
|
|
)
|
|
|
|
Membership.create_member_group(%{member_id: member2.id, group_id: group.id},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, view, html} = live(conn, "/groups/#{group.slug}")
|
|
|
|
# Both should be in list initially
|
|
assert html =~ "Henry"
|
|
assert html =~ "Isabel"
|
|
|
|
# Remove first member
|
|
view
|
|
|> element("button[phx-click='remove_member']", "")
|
|
|> render_click()
|
|
|
|
# Remove second member
|
|
view
|
|
|> element("button[phx-click='remove_member']", "")
|
|
|> render_click()
|
|
|
|
# Both should be removed
|
|
html = render(view)
|
|
refute html =~ "Henry"
|
|
refute html =~ "Isabel"
|
|
end
|
|
|
|
test "add and remove can be mixed", %{conn: conn} do
|
|
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
|
group = Fixtures.group_fixture()
|
|
|
|
{:ok, member1} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Jack",
|
|
last_name: "White",
|
|
email: "jack@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, member2} =
|
|
Membership.create_member(
|
|
%{
|
|
first_name: "Kate",
|
|
last_name: "Black",
|
|
email: "kate@example.com"
|
|
},
|
|
actor: system_actor
|
|
)
|
|
|
|
# Add member1 first
|
|
Membership.create_member_group(%{member_id: member1.id, group_id: group.id},
|
|
actor: system_actor
|
|
)
|
|
|
|
{:ok, view, _html} = live(conn, "/groups/#{group.slug}")
|
|
|
|
# Add member2
|
|
view
|
|
|> element("button", "Add Member")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_focus()
|
|
|
|
view
|
|
|> element("#member-search-input")
|
|
|> render_change(%{"member_search" => "Kate"})
|
|
|
|
view
|
|
|> element("[data-member-id='#{member2.id}']")
|
|
|> render_click()
|
|
|
|
view
|
|
|> element("button", "Add")
|
|
|> render_click()
|
|
|
|
# Remove member1
|
|
view
|
|
|> element("button[phx-click='remove_member']", "")
|
|
|> render_click()
|
|
|
|
# Only member2 should remain
|
|
html = render(view)
|
|
refute html =~ "Jack"
|
|
assert html =~ "Kate"
|
|
end
|
|
end
|
|
end
|