From 9991291b2f42ce6d2239edfdcbaff36228d01072 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 27 Jan 2026 23:40:12 +0100 Subject: [PATCH] test: adapt tests to reflect implementation details --- lib/mv_web/live/group_live/form.ex | 51 ++++++++++++------- lib/mv_web/live/group_live/index.ex | 4 +- test/mv_web/live/group_live/form_test.exs | 44 ++++++++-------- test/mv_web/live/group_live/index_test.exs | 18 ++++--- .../live/group_live/integration_test.exs | 16 +++--- test/mv_web/live/group_live/show_test.exs | 33 +++++++----- test/support/conn_case.ex | 3 +- 7 files changed, 98 insertions(+), 71 deletions(-) diff --git a/lib/mv_web/live/group_live/form.ex b/lib/mv_web/live/group_live/form.ex index 7db2345..aef6fc6 100644 --- a/lib/mv_web/live/group_live/form.ex +++ b/lib/mv_web/live/group_live/form.ex @@ -28,8 +28,13 @@ defmodule MvWeb.GroupLive.Form do resource = Mv.Membership.Group if can?(actor, action, resource) do - socket = load_group_for_form(socket, params, actor) - {:ok, assign_form(socket)} + case load_group_for_form(socket, params, actor) do + {:redirect, socket} -> + {:ok, socket} + + {:ok, socket} -> + {:ok, assign_form(socket)} + end else {:ok, redirect(socket, to: ~p"/groups")} end @@ -39,10 +44,13 @@ defmodule MvWeb.GroupLive.Form do case params["slug"] do nil -> # New group - socket - |> assign(:group, nil) - |> assign(:page_title, gettext("Create Group")) - |> assign(:return_to, "index") + socket = + socket + |> assign(:group, nil) + |> assign(:page_title, gettext("Create Group")) + |> assign(:return_to, "index") + + {:ok, socket} slug -> # Edit existing group @@ -53,20 +61,29 @@ defmodule MvWeb.GroupLive.Form do defp load_existing_group(socket, slug, actor) do case Membership.get_group_by_slug(slug, actor: actor) do {:ok, nil} -> - socket - |> put_flash(:error, gettext("Group not found.")) - |> redirect(to: ~p"/groups") + socket = + socket + |> put_flash(:error, gettext("Group not found.")) + |> redirect(to: ~p"/groups") + + {:redirect, socket} {:ok, group} -> - socket - |> assign(:group, group) - |> assign(:page_title, gettext("Edit Group")) - |> assign(:return_to, "show") + socket = + socket + |> assign(:group, group) + |> assign(:page_title, gettext("Edit Group")) + |> assign(:return_to, "show") + + {:ok, socket} {:error, _error} -> - socket - |> put_flash(:error, gettext("Failed to load group.")) - |> redirect(to: ~p"/groups") + socket = + socket + |> put_flash(:error, gettext("Failed to load group.")) + |> redirect(to: ~p"/groups") + + {:redirect, socket} end end @@ -174,7 +191,7 @@ defmodule MvWeb.GroupLive.Form do defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) defp assign_form(%{assigns: assigns} = socket) do - group = assigns.group + group = Map.get(assigns, :group) actor = assigns.current_user form = diff --git a/lib/mv_web/live/group_live/index.ex b/lib/mv_web/live/group_live/index.ex index 80431e2..0122733 100644 --- a/lib/mv_web/live/group_live/index.ex +++ b/lib/mv_web/live/group_live/index.ex @@ -22,8 +22,8 @@ defmodule MvWeb.GroupLive.Index do def mount(_params, _session, socket) do actor = current_actor(socket) - # Check if user can read groups - if can?(actor, :read, Mv.Membership.Group) do + # Check if user can access the groups page (page permission check) + if can_access_page?(actor, "/groups") do groups = load_groups(actor) {:ok, diff --git a/test/mv_web/live/group_live/form_test.exs b/test/mv_web/live/group_live/form_test.exs index fd525e0..7da8da4 100644 --- a/test/mv_web/live/group_live/form_test.exs +++ b/test/mv_web/live/group_live/form_test.exs @@ -19,7 +19,7 @@ defmodule MvWeb.GroupLive.FormTest do test "form renders with empty fields", %{conn: conn} do {:ok, view, html} = live(conn, "/groups/new") - assert html =~ gettext("Create Group") || html =~ "create" + assert html =~ gettext("Create Group") or html =~ "create" or html =~ "Gruppe erstellen" assert has_element?(view, "form") end @@ -32,7 +32,7 @@ defmodule MvWeb.GroupLive.FormTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() # Should redirect to groups list or show page @@ -47,7 +47,7 @@ defmodule MvWeb.GroupLive.FormTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() assert_redirect(view, "/groups") @@ -62,10 +62,11 @@ defmodule MvWeb.GroupLive.FormTest do html = view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() - assert html =~ gettext("required") || html =~ "name" || html =~ "error" + assert html =~ gettext("required") or html =~ "name" or html =~ "error" or + html =~ "erforderlich" end test "shows error when name exceeds 100 characters", %{conn: conn} do @@ -76,10 +77,10 @@ defmodule MvWeb.GroupLive.FormTest do html = view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() - assert html =~ "100" || html =~ "length" || html =~ "error" + assert html =~ "100" or html =~ "length" or html =~ "error" or html =~ "Länge" end test "shows error when description exceeds 500 characters", %{conn: conn} do @@ -94,10 +95,10 @@ defmodule MvWeb.GroupLive.FormTest do html = view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() - assert html =~ "500" || html =~ "length" || html =~ "error" + assert html =~ "500" or html =~ "length" or html =~ "error" or html =~ "Länge" end test "shows error when name already exists (case-insensitive)", %{conn: conn} do @@ -111,7 +112,7 @@ defmodule MvWeb.GroupLive.FormTest do html = view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() assert html =~ "already" || html =~ "taken" || html =~ "exists" || html =~ "error" @@ -126,10 +127,10 @@ defmodule MvWeb.GroupLive.FormTest do html = view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() - assert html =~ "error" || html =~ "invalid" + assert html =~ "error" or html =~ "invalid" or html =~ "Fehler" or html =~ "ungültig" end end @@ -156,7 +157,7 @@ defmodule MvWeb.GroupLive.FormTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() # Verify slug didn't change by checking redirect URL or reloading @@ -173,7 +174,7 @@ defmodule MvWeb.GroupLive.FormTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() assert_redirect(view, "/groups/#{group.slug}") @@ -191,10 +192,11 @@ defmodule MvWeb.GroupLive.FormTest do html = view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() - assert html =~ "already" || html =~ "taken" || html =~ "exists" || html =~ "error" + assert html =~ "already" or html =~ "taken" or html =~ "exists" or html =~ "error" or + html =~ "bereits" or html =~ "vergeben" end test "slug is not displayed in form (immutable)", %{conn: conn} do @@ -203,7 +205,7 @@ defmodule MvWeb.GroupLive.FormTest do {:ok, _view, html} = live(conn, "/groups/#{group.slug}/edit") # Slug should not be in form (it's immutable) - refute html =~ ~r/slug.*input/i || html =~ ~r/input.*slug/i + refute html =~ ~r/slug.*input/i or html =~ ~r/input.*slug/i end end @@ -216,7 +218,7 @@ defmodule MvWeb.GroupLive.FormTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() # Name should be trimmed @@ -231,7 +233,7 @@ defmodule MvWeb.GroupLive.FormTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() assert_redirect(view, "/groups") @@ -261,8 +263,8 @@ defmodule MvWeb.GroupLive.FormTest do test "unauthenticated users are redirected to login", %{conn: conn} do result = live(conn, "/groups/new") - assert match?({:error, {:redirect, %{to: "/auth/sign_in"}}}, result) || - match?({:error, {:live_redirect, %{to: "/auth/sign_in"}}}, result) + assert match?({:error, {:redirect, %{to: "/sign-in"}}}, result) || + match?({:error, {:live_redirect, %{to: "/sign-in"}}}, result) end test "user cannot edit group with non-existent slug", %{conn: conn} do diff --git a/test/mv_web/live/group_live/index_test.exs b/test/mv_web/live/group_live/index_test.exs index 7674d79..7dabcab 100644 --- a/test/mv_web/live/group_live/index_test.exs +++ b/test/mv_web/live/group_live/index_test.exs @@ -41,20 +41,22 @@ defmodule MvWeb.GroupLive.IndexTest do assert html =~ "Test Group" assert html =~ "Test description" # Member count should be displayed (0 for empty group) - assert html =~ "0" || html =~ gettext("Members") + assert html =~ "0" or html =~ gettext("Members") or html =~ "Mitglieder" 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" + assert html =~ gettext("Create Group") or html =~ "create" or html =~ "new" or + html =~ "Gruppe erstellen" 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" + assert html =~ gettext("No groups") or html =~ "0" or html =~ "empty" or + html =~ "Keine Gruppen" end end @@ -74,7 +76,7 @@ defmodule MvWeb.GroupLive.IndexTest do {:ok, _view, html} = live(conn, "/groups") - assert html =~ long_description || html =~ String.slice(long_description, 0, 100) + assert html =~ long_description or html =~ String.slice(long_description, 0, 100) end end @@ -92,8 +94,8 @@ defmodule MvWeb.GroupLive.IndexTest do 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) + assert match?({:error, {:redirect, %{to: "/sign-in"}}}, result) || + match?({:error, {:live_redirect, %{to: "/sign-in"}}}, result) end @tag role: :member @@ -108,7 +110,7 @@ defmodule MvWeb.GroupLive.IndexTest do assert html =~ gettext("Groups") # Should NOT see create button - refute html =~ gettext("Create Group") || html =~ "create" + refute html =~ gettext("Create Group") or html =~ "create" end end @@ -143,7 +145,7 @@ defmodule MvWeb.GroupLive.IndexTest do {:ok, _view, html} = live(conn, "/groups") # Member count should be displayed (should be 2) - assert html =~ "2" || html =~ gettext("Members") + assert html =~ "2" or html =~ gettext("Members") or html =~ "Mitglieder" end end end diff --git a/test/mv_web/live/group_live/integration_test.exs b/test/mv_web/live/group_live/integration_test.exs index 4d58be1..a98de85 100644 --- a/test/mv_web/live/group_live/integration_test.exs +++ b/test/mv_web/live/group_live/integration_test.exs @@ -31,7 +31,7 @@ defmodule MvWeb.GroupLive.IntegrationTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() # Get the created group by name using current user (tests authorization) @@ -54,7 +54,7 @@ defmodule MvWeb.GroupLive.IntegrationTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() # View again via slug (should still work with original slug) @@ -63,7 +63,7 @@ defmodule MvWeb.GroupLive.IntegrationTest do assert html =~ "Updated Workflow Test Group" assert html =~ "Updated description" # Slug should remain unchanged - assert html =~ original_slug || html =~ "workflow-test-group" + assert html =~ original_slug or html =~ "workflow-test-group" end test "create group → add members → view (member count updated)", %{ @@ -78,7 +78,7 @@ defmodule MvWeb.GroupLive.IntegrationTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() # Get the created group using current user (tests authorization) @@ -102,9 +102,9 @@ defmodule MvWeb.GroupLive.IntegrationTest do {:ok, _view, html} = live(conn, "/groups/#{group.slug}") # Member count should be 2 - assert html =~ "2" || html =~ gettext("Members") - assert html =~ member1.first_name || html =~ member1.last_name - assert html =~ member2.first_name || html =~ member2.last_name + 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)", %{ @@ -119,7 +119,7 @@ defmodule MvWeb.GroupLive.IntegrationTest do } view - |> form("form", group: form_data) + |> form("#group-form", group: form_data) |> render_submit() # Get the created group using current user (tests authorization) diff --git a/test/mv_web/live/group_live/show_test.exs b/test/mv_web/live/group_live/show_test.exs index 036e249..af298fd 100644 --- a/test/mv_web/live/group_live/show_test.exs +++ b/test/mv_web/live/group_live/show_test.exs @@ -49,7 +49,7 @@ defmodule MvWeb.GroupLive.ShowTest do {:ok, _view, html} = live(conn, "/groups/#{group.slug}") # Member count should be displayed (might be 0 or more) - assert html =~ "0" || html =~ gettext("Members") || html =~ "member" + assert html =~ "0" or html =~ gettext("Members") or html =~ "member" or html =~ "Mitglied" end test "displays list of members in group", %{conn: conn} do @@ -69,8 +69,8 @@ defmodule MvWeb.GroupLive.ShowTest do {:ok, _view, html} = live(conn, "/groups/#{group.slug}") - assert html =~ "Alice" || html =~ "Smith" - assert html =~ "Bob" || html =~ "Jones" + assert html =~ "Alice" or html =~ "Smith" + assert html =~ "Bob" or html =~ "Jones" end test "displays edit button for admin users", %{conn: conn} do @@ -78,7 +78,7 @@ defmodule MvWeb.GroupLive.ShowTest do {:ok, _view, html} = live(conn, "/groups/#{group.slug}") - assert html =~ gettext("Edit") || html =~ "edit" + assert html =~ gettext("Edit") or html =~ "edit" or html =~ "Bearbeiten" end test "displays delete button for admin users", %{conn: conn} do @@ -86,7 +86,7 @@ defmodule MvWeb.GroupLive.ShowTest do {:ok, _view, html} = live(conn, "/groups/#{group.slug}") - assert html =~ gettext("Delete") || html =~ "delete" + assert html =~ gettext("Delete") or html =~ "delete" or html =~ "Löschen" end end @@ -98,7 +98,7 @@ defmodule MvWeb.GroupLive.ShowTest do assert html =~ "Board Members" # Verify slug is in URL - assert html =~ group.slug || html =~ "board-members" + assert html =~ group.slug or html =~ "board-members" end test "group is found by slug via unique_slug identity", %{conn: conn} do @@ -147,7 +147,8 @@ defmodule MvWeb.GroupLive.ShowTest do {:ok, _view, html} = live(conn, "/groups/#{group.slug}") - assert html =~ "0" || html =~ gettext("No members") || html =~ "empty" + assert html =~ "0" or html =~ gettext("No members") or html =~ "empty" or + html =~ "Keine Mitglieder" end test "handles group without description correctly", %{conn: conn} do @@ -165,7 +166,7 @@ defmodule MvWeb.GroupLive.ShowTest do {:ok, _view, html} = live(conn, "/groups/#{group.slug}") - assert html =~ "Test-Group-Name" || html =~ group.name + assert html =~ "Test-Group-Name" or html =~ group.name end end @@ -180,7 +181,7 @@ defmodule MvWeb.GroupLive.ShowTest do assert html =~ group.name # Should NOT see edit/delete buttons - refute html =~ gettext("Edit") || html =~ gettext("Delete") + refute html =~ gettext("Edit") or html =~ gettext("Delete") end @tag role: :unauthenticated @@ -189,8 +190,8 @@ defmodule MvWeb.GroupLive.ShowTest do result = live(conn, "/groups/#{group.slug}") - assert match?({:error, {:redirect, %{to: "/auth/sign_in"}}}, result) || - match?({:error, {:live_redirect, %{to: "/auth/sign_in"}}}, result) + assert match?({:error, {:redirect, %{to: "/sign-in"}}}, result) || + match?({:error, {:live_redirect, %{to: "/sign-in"}}}, result) end test "slug injection attempts are prevented", %{conn: conn} do @@ -238,7 +239,7 @@ defmodule MvWeb.GroupLive.ShowTest do # All members should be displayed Enum.each(members, fn member -> - assert html =~ member.first_name || html =~ member.last_name + assert html =~ member.first_name or html =~ member.last_name end) end @@ -260,7 +261,9 @@ defmodule MvWeb.GroupLive.ShowTest do assert {:error, {:live_redirect, %{to: to}}} = view - |> element("a[aria-label*='Back'], button[aria-label*='Back']") + |> element( + "a[aria-label*='Back'], button[aria-label*='Back'], a[aria-label*='groups list'], button[aria-label*='groups list']" + ) |> render_click() assert to == "/groups" @@ -271,9 +274,11 @@ defmodule MvWeb.GroupLive.ShowTest do {:ok, view, _html} = live(conn, "/groups/#{group.slug}") + # Button with navigate is rendered as tag via <.link> + # Use element with text content to find the link assert {:error, {:live_redirect, %{to: to}}} = view - |> element("a[href*='edit'], button[href*='edit']") + |> element("a", gettext("Edit")) |> render_click() assert to == "/groups/#{group.slug}/edit" diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 290b3ac..7dd118b 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -170,7 +170,8 @@ defmodule MvWeb.ConnCase do :member -> # Create member user for role-based testing - member_user = Mv.Fixtures.user_with_role_fixture("member") + # "member" role uses "own_data" permission set (Mitglied role) + member_user = Mv.Fixtures.user_with_role_fixture("own_data") authenticated_conn = conn_with_password_user(conn, member_user) {authenticated_conn, member_user}