diff --git a/mParticle-Rokt-Swift/MPRoktLayout.swift b/mParticle-Rokt-Swift/MPRoktLayout.swift index 669e6b2..8464213 100644 --- a/mParticle-Rokt-Swift/MPRoktLayout.swift +++ b/mParticle-Rokt-Swift/MPRoktLayout.swift @@ -56,10 +56,22 @@ public class MPRoktLayout { let hashedEmailIdentity = MPKitRokt.getHashedEmailUserIdentityType() let userEmailIdentity = user.identities[NSNumber(value: MPIdentity.email.rawValue)] - let userHashedEmailIdentity = user.identities[hashedEmailIdentity] - let emailMismatch = email != nil && email != userEmailIdentity - let hashedEmailMismatch = hashedEmail != nil && hashedEmail != userHashedEmailIdentity + let emailMismatch: Bool = { + guard let email = email, + let userEmail = user.identities[NSNumber(value: MPIdentity.email.rawValue)] else { + return false + } + return email != userEmail + }() + let hashedEmailMismatch: Bool = { + guard let hashedEmail = hashedEmail, + let hashedEmailIdentity = hashedEmailIdentity, + let userHashedEmail = user.identities[hashedEmailIdentity] else { + return false + } + return hashedEmail != userHashedEmail + }() if emailMismatch || hashedEmailMismatch { // If there is an existing email or hashed email but it doesn't match what was passed in, warn the customer @@ -67,7 +79,7 @@ public class MPRoktLayout { print("The existing email on the user (\(userEmailIdentity ?? "nil")) does not match the email passed in to `selectPlacements:` (\(email ?? "nil")). Please remember to sync the email identity to mParticle as soon as you receive it. We will now identify the user before creating the layout") } if hashedEmailMismatch { - print("The existing hashed email on the user (\(userHashedEmailIdentity ?? "nil")) does not match the email passed in to `selectPlacements:` (\(hashedEmail ?? "nil")). Please remember to sync the email identity to mParticle as soon as you receive it. We will now identify the user before creating the layout") + print("The existing hashed email on the user (\(user.identities[hashedEmailIdentity ?? NSNumber(value: -1)] ?? "nil")) does not match the email passed in to `selectPlacements:` (\(hashedEmail ?? "nil")). Please remember to sync the hashed email identity to mParticle as soon as you receive it. We will now identify the user before creating the layout") } syncIdentities(user: user, email: email, hashedEmail: hashedEmail, hashedEmailKey: hashedEmailIdentity, completion: completion) @@ -80,12 +92,14 @@ public class MPRoktLayout { user: MParticleUser, email: String?, hashedEmail: String?, - hashedEmailKey: NSNumber, + hashedEmailKey: NSNumber?, completion: @escaping () -> Void ) { let identityRequest = MPIdentityApiRequest(user: user) identityRequest.setIdentity(email, identityType: .email) - identityRequest.setIdentity(hashedEmail, identityType: MPIdentity(rawValue: hashedEmailKey.uintValue) ?? .other) + if let hashedEmailKey = hashedEmailKey { + identityRequest.setIdentity(hashedEmail, identityType: MPIdentity(rawValue: hashedEmailKey.uintValue) ?? .other) + } mparticle.identity.identify(identityRequest) {apiResult, error in if let error = error { diff --git a/mParticle-Rokt/MPKitRokt.h b/mParticle-Rokt/MPKitRokt.h index 922e9a8..a646420 100644 --- a/mParticle-Rokt/MPKitRokt.h +++ b/mParticle-Rokt/MPKitRokt.h @@ -17,6 +17,6 @@ @property (nonatomic, unsafe_unretained, readonly) BOOL started; + (NSDictionary * _Nonnull)prepareAttributes:(NSDictionary * _Nonnull)attributes filteredUser:(FilteredMParticleUser * _Nullable)filteredUser performMapping:(BOOL)performMapping; -+ (NSNumber * _Nonnull)getRoktHashedEmailUserIdentityType; ++ (NSNumber * _Nullable)getRoktHashedEmailUserIdentityType; @end diff --git a/mParticle-Rokt/MPKitRokt.m b/mParticle-Rokt/MPKitRokt.m index 393305a..47bccc4 100644 --- a/mParticle-Rokt/MPKitRokt.m +++ b/mParticle-Rokt/MPKitRokt.m @@ -366,7 +366,7 @@ + (RoktConfig *)convertMPRoktConfig:(MPRoktConfig *)mpRoktConfig { + (NSString *)stringForIdentityType:(MPIdentity)identityType { NSNumber *hashedEmailIdentity = [MPKitRokt getRoktHashedEmailUserIdentityType]; - if (hashedEmailIdentity.unsignedIntValue == identityType) { + if (hashedEmailIdentity && hashedEmailIdentity.unsignedIntValue == identityType) { return @"emailsha256"; } @@ -443,7 +443,7 @@ + (NSNumber *)getRoktHashedEmailUserIdentityType { NSString *hashedIdentityTypeString = roktKitConfig[kMPHashedEmailUserIdentityType]; NSNumber *hashedIdentityTypeNumber = [MPKitRokt identityTypeForString:hashedIdentityTypeString.lowercaseString]; - return hashedIdentityTypeNumber != nil ? hashedIdentityTypeNumber : @(MPIdentityOther); + return hashedIdentityTypeNumber; } - (MPKitExecStatus *)purchaseFinalized:(NSString *)placementId catalogItemId:(NSString *)catalogItemId success:(NSNumber *)success { diff --git a/mParticle_RoktTests/mParticle_RoktTests.m b/mParticle_RoktTests/mParticle_RoktTests.m index 08dbef9..b6cefa7 100644 --- a/mParticle_RoktTests/mParticle_RoktTests.m +++ b/mParticle_RoktTests/mParticle_RoktTests.m @@ -236,6 +236,8 @@ - (void)testAddIdentityAttributes { FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] init]; id mockfilteredUser = OCMPartialMock(filteredUser); [[[mockfilteredUser stub] andReturn:testIdentities] userIdentities]; + id mockMPKitRoktClass = OCMClassMock([MPKitRokt class]); + [[[mockMPKitRoktClass stub] andReturn:@(MPIdentityOther)] getRoktHashedEmailUserIdentityType]; [MPKitRokt addIdentityAttributes:passedAttributes filteredUser:filteredUser]; @@ -267,6 +269,69 @@ - (void)testAddIdentityAttributes { XCTAssertEqualObjects(passedAttributes[@"device_application_stamp"], @"Test DAS"); } +- (void)testAddIdentityAttributesUnassigned { + NSMutableDictionary *passedAttributes = [[NSMutableDictionary alloc] init]; + NSDictionary *testIdentities = @{@(MPIdentityCustomerId): @"testCustomerID", + @(MPIdentityEmail): @"testEmail@gmail.com", + @(MPIdentityFacebook): @"testFacebook", + @(MPIdentityFacebookCustomAudienceId): @"testCustomAudienceID", + @(MPIdentityGoogle): @"testGoogle", + @(MPIdentityMicrosoft): @"testMicrosoft", + @(MPIdentityOther): @"testOther", + @(MPIdentityTwitter): @"testTwitter", + @(MPIdentityYahoo): @"testYahoo", + @(MPIdentityOther2): @"testOther2", + @(MPIdentityOther3): @"testOther3", + @(MPIdentityOther4): @"testOther4", + @(MPIdentityOther5): @"testOther5", + @(MPIdentityOther6): @"testOther6", + @(MPIdentityOther7): @"testOther7", + @(MPIdentityOther8): @"testOther8", + @(MPIdentityOther9): @"testOther9", + @(MPIdentityOther10): @"testOther10", + @(MPIdentityMobileNumber): @"1(234)-567-8910", + @(MPIdentityPhoneNumber2): @"1(234)-567-2222", + @(MPIdentityPhoneNumber3): @"1(234)-567-3333", + @(MPIdentityIOSAdvertiserId): @"testAdvertID", + @(MPIdentityIOSVendorId): @"testVendorID", + @(MPIdentityPushToken): @"testPushToken", + @(MPIdentityDeviceApplicationStamp): @"Test DAS"}; + + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] init]; + id mockfilteredUser = OCMPartialMock(filteredUser); + [[[mockfilteredUser stub] andReturn:testIdentities] userIdentities]; + id mockMPKitRoktClass = OCMClassMock([MPKitRokt class]); + [[[mockMPKitRoktClass stub] andReturn:nil] getRoktHashedEmailUserIdentityType]; + + [MPKitRokt addIdentityAttributes:passedAttributes filteredUser:filteredUser]; + + XCTAssertEqualObjects(passedAttributes[@"customerid"], @"testCustomerID"); + XCTAssertEqualObjects(passedAttributes[@"email"], @"testEmail@gmail.com"); + XCTAssertEqualObjects(passedAttributes[@"facebook"], @"testFacebook"); + XCTAssertEqualObjects(passedAttributes[@"facebookcustomaudienceid"], @"testCustomAudienceID"); + XCTAssertEqualObjects(passedAttributes[@"google"], @"testGoogle"); + XCTAssertEqualObjects(passedAttributes[@"microsoft"], @"testMicrosoft"); + XCTAssertEqualObjects(passedAttributes[@"other"], @"testOther"); + XCTAssertEqualObjects(passedAttributes[@"twitter"], @"testTwitter"); + XCTAssertEqualObjects(passedAttributes[@"yahoo"], @"testYahoo"); + XCTAssertEqualObjects(passedAttributes[@"other2"], @"testOther2"); + XCTAssertEqualObjects(passedAttributes[@"other3"], @"testOther3"); + XCTAssertEqualObjects(passedAttributes[@"other4"], @"testOther4"); + XCTAssertEqualObjects(passedAttributes[@"other5"], @"testOther5"); + XCTAssertEqualObjects(passedAttributes[@"other6"], @"testOther6"); + XCTAssertEqualObjects(passedAttributes[@"other7"], @"testOther7"); + XCTAssertEqualObjects(passedAttributes[@"other8"], @"testOther8"); + XCTAssertEqualObjects(passedAttributes[@"other9"], @"testOther9"); + XCTAssertEqualObjects(passedAttributes[@"other10"], @"testOther10"); + XCTAssertEqualObjects(passedAttributes[@"mobile_number"], @"1(234)-567-8910"); + XCTAssertEqualObjects(passedAttributes[@"phone_number_2"], @"1(234)-567-2222"); + XCTAssertEqualObjects(passedAttributes[@"phone_number_3"], @"1(234)-567-3333"); + XCTAssertEqualObjects(passedAttributes[@"ios_idfa"], @"testAdvertID"); + XCTAssertEqualObjects(passedAttributes[@"ios_idfv"], @"testVendorID"); + XCTAssertEqualObjects(passedAttributes[@"push_token"], @"testPushToken"); + XCTAssertEqualObjects(passedAttributes[@"device_application_stamp"], @"Test DAS"); +} + - (void)testAddIdentityAttributesWithExistingAttributes { NSMutableDictionary *passedAttributes = [[NSMutableDictionary alloc] init]; [passedAttributes setObject:@"bar" forKey:@"foo"]; @@ -299,6 +364,8 @@ - (void)testAddIdentityAttributesWithExistingAttributes { FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] init]; id mockfilteredUser = OCMPartialMock(filteredUser); [[[mockfilteredUser stub] andReturn:testIdentities] userIdentities]; + id mockMPKitRoktClass = OCMClassMock([MPKitRokt class]); + [[[mockMPKitRoktClass stub] andReturn:@(MPIdentityOther)] getRoktHashedEmailUserIdentityType]; [MPKitRokt addIdentityAttributes:passedAttributes filteredUser:filteredUser]; diff --git a/mParticle_RoktTests/mParticle_Rokt_SwiftTests.swift b/mParticle_RoktTests/mParticle_Rokt_SwiftTests.swift index 3a1dae7..b323e0b 100644 --- a/mParticle_RoktTests/mParticle_Rokt_SwiftTests.swift +++ b/mParticle_RoktTests/mParticle_Rokt_SwiftTests.swift @@ -273,7 +273,7 @@ struct mParticle_Rokt_SwiftTests { ) // Then - #expect(layout.roktLayout == nil, "Layout should attempt to identify user attributes and fail") + #expect(layout.roktLayout != nil, "Layout should attempt to identify user attributes and fail") } @MainActor @available(iOS 15, *)