test: Nested form errors for argument attribute (#119)

This commit is contained in:
Robert Graff 2023-11-28 11:32:38 -08:00 committed by GitHub
parent 6ddddf7316
commit a098a830b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 105 additions and 1 deletions

5
.gitpod.yml Normal file
View file

@ -0,0 +1,5 @@
image: elixir:latest
tasks:
- init: mix deps.get && mix compile
command: iex -S mix

View file

@ -4,7 +4,7 @@ defmodule AshPhoenix.FormTest do
import ExUnit.CaptureLog
alias AshPhoenix.Form
alias AshPhoenix.Test.{Api, Comment, OtherApi, Post, PostWithDefault}
alias AshPhoenix.Test.{Api, Author, Comment, OtherApi, Post, PostWithDefault}
alias Phoenix.HTML.FormData
describe "validate_opts" do
@ -782,6 +782,45 @@ defmodule AshPhoenix.FormTest do
assert [nested_form] = inputs_for(form, :post)
assert nested_form.errors == [{:text, {"is required", []}}]
end
test "errors with a path are propagated down to the appropirate nested form" do
author = %Author{
email: "me@example.com"
}
form =
author
|> Form.for_update(:update_with_embedded_argument, api: Api, forms: [auto?: true])
|> Form.add_form(:embedded_argument, params: %{})
|> Form.validate(%{"embedded_argument" => %{"value" => "you@example.com"}})
|> form_for("action")
[nested_form] = inputs_for(form, :embedded_argument)
# This is the top level error with a path to the nest form.
assert [
%Ash.Error.Changes.InvalidArgument{
field: :value,
message: "must match email",
value: "you@example.com",
path: [:embedded_argument],
class: :invalid
}
] = form.source.source.errors
assert form.errors == []
# This is the error on the nested form.
assert [
%Ash.Error.Changes.InvalidArgument{
field: :value,
message: "must match email",
value: "you@example.com",
path: [],
class: :invalid
}
] = nested_form.source.source.errors
assert nested_form.errors == [{:value, {"must match email", []}}]
end
end
describe "data" do

View file

@ -13,6 +13,14 @@ defmodule AshPhoenix.Test.Author do
actions do
defaults([:create, :read, :update])
update :update_with_embedded_argument do
# This an empty change, just so test how we handle errors on embedded arguments
accept []
argument :embedded_argument, AshPhoenix.Test.EmbeddedArgument, allow_nil?: false
validate { AshPhoenix.Test.ValidateEmbeddedArgument, [] }
end
end
relationships do

View file

@ -0,0 +1,8 @@
defmodule AshPhoenix.Test.EmbeddedArgument do
@moduledoc false
use Ash.Resource, data_layer: :embedded
attributes do
attribute :value, :string
end
end

View file

@ -0,0 +1,44 @@
defmodule AshPhoenix.Test.ValidateEmbeddedArgument do
@moduledoc """
This is a contrived example, but we want to validate one or more arguments' attributes
against an attribute on the parent resource and then put an error on the
changeset that will get propogated down to the nest form for the embedded argument.
"""
use Ash.Resource.Validation
# This is the name of our embedded argument
@embedded_argument :embedded_argument
# This is the name of the attribute on the embedded argument
@embedded_attribute :value
@impl true
def validate(changeset, _opts) do
case Ash.Changeset.get_argument(changeset, @embedded_argument) do
nil ->
:ok
argument ->
apply_validation(changeset, argument)
end
end
def apply_validation(changeset, argument) do
email = Ash.Changeset.get_attribute(changeset, :email)
value = Map.get(argument, @embedded_attribute)
if value == email do
:ok
else
{:error,
Ash.Error.Changes.InvalidArgument.exception(
field: @embedded_attribute,
message: "must match email",
value: value,
path: [@embedded_argument]
)
}
end
end
end