fix: Allow optional email values in custom fields
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
e9290b7156
commit
2b3c94d3b2
3 changed files with 42 additions and 6 deletions
|
|
@ -8,10 +8,11 @@ defmodule Mv.Membership.Email do
|
||||||
addresses according to a standard regex pattern.
|
addresses according to a standard regex pattern.
|
||||||
|
|
||||||
## Validation Rules
|
## Validation Rules
|
||||||
- Minimum length: 5 characters
|
- **Optional**: `nil` and empty strings are allowed (custom fields are optional)
|
||||||
|
- Minimum length: 5 characters (for non-empty values)
|
||||||
- Maximum length: 254 characters (RFC 5321 maximum)
|
- Maximum length: 254 characters (RFC 5321 maximum)
|
||||||
- Pattern: Standard email format (username@domain.tld)
|
- Pattern: Standard email format (username@domain.tld)
|
||||||
- Automatic trimming of leading/trailing whitespace
|
- Automatic trimming of leading/trailing whitespace (empty strings become `nil`)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
This type is used in the CustomFieldValue union type for custom fields with
|
This type is used in the CustomFieldValue union type for custom fields with
|
||||||
|
|
@ -46,11 +47,18 @@ defmodule Mv.Membership.Email do
|
||||||
max_length: @max_length
|
max_length: @max_length
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def cast_input(nil, _), do: {:ok, nil}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def cast_input(value, _) when is_binary(value) do
|
def cast_input(value, _) when is_binary(value) do
|
||||||
value = String.trim(value)
|
value = String.trim(value)
|
||||||
|
|
||||||
cond do
|
cond do
|
||||||
|
# Empty string after trim becomes nil (optional field)
|
||||||
|
value == "" ->
|
||||||
|
{:ok, nil}
|
||||||
|
|
||||||
String.length(value) < @min_length ->
|
String.length(value) < @min_length ->
|
||||||
:error
|
:error
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule Mv.Membership.CustomFieldValidationTest do
|
defmodule Mv.Membership.CustomFieldValidationTest do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Tests for CustomField validation constraints.
|
Tests for CustomField validation constraints.
|
||||||
|
|
||||||
Tests cover:
|
Tests cover:
|
||||||
- Name length validation (max 100 characters)
|
- Name length validation (max 100 characters)
|
||||||
- Name trimming
|
- Name trimming
|
||||||
|
|
@ -203,4 +203,3 @@ defmodule Mv.Membership.CustomFieldValidationTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule Mv.Membership.CustomFieldValueValidationTest do
|
defmodule Mv.Membership.CustomFieldValueValidationTest do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Tests for CustomFieldValue validation constraints.
|
Tests for CustomFieldValue validation constraints.
|
||||||
|
|
||||||
Tests cover:
|
Tests cover:
|
||||||
- String value length validation (max 10,000 characters)
|
- String value length validation (max 10,000 characters)
|
||||||
- String value trimming
|
- String value trimming
|
||||||
|
|
@ -184,6 +184,36 @@ defmodule Mv.Membership.CustomFieldValueValidationTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "email value validation" do
|
describe "email value validation" do
|
||||||
|
test "accepts nil value (optional field)", %{member: member, email_field: email_field} do
|
||||||
|
assert {:ok, custom_field_value} =
|
||||||
|
CustomFieldValue
|
||||||
|
|> Ash.Changeset.for_create(:create, %{
|
||||||
|
member_id: member.id,
|
||||||
|
custom_field_id: email_field.id,
|
||||||
|
value: %{"_union_type" => "email", "_union_value" => nil}
|
||||||
|
})
|
||||||
|
|> Ash.create()
|
||||||
|
|
||||||
|
assert custom_field_value.value.value == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "accepts empty string (becomes nil after trim)", %{
|
||||||
|
member: member,
|
||||||
|
email_field: email_field
|
||||||
|
} do
|
||||||
|
assert {:ok, custom_field_value} =
|
||||||
|
CustomFieldValue
|
||||||
|
|> Ash.Changeset.for_create(:create, %{
|
||||||
|
member_id: member.id,
|
||||||
|
custom_field_id: email_field.id,
|
||||||
|
value: %{"_union_type" => "email", "_union_value" => ""}
|
||||||
|
})
|
||||||
|
|> Ash.create()
|
||||||
|
|
||||||
|
# Empty string after trim should become nil
|
||||||
|
assert custom_field_value.value.value == nil
|
||||||
|
end
|
||||||
|
|
||||||
test "accepts valid email", %{member: member, email_field: email_field} do
|
test "accepts valid email", %{member: member, email_field: email_field} do
|
||||||
assert {:ok, custom_field_value} =
|
assert {:ok, custom_field_value} =
|
||||||
CustomFieldValue
|
CustomFieldValue
|
||||||
|
|
@ -273,4 +303,3 @@ defmodule Mv.Membership.CustomFieldValueValidationTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue