defmodule MvWeb.CustomFieldLive.DeletionTest do @moduledoc """ Tests for CustomFieldLive.IndexComponent deletion modal and slug confirmation. Tests the custom field management component embedded in the settings page. Tests cover: - Opening deletion confirmation modal - Displaying correct member count - Slug confirmation input - Successful deletion with correct slug - Failed deletion with incorrect slug - Canceling deletion - Button states (enabled/disabled based on slug match) """ use MvWeb.ConnCase, async: true import Phoenix.LiveViewTest alias Mv.Membership.{CustomField, CustomFieldValue, Member} setup do # Create admin user for testing {:ok, user} = Mv.Accounts.User |> Ash.Changeset.for_create(:register_with_password, %{ email: "admin#{System.unique_integer([:positive])}@mv.local", password: "testpassword123" }) |> Ash.create() conn = log_in_user(build_conn(), user) %{conn: conn, user: user} end describe "delete button and modal" do test "opens modal with correct member count when delete is clicked", %{conn: conn} do {:ok, member} = create_member() {:ok, custom_field} = create_custom_field("test_field", :string) # Create custom field value create_custom_field_value(member, custom_field, "test") {:ok, view, _html} = live(conn, ~p"/settings") # Click delete button - find the delete link within the component view |> element("#custom-fields-component a", "Delete") |> render_click() # Modal should be visible assert has_element?(view, "#delete-custom-field-modal") # Should show correct member count (1 member) assert render(view) =~ "1 member has a value assigned for this custom field" # Should show the slug assert render(view) =~ custom_field.slug end test "shows correct plural form for multiple members", %{conn: conn} do {:ok, member1} = create_member() {:ok, member2} = create_member() {:ok, custom_field} = create_custom_field("test_field", :string) # Create values for both members create_custom_field_value(member1, custom_field, "test1") create_custom_field_value(member2, custom_field, "test2") {:ok, view, _html} = live(conn, ~p"/settings") view |> element("#custom-fields-component a", "Delete") |> render_click() # Should show plural form assert render(view) =~ "2 members have values assigned for this custom field" end test "shows 0 members for custom field without values", %{conn: conn} do {:ok, _custom_field} = create_custom_field("test_field", :string) {:ok, view, _html} = live(conn, ~p"/settings") view |> element("#custom-fields-component a", "Delete") |> render_click() # Should show 0 members assert render(view) =~ "0 members have values assigned for this custom field" end end describe "slug confirmation input" do test "updates confirmation state when typing", %{conn: conn} do {:ok, custom_field} = create_custom_field("test_field", :string) {:ok, view, _html} = live(conn, ~p"/settings") view |> element("#custom-fields-component a", "Delete") |> render_click() # Type in slug input - use element to find the form with phx-target view |> element("#delete-custom-field-modal form") |> render_change(%{"slug" => custom_field.slug}) # Confirm button should be enabled now (no disabled attribute) html = render(view) refute html =~ ~r/disabled(?:=""|(?!\w))/ end test "delete button is disabled when slug doesn't match", %{conn: conn} do {:ok, _custom_field} = create_custom_field("test_field", :string) {:ok, view, _html} = live(conn, ~p"/settings") view |> element("#custom-fields-component a", "Delete") |> render_click() # Type wrong slug - use element to find the form with phx-target view |> element("#delete-custom-field-modal form") |> render_change(%{"slug" => "wrong-slug"}) # Button should be disabled html = render(view) assert html =~ ~r/disabled(?:=""|(?!\w))/ end end describe "confirm deletion" do test "successfully deletes custom field with correct slug", %{conn: conn} do {:ok, member} = create_member() {:ok, custom_field} = create_custom_field("test_field", :string) {:ok, custom_field_value} = create_custom_field_value(member, custom_field, "test") {:ok, view, _html} = live(conn, ~p"/settings") # Open modal view |> element("#custom-fields-component a", "Delete") |> render_click() # Enter correct slug - use element to find the form with phx-target view |> element("#delete-custom-field-modal form") |> render_change(%{"slug" => custom_field.slug}) # Click confirm view |> element("#delete-custom-field-modal button", "Delete Custom Field and All Values") |> render_click() # Should show success message assert render(view) =~ "Custom field deleted successfully" # Custom field should be gone from database assert {:error, _} = Ash.get(CustomField, custom_field.id) # Custom field value should also be gone (CASCADE) assert {:error, _} = Ash.get(CustomFieldValue, custom_field_value.id) # Member should still exist assert {:ok, _} = Ash.get(Member, member.id) end test "button remains disabled and custom field not deleted when slug doesn't match", %{ conn: conn } do {:ok, custom_field} = create_custom_field("test_field", :string) {:ok, view, _html} = live(conn, ~p"/settings") view |> element("#custom-fields-component a", "Delete") |> render_click() # Enter wrong slug - use element to find the form with phx-target view |> element("#delete-custom-field-modal form") |> render_change(%{"slug" => "wrong-slug"}) # Button should be disabled and we cannot click it # The test verifies that the button is properly disabled in the UI html = render(view) assert html =~ ~r/disabled(?:=""|(?!\w))/ # Custom field should still exist since deletion couldn't proceed assert {:ok, _} = Ash.get(CustomField, custom_field.id) end end describe "cancel deletion" do test "closes modal without deleting", %{conn: conn} do {:ok, custom_field} = create_custom_field("test_field", :string) {:ok, view, _html} = live(conn, ~p"/settings") view |> element("#custom-fields-component a", "Delete") |> render_click() # Modal should be visible assert has_element?(view, "#delete-custom-field-modal") # Click cancel view |> element("#delete-custom-field-modal button", "Cancel") |> render_click() # Modal should be gone refute has_element?(view, "#delete-custom-field-modal") # Custom field should still exist assert {:ok, _} = Ash.get(CustomField, custom_field.id) end end # Helper functions defp create_member do Member |> Ash.Changeset.for_create(:create_member, %{ first_name: "Test", last_name: "User#{System.unique_integer([:positive])}", email: "test#{System.unique_integer([:positive])}@example.com" }) |> Ash.create() end defp create_custom_field(name, value_type) do CustomField |> Ash.Changeset.for_create(:create, %{ name: "#{name}_#{System.unique_integer([:positive])}", value_type: value_type }) |> Ash.create() end defp create_custom_field_value(member, custom_field, value) do CustomFieldValue |> Ash.Changeset.for_create(:create, %{ member_id: member.id, custom_field_id: custom_field.id, value: %{"_union_type" => "string", "_union_value" => value} }) |> Ash.create() end defp log_in_user(conn, user) do conn |> Phoenix.ConnTest.init_test_session(%{}) |> AshAuthentication.Plug.Helpers.store_in_session(user) end end