defmodule MvWeb.GroupLive.IntegrationTest do @moduledoc """ Integration tests for complete group management workflows. Tests cover: - Complete workflows (Create → View → Edit → Delete) - Slug-based navigation - Member-group associations - URL persistence """ use MvWeb.ConnCase, async: false import Phoenix.LiveViewTest require Ash.Query import Ash.Expr use Gettext, backend: MvWeb.Gettext alias Mv.Membership alias Mv.Fixtures describe "complete workflow" do test "create → view via slug → edit → view via slug (slug unchanged)", %{ conn: conn, current_user: current_user } do # Create group {:ok, view, _html} = live(conn, "/groups/new") form_data = %{ "name" => "Workflow Test Group", "description" => "Initial description" } view |> form("#group-form", group: form_data) |> render_submit() # Get the created group by name using current user (tests authorization) {:ok, groups} = Membership.list_groups(actor: current_user) group = Enum.find(groups, &(&1.name == "Workflow Test Group")) original_slug = group.slug # View via slug {:ok, _view, html} = live(conn, "/groups/#{group.slug}") assert html =~ "Workflow Test Group" assert html =~ "Initial description" # Edit group {:ok, view, _html} = live(conn, "/groups/#{group.slug}/edit") form_data = %{ "name" => "Updated Workflow Test Group", "description" => "Updated description" } view |> form("#group-form", group: form_data) |> render_submit() # View again via slug (should still work with original slug) {:ok, _view, html} = live(conn, "/groups/#{original_slug}") assert html =~ "Updated Workflow Test Group" assert html =~ "Updated description" # Slug should remain unchanged assert html =~ original_slug or html =~ "workflow-test-group" end test "create group → add members → view (member count updated)", %{ conn: conn, current_user: current_user } do # Create group {:ok, view, _html} = live(conn, "/groups/new") form_data = %{ "name" => "Member Test Group" } view |> form("#group-form", group: form_data) |> render_submit() # Get the created group using current user (tests authorization) {:ok, groups} = Membership.list_groups(actor: current_user) group = Enum.find(groups, &(&1.name == "Member Test Group")) # Add members to group (use system_actor for test data setup) system_actor = Mv.Helpers.SystemActor.get_system_actor() member1 = Fixtures.member_fixture() member2 = Fixtures.member_fixture() 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 ) # View group via slug {:ok, _view, html} = live(conn, "/groups/#{group.slug}") # Member count should be 2 assert html =~ "2" or html =~ gettext("Members") or html =~ "Mitglieder" assert html =~ member1.first_name or html =~ member1.last_name assert html =~ member2.first_name or html =~ member2.last_name end test "create group → add members → delete (cascade works)", %{ conn: conn, current_user: current_user } do # Create group {:ok, view, _html} = live(conn, "/groups/new") form_data = %{ "name" => "Delete Test Group" } view |> form("#group-form", group: form_data) |> render_submit() # Get the created group using current user (tests authorization) {:ok, groups} = Membership.list_groups(actor: current_user) group = Enum.find(groups, &(&1.name == "Delete Test Group")) # Add member to group (use system_actor for test data setup) system_actor = Mv.Helpers.SystemActor.get_system_actor() member = Fixtures.member_fixture() Membership.create_member_group(%{member_id: member.id, group_id: group.id}, actor: system_actor ) # Delete group (via UI - would need delete confirmation modal test) # For now, test via API that cascade works # Use current_user to test authorization (admin can delete) :ok = Membership.destroy_group(group, actor: current_user) # Verify member still exists (use system_actor for verification - this is test verification, not user action) system_actor = Mv.Helpers.SystemActor.get_system_actor() {:ok, member_reloaded} = Ash.get(Mv.Membership.Member, member.id, actor: system_actor) assert member_reloaded != nil # Verify member-group association is deleted {:ok, mgs} = Ash.read( Mv.Membership.MemberGroup |> Ash.Query.filter(expr(group_id == ^group.id)), actor: system_actor, domain: Mv.Membership ) assert mgs == [] end end describe "slug-based navigation" do test "links to group detail use slug (not ID)", %{conn: conn} do group = Fixtures.group_fixture(%{name: "Navigation Test Group"}) {:ok, _view, html} = live(conn, "/groups") # Links should use slug, not UUID assert html =~ "/groups/#{group.slug}" refute html =~ "/groups/#{group.id}" end test "deep links to group detail per slug work", %{conn: conn} do group = Fixtures.group_fixture(%{name: "Deep Link Test"}) # Direct navigation to slug URL {:ok, _view, html} = live(conn, "/groups/#{group.slug}") assert html =~ "Deep Link Test" end test "browser back button works correctly", %{conn: conn} do group = Fixtures.group_fixture() # Navigate to group detail {:ok, _view1, _html} = live(conn, "/groups/#{group.slug}") # Navigate to edit {:ok, view2, _html} = live(conn, "/groups/#{group.slug}/edit") # Browser back should work (tested via navigation) assert view2 != nil end end describe "URL persistence" do test "slug-based URLs persist across page reloads", %{conn: conn} do group = Fixtures.group_fixture(%{name: "Persistent URL Test"}) # First visit {:ok, _view1, html1} = live(conn, "/groups/#{group.slug}") assert html1 =~ "Persistent URL Test" # Simulate page reload (new connection) {:ok, _view2, html2} = live(conn, "/groups/#{group.slug}") assert html2 =~ "Persistent URL Test" end end end