fix: custom field substring search - pass id as parameter
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Fragment 'member_id = id' did not resolve correctly. Now passes id as Ash expression. Also changed LIKE to ILIKE for case-insensitive search.
This commit is contained in:
parent
ca5fad0dcc
commit
00fe471bc0
2 changed files with 160 additions and 3 deletions
|
|
@ -544,4 +544,159 @@ defmodule Mv.Membership.MemberSearchWithCustomFieldsTest do
|
|||
# Substring matching for custom fields may need to be implemented separately
|
||||
end
|
||||
end
|
||||
|
||||
describe "custom field substring search (ILIKE)" do
|
||||
test "finds member by prefix of custom field value", %{
|
||||
member1: member1,
|
||||
string_field: string_field
|
||||
} do
|
||||
# Create custom field value with a distinct word
|
||||
{:ok, _cfv} =
|
||||
CustomFieldValue
|
||||
|> Ash.Changeset.for_create(:create, %{
|
||||
member_id: member1.id,
|
||||
custom_field_id: string_field.id,
|
||||
value: %{"_union_type" => "string", "_union_value" => "Premium"}
|
||||
})
|
||||
|> Ash.create()
|
||||
|
||||
# Test prefix searches - should all find the member
|
||||
for prefix <- ["Premium", "Premiu", "Premi", "Prem", "Pre"] do
|
||||
results =
|
||||
Member
|
||||
|> Member.fuzzy_search(%{query: prefix})
|
||||
|> Ash.read!()
|
||||
|
||||
assert Enum.any?(results, fn m -> m.id == member1.id end),
|
||||
"Prefix '#{prefix}' should find member with custom field 'Premium'"
|
||||
end
|
||||
end
|
||||
|
||||
test "custom field search is case-insensitive", %{
|
||||
member1: member1,
|
||||
string_field: string_field
|
||||
} do
|
||||
# Create custom field value
|
||||
{:ok, _cfv} =
|
||||
CustomFieldValue
|
||||
|> Ash.Changeset.for_create(:create, %{
|
||||
member_id: member1.id,
|
||||
custom_field_id: string_field.id,
|
||||
value: %{"_union_type" => "string", "_union_value" => "GoldMember"}
|
||||
})
|
||||
|> Ash.create()
|
||||
|
||||
# Test case variations - should all find the member
|
||||
for variant <- [
|
||||
"GoldMember",
|
||||
"goldmember",
|
||||
"GOLDMEMBER",
|
||||
"GoLdMeMbEr",
|
||||
"gold",
|
||||
"GOLD",
|
||||
"Gold"
|
||||
] do
|
||||
results =
|
||||
Member
|
||||
|> Member.fuzzy_search(%{query: variant})
|
||||
|> Ash.read!()
|
||||
|
||||
assert Enum.any?(results, fn m -> m.id == member1.id end),
|
||||
"Case variant '#{variant}' should find member with custom field 'GoldMember'"
|
||||
end
|
||||
end
|
||||
|
||||
test "finds member by suffix/middle of custom field value", %{
|
||||
member1: member1,
|
||||
string_field: string_field
|
||||
} do
|
||||
# Create custom field value
|
||||
{:ok, _cfv} =
|
||||
CustomFieldValue
|
||||
|> Ash.Changeset.for_create(:create, %{
|
||||
member_id: member1.id,
|
||||
custom_field_id: string_field.id,
|
||||
value: %{"_union_type" => "string", "_union_value" => "ActiveMember"}
|
||||
})
|
||||
|> Ash.create()
|
||||
|
||||
# Test suffix and middle substring searches
|
||||
for substring <- ["Member", "ember", "tiveMem", "ctive"] do
|
||||
results =
|
||||
Member
|
||||
|> Member.fuzzy_search(%{query: substring})
|
||||
|> Ash.read!()
|
||||
|
||||
assert Enum.any?(results, fn m -> m.id == member1.id end),
|
||||
"Substring '#{substring}' should find member with custom field 'ActiveMember'"
|
||||
end
|
||||
end
|
||||
|
||||
test "finds correct member among multiple with different custom field values", %{
|
||||
member1: member1,
|
||||
member2: member2,
|
||||
member3: member3,
|
||||
string_field: string_field
|
||||
} do
|
||||
# Create different custom field values for each member
|
||||
{:ok, _cfv1} =
|
||||
CustomFieldValue
|
||||
|> Ash.Changeset.for_create(:create, %{
|
||||
member_id: member1.id,
|
||||
custom_field_id: string_field.id,
|
||||
value: %{"_union_type" => "string", "_union_value" => "Beginner"}
|
||||
})
|
||||
|> Ash.create()
|
||||
|
||||
{:ok, _cfv2} =
|
||||
CustomFieldValue
|
||||
|> Ash.Changeset.for_create(:create, %{
|
||||
member_id: member2.id,
|
||||
custom_field_id: string_field.id,
|
||||
value: %{"_union_type" => "string", "_union_value" => "Advanced"}
|
||||
})
|
||||
|> Ash.create()
|
||||
|
||||
{:ok, _cfv3} =
|
||||
CustomFieldValue
|
||||
|> Ash.Changeset.for_create(:create, %{
|
||||
member_id: member3.id,
|
||||
custom_field_id: string_field.id,
|
||||
value: %{"_union_type" => "string", "_union_value" => "Expert"}
|
||||
})
|
||||
|> Ash.create()
|
||||
|
||||
# Search for "Begin" - should only find member1
|
||||
results_begin =
|
||||
Member
|
||||
|> Member.fuzzy_search(%{query: "Begin"})
|
||||
|> Ash.read!()
|
||||
|
||||
assert length(results_begin) == 1
|
||||
assert List.first(results_begin).id == member1.id
|
||||
|
||||
# Search for "Advan" - should only find member2
|
||||
results_advan =
|
||||
Member
|
||||
|> Member.fuzzy_search(%{query: "Advan"})
|
||||
|> Ash.read!()
|
||||
|
||||
assert length(results_advan) == 1
|
||||
assert List.first(results_advan).id == member2.id
|
||||
|
||||
# Search for "Exper" - should only find member3
|
||||
results_exper =
|
||||
Member
|
||||
|> Member.fuzzy_search(%{query: "Exper"})
|
||||
|> Ash.read!()
|
||||
|
||||
assert length(results_exper) == 1
|
||||
assert List.first(results_exper).id == member3.id
|
||||
end
|
||||
|
||||
# Note: Legacy format (type/value) is supported via the SQL ILIKE query on value->>'value'
|
||||
# This is tested implicitly by the migration trigger which handles both formats.
|
||||
# The Ash union type only accepts the new format (_union_type/_union_value) for creation,
|
||||
# but the search works on existing legacy data.
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue