diff --git a/lib/macros/guarded_struct.ex b/lib/macros/guarded_struct.ex index cf7b309..17d7e88 100644 --- a/lib/macros/guarded_struct.ex +++ b/lib/macros/guarded_struct.ex @@ -1885,6 +1885,25 @@ defmodule GuardedStruct do |> Tuple.insert_at(4, new_derives) end + def replace_condition_fields_derives({:error, _, data} = error, _) when data == :halt, do: error + + def replace_condition_fields_derives({:error, error, data}, derives) + when data == %{} or derives == [], + do: {:error, error} + + def replace_condition_fields_derives({:error, error, data}, derives) do + derive_inputs = Enum.filter(derives, &(&1.field in Enum.uniq(Map.keys(data)))) + + derives_error = + Derive.derive({:ok, data, derive_inputs}) + |> case do + {:ok, _} -> [] + {:error, error} -> error + end + + {:error, derives_error ++ error} + end + def replace_condition_fields_derives(error, _derives), do: error @spec exceptions_handler({:ok, any()} | {:error, any()}, module(), boolean()) :: @@ -2580,8 +2599,7 @@ defmodule GuardedStruct do {:ok, _, _, false} -> errors = cond_errors_converter(conds) - - {:error, validated_errors ++ sub_builders_errors ++ errors} + {:error, validated_errors ++ sub_builders_errors ++ errors, main_error_or_data} {:error, _, _, false} -> errors = cond_errors_converter(conds) diff --git a/test/guarded_struct_test/conditional_field_test.exs b/test/guarded_struct_test/conditional_field_test.exs index 01f97f0..19f2b9f 100644 --- a/test/guarded_struct_test/conditional_field_test.exs +++ b/test/guarded_struct_test/conditional_field_test.exs @@ -17,7 +17,7 @@ defmodule MishkaDeveloperToolsTest.GuardedStruct.ConditionalFieldTest do alias ConditionalFieldValidatorTestValidators, as: VAL guardedstruct do - field(:nickname, String.t()) + field(:nickname, String.t(), derive: "validate(string, not_empty)") # For domain sub_field(:identity, struct()) do @@ -2331,4 +2331,109 @@ defmodule MishkaDeveloperToolsTest.GuardedStruct.ConditionalFieldTest do activity3: %{action: "admin:edit", type: "normal"} }) end + + test "mix 2 conditional/normal errors per-rows" do + {:error, + [ + %{ + message: + "Invalid NotEmpty format in the nickname field, you must pass data which is string, list or map.", + field: :nickname, + action: :not_empty + }, + %{ + message: "The nickname field must be string", + field: :nickname, + action: :string + }, + %{ + field: :location, + errors: [ + %{ + message: "It is not map", + field: :location, + action: :validator, + __hint__: "location1" + }, + %{ + message: + "Invalid geo url format in the location field, you should send latitude and longitude", + field: :location, + action: :location, + __hint__: "location2" + } + ], + action: :conditionals + } + ]} = + assert __MODULE__.ConditionalProfileFieldStructs.builder(%{ + nickname: :mishka, + list_sub_field_on_header: "Mishka", + location: "bad_location" + }) + + {:error, + [ + %{ + message: + "Invalid NotEmpty format in the nickname field, you must pass data which is string, list or map.", + field: :nickname, + action: :not_empty + }, + %{ + message: "The nickname field must be string", + field: :nickname, + action: :string + }, + %{ + field: :auth, + errors: [ + %{ + message: "It is not list", + field: :auth, + action: :validator, + __hint__: "auth1" + }, + %{ + message: "Your input must be a list of items", + field: :auth, + action: :type, + __hint__: "auth2" + }, + %{ + message: "It is not string", + field: :auth, + action: :validator, + __hint__: "auth3" + } + ], + action: :conditionals + }, + %{ + field: :location, + errors: [ + %{ + message: "It is not map", + field: :location, + action: :validator, + __hint__: "location1" + }, + %{ + message: + "Invalid geo url format in the location field, you should send latitude and longitude", + field: :location, + action: :location, + __hint__: "location2" + } + ], + action: :conditionals + } + ]} = + assert __MODULE__.ConditionalProfileFieldStructs.builder(%{ + nickname: :mishka, + list_sub_field_on_header: "Mishka", + auth: :bad_auth, + location: "bad_location" + }) + end end diff --git a/test/guarded_struct_test/validator_derive_test.exs b/test/guarded_struct_test/validator_derive_test.exs index 76c01c5..363e079 100644 --- a/test/guarded_struct_test/validator_derive_test.exs +++ b/test/guarded_struct_test/validator_derive_test.exs @@ -38,7 +38,11 @@ defmodule MishkaDeveloperToolsTest.GuardedStruct.ValidatorDeriveTest do end def main_validator(value) do - {:ok, value} + if Map.get(value, :changed) == 555_555 do + {:error, %{message: "there is an Error", field: :global, action: :main_validator}} + else + {:ok, value} + end end end @@ -431,5 +435,11 @@ defmodule MishkaDeveloperToolsTest.GuardedStruct.ValidatorDeriveTest do action: nil }} = TestAuthStruct.builder(%{changed: "https://github.com/mishka-group"}) + + {:error, + [ + %{message: "No, never", field: :changed, action: :validator}, + %{message: "there is an Error", field: :global, action: :main_validator} + ]} = assert TestAuthStruct.builder(%{changed: 555_555}) end end