fix: add validation for required custom fields
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
894b9b9d5c
commit
bbc094daaa
3 changed files with 519 additions and 0 deletions
|
|
@ -329,6 +329,63 @@ defmodule Mv.Membership.Member do
|
||||||
{:error, field: :email, message: "is not a valid email"}
|
{:error, field: :email, message: "is not a valid email"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Validate required custom fields
|
||||||
|
validate fn changeset, _ ->
|
||||||
|
custom_field_values_arg = Ash.Changeset.get_argument(changeset, :custom_field_values)
|
||||||
|
|
||||||
|
# If argument is not provided (nil), check existing values from member data (update scenario)
|
||||||
|
# If argument is provided (empty list or list with values), use those values
|
||||||
|
provided_values =
|
||||||
|
if is_nil(custom_field_values_arg) do
|
||||||
|
# Update scenario: check existing custom field values from member
|
||||||
|
case Ash.load(changeset.data, :custom_field_values) do
|
||||||
|
{:ok, %{custom_field_values: existing_values}} ->
|
||||||
|
Enum.reduce(existing_values, %{}, fn cfv, acc ->
|
||||||
|
value = if is_map(cfv.value), do: Map.get(cfv.value, :value), else: nil
|
||||||
|
Map.put(acc, cfv.custom_field_id, value)
|
||||||
|
end)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
%{}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# Create or update scenario: use provided argument values
|
||||||
|
Enum.reduce(custom_field_values_arg, %{}, fn cfv, acc ->
|
||||||
|
custom_field_id = Map.get(cfv, "custom_field_id")
|
||||||
|
value_map = Map.get(cfv, "value", %{})
|
||||||
|
actual_value = Map.get(value_map, "value")
|
||||||
|
Map.put(acc, custom_field_id, actual_value)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Load all required custom fields
|
||||||
|
case Mv.Membership.list_custom_fields() do
|
||||||
|
{:ok, all_custom_fields} ->
|
||||||
|
required_custom_fields = Enum.filter(all_custom_fields, & &1.required)
|
||||||
|
|
||||||
|
# Check each required custom field
|
||||||
|
missing_fields =
|
||||||
|
Enum.filter(required_custom_fields, fn cf ->
|
||||||
|
value = Map.get(provided_values, cf.id)
|
||||||
|
not value_present?(value, cf.value_type)
|
||||||
|
end)
|
||||||
|
|
||||||
|
if Enum.empty?(missing_fields) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
missing_names = Enum.map_join(missing_fields, ", ", & &1.name)
|
||||||
|
|
||||||
|
{:error,
|
||||||
|
field: :custom_field_values,
|
||||||
|
message: "Required custom fields missing: #{missing_names}"}
|
||||||
|
end
|
||||||
|
|
||||||
|
{:error, _} ->
|
||||||
|
# If we can't load custom fields, skip validation (shouldn't happen in normal operation)
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes do
|
attributes do
|
||||||
|
|
@ -665,4 +722,18 @@ defmodule Mv.Membership.Member do
|
||||||
query
|
query
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Helper function to check if a value is present for a given custom field type
|
||||||
|
# Boolean: false is valid, only nil is invalid
|
||||||
|
# String: nil or empty strings are invalid
|
||||||
|
# Integer: nil is invalid, 0 is valid
|
||||||
|
# Date: nil is invalid
|
||||||
|
# Email: nil is invalid
|
||||||
|
defp value_present?(nil, _type), do: false
|
||||||
|
defp value_present?(value, :boolean), do: not is_nil(value)
|
||||||
|
defp value_present?(value, :string), do: is_binary(value) and String.trim(value) != ""
|
||||||
|
defp value_present?(value, :integer), do: not is_nil(value)
|
||||||
|
defp value_present?(value, :date), do: not is_nil(value)
|
||||||
|
defp value_present?(value, :email), do: not is_nil(value)
|
||||||
|
defp value_present?(_value, _type), do: false
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,7 @@ defmodule MvWeb.MemberLive.Form do
|
||||||
field={value_form[:value]}
|
field={value_form[:value]}
|
||||||
label={cf.name}
|
label={cf.name}
|
||||||
type={custom_field_input_type(cf.value_type)}
|
type={custom_field_input_type(cf.value_type)}
|
||||||
|
required={cf.required}
|
||||||
/>
|
/>
|
||||||
</.inputs_for>
|
</.inputs_for>
|
||||||
<input
|
<input
|
||||||
|
|
|
||||||
447
test/membership/member_required_custom_fields_test.exs
Normal file
447
test/membership/member_required_custom_fields_test.exs
Normal file
|
|
@ -0,0 +1,447 @@
|
||||||
|
defmodule Mv.Membership.MemberRequiredCustomFieldsTest do
|
||||||
|
@moduledoc """
|
||||||
|
Tests for required custom fields validation.
|
||||||
|
|
||||||
|
Tests cover:
|
||||||
|
- Member creation without required custom field → error
|
||||||
|
- Member creation with empty required custom field (nil/empty string) → error
|
||||||
|
- Member creation with valid required custom field → success
|
||||||
|
- Member update: removing a required custom field value → error
|
||||||
|
- Boolean required custom field: false is valid, nil is invalid
|
||||||
|
"""
|
||||||
|
use Mv.DataCase, async: true
|
||||||
|
|
||||||
|
alias Mv.Membership
|
||||||
|
|
||||||
|
setup do
|
||||||
|
# Create required custom fields for different types
|
||||||
|
{:ok, required_string_field} =
|
||||||
|
Membership.CustomField
|
||||||
|
|> Ash.Changeset.for_create(:create, %{
|
||||||
|
name: "required_string",
|
||||||
|
value_type: :string,
|
||||||
|
required: true
|
||||||
|
})
|
||||||
|
|> Ash.create()
|
||||||
|
|
||||||
|
{:ok, required_integer_field} =
|
||||||
|
Membership.CustomField
|
||||||
|
|> Ash.Changeset.for_create(:create, %{
|
||||||
|
name: "required_integer",
|
||||||
|
value_type: :integer,
|
||||||
|
required: true
|
||||||
|
})
|
||||||
|
|> Ash.create()
|
||||||
|
|
||||||
|
{:ok, required_boolean_field} =
|
||||||
|
Membership.CustomField
|
||||||
|
|> Ash.Changeset.for_create(:create, %{
|
||||||
|
name: "required_boolean",
|
||||||
|
value_type: :boolean,
|
||||||
|
required: true
|
||||||
|
})
|
||||||
|
|> Ash.create()
|
||||||
|
|
||||||
|
{:ok, required_date_field} =
|
||||||
|
Membership.CustomField
|
||||||
|
|> Ash.Changeset.for_create(:create, %{
|
||||||
|
name: "required_date",
|
||||||
|
value_type: :date,
|
||||||
|
required: true
|
||||||
|
})
|
||||||
|
|> Ash.create()
|
||||||
|
|
||||||
|
{:ok, optional_field} =
|
||||||
|
Membership.CustomField
|
||||||
|
|> Ash.Changeset.for_create(:create, %{
|
||||||
|
name: "optional_string",
|
||||||
|
value_type: :string,
|
||||||
|
required: false
|
||||||
|
})
|
||||||
|
|> Ash.create()
|
||||||
|
|
||||||
|
%{
|
||||||
|
required_string_field: required_string_field,
|
||||||
|
required_integer_field: required_integer_field,
|
||||||
|
required_boolean_field: required_boolean_field,
|
||||||
|
required_date_field: required_date_field,
|
||||||
|
optional_field: optional_field
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "create_member with required custom fields" do
|
||||||
|
@valid_attrs %{
|
||||||
|
first_name: "John",
|
||||||
|
last_name: "Doe",
|
||||||
|
email: "john@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fails when required custom field is missing", %{required_string_field: field} do
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, [])
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.create_member(attrs)
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when required string custom field has nil value", %{
|
||||||
|
required_string_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => nil}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.create_member(attrs)
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when required string custom field has empty string value", %{
|
||||||
|
required_string_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => ""}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.create_member(attrs)
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when required string custom field has whitespace-only value", %{
|
||||||
|
required_string_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => " "}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.create_member(attrs)
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when required string custom field has valid value", %{
|
||||||
|
required_string_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => "test value"}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when required integer custom field has nil value", %{
|
||||||
|
required_integer_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "integer", "value" => nil}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.create_member(attrs)
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when required integer custom field has zero value", %{
|
||||||
|
required_integer_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "integer", "value" => 0}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when required integer custom field has positive value", %{
|
||||||
|
required_integer_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "integer", "value" => 42}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when required boolean custom field has nil value", %{
|
||||||
|
required_boolean_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "boolean", "value" => nil}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.create_member(attrs)
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when required boolean custom field has false value", %{
|
||||||
|
required_boolean_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "boolean", "value" => false}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when required boolean custom field has true value", %{
|
||||||
|
required_boolean_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "boolean", "value" => true}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when required date custom field has nil value", %{
|
||||||
|
required_date_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "date", "value" => nil}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.create_member(attrs)
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when required date custom field has valid date value", %{
|
||||||
|
required_date_field: field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "date", "value" => ~D[2020-01-01]}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when multiple required custom fields are provided", %{
|
||||||
|
required_string_field: string_field,
|
||||||
|
required_integer_field: integer_field,
|
||||||
|
required_boolean_field: boolean_field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => string_field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => "test"}
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"custom_field_id" => integer_field.id,
|
||||||
|
"value" => %{"type" => "integer", "value" => 42}
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
"custom_field_id" => boolean_field.id,
|
||||||
|
"value" => %{"type" => "boolean", "value" => true}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when one of multiple required custom fields is missing", %{
|
||||||
|
required_string_field: string_field,
|
||||||
|
required_integer_field: integer_field
|
||||||
|
} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => string_field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => "test"}
|
||||||
|
}
|
||||||
|
# Missing required_integer_field
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.create_member(attrs)
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ integer_field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when optional custom field is missing", %{optional_field: field} do
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, [])
|
||||||
|
|
||||||
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when optional custom field has nil value", %{optional_field: field} do
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => nil}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
attrs = Map.put(@valid_attrs, :custom_field_values, custom_field_values)
|
||||||
|
|
||||||
|
assert {:ok, _member} = Membership.create_member(attrs)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "update_member with required custom fields" do
|
||||||
|
test "fails when removing a required custom field value", %{
|
||||||
|
required_string_field: field
|
||||||
|
} do
|
||||||
|
# Create member with required custom field
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => "test"}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
{:ok, member} =
|
||||||
|
Membership.create_member(%{
|
||||||
|
first_name: "John",
|
||||||
|
last_name: "Doe",
|
||||||
|
email: "john@example.com",
|
||||||
|
custom_field_values: custom_field_values
|
||||||
|
})
|
||||||
|
|
||||||
|
# Try to update without the required custom field
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} =
|
||||||
|
Membership.update_member(member, %{custom_field_values: []})
|
||||||
|
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when setting required custom field value to empty", %{
|
||||||
|
required_string_field: field
|
||||||
|
} do
|
||||||
|
# Create member with required custom field
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => "test"}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
{:ok, member} =
|
||||||
|
Membership.create_member(%{
|
||||||
|
first_name: "John",
|
||||||
|
last_name: "Doe",
|
||||||
|
email: "john@example.com",
|
||||||
|
custom_field_values: custom_field_values
|
||||||
|
})
|
||||||
|
|
||||||
|
# Try to update with empty value
|
||||||
|
updated_custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => ""}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{errors: errors}} =
|
||||||
|
Membership.update_member(member, %{
|
||||||
|
custom_field_values: updated_custom_field_values
|
||||||
|
})
|
||||||
|
|
||||||
|
assert error_message(errors, :custom_field_values) =~ "Required custom fields missing"
|
||||||
|
assert error_message(errors, :custom_field_values) =~ field.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds when updating required custom field to valid value", %{
|
||||||
|
required_string_field: field
|
||||||
|
} do
|
||||||
|
# Create member with required custom field
|
||||||
|
custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => "old value"}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
{:ok, member} =
|
||||||
|
Membership.create_member(%{
|
||||||
|
first_name: "John",
|
||||||
|
last_name: "Doe",
|
||||||
|
email: "john@example.com",
|
||||||
|
custom_field_values: custom_field_values
|
||||||
|
})
|
||||||
|
|
||||||
|
# Update with new valid value
|
||||||
|
updated_custom_field_values = [
|
||||||
|
%{
|
||||||
|
"custom_field_id" => field.id,
|
||||||
|
"value" => %{"type" => "string", "value" => "new value"}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
assert {:ok, _updated_member} =
|
||||||
|
Membership.update_member(member, %{
|
||||||
|
custom_field_values: updated_custom_field_values
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Helper function for error evaluation
|
||||||
|
defp error_message(errors, field) do
|
||||||
|
errors
|
||||||
|
|> Enum.filter(fn err -> Map.get(err, :field) == field end)
|
||||||
|
|> Enum.map_join(" ", &Map.get(&1, :message, ""))
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Add table
Add a link
Reference in a new issue