defmodule MvWeb.Helpers.AshErrorHelpersTest do @moduledoc """ Tests for format_error/1, the shared Ash error formatter used by the member show LiveComponents. """ use Mv.DataCase, async: true import MvWeb.Helpers.AshErrorHelpers describe "format_error/1" do test "joins messages of an Ash.Error.Invalid with commas" do error = %Ash.Error.Invalid{ errors: [%{message: "exit_date must be after join_date"}, %{message: "another"}] } assert format_error(error) == "exit_date must be after join_date, another" end test "falls back to inspect for invalid sub-errors without a message" do error = %Ash.Error.Invalid{errors: [:boom]} assert format_error(error) == inspect(:boom) end test "returns a localized message for an Ash.Error.Forbidden" do assert format_error(%Ash.Error.Forbidden{}) =~ "allowed" end test "passes through a plain binary unchanged" do assert format_error("custom message") == "custom message" end test "returns a generic localized message for anything else" do assert format_error(:unexpected) == "An error occurred" end test "renders the genuine update_member validation error as a user-facing message" do system_actor = Mv.Helpers.SystemActor.get_system_actor() {:ok, member} = Mv.Membership.create_member( %{ first_name: "Exit", last_name: "Validation", email: "exit-validation-#{System.unique_integer([:positive])}@example.com", join_date: ~D[2024-01-01] }, actor: system_actor ) # exit_date earlier than join_date triggers the resource validation {:error, %Ash.Error.Invalid{} = error} = Mv.Membership.update_member(member, %{exit_date: ~D[2023-12-31]}, actor: system_actor) formatted = format_error(error) # The real Ash sub-error must surface its localized :message, not an inspect()'d struct. assert formatted == "cannot be before join date" refute formatted =~ "InvalidAttribute" refute formatted =~ "%{" end end end