Implements validation for required custom fields closes #274 #301
2 changed files with 278 additions and 192 deletions
|
|
@ -354,7 +354,15 @@ defmodule Mv.Membership.Member do
|
||||||
Enum.reduce(custom_field_values_arg, %{}, fn cfv, acc ->
|
Enum.reduce(custom_field_values_arg, %{}, fn cfv, acc ->
|
||||||
custom_field_id = Map.get(cfv, "custom_field_id")
|
custom_field_id = Map.get(cfv, "custom_field_id")
|
||||||
value_map = Map.get(cfv, "value", %{})
|
value_map = Map.get(cfv, "value", %{})
|
||||||
actual_value = Map.get(value_map, "value")
|
|
||||||
|
# Support both "value" and "_union_value" keys, without using || to preserve false values
|
||||||
|
actual_value =
|
||||||
|
cond do
|
||||||
|
Map.has_key?(value_map, "value") -> Map.get(value_map, "value")
|
||||||
|
Map.has_key?(value_map, "_union_value") -> Map.get(value_map, "_union_value")
|
||||||
|
true -> nil
|
||||||
|
end
|
||||||
|
|
||||||
Map.put(acc, custom_field_id, actual_value)
|
Map.put(acc, custom_field_id, actual_value)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,33 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Helper function to create all required custom fields with valid default values
|
||||||
|
defp all_required_custom_fields_with_defaults(%{
|
||||||
|
required_string_field: string_field,
|
||||||
|
required_integer_field: integer_field,
|
||||||
|
required_boolean_field: boolean_field,
|
||||||
|
required_date_field: date_field
|
||||||
|
}) do
|
||||||
|
[
|
||||||
|
%{
|
||||||
|
"custom_field_id" => string_field.id,
|
||||||
|
"value" => %{"_union_type" => "string", "_union_value" => "default"}
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"custom_field_id" => integer_field.id,
|
||||||
|
"value" => %{"_union_type" => "integer", "_union_value" => 0}
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"custom_field_id" => boolean_field.id,
|
||||||
|
"value" => %{"_union_type" => "boolean", "_union_value" => false}
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"custom_field_id" => date_field.id,
|
||||||
|
"value" => %{"_union_type" => "date", "_union_value" => ~D[2020-01-01]}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
describe "create_member with required custom fields" do
|
describe "create_member with required custom fields" do
|
||||||
@valid_attrs %{
|
@valid_attrs %{
|
||||||
first_name: "John",
|
first_name: "John",
|
||||||
|
|
@ -84,15 +111,20 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ field.name
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails when required string custom field has nil value", %{
|
test "fails when required string custom field has nil value",
|
||||||
required_string_field: field
|
%{
|
||||||
} do
|
required_string_field: field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
# Start with all required fields having valid values
|
||||||
"custom_field_id" => field.id,
|
custom_field_values =
|
||||||
"value" => %{"type" => "string", "value" => nil}
|
all_required_custom_fields_with_defaults(context)
|
||||||
}
|
|> Enum.map(fn cfv ->
|
||||||
]
|
if cfv["custom_field_id"] == field.id do
|
||||||
|
%{cfv | "value" => %{"_union_type" => "string", "_union_value" => nil}}
|
||||||
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
|
@ -101,15 +133,20 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ field.name
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails when required string custom field has empty string value", %{
|
test "fails when required string custom field has empty string value",
|
||||||
required_string_field: field
|
%{
|
||||||
} do
|
required_string_field: field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
# Start with all required fields having valid values
|
||||||
"custom_field_id" => field.id,
|
custom_field_values =
|
||||||
"value" => %{"type" => "string", "value" => ""}
|
all_required_custom_fields_with_defaults(context)
|
||||||
}
|
|> Enum.map(fn cfv ->
|
||||||
]
|
if cfv["custom_field_id"] == field.id do
|
||||||
|
%{cfv | "value" => %{"_union_type" => "string", "_union_value" => ""}}
|
||||||
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
|
@ -118,15 +155,20 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ field.name
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails when required string custom field has whitespace-only value", %{
|
test "fails when required string custom field has whitespace-only value",
|
||||||
required_string_field: field
|
%{
|
||||||
} do
|
required_string_field: field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
# Start with all required fields having valid values
|
||||||
"custom_field_id" => field.id,
|
custom_field_values =
|
||||||
"value" => %{"type" => "string", "value" => " "}
|
all_required_custom_fields_with_defaults(context)
|
||||||
}
|
|> Enum.map(fn cfv ->
|
||||||
]
|
if cfv["custom_field_id"] == field.id do
|
||||||
|
%{cfv | "value" => %{"_union_type" => "string", "_union_value" => " "}}
|
||||||
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
|
@ -135,30 +177,39 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ field.name
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when required string custom field has valid value", %{
|
test "succeeds when required string custom field has valid value",
|
||||||
required_string_field: field
|
%{
|
||||||
} do
|
required_string_field: field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
# Start with all required fields having valid values, then update the string field
|
||||||
"custom_field_id" => field.id,
|
custom_field_values =
|
||||||
"value" => %{"type" => "string", "value" => "test value"}
|
all_required_custom_fields_with_defaults(context)
|
||||||
}
|
|> Enum.map(fn cfv ->
|
||||||
]
|
if cfv["custom_field_id"] == field.id do
|
||||||
|
%{cfv | "value" => %{"_union_type" => "string", "_union_value" => "test value"}}
|
||||||
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
assert {:ok, _member} = Membership.create_member(attrs)
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails when required integer custom field has nil value", %{
|
test "fails when required integer custom field has nil value",
|
||||||
required_integer_field: field
|
%{
|
||||||
} do
|
required_integer_field: field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
custom_field_values =
|
||||||
"custom_field_id" => field.id,
|
all_required_custom_fields_with_defaults(context)
|
||||||
"value" => %{"type" => "integer", "value" => nil}
|
|> Enum.map(fn cfv ->
|
||||||
}
|
if cfv["custom_field_id"] == field.id do
|
||||||
]
|
%{cfv | "value" => %{"_union_type" => "integer", "_union_value" => nil}}
|
||||||
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
|
@ -167,45 +218,49 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ field.name
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when required integer custom field has zero value", %{
|
test "succeeds when required integer custom field has zero value",
|
||||||
required_integer_field: field
|
%{
|
||||||
} do
|
required_integer_field: _field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
custom_field_values = all_required_custom_fields_with_defaults(context)
|
||||||
"custom_field_id" => field.id,
|
|
||||||
"value" => %{"type" => "integer", "value" => 0}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
assert {:ok, _member} = Membership.create_member(attrs)
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when required integer custom field has positive value", %{
|
test "succeeds when required integer custom field has positive value",
|
||||||
required_integer_field: field
|
%{
|
||||||
} do
|
required_integer_field: field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
custom_field_values =
|
||||||
"custom_field_id" => field.id,
|
all_required_custom_fields_with_defaults(context)
|
||||||
"value" => %{"type" => "integer", "value" => 42}
|
|> Enum.map(fn cfv ->
|
||||||
}
|
if cfv["custom_field_id"] == field.id do
|
||||||
]
|
%{cfv | "value" => %{"_union_type" => "integer", "_union_value" => 42}}
|
||||||
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
assert {:ok, _member} = Membership.create_member(attrs)
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails when required boolean custom field has nil value", %{
|
test "fails when required boolean custom field has nil value",
|
||||||
required_boolean_field: field
|
%{
|
||||||
} do
|
required_boolean_field: field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
custom_field_values =
|
||||||
"custom_field_id" => field.id,
|
all_required_custom_fields_with_defaults(context)
|
||||||
"value" => %{"type" => "boolean", "value" => nil}
|
|> Enum.map(fn cfv ->
|
||||||
}
|
if cfv["custom_field_id"] == field.id do
|
||||||
]
|
%{cfv | "value" => %{"_union_type" => "boolean", "_union_value" => nil}}
|
||||||
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
|
@ -214,45 +269,49 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ field.name
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when required boolean custom field has false value", %{
|
test "succeeds when required boolean custom field has false value",
|
||||||
required_boolean_field: field
|
%{
|
||||||
} do
|
required_boolean_field: _field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
custom_field_values = all_required_custom_fields_with_defaults(context)
|
||||||
"custom_field_id" => field.id,
|
|
||||||
"value" => %{"type" => "boolean", "value" => false}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
assert {:ok, _member} = Membership.create_member(attrs)
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when required boolean custom field has true value", %{
|
test "succeeds when required boolean custom field has true value",
|
||||||
required_boolean_field: field
|
%{
|
||||||
} do
|
required_boolean_field: field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
custom_field_values =
|
||||||
"custom_field_id" => field.id,
|
all_required_custom_fields_with_defaults(context)
|
||||||
"value" => %{"type" => "boolean", "value" => true}
|
|> Enum.map(fn cfv ->
|
||||||
}
|
if cfv["custom_field_id"] == field.id do
|
||||||
]
|
%{cfv | "value" => %{"_union_type" => "boolean", "_union_value" => true}}
|
||||||
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
assert {:ok, _member} = Membership.create_member(attrs)
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails when required date custom field has nil value", %{
|
test "fails when required date custom field has nil value",
|
||||||
required_date_field: field
|
%{
|
||||||
} do
|
required_date_field: field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
custom_field_values =
|
||||||
"custom_field_id" => field.id,
|
all_required_custom_fields_with_defaults(context)
|
||||||
"value" => %{"type" => "date", "value" => nil}
|
|> Enum.map(fn cfv ->
|
||||||
}
|
if cfv["custom_field_id"] == field.id do
|
||||||
]
|
%{cfv | "value" => %{"_union_type" => "date", "_union_value" => nil}}
|
||||||
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
|
@ -261,57 +320,60 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ field.name
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when required date custom field has valid date value", %{
|
test "succeeds when required date custom field has valid date value",
|
||||||
required_date_field: field
|
%{
|
||||||
} do
|
required_date_field: _field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
custom_field_values = all_required_custom_fields_with_defaults(context)
|
||||||
"custom_field_id" => field.id,
|
|
||||||
"value" => %{"type" => "date", "value" => ~D[2020-01-01]}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
assert {:ok, _member} = Membership.create_member(attrs)
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when multiple required custom fields are provided", %{
|
test "succeeds when multiple required custom fields are provided",
|
||||||
required_string_field: string_field,
|
%{
|
||||||
required_integer_field: integer_field,
|
required_string_field: string_field,
|
||||||
required_boolean_field: boolean_field
|
required_integer_field: integer_field,
|
||||||
} do
|
required_boolean_field: boolean_field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
custom_field_values =
|
||||||
"custom_field_id" => string_field.id,
|
all_required_custom_fields_with_defaults(context)
|
||||||
"value" => %{"type" => "string", "value" => "test"}
|
|> Enum.map(fn cfv ->
|
||||||
},
|
cond do
|
||||||
%{
|
cfv["custom_field_id"] == string_field.id ->
|
||||||
"custom_field_id" => integer_field.id,
|
%{cfv | "value" => %{"_union_type" => "string", "_union_value" => "test"}}
|
||||||
"value" => %{"type" => "integer", "value" => 42}
|
|
||||||
},
|
cfv["custom_field_id"] == integer_field.id ->
|
||||||
%{
|
%{cfv | "value" => %{"_union_type" => "integer", "_union_value" => 42}}
|
||||||
"custom_field_id" => boolean_field.id,
|
|
||||||
"value" => %{"type" => "boolean", "value" => true}
|
cfv["custom_field_id"] == boolean_field.id ->
|
||||||
}
|
%{cfv | "value" => %{"_union_type" => "boolean", "_union_value" => true}}
|
||||||
]
|
|
||||||
|
true ->
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
assert {:ok, _member} = Membership.create_member(attrs)
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails when one of multiple required custom fields is missing", %{
|
test "fails when one of multiple required custom fields is missing",
|
||||||
required_string_field: string_field,
|
%{
|
||||||
required_integer_field: integer_field
|
required_string_field: string_field,
|
||||||
} do
|
required_integer_field: integer_field
|
||||||
custom_field_values = [
|
} = context do
|
||||||
%{
|
# Provide only string field, missing integer, boolean, and date
|
||||||
"custom_field_id" => string_field.id,
|
custom_field_values =
|
||||||
"value" => %{"type" => "string", "value" => "test"}
|
all_required_custom_fields_with_defaults(context)
|
||||||
}
|
|> Enum.filter(fn cfv ->
|
||||||
# Missing required_integer_field
|
cfv["custom_field_id"] == string_field.id
|
||||||
]
|
end)
|
||||||
|
|> Enum.map(fn cfv ->
|
||||||
|
%{cfv | "value" => %{"_union_type" => "string", "_union_value" => "test"}}
|
||||||
|
end)
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
|
@ -320,19 +382,26 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ integer_field.name
|
assert error_message(errors, :custom_field_values) =~ integer_field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when optional custom field is missing", %{optional_field: field} do
|
test "succeeds when optional custom field is missing", %{} = context do
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, [])
|
# Provide all required fields, but no optional field
|
||||||
|
custom_field_values = all_required_custom_fields_with_defaults(context)
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
assert {:ok, _member} = Membership.create_member(attrs)
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when optional custom field has nil value", %{optional_field: field} do
|
test "succeeds when optional custom field has nil value",
|
||||||
custom_field_values = [
|
%{optional_field: field} = context do
|
||||||
%{
|
# Provide all required fields plus optional field with nil
|
||||||
"custom_field_id" => field.id,
|
custom_field_values =
|
||||||
"value" => %{"type" => "string", "value" => nil}
|
all_required_custom_fields_with_defaults(context) ++
|
||||||
}
|
[
|
||||||
]
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"_union_type" => "string", "_union_value" => nil}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
|
@ -341,16 +410,12 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "update_member with required custom fields" do
|
describe "update_member with required custom fields" do
|
||||||
test "fails when removing a required custom field value", %{
|
test "fails when removing a required custom field value",
|
||||||
required_string_field: field
|
%{
|
||||||
} do
|
required_string_field: field
|
||||||
# Create member with required custom field
|
} = context do
|
||||||
custom_field_values = [
|
# Create member with all required custom fields
|
||||||
%{
|
custom_field_values = all_required_custom_fields_with_defaults(context)
|
||||||
"custom_field_id" => field.id,
|
|
||||||
"value" => %{"type" => "string", "value" => "test"}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
{:ok, member} =
|
{:ok, member} =
|
||||||
Membership.create_member(%{
|
Membership.create_member(%{
|
||||||
|
|
@ -368,16 +433,12 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ field.name
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails when setting required custom field value to empty", %{
|
test "fails when setting required custom field value to empty",
|
||||||
required_string_field: field
|
%{
|
||||||
} do
|
required_string_field: field
|
||||||
# Create member with required custom field
|
} = context do
|
||||||
custom_field_values = [
|
# Create member with all required custom fields
|
||||||
%{
|
custom_field_values = all_required_custom_fields_with_defaults(context)
|
||||||
"custom_field_id" => field.id,
|
|
||||||
"value" => %{"type" => "string", "value" => "test"}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
{:ok, member} =
|
{:ok, member} =
|
||||||
Membership.create_member(%{
|
Membership.create_member(%{
|
||||||
|
|
@ -387,13 +448,16 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
custom_field_values: custom_field_values
|
custom_field_values: custom_field_values
|
||||||
})
|
})
|
||||||
|
|
||||||
# Try to update with empty value
|
# Try to update with empty value for the string field
|
||||||
updated_custom_field_values = [
|
updated_custom_field_values =
|
||||||
%{
|
all_required_custom_fields_with_defaults(context)
|
||||||
"custom_field_id" => field.id,
|
|> Enum.map(fn cfv ->
|
||||||
"value" => %{"type" => "string", "value" => ""}
|
if cfv["custom_field_id"] == field.id do
|
||||||
}
|
%{cfv | "value" => %{"_union_type" => "string", "_union_value" => ""}}
|
||||||
]
|
else
|
||||||
|
cfv
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
assert {:error, %Ash.Error.Invalid{errors: errors}} =
|
assert {:error, %Ash.Error.Invalid{errors: errors}} =
|
||||||
Membership.update_member(member, %{
|
Membership.update_member(member, %{
|
||||||
|
|
@ -404,16 +468,12 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
assert error_message(errors, :custom_field_values) =~ field.name
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
end
|
end
|
||||||
|
|
||||||
test "succeeds when updating required custom field to valid value", %{
|
test "succeeds when updating required custom field to valid value",
|
||||||
required_string_field: field
|
%{
|
||||||
} do
|
required_string_field: field
|
||||||
# Create member with required custom field
|
} = context do
|
||||||
custom_field_values = [
|
# Create member with all required custom fields
|
||||||
%{
|
custom_field_values = all_required_custom_fields_with_defaults(context)
|
||||||
"custom_field_id" => field.id,
|
|
||||||
"value" => %{"type" => "string", "value" => "old value"}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
{:ok, member} =
|
{:ok, member} =
|
||||||
Membership.create_member(%{
|
Membership.create_member(%{
|
||||||
|
|
@ -423,13 +483,31 @@ defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
custom_field_values: custom_field_values
|
custom_field_values: custom_field_values
|
||||||
})
|
})
|
||||||
|
|
||||||
# Update with new valid value
|
# Load existing custom field values to get their IDs
|
||||||
updated_custom_field_values = [
|
{:ok, member_with_cfvs} = Ash.load(member, :custom_field_values)
|
||||||
%{
|
|
||||||
"custom_field_id" => field.id,
|
# Update with new valid value for the string field, using existing IDs
|
||||||
"value" => %{"type" => "string", "value" => "new value"}
|
updated_custom_field_values =
|
||||||
}
|
member_with_cfvs.custom_field_values
|
||||||
]
|
|> Enum.map(fn cfv ->
|
||||||
|
if cfv.custom_field_id == field.id do
|
||||||
|
%{
|
||||||
|
"id" => cfv.id,
|
||||||
|
"custom_field_id" => cfv.custom_field_id,
|
||||||
|
"value" => %{"_union_type" => "string", "_union_value" => "new value"}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# Keep other fields as they are
|
||||||
|
value_type = Atom.to_string(cfv.value.type)
|
||||||
|
actual_value = cfv.value.value
|
||||||
|
|
||||||
|
%{
|
||||||
|
"id" => cfv.id,
|
||||||
|
"custom_field_id" => cfv.custom_field_id,
|
||||||
|
"value" => %{"_union_type" => value_type, "_union_value" => actual_value}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
assert {:ok, _updated_member} =
|
assert {:ok, _updated_member} =
|
||||||
Membership.update_member(member, %{
|
Membership.update_member(member, %{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue