mirror of
https://github.com/ash-project/ash_phoenix.git
synced 2024-09-19 06:42:47 +12:00
test: Nested form errors for argument attribute (#119)
This commit is contained in:
parent
6ddddf7316
commit
a098a830b1
5 changed files with 105 additions and 1 deletions
5
.gitpod.yml
Normal file
5
.gitpod.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
image: elixir:latest
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- init: mix deps.get && mix compile
|
||||||
|
command: iex -S mix
|
|
@ -4,7 +4,7 @@ defmodule AshPhoenix.FormTest do
|
||||||
import ExUnit.CaptureLog
|
import ExUnit.CaptureLog
|
||||||
|
|
||||||
alias AshPhoenix.Form
|
alias AshPhoenix.Form
|
||||||
alias AshPhoenix.Test.{Api, Comment, OtherApi, Post, PostWithDefault}
|
alias AshPhoenix.Test.{Api, Author, Comment, OtherApi, Post, PostWithDefault}
|
||||||
alias Phoenix.HTML.FormData
|
alias Phoenix.HTML.FormData
|
||||||
|
|
||||||
describe "validate_opts" do
|
describe "validate_opts" do
|
||||||
|
@ -782,6 +782,45 @@ defmodule AshPhoenix.FormTest do
|
||||||
assert [nested_form] = inputs_for(form, :post)
|
assert [nested_form] = inputs_for(form, :post)
|
||||||
assert nested_form.errors == [{:text, {"is required", []}}]
|
assert nested_form.errors == [{:text, {"is required", []}}]
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
describe "data" do
|
describe "data" do
|
||||||
|
|
|
@ -13,6 +13,14 @@ defmodule AshPhoenix.Test.Author do
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
defaults([:create, :read, :update])
|
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
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
|
|
8
test/support/resources/embedded_argument.ex
Normal file
8
test/support/resources/embedded_argument.ex
Normal 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
|
44
test/support/validations/validate_embedded_argument.ex
Normal file
44
test/support/validations/validate_embedded_argument.ex
Normal 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
|
Loading…
Reference in a new issue