fix(captain): match all selected labels in audience conditions

The labels multi-select serializes every selected label into values, but
the matcher only compared values.first. equal_to now matches contacts
carrying any selected label and not_equal_to rejects them.
This commit is contained in:
Pranav
2026-07-14 17:53:42 -07:00
parent cba79636cb
commit 2dec6ef362
2 changed files with 14 additions and 4 deletions
@@ -42,14 +42,14 @@ class Captain::AudienceMatcher
def matches_leaf?(leaf)
key = leaf[:attribute_key]
actual = attribute_value(key)
expected = Array(leaf[:values]).first
values = Array(leaf[:values])
case leaf[:filter_operator]
when 'is_present' then actual.present?
when 'is_not_present' then actual.blank?
when 'equal_to' then value_equal?(key, actual, expected)
when 'not_equal_to' then !value_equal?(key, actual, expected)
else matches_text_or_range?(leaf[:filter_operator], actual, expected)
when 'equal_to' then values.any? { |expected| value_equal?(key, actual, expected) }
when 'not_equal_to' then values.none? { |expected| value_equal?(key, actual, expected) }
else matches_text_or_range?(leaf[:filter_operator], actual, values.first)
end
end
@@ -77,6 +77,16 @@ RSpec.describe Captain::AudienceMatcher do
expect(matches?(leaf('labels', 'equal_to', 'vip'))).to be(true)
expect(matches?(leaf('labels', 'equal_to', 'enterprise'))).to be(false)
end
it 'matches any of multiple selected labels' do
expect(matches?(leaf('labels', 'equal_to', %w[enterprise vip]))).to be(true)
expect(matches?(leaf('labels', 'equal_to', %w[enterprise smb]))).to be(false)
end
it 'not_equal_to rejects contacts carrying any selected label' do
expect(matches?(leaf('labels', 'not_equal_to', %w[enterprise vip]))).to be(false)
expect(matches?(leaf('labels', 'not_equal_to', %w[enterprise smb]))).to be(true)
end
end
context 'with conversation language fields' do