2021-07-17 08:50:36 +12:00
|
|
|
defmodule AshPhoenix.AutoFormTest do
|
|
|
|
use ExUnit.Case
|
|
|
|
|
|
|
|
alias AshPhoenix.Form.Auto
|
2024-03-28 16:44:54 +13:00
|
|
|
alias AshPhoenix.Test.{Domain, Post}
|
2023-08-13 14:54:35 +12:00
|
|
|
import AshPhoenix.Form, only: [update_opts: 2]
|
2021-07-17 08:50:36 +12:00
|
|
|
|
2024-01-22 06:59:55 +13:00
|
|
|
defp form_for(a, _b), do: Phoenix.HTML.FormData.to_form(a, [])
|
|
|
|
|
2021-07-17 08:50:36 +12:00
|
|
|
test "it works for simple relationships" do
|
|
|
|
forms =
|
|
|
|
Post
|
|
|
|
|> auto_forms(:create)
|
|
|
|
|> Keyword.get(:forms)
|
|
|
|
|
2023-08-13 14:54:35 +12:00
|
|
|
assert update_opts(forms[:comments], %{})[:update_action] == :update
|
|
|
|
assert update_opts(forms[:comments], %{})[:create_action] == :create
|
|
|
|
assert update_opts(forms[:linked_posts], %{})[:update_action] == :update
|
|
|
|
assert update_opts(forms[:linked_posts], %{})[:create_action] == :create
|
2021-07-17 08:50:36 +12:00
|
|
|
end
|
|
|
|
|
2021-07-17 12:40:49 +12:00
|
|
|
test "it works for simple relationships when toggled" do
|
|
|
|
forms =
|
|
|
|
Post
|
|
|
|
|> AshPhoenix.Form.for_create(:create, forms: [auto?: true])
|
|
|
|
|> Map.get(:form_keys)
|
|
|
|
|
2023-08-13 14:54:35 +12:00
|
|
|
assert update_opts(forms[:comments], %{})[:update_action] == :update
|
|
|
|
assert update_opts(forms[:comments], %{})[:create_action] == :create
|
|
|
|
assert update_opts(forms[:linked_posts], %{})[:update_action] == :update
|
|
|
|
assert update_opts(forms[:linked_posts], %{})[:create_action] == :create
|
2021-07-17 12:40:49 +12:00
|
|
|
end
|
|
|
|
|
2022-08-23 06:31:28 +12:00
|
|
|
test "when using a non-map value it operates on maps, then transforms the params accordingly" do
|
|
|
|
form =
|
|
|
|
Post
|
2022-08-24 14:44:57 +12:00
|
|
|
|> AshPhoenix.Form.for_create(:create_with_non_map_relationship_args,
|
2023-03-21 03:20:06 +13:00
|
|
|
forms: [
|
|
|
|
auto?: [include_non_map_types?: true]
|
|
|
|
]
|
2022-08-24 14:44:57 +12:00
|
|
|
)
|
2022-08-23 06:31:28 +12:00
|
|
|
|
|
|
|
assert is_function(form.form_keys[:comment_ids][:transform_params])
|
|
|
|
|
|
|
|
validated =
|
|
|
|
form
|
|
|
|
|> AshPhoenix.Form.validate(%{"comment_ids" => %{"0" => %{"id" => 1}}})
|
|
|
|
|
2022-11-03 16:37:41 +13:00
|
|
|
assert validated.form_keys[:comment_ids][:transform_params].(
|
|
|
|
Enum.at(validated.forms[:comment_ids], 0),
|
|
|
|
%{"id" => 1},
|
|
|
|
:nested
|
|
|
|
) == 1
|
|
|
|
|
2022-08-23 06:31:28 +12:00
|
|
|
assert validated.source.arguments[:comment_ids] == [1]
|
|
|
|
end
|
|
|
|
|
2023-08-13 16:29:37 +12:00
|
|
|
describe "single unions" do
|
|
|
|
test "a form can be added for a union" do
|
2023-08-14 00:46:42 +12:00
|
|
|
Post
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
2024-03-28 16:44:54 +13:00
|
|
|
domain: Domain,
|
2023-08-14 00:46:42 +12:00
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:union, params: %{"type" => "foo"})
|
|
|
|
|> form_for("action")
|
2023-08-13 16:29:37 +12:00
|
|
|
end
|
|
|
|
|
|
|
|
test "a form can be removed from a union" do
|
|
|
|
form =
|
|
|
|
Post
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
2024-03-28 16:44:54 +13:00
|
|
|
domain: Domain,
|
2023-08-13 16:29:37 +12:00
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:union, params: %{"type" => "foo"})
|
|
|
|
|> form_for("action")
|
|
|
|
|
|
|
|
AshPhoenix.Form.remove_form(form, [:union])
|
|
|
|
end
|
|
|
|
|
|
|
|
test "a form can be added for a non-embedded type" do
|
|
|
|
Post
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
2024-03-28 16:44:54 +13:00
|
|
|
domain: Domain,
|
2023-08-13 16:29:37 +12:00
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
],
|
|
|
|
params: %{
|
|
|
|
"text" => "foobar"
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:union, params: %{"_union_type" => "bar", "value" => 10})
|
|
|
|
|> AshPhoenix.Form.submit!()
|
|
|
|
end
|
2024-06-04 15:23:44 +12:00
|
|
|
|
2024-06-05 04:23:43 +12:00
|
|
|
test "deeply nested unions" do
|
2024-06-04 15:23:44 +12:00
|
|
|
AshPhoenix.Test.DeepNestedUnionResource
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
|
|
|
domain: Domain,
|
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:items,
|
|
|
|
params: %{"subject" => %{"_union_type" => "predefined"}}
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.submit!(
|
|
|
|
params: %{
|
|
|
|
"items" => %{
|
|
|
|
"0" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,subject",
|
|
|
|
"subject" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
|
|
|
"_union_type" => "predefined",
|
2024-06-05 04:23:43 +12:00
|
|
|
"value" => "update"
|
2024-06-04 15:23:44 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
2024-06-05 04:23:43 +12:00
|
|
|
|> then(fn result ->
|
|
|
|
assert %Ash.Union{value: :update, type: :predefined} === Enum.at(result.items, 0).subject
|
|
|
|
end)
|
|
|
|
|
|
|
|
AshPhoenix.Test.DeepNestedUnionResource
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
|
|
|
domain: Domain,
|
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:items,
|
|
|
|
params: %{"subject" => %{"_union_type" => "predefined"}}
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.submit!(
|
|
|
|
params: %{
|
|
|
|
"items" => %{
|
|
|
|
"0" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,subject",
|
|
|
|
"subject" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
|
|
|
"_union_type" => "predefined",
|
|
|
|
"value" => "this_is_completely_unique"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|> then(fn result ->
|
|
|
|
assert :it_should_be_error === Enum.at(result.items, 0).subject
|
|
|
|
end)
|
|
|
|
|
|
|
|
AshPhoenix.Test.DeepNestedUnionResource
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
|
|
|
domain: Domain,
|
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:items,
|
|
|
|
params: %{"subject" => %{"_union_type" => "predefined"}}
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.submit!(
|
|
|
|
params: %{
|
|
|
|
"items" => %{
|
|
|
|
"0" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,subject",
|
|
|
|
"subject" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
|
|
|
"_union_type" => "custom",
|
|
|
|
"value" => "update"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|> then(fn result ->
|
|
|
|
assert %Ash.Union{value: "update", type: "custom"} === Enum.at(result.items, 0).subject
|
|
|
|
end)
|
|
|
|
|
|
|
|
AshPhoenix.Test.DeepNestedUnionResource
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
|
|
|
domain: Domain,
|
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:items,
|
|
|
|
params: %{"subject" => %{"_union_type" => "predefined"}}
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.submit!(
|
|
|
|
params: %{
|
|
|
|
"items" => %{
|
|
|
|
"0" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,subject",
|
|
|
|
"subject" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
|
|
|
"value" => "update"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|> then(fn result ->
|
|
|
|
assert %Ash.Union{value: :update, type: :predefined} === Enum.at(result.items, 0).subject
|
|
|
|
end)
|
|
|
|
|
|
|
|
AshPhoenix.Test.DeepNestedUnionResource
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
|
|
|
domain: Domain,
|
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:items,
|
|
|
|
params: %{"subject" => %{"_union_type" => "predefined"}}
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.submit!(
|
|
|
|
params: %{
|
|
|
|
"items" => %{
|
|
|
|
"0" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,subject",
|
|
|
|
"subject" => %{
|
|
|
|
"_form_type" => "create",
|
|
|
|
"_persistent_id" => "0",
|
|
|
|
"_touched" => "_form_type,_persistent_id,_touched,_union_type,value",
|
|
|
|
"value" => "this_is_another_custom_one"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|> then(fn result ->
|
|
|
|
assert %Ash.Union{value: "this_is_another_custom_one", type: "custom"} ===
|
|
|
|
Enum.at(result.items, 0).subject
|
|
|
|
end)
|
2024-06-04 15:23:44 +12:00
|
|
|
end
|
2023-08-13 16:29:37 +12:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "list unions" do
|
|
|
|
test "a form can be added for a union" do
|
|
|
|
Post
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
2024-03-28 16:44:54 +13:00
|
|
|
domain: Domain,
|
2023-08-13 16:29:37 +12:00
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:union_array, params: %{"type" => "foo"})
|
|
|
|
|> form_for("action")
|
|
|
|
end
|
|
|
|
|
|
|
|
test "a form can be removed from a union" do
|
|
|
|
form =
|
2023-08-14 00:46:42 +12:00
|
|
|
Post
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
2024-03-28 16:44:54 +13:00
|
|
|
domain: Domain,
|
2023-08-14 00:46:42 +12:00
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:union_array, params: %{"type" => "foo"})
|
|
|
|
|> form_for("action")
|
2023-08-13 16:29:37 +12:00
|
|
|
|
|
|
|
AshPhoenix.Form.remove_form(form, [:union_array, 0])
|
|
|
|
end
|
|
|
|
|
2023-08-14 00:46:42 +12:00
|
|
|
test "validating a form with valid values works" do
|
|
|
|
form =
|
|
|
|
Post
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
2024-03-28 16:44:54 +13:00
|
|
|
domain: Domain,
|
2023-08-14 00:46:42 +12:00
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:union_array, params: %{"type" => "foo"})
|
|
|
|
|> form_for("action")
|
|
|
|
|
|
|
|
assert %{union_array: [%Ash.Union{value: %{value: "abc"}}]} =
|
|
|
|
form
|
|
|
|
|> AshPhoenix.Form.validate(%{
|
|
|
|
"text" => "text",
|
|
|
|
"union_array" => %{
|
|
|
|
"0" => %{
|
|
|
|
"type" => "foo",
|
|
|
|
"value" => "abc"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|> AshPhoenix.Form.submit!()
|
|
|
|
end
|
|
|
|
|
|
|
|
test "validating a form with an invalid value works" do
|
|
|
|
form =
|
|
|
|
Post
|
|
|
|
|> AshPhoenix.Form.for_create(:create,
|
2024-03-28 16:44:54 +13:00
|
|
|
domain: Domain,
|
2023-08-14 00:46:42 +12:00
|
|
|
forms: [
|
|
|
|
auto?: true
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|> AshPhoenix.Form.add_form(:union_array, params: %{"type" => "foo"})
|
|
|
|
|> form_for("action")
|
|
|
|
|
|
|
|
assert_raise Ash.Error.Invalid, ~r/must match the pattern/, fn ->
|
|
|
|
form
|
|
|
|
|> AshPhoenix.Form.validate(%{
|
|
|
|
"text" => "text",
|
|
|
|
"union_array" => %{
|
|
|
|
"0" => %{
|
|
|
|
"type" => "foo",
|
|
|
|
"value" => "def"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|> AshPhoenix.Form.submit!()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2023-08-13 16:29:37 +12:00
|
|
|
|
2021-07-17 08:50:36 +12:00
|
|
|
defp auto_forms(resource, action) do
|
|
|
|
[forms: Auto.auto(resource, action)]
|
|
|
|
end
|
|
|
|
end
|