Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MC-2359] Add normalized event and property names evaluation #385

Merged
merged 8 commits into from
Nov 28, 2024
10 changes: 10 additions & 0 deletions CleverTapSDK/CTUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,14 @@
+ (NSNumber * _Nullable)numberFromString:(NSString * _Nullable)string;
+ (NSNumber * _Nullable)numberFromString:(NSString * _Nullable)string withLocale:(NSLocale * _Nullable)locale;

/**
* Get the CT normalized version of an event or a property name.
*/
+ (NSString * _Nullable)getNormalizedName:(NSString * _Nullable)name;

/**
* Check if two event/property names are equal with applied CT normalization
*/
+ (BOOL)areEqualNormalizedName:(NSString * _Nullable)firstName andName:(NSString * _Nullable)secondName;

@end
30 changes: 30 additions & 0 deletions CleverTapSDK/CTUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,34 @@ + (NSNumber * _Nullable)numberFromString:(NSString * _Nullable)string withLocale
return nil;
}

+ (NSString * _Nullable)getNormalizedName:(NSString * _Nullable)name {
if (name) {
// Lowercase with English locale for consistent behavior with the backend
// and across different device locales.
NSString *normalizedName = [name stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLocale *englishLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
normalizedName = [normalizedName lowercaseStringWithLocale:englishLocale];
normalizedName = [normalizedName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
return normalizedName;
}

return nil;
}

+ (BOOL)areEqualNormalizedName:(NSString * _Nullable)firstName
andName:(NSString * _Nullable)secondName {
if (firstName == nil && secondName == nil) {
return YES;
}

if (firstName == nil || secondName == nil) {
return NO;
}

NSString *normalizedFirstName = [CTUtils getNormalizedName:firstName];
NSString *normalizedSecondName = [CTUtils getNormalizedName:secondName];

return [normalizedFirstName isEqualToString:normalizedSecondName];
}

@end
5 changes: 3 additions & 2 deletions CleverTapSDK/CTValidator.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#import "CTValidationResult.h"
#import "CTConstants.h"
#import "CTKnownProfileFields.h"
#import "CTUtils.h"

static const int kMaxKeyChars = 120;
static const int kMaxValueChars = 1024;
Expand Down Expand Up @@ -231,7 +232,7 @@ + (BOOL)isRestrictedEventName:(NSString *)name {
NSArray *restrictedNames = @[@"Notification Sent", @"Notification Viewed", @"Notification Clicked",
@"UTM Visited", @"App Launched", @"Stayed", @"App Uninstalled", @"wzrk_d", @"wzrk_fetch", @"SCCampaignOptOut", CLTAP_GEOFENCE_ENTERED_EVENT_NAME, CLTAP_GEOFENCE_EXITED_EVENT_NAME];
for (NSString *x in restrictedNames)
if ([name.lowercaseString isEqualToString:x.lowercaseString]) {
if ([CTUtils areEqualNormalizedName:name andName:x]) {
// The event name is restricted
CTValidationResult *error = [[CTValidationResult alloc] init];
[error setErrorCode:513];
Expand All @@ -244,7 +245,7 @@ + (BOOL)isRestrictedEventName:(NSString *)name {

+ (BOOL)isDiscaredEventName:(NSString *)name {
for (NSString *x in discardedEvents)
if ([name.lowercaseString isEqualToString:x.lowercaseString]) {
if ([CTUtils areEqualNormalizedName:name andName:x]) {
// The event name is discarded
CTValidationResult *error = [[CTValidationResult alloc] init];
[error setErrorCode:513];
Expand Down
6 changes: 3 additions & 3 deletions CleverTapSDK/InApps/Matchers/CTTriggersMatcher.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import "CTTriggerValue.h"
#import "CTConstants.h"
#import "CTTriggerEvaluator.h"
#import "CTUtils.h"

@implementation CTTriggersMatcher

Expand All @@ -30,9 +31,8 @@ - (BOOL)matchEventWhenTriggers:(NSArray *)whenTriggers event:(CTEventAdapter *)e
}

- (BOOL)match:(CTTriggerAdapter *)trigger event:(CTEventAdapter *)event {

BOOL eventNameMatch = [[event eventName] isEqualToString:[trigger eventName]];
BOOL profileAttrNameMatch = [event profileAttrName] != nil && [[event profileAttrName] isEqualToString:[trigger profileAttrName]];
BOOL eventNameMatch = [CTUtils areEqualNormalizedName:[event eventName] andName:[trigger eventName]];
BOOL profileAttrNameMatch = [event profileAttrName] != nil && [CTUtils areEqualNormalizedName:[event profileAttrName] andName:[trigger profileAttrName]];
if (!eventNameMatch && !profileAttrNameMatch) {
return NO;
}
Expand Down
19 changes: 19 additions & 0 deletions CleverTapSDKTests/CTUtilsTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,23 @@ - (void)test_numberFromStringWithLocale {
XCTAssertNil([CTUtils numberFromString:@"12.3" withLocale:locale]);
}

- (void)testGetNormalizedName {
XCTAssertNil([CTUtils getNormalizedName:nil]);
XCTAssertEqualObjects(@"", [CTUtils getNormalizedName:@""]);
XCTAssertEqualObjects(@"event1", [CTUtils getNormalizedName:@"Event 1"]);
XCTAssertEqualObjects(@"event1", [CTUtils getNormalizedName:@"EVENT 1"]);
XCTAssertEqualObjects(@"event1", [CTUtils getNormalizedName:@"event1"]);
}

- (void)testAreEqualNormalizedNames {
XCTAssertTrue([CTUtils areEqualNormalizedName:nil andName:nil]);
XCTAssertTrue([CTUtils areEqualNormalizedName:@"" andName:@""]);
XCTAssertTrue([CTUtils areEqualNormalizedName:@"Event 1" andName:@"Event1"]);
XCTAssertTrue([CTUtils areEqualNormalizedName:@"Event 1" andName:@"event1"]);
XCTAssertTrue([CTUtils areEqualNormalizedName:@"Event 1" andName:@"EVENT 1"]);
XCTAssertFalse([CTUtils areEqualNormalizedName:@"" andName:nil]);
XCTAssertFalse([CTUtils areEqualNormalizedName:@"Event 1" andName:nil]);
XCTAssertFalse([CTUtils areEqualNormalizedName:@"Event 1" andName:@"Event 2"]);
}

@end
16 changes: 16 additions & 0 deletions CleverTapSDKTests/InApps/CTTriggersMatcherTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,22 @@ - (void)testMatchEventWithoutProps {
XCTAssertFalse(matchNoProps);
}

- (void)testMatchEventWithNormalizedName {
NSArray *whenTriggers = @[
@{
@"eventName": @"event1",
@"eventProperties": @[
]
}
];

CTTriggersMatcher *triggerMatcher = [[CTTriggersMatcher alloc] init];
BOOL match = [triggerMatcher matchEventWhenTriggers:whenTriggers eventName:@"Event 1" eventProperties:@{
@"prop1": @"clevertap"
}];
XCTAssertTrue(match);
}

#pragma mark Charged Event

- (void)testMatchChargedEvent {
Expand Down
Loading