defmodule MvWeb.GroupLive.IndexTest do @moduledoc """ Tests for the groups overview page. Tests cover: - Displaying list of groups - Creating new groups - Deleting groups with confirmation - Permission checks - Edge cases """ use MvWeb.ConnCase, async: false import Phoenix.LiveViewTest use Gettext, backend: MvWeb.Gettext alias Mv.Membership alias Mv.Fixtures describe "mount and display" do test "page renders successfully for admin user", %{conn: conn} do {:ok, _view, html} = live(conn, "/groups") assert html =~ gettext("Groups") end test "lists all groups", %{conn: conn} do group1 = Fixtures.group_fixture(%{name: "Group One"}) group2 = Fixtures.group_fixture(%{name: "Group Two"}) {:ok, _view, html} = live(conn, "/groups") assert html =~ group1.name assert html =~ group2.name end test "displays group name, description, and member count", %{conn: conn} do _group = Fixtures.group_fixture(%{name: "Test Group", description: "Test description"}) {:ok, _view, html} = live(conn, "/groups") assert html =~ "Test Group" assert html =~ "Test description" # Member count should be displayed (0 for empty group) assert html =~ "0" || html =~ gettext("Members") end test "displays 'Create Group' button for admin users", %{conn: conn} do {:ok, _view, html} = live(conn, "/groups") assert html =~ gettext("Create Group") || html =~ "create" || html =~ "new" end test "displays empty state when no groups exist", %{conn: conn} do {:ok, _view, html} = live(conn, "/groups") # Should show empty state or empty list message assert html =~ gettext("No groups") || html =~ "0" || html =~ "empty" end end describe "edge cases" do test "handles very long group names correctly", %{conn: conn} do long_name = String.duplicate("a", 100) _group = Fixtures.group_fixture(%{name: long_name}) {:ok, _view, html} = live(conn, "/groups") assert html =~ long_name end test "handles very long descriptions correctly", %{conn: conn} do long_description = String.duplicate("a", 500) _group = Fixtures.group_fixture(%{description: long_description}) {:ok, _view, html} = live(conn, "/groups") assert html =~ long_description || html =~ String.slice(long_description, 0, 100) end end describe "security" do @tag role: :member test "non-admin users cannot access groups page", %{conn: conn} do # Should redirect or show 403 result = live(conn, "/groups") assert match?({:error, {:redirect, %{to: _}}}, result) || match?({:error, {:live_redirect, %{to: _}}}, result) end @tag role: :unauthenticated test "unauthenticated users are redirected to login", %{conn: conn} do result = live(conn, "/groups") assert match?({:error, {:redirect, %{to: "/auth/sign_in"}}}, result) || match?({:error, {:live_redirect, %{to: "/auth/sign_in"}}}, result) end @tag role: :member test "read-only users can view groups but not create", %{conn: conn} do # Create read-only user read_only_user = Fixtures.user_with_role_fixture("read_only") conn = conn_with_password_user(conn, read_only_user) {:ok, _view, html} = live(conn, "/groups") # Should be able to see groups assert html =~ gettext("Groups") # Should NOT see create button refute html =~ gettext("Create Group") || html =~ "create" end end describe "performance" do test "page loads efficiently with many groups", %{conn: conn} do # Create multiple groups Enum.each(1..10, fn _ -> Fixtures.group_fixture() end) # Should load without N+1 queries {:ok, _view, html} = live(conn, "/groups") # Verify all groups are displayed assert html =~ gettext("Groups") end test "member count is loaded efficiently via calculation", %{conn: conn} do group = Fixtures.group_fixture() member1 = Fixtures.member_fixture() member2 = Fixtures.member_fixture() # Add members to group system_actor = Mv.Helpers.SystemActor.get_system_actor() 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") # Member count should be displayed (should be 2) assert html =~ "2" || html =~ gettext("Members") end end end