From ee8ec19a544e35a07408e391f08102a08349ec90 Mon Sep 17 00:00:00 2001 From: Karen Zeng Date: Fri, 15 Apr 2022 12:41:15 -0700 Subject: [PATCH 1/4] Extract first open time from analytics user properties --- .../Sources/RCNConfigSettings.m | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/FirebaseRemoteConfig/Sources/RCNConfigSettings.m b/FirebaseRemoteConfig/Sources/RCNConfigSettings.m index 09af88f32dc..5c9869093b7 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigSettings.m +++ b/FirebaseRemoteConfig/Sources/RCNConfigSettings.m @@ -28,6 +28,7 @@ static NSString *const kRCNGroupPrefix = @"frc.group."; static NSString *const kRCNUserDefaultsKeyNamelastETag = @"lastETag"; static NSString *const kRCNUserDefaultsKeyNameLastSuccessfulFetchTime = @"lastSuccessfulFetchTime"; +static NSString *const kRCNAnlyticsFirstOpenTimePropertyName = @"_fot"; static const int kRCNExponentialBackoffMinimumInterval = 60 * 2; // 2 mins. static const int kRCNExponentialBackoffMaximumInterval = 60 * 60 * 4; // 4 hours. @@ -359,16 +360,32 @@ - (NSString *)nextRequestWithUserProperties:(NSDictionary *)userProperties { if (userProperties && userProperties.count > 0) { NSError *error; - NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userProperties - options:0 - error:&error]; - if (!error) { - ret = [ret - stringByAppendingString:[NSString - stringWithFormat:@", analytics_user_properties:%@", - [[NSString alloc] - initWithData:jsonData - encoding:NSUTF8StringEncoding]]]; + + // Extract first open time from user properties and send as a separate field + NSNumber *firstOpenTime = [userProperties valueForKey:kRCNAnlyticsFirstOpenTimePropertyName]; + if (firstOpenTime) { + NSDate *date = [NSDate dateWithTimeIntervalSince1970:([firstOpenTime longValue] / 1000)]; + NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init]; + NSString *firstOpenTimeISOString = [formatter stringFromDate:date]; + ret = [ret stringByAppendingString:[NSString stringWithFormat:@", first_open_time:'%@'", + firstOpenTimeISOString]]; + + NSMutableDictionary *userPropertiesCopy = [userProperties mutableCopy]; + [userPropertiesCopy removeObjectForKey:kRCNAnlyticsFirstOpenTimePropertyName]; + userProperties = userPropertiesCopy; + } + if (userProperties.count > 0) { + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userProperties + options:0 + error:&error]; + if (!error) { + ret = [ret + stringByAppendingString:[NSString + stringWithFormat:@", analytics_user_properties:%@", + [[NSString alloc] + initWithData:jsonData + encoding:NSUTF8StringEncoding]]]; + } } } ret = [ret stringByAppendingString:@"}"]; From 84ac86c7c239e6fcf5e0e0dd9fa7cfa90dfd0c45 Mon Sep 17 00:00:00 2001 From: Karen Zeng Date: Fri, 15 Apr 2022 17:09:07 -0700 Subject: [PATCH 2/4] Add tests --- .../Tests/Unit/RCNRemoteConfigTest.m | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m b/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m index 5fc426b1e42..ffd3ab04407 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m @@ -79,6 +79,10 @@ @interface RCNUserDefaultsManager (Test) + (NSUserDefaults *)sharedUserDefaultsForBundleIdentifier:(NSString *)bundleIdentifier; @end +@interface RCNConfigSettings (Test) +- (NSString *)nextRequestWithUserProperties:(NSDictionary *)userProperties; +@end + typedef NS_ENUM(NSInteger, RCNTestRCInstance) { RCNTestRCInstanceDefault, RCNTestRCInstanceSecondNamespace, @@ -1415,6 +1419,29 @@ - (void)testSetFetchTimeoutConfigSetting { } } +- (void)testFetchRequestWithUserProperties { + NSDictionary *userProperties = @{@"user_key" : @"user_value"}; + NSString *req = [_settings nextRequestWithUserProperties:userProperties]; + + XCTAssertTrue([req containsString:@"analytics_user_properties:{\"user_key\":\"user_value\"}"]); +} + +- (void)testFetchRequestWithFirstOpenTimeAndUserProperties { + NSDictionary *userProperties = @{@"_fot" : @1649116800000, @"user_key" : @"user_value"}; + NSString *req = [_settings nextRequestWithUserProperties:userProperties]; + + XCTAssertTrue([req containsString:@"first_open_time:'2022-04-05T00:00:00Z'"]); + XCTAssertTrue([req containsString:@"analytics_user_properties:{\"user_key\":\"user_value\"}"]); +} + +- (void)testFetchRequestFirstOpenTimeOnly { + NSDictionary *userProperties = @{@"_fot" : @1649116800000}; + NSString *req = [_settings nextRequestWithUserProperties:userProperties]; + + XCTAssertTrue([req containsString:@"first_open_time:'2022-04-05T00:00:00Z'"]); + XCTAssertFalse([req containsString:@"analytics_user_properties"]); +} + #pragma mark - Public Factory Methods - (void)testConfigureConfigWithValidInput { From eb3a738f54dff0824c4337875b3c377b3c1ba026 Mon Sep 17 00:00:00 2001 From: Karen Zeng Date: Mon, 18 Apr 2022 14:34:08 -0700 Subject: [PATCH 3/4] Address comments --- FirebaseRemoteConfig/Sources/RCNConfigSettings.m | 15 +++++++-------- .../Tests/Unit/RCNRemoteConfigTest.m | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/FirebaseRemoteConfig/Sources/RCNConfigSettings.m b/FirebaseRemoteConfig/Sources/RCNConfigSettings.m index 5c9869093b7..45b672ae4cf 100644 --- a/FirebaseRemoteConfig/Sources/RCNConfigSettings.m +++ b/FirebaseRemoteConfig/Sources/RCNConfigSettings.m @@ -28,7 +28,7 @@ static NSString *const kRCNGroupPrefix = @"frc.group."; static NSString *const kRCNUserDefaultsKeyNamelastETag = @"lastETag"; static NSString *const kRCNUserDefaultsKeyNameLastSuccessfulFetchTime = @"lastSuccessfulFetchTime"; -static NSString *const kRCNAnlyticsFirstOpenTimePropertyName = @"_fot"; +static NSString *const kRCNAnalyticsFirstOpenTimePropertyName = @"_fot"; static const int kRCNExponentialBackoffMinimumInterval = 60 * 2; // 2 mins. static const int kRCNExponentialBackoffMaximumInterval = 60 * 60 * 4; // 4 hours. @@ -362,20 +362,19 @@ - (NSString *)nextRequestWithUserProperties:(NSDictionary *)userProperties { NSError *error; // Extract first open time from user properties and send as a separate field - NSNumber *firstOpenTime = [userProperties valueForKey:kRCNAnlyticsFirstOpenTimePropertyName]; - if (firstOpenTime) { + NSNumber *firstOpenTime = userProperties[kRCNAnalyticsFirstOpenTimePropertyName]; + NSMutableDictionary *remainingUserProperties = [userProperties mutableCopy]; + if (firstOpenTime != nil) { NSDate *date = [NSDate dateWithTimeIntervalSince1970:([firstOpenTime longValue] / 1000)]; NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init]; NSString *firstOpenTimeISOString = [formatter stringFromDate:date]; ret = [ret stringByAppendingString:[NSString stringWithFormat:@", first_open_time:'%@'", firstOpenTimeISOString]]; - NSMutableDictionary *userPropertiesCopy = [userProperties mutableCopy]; - [userPropertiesCopy removeObjectForKey:kRCNAnlyticsFirstOpenTimePropertyName]; - userProperties = userPropertiesCopy; + [remainingUserProperties removeObjectForKey:kRCNAnalyticsFirstOpenTimePropertyName]; } - if (userProperties.count > 0) { - NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userProperties + if (remainingUserProperties.count > 0) { + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:remainingUserProperties options:0 error:&error]; if (!error) { diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m b/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m index ffd3ab04407..d36b6aa8fc8 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m @@ -1435,10 +1435,10 @@ - (void)testFetchRequestWithFirstOpenTimeAndUserProperties { } - (void)testFetchRequestFirstOpenTimeOnly { - NSDictionary *userProperties = @{@"_fot" : @1649116800000}; + NSDictionary *userProperties = @{@"_fot" : @1650312375543}; NSString *req = [_settings nextRequestWithUserProperties:userProperties]; - XCTAssertTrue([req containsString:@"first_open_time:'2022-04-05T00:00:00Z'"]); + XCTAssertTrue([req containsString:@"first_open_time:'2022-04-18T20:06:15Z'"]); XCTAssertFalse([req containsString:@"analytics_user_properties"]); } From 59c4ffbfacb124370475c3383db7fadb92aff67e Mon Sep 17 00:00:00 2001 From: Karen Zeng Date: Mon, 18 Apr 2022 15:28:57 -0700 Subject: [PATCH 4/4] Update tests --- FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m b/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m index d36b6aa8fc8..cb3c869d70d 100644 --- a/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m +++ b/FirebaseRemoteConfig/Tests/Unit/RCNRemoteConfigTest.m @@ -1419,11 +1419,12 @@ - (void)testSetFetchTimeoutConfigSetting { } } -- (void)testFetchRequestWithUserProperties { +- (void)testFetchRequestWithUserPropertiesOnly { NSDictionary *userProperties = @{@"user_key" : @"user_value"}; NSString *req = [_settings nextRequestWithUserProperties:userProperties]; XCTAssertTrue([req containsString:@"analytics_user_properties:{\"user_key\":\"user_value\"}"]); + XCTAssertFalse([req containsString:@"first_open_time"]); } - (void)testFetchRequestWithFirstOpenTimeAndUserProperties { @@ -1435,10 +1436,10 @@ - (void)testFetchRequestWithFirstOpenTimeAndUserProperties { } - (void)testFetchRequestFirstOpenTimeOnly { - NSDictionary *userProperties = @{@"_fot" : @1650312375543}; + NSDictionary *userProperties = @{@"_fot" : @1650315600000}; NSString *req = [_settings nextRequestWithUserProperties:userProperties]; - XCTAssertTrue([req containsString:@"first_open_time:'2022-04-18T20:06:15Z'"]); + XCTAssertTrue([req containsString:@"first_open_time:'2022-04-18T21:00:00Z'"]); XCTAssertFalse([req containsString:@"analytics_user_properties"]); }