defmodule Ash.Test.Resource.Validation.NegateTest do @moduledoc false use ExUnit.Case, async: true alias Ash.Resource.Validation.Negate alias Ash.Test.Domain, as: Domain defmodule Post do use Ash.Resource, domain: Domain actions do default_accept :* defaults [:read, :destroy, create: :*, update: :*] end attributes do uuid_primary_key :id attribute :status, :atom do public?(true) end end end defmodule CustomValidation do use Ash.Resource.Validation @impl true def validate(_, _, _), do: {:error, :some_error} @impl true def describe(_opts), do: [message: "Custom validation error message", vars: []] end defmodule CustomValidationNoDescribe do use Ash.Resource.Validation @impl true def validate(_, _, _), do: {:error, :some_error} end describe "Negate validation" do test "passes when inner validation fails" do {:ok, opts} = Negate.init(validation: Ash.Resource.Validation.Builtins.one_of(:status, [:canceled])) changeset = Post |> Ash.Changeset.for_create(:create, %{status: :valid}) assert :ok = Negate.validate(changeset, opts, %{}) end test "fails when inner validation passes" do {:ok, opts} = Negate.init(validation: Ash.Resource.Validation.Builtins.one_of(:status, [:canceled])) changeset = Post |> Ash.Changeset.for_create(:create, %{status: :canceled}) assert {:error, %Ash.Error.Changes.InvalidAttribute{}} = Negate.validate(changeset, opts, %{}) end test "support custom validations" do {:ok, opts} = Negate.init(validation: CustomValidation) changeset = Post |> Ash.Changeset.for_create(:create, %{status: :valid}) assert :ok = Negate.validate(changeset, opts, %{}) end test "returns error on init if validation do not export `describe/1`" do assert_raise ArgumentError, ~r/must implement `describe\/1`/, fn -> Negate.init(validation: CustomValidationNoDescribe) end end end end