defmodule Mv.Membership.SettingTest do use Mv.DataCase, async: false alias Mv.Membership describe "Settings Resource" do setup do {:ok, settings} = Membership.get_settings() saved_visibility = settings.member_field_visibility || %{} saved_required = settings.member_field_required || %{} on_exit(fn -> {:ok, s} = Membership.get_settings() Membership.update_settings(s, %{ member_field_visibility: saved_visibility, member_field_required: saved_required }) end) :ok end test "can read settings" do # Settings should be a singleton resource assert {:ok, _settings} = Membership.get_settings() end test "settings have club_name attribute" do {:ok, settings} = Membership.get_settings() assert Map.has_key?(settings, :club_name) end test "can update club_name" do {:ok, settings} = Membership.get_settings() assert {:ok, updated_settings} = Membership.update_settings(settings, %{club_name: "New Club Name"}) assert updated_settings.club_name == "New Club Name" end test "club_name is required" do {:ok, settings} = Membership.get_settings() assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.update_settings(settings, %{club_name: nil}) assert error_message(errors, :club_name) =~ "must be present" end test "club_name cannot be empty" do {:ok, settings} = Membership.get_settings() assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.update_settings(settings, %{club_name: ""}) assert error_message(errors, :club_name) =~ "must be present" end test "can update and read member_field_required" do {:ok, settings} = Membership.get_settings() required_config = %{"first_name" => true, "last_name" => true} assert {:ok, updated} = Membership.update_settings(settings, %{member_field_required: required_config}) assert updated.member_field_required["first_name"] == true assert updated.member_field_required["last_name"] == true end test "member_field_required rejects invalid keys" do {:ok, settings} = Membership.get_settings() assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.update_settings(settings, %{ member_field_required: %{"invalid_field" => true} }) assert error_message(errors, :member_field_required) =~ "Invalid member field" end test "member_field_required rejects non-boolean values" do {:ok, settings} = Membership.get_settings() assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.update_settings(settings, %{ member_field_required: %{"first_name" => "yes"} }) assert error_message(errors, :member_field_required) =~ "must be booleans" end test "update_single_member_field updates both visibility and required" do {:ok, settings} = Membership.get_settings() assert {:ok, updated} = Membership.update_single_member_field(settings, field: "first_name", show_in_overview: true, required: true ) assert updated.member_field_visibility["first_name"] == true assert updated.member_field_required["first_name"] == true # Update same field to required: false assert {:ok, updated2} = Membership.update_single_member_field(updated, field: "first_name", show_in_overview: false, required: false ) assert updated2.member_field_visibility["first_name"] == false assert updated2.member_field_required["first_name"] == false end end # Helper function to extract error messages defp error_message(errors, field) do errors |> Enum.filter(fn err -> Map.get(err, :field) == field end) |> Enum.map(&Map.get(&1, :message, "")) |> List.first() || "" end end