fix(captain): treat missing checkbox attributes as false in audience matcher
An unset checkbox custom attribute now matches equal_to false and not_equal_to true instead of never matching.
This commit is contained in:
@@ -72,11 +72,17 @@ class Captain::AudienceMatcher
|
||||
# ignore the "+" prefix, and text compares case-insensitively.
|
||||
def value_equal?(key, actual, expected)
|
||||
return Array(actual).include?(expected) if key == 'labels'
|
||||
return ActiveModel::Type::Boolean.new.cast(expected) == actual if [true, false].include?(actual)
|
||||
return ActiveModel::Type::Boolean.new.cast(expected) == (actual == true) if boolean_condition?(actual, expected)
|
||||
|
||||
normalize(key, actual) == normalize(key, expected)
|
||||
end
|
||||
|
||||
# An unset checkbox attribute counts as false; the expected value identifies
|
||||
# the condition as boolean when the attribute is missing.
|
||||
def boolean_condition?(actual, expected)
|
||||
[true, false].include?(actual) || (actual.nil? && %w[true false].include?(expected.to_s))
|
||||
end
|
||||
|
||||
def normalize(key, value)
|
||||
return value if value.nil?
|
||||
return "+#{value.to_s.delete('+')}" if key == 'phone_number'
|
||||
|
||||
@@ -37,6 +37,18 @@ RSpec.describe Captain::AudienceMatcher do
|
||||
expect(matches?(leaf('plan_tier', 'not_equal_to', 'free'))).to be(true)
|
||||
end
|
||||
|
||||
it 'matches checkbox custom attributes' do
|
||||
contact.update!(custom_attributes: contact.custom_attributes.merge('newsletter_opt_in' => true))
|
||||
expect(matches?(leaf('newsletter_opt_in', 'equal_to', 'true'))).to be(true)
|
||||
expect(matches?(leaf('newsletter_opt_in', 'equal_to', 'false'))).to be(false)
|
||||
end
|
||||
|
||||
it 'treats a missing checkbox attribute as false' do
|
||||
expect(matches?(leaf('newsletter_opt_in', 'equal_to', 'false'))).to be(true)
|
||||
expect(matches?(leaf('newsletter_opt_in', 'equal_to', 'true'))).to be(false)
|
||||
expect(matches?(leaf('newsletter_opt_in', 'not_equal_to', 'true'))).to be(true)
|
||||
end
|
||||
|
||||
it 'supports contains / starts_with on text' do
|
||||
expect(matches?(leaf('email', 'contains', contact.email[2..5]))).to be(true)
|
||||
expect(matches?(leaf('city', 'starts_with', 'Bos'))).to be(true)
|
||||
|
||||
Reference in New Issue
Block a user